xf86-video-intel: 14 commits - src/intel_glamor.c src/intel_glamor.h src/sna/gen3_render.c src/sna/kgem.c src/sna/sna_accel.c src/sna/sna_blt.c src/sna/sna_damage.c src/sna/sna_damage.h src/sna/sna.h src/sna/sna_render_inline.h src/sna/sna_trapezoids.c uxa/uxa-accel.c uxa/uxa.c uxa/uxa-glamor.h

Chris Wilson ickle at kemper.freedesktop.org
Tue Jan 3 13:38:53 PST 2012


 src/intel_glamor.c          |   14 ----
 src/intel_glamor.h          |    2 
 src/sna/gen3_render.c       |   31 +++++----
 src/sna/kgem.c              |   95 +++++++++++++++++++++++++----
 src/sna/sna.h               |   12 +++
 src/sna/sna_accel.c         |   28 ++++----
 src/sna/sna_blt.c           |   23 +++++--
 src/sna/sna_damage.c        |   27 ++++++--
 src/sna/sna_damage.h        |    4 -
 src/sna/sna_render_inline.h |    2 
 src/sna/sna_trapezoids.c    |   14 +---
 uxa/uxa-accel.c             |  142 ++++++++++++++++++++++++++++++++++++++++++--
 uxa/uxa-glamor.h            |   11 +++
 uxa/uxa.c                   |   12 +++
 14 files changed, 334 insertions(+), 83 deletions(-)

New commits:
commit feb75c55d6105a9ecc5f5ec7830276d1654918b9
Author: Zhigang Gong <zhigang.gong at linux.intel.com>
Date:   Sat Dec 31 21:18:15 2011 +0800

    uxa/glamor: Route some missing drawing function to glamor
    
    We have to route all the drawing function to glamor first, when
    glamor is enabled. This adds a few more functions that were previously
    just falling back to swrast and passes them to glamor instead.
    
    Signed-off-by: Zhigang Gong <zhigang.gong at linux.intel.com>
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/uxa/uxa-accel.c b/uxa/uxa-accel.c
index 53ff24c..4e5bac3 100644
--- a/uxa/uxa-accel.c
+++ b/uxa/uxa-accel.c
@@ -558,6 +558,18 @@ uxa_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
 {
 	int i;
 	xRectangle *prect;
+	uxa_screen_t *uxa_screen = uxa_get_screen(pDrawable->pScreen);
+
+	if (uxa_screen->info->flags & UXA_USE_GLAMOR) {
+		int ok;
+
+		uxa_prepare_access(pDrawable, UXA_GLAMOR_ACCESS_RW);
+		ok = glamor_poly_point_nf(pDrawable, pGC, mode, npt, ppt);
+		uxa_finish_access(pDrawable, UXA_GLAMOR_ACCESS_RW);
+
+		if (ok)
+			return;
+	}
 
 	/* If we can't reuse the current GC as is, don't bother accelerating the
 	 * points.
@@ -596,6 +608,18 @@ uxa_poly_lines(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
 	xRectangle *prect;
 	int x1, x2, y1, y2;
 	int i;
+	uxa_screen_t *uxa_screen = uxa_get_screen(pDrawable->pScreen);
+
+	if (uxa_screen->info->flags & UXA_USE_GLAMOR) {
+		int ok;
+
+		uxa_prepare_access(pDrawable, UXA_GLAMOR_ACCESS_RW);
+		ok = glamor_poly_lines_nf(pDrawable, pGC, mode, npt, ppt);
+		uxa_finish_access(pDrawable, UXA_GLAMOR_ACCESS_RW);
+
+		if (ok)
+			return;
+	}
 
 	/* Don't try to do wide lines or non-solid fill style. */
 	if (pGC->lineWidth != 0 || pGC->lineStyle != LineSolid ||
@@ -657,6 +681,18 @@ uxa_poly_segment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment * pSeg)
 {
 	xRectangle *prect;
 	int i;
+	uxa_screen_t *uxa_screen = uxa_get_screen(pDrawable->pScreen);
+
+	if (uxa_screen->info->flags & UXA_USE_GLAMOR) {
+		int ok;
+
+		uxa_prepare_access(pDrawable, UXA_GLAMOR_ACCESS_RW);
+		ok = glamor_poly_segment_nf(pDrawable, pGC, nseg, pSeg);
+		uxa_finish_access(pDrawable, UXA_GLAMOR_ACCESS_RW);
+
+		if (ok)
+			return;
+	}
 
 	/* Don't try to do wide lines or non-solid fill style. */
 	if (pGC->lineWidth != 0 || pGC->lineStyle != LineSolid ||
@@ -889,12 +925,110 @@ fallback:
 	uxa_check_set_spans(pDrawable, gc, src, points, widths, n, sorted);
 }
 
+static RegionPtr
+uxa_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
+	       int srcx, int srcy, int w, int h, int dstx, int dsty,
+	       unsigned long bitPlane)
+{
+	ScreenPtr screen = pDst->pScreen;
+	uxa_screen_t *uxa_screen = uxa_get_screen(screen);
+
+	if (uxa_screen->info->flags & UXA_USE_GLAMOR) {
+		int ok;
+		RegionPtr region;
+
+		uxa_prepare_access(pDst, UXA_GLAMOR_ACCESS_RW);
+		uxa_prepare_access(pSrc, UXA_GLAMOR_ACCESS_RO);
+		ok = glamor_copy_plane_nf(pSrc, pDst, pGC, srcx, srcy, w, h,
+					   dstx, dsty, bitPlane, &region);
+		uxa_finish_access(pSrc, UXA_GLAMOR_ACCESS_RO);
+		uxa_finish_access(pDst, UXA_GLAMOR_ACCESS_RW);
+		if (!ok)
+			goto fallback;
+		return region;
+	}
+
+fallback:
+	return uxa_check_copy_plane(pSrc, pDst, pGC, srcx, srcy, w, h,
+				    dstx, dsty, bitPlane);
+}
+
+static void
+uxa_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
+		    int x, int y, unsigned int nglyph,
+		    CharInfoPtr * ppci, pointer pglyphBase)
+{
+	ScreenPtr screen = pDrawable->pScreen;
+	uxa_screen_t *uxa_screen = uxa_get_screen(screen);
+
+	if (uxa_screen->info->flags & UXA_USE_GLAMOR) {
+		int ok;
+
+		uxa_prepare_access(pDrawable, UXA_GLAMOR_ACCESS_RW);
+		ok = glamor_image_glyph_blt_nf(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
+		uxa_finish_access(pDrawable, UXA_GLAMOR_ACCESS_RW);
+		if (!ok)
+			goto fallback;
+		return;
+	}
+
+fallback:
+	uxa_check_image_glyph_blt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
+}
+
+static void
+uxa_poly_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
+		   int x, int y, unsigned int nglyph,
+		   CharInfoPtr * ppci, pointer pglyphBase)
+{
+	ScreenPtr screen = pDrawable->pScreen;
+	uxa_screen_t *uxa_screen = uxa_get_screen(screen);
+
+	if (uxa_screen->info->flags & UXA_USE_GLAMOR) {
+		int ok;
+
+		uxa_prepare_access(pDrawable, UXA_GLAMOR_ACCESS_RW);
+		ok = glamor_poly_glyph_blt_nf(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
+		uxa_finish_access(pDrawable, UXA_GLAMOR_ACCESS_RW);
+		if (!ok)
+			goto fallback;
+		return;
+	}
+
+fallback:
+	uxa_check_poly_glyph_blt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
+}
+
+static void
+uxa_push_pixels(GCPtr pGC, PixmapPtr pBitmap,
+		DrawablePtr pDrawable, int w, int h, int x, int y)
+{
+	ScreenPtr screen = pDrawable->pScreen;
+	uxa_screen_t *uxa_screen = uxa_get_screen(screen);
+
+	if (uxa_screen->info->flags & UXA_USE_GLAMOR) {
+		int ok;
+
+		uxa_prepare_access(pDrawable, UXA_GLAMOR_ACCESS_RW);
+		uxa_prepare_access(&pBitmap->drawable, UXA_GLAMOR_ACCESS_RO);
+		ok = glamor_push_pixels_nf(pGC, pBitmap, pDrawable, w, h, x, y);
+		uxa_finish_access(&pBitmap->drawable, UXA_GLAMOR_ACCESS_RO);
+		uxa_prepare_access(pDrawable, UXA_GLAMOR_ACCESS_RW);
+		if (!ok)
+			goto fallback;
+		return;
+	}
+
+fallback:
+	uxa_check_push_pixels(pGC, pBitmap, pDrawable, w, h, x, y);
+}
+
 const GCOps uxa_ops = {
 	uxa_fill_spans,
 	uxa_set_spans,
 	uxa_put_image,
 	uxa_copy_area,
-	uxa_check_copy_plane,
+	uxa_copy_plane,
 	uxa_poly_point,
 	uxa_poly_lines,
 	uxa_poly_segment,
@@ -907,9 +1041,9 @@ const GCOps uxa_ops = {
 	miPolyText16,
 	miImageText8,
 	miImageText16,
-	uxa_check_image_glyph_blt,
-	uxa_check_poly_glyph_blt,
-	uxa_check_push_pixels,
+	uxa_image_glyph_blt,
+	uxa_poly_glyph_blt,
+	uxa_push_pixels,
 };
 
 void uxa_copy_window(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
diff --git a/uxa/uxa-glamor.h b/uxa/uxa-glamor.h
index 950a878..5ff19e0 100644
--- a/uxa/uxa-glamor.h
+++ b/uxa/uxa-glamor.h
@@ -53,6 +53,13 @@
 #define glamor_add_traps_nf(...)	FALSE
 #define glamor_create_gc(...)		FALSE
 #define glamor_validate_gc(...)		do { } while(0)
+#define glamor_poly_point_nf(...)	FALSE
+#define glamor_poly_segment_nf(...)	FALSE
+#define glamor_poly_lines_nf(...)	FALSE
+#define glamor_push_pixels_nf(...)	FALSE
+#define glamor_copy_plane_nf(...)	FALSE
+#define glamor_image_glyph_blt_nf(...)	FALSE
+#define glamor_poly_glyph_blt_nf(...)	FALSE
 #endif
 
 #endif /* UXA_GLAMOR_H */
commit f4ea732d7181d4ef7f97fb2585e87cdcaef99d46
Author: Zhigang Gong <zhigang.gong at linux.intel.com>
Date:   Tue Dec 27 17:09:17 2011 +0800

    uxa/glamor: Let glamor do the GC validation
    
    If we are using GLAMOR, then a tile pixmap or stipple pixmap
    may be pure glamor pixmap and thus UXA will not know how to
    render to them, and we need to let glamor do the validation.
    
    Signed-off-by: Zhigang Gong <zhigang.gong at linux.intel.com>
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/uxa/uxa-glamor.h b/uxa/uxa-glamor.h
index 71a9c29..950a878 100644
--- a/uxa/uxa-glamor.h
+++ b/uxa/uxa-glamor.h
@@ -45,12 +45,14 @@
 #define glamor_set_spans_nf(...)	FALSE
 #define glamor_get_image_nf(...)	FALSE
 #define glamor_glyphs_nf(...)		FALSE
-#define glamor_glyph_unrealize(...)	;
+#define glamor_glyph_unrealize(...)	do { } while(0)
 #define glamor_composite_nf(...)	FALSE
 #define glamor_composite_rects_nf(...)	FALSE
 #define glamor_trapezoids_nf(...)	FALSE
 #define glamor_triangles_nf(...)	FALSE
 #define glamor_add_traps_nf(...)	FALSE
+#define glamor_create_gc(...)		FALSE
+#define glamor_validate_gc(...)		do { } while(0)
 #endif
 
 #endif /* UXA_GLAMOR_H */
diff --git a/uxa/uxa.c b/uxa/uxa.c
index d912b03..eb2ae03 100644
--- a/uxa/uxa.c
+++ b/uxa/uxa.c
@@ -38,6 +38,7 @@
 #include <X11/fonts/fontstruct.h>
 #include "dixfontstr.h"
 #include "uxa.h"
+#include "uxa-glamor.h"
 
 #if HAS_DEVPRIVATEKEYREC
 DevPrivateKeyRec uxa_screen_index;
@@ -183,11 +184,21 @@ void uxa_finish_access(DrawablePtr pDrawable, uxa_access_t access)
 static void
 uxa_validate_gc(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
 {
+	uxa_screen_t *uxa_screen = uxa_get_screen(pGC->pScreen);
 	/* fbValidateGC will do direct access to pixmaps if the tiling has
 	 * changed.
 	 * Preempt fbValidateGC by doing its work and masking the change out, so
 	 * that we can do the Prepare/finish_access.
 	 */
+
+	/* If we are using GLAMOR, then the tile or stipple pixmap
+	 * may be pure GLAMOR pixmap, then we should let the glamor
+	 * to do the validation.
+	 */
+	if (uxa_screen->info->flags & UXA_USE_GLAMOR) {
+		glamor_validate_gc(pGC, changes, pDrawable);
+		goto set_ops;
+	}
 #ifdef FB_24_32BIT
 	if ((changes & GCTile) && fbGetRotatedPixmap(pGC)) {
 		(*pGC->pScreen->DestroyPixmap) (fbGetRotatedPixmap(pGC));
@@ -256,6 +267,7 @@ uxa_validate_gc(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
 		fbValidateGC(pGC, changes, pDrawable);
 	}
 
+set_ops:
 	pGC->ops = (GCOps *) & uxa_ops;
 }
 
commit e8aa9cedbfca09e22d46ec8882b9bebb3eb83022
Author: Zhigang Gong <zhigang.gong at linux.intel.com>
Date:   Tue Dec 27 17:09:16 2011 +0800

    uxa/glamor: Remove extraneous flush
    
    When glamor is enabled, a pixmap will not be accessed by UXA's
    accelerated functions. Only unaccelerated functions may access those
    pixmaps, and before each unaccelerated rendering, it calls
    uxa_prepare_access which will do a glFlush. Combined with a flush before
    sending to DRI clients, we no longer need to flush after every
    operation.
    
    Signed-off-by: Zhigang Gong <zhigang.gong at linux.intel.com>
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/intel_glamor.c b/src/intel_glamor.c
index 2b56ae5..669b1b8 100644
--- a/src/intel_glamor.c
+++ b/src/intel_glamor.c
@@ -135,7 +135,6 @@ intel_glamor_finish_access(PixmapPtr pixmap, uxa_access_t access)
 		break;
 	case UXA_GLAMOR_ACCESS_RW:
 		intel_glamor_need_flush(&pixmap->drawable);
-		glamor_block_handler(pixmap->drawable.pScreen);
 		break;
 	default:
 		ErrorF("Invalid access mode %d\n", access);
commit 4ca94ed91fab7a9de5eed1053b891e8420cdf43d
Author: Zhigang Gong <zhigang.gong at linux.intel.com>
Date:   Tue Dec 27 17:09:15 2011 +0800

    uxa/glamor: Remove dead code.
    
    Signed-off-by: Zhigang Gong <zhigang.gong at linux.intel.com>
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/intel_glamor.c b/src/intel_glamor.c
index 8daa4b1..2b56ae5 100644
--- a/src/intel_glamor.c
+++ b/src/intel_glamor.c
@@ -192,19 +192,6 @@ intel_glamor_flush(intel_screen_private * intel)
 }
 
 Bool
-intel_glamor_create_screen_image(ScreenPtr screen, int handle, int stride)
-{
-	ScrnInfoPtr scrn = xf86Screens[screen->myNum];
-	intel_screen_private *intel;
-
-	intel = intel_get_screen_private(scrn);
-	if ((intel->uxa_flags & UXA_USE_GLAMOR) == 0)
-		return TRUE;
-
-	return glamor_egl_create_textured_screen(screen, handle, stride);
-}
-
-Bool
 intel_glamor_close_screen(ScreenPtr screen)
 {
 	ScrnInfoPtr scrn = xf86Screens[screen->myNum];
diff --git a/src/intel_glamor.h b/src/intel_glamor.h
index 1374588..3065132 100644
--- a/src/intel_glamor.h
+++ b/src/intel_glamor.h
@@ -35,7 +35,6 @@
 Bool intel_glamor_pre_init(ScrnInfoPtr scrn);
 Bool intel_glamor_init(ScreenPtr screen);
 Bool intel_glamor_create_screen_resources(ScreenPtr screen);
-Bool intel_glamor_create_screen_image(ScreenPtr screen, int handle, int stride);
 Bool intel_glamor_close_screen(ScreenPtr screen);
 void intel_glamor_free_screen(int scrnIndex, int flags);
 
@@ -51,7 +50,6 @@ PixmapPtr intel_glamor_create_pixmap(ScreenPtr screen, int w, int h,
 static inline Bool intel_glamor_pre_init(ScrnInfoPtr scrn) { return TRUE; }
 static inline Bool intel_glamor_init(ScreenPtr screen) { return TRUE; }
 static inline Bool intel_glamor_create_screen_resources(ScreenPtr screen) { return TRUE; }
-static inline Bool intel_glamor_create_screen_image(ScreenPtr screen, int handle, int stride) { return TRUE; }
 static inline Bool intel_glamor_close_screen(ScreenPtr screen) { return TRUE; }
 static inline void intel_glamor_free_screen(int scrnIndex, int flags) { }
 
commit 5576afc7d12ec0f028e416f4b4a076fc6d3c29d9
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jan 3 16:48:52 2012 +0000

    sna: Inline checks for over-sized buffers during pixmap creation
    
    Make the tests for acceptable GPU pixmaps explicit and upfront.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index e2e90c1..f4f3521 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -556,6 +556,7 @@ static PixmapPtr sna_create_pixmap(ScreenPtr screen,
 				   int width, int height, int depth,
 				   unsigned int usage)
 {
+	struct sna *sna = to_sna_from_screen(screen);
 	PixmapPtr pixmap;
 	int pad, size;
 
@@ -568,7 +569,7 @@ static PixmapPtr sna_create_pixmap(ScreenPtr screen,
 						 width, height, depth,
 						 I915_TILING_X);
 #else
-		return create_pixmap(to_sna_from_screen(screen), screen,
+		return create_pixmap(sna, screen,
 				     width, height, depth,
 				     usage);
 #endif
@@ -583,22 +584,26 @@ static PixmapPtr sna_create_pixmap(ScreenPtr screen,
 						 width, height, depth,
 						 I915_TILING_X);
 
+	if (usage == CREATE_PIXMAP_USAGE_GLYPH_PICTURE ||
+	    !kgem_can_create_2d(&sna->kgem, width, height,
+				BitsPerPixel(depth), I915_TILING_NONE))
+		return create_pixmap(sna, screen, width, height, depth, usage);
+
 #if FAKE_CREATE_PIXMAP_USAGE_SCRATCH_HEADER
 	if (width == 0 || height == 0)
-		usage = CREATE_PIXMAP_USAGE_SCRATCH_HEADER;
+		return create_pixmap(sna, screen, width, height, depth, usage);
 #endif
 
 	pad = PixmapBytePad(width, depth);
 	size = pad * height;
 	if (size <= 4096) {
-		pixmap = create_pixmap(to_sna_from_screen(screen), screen,
+		pixmap = create_pixmap(sna, screen,
 				       width, height, depth, usage);
 		if (pixmap == NullPixmap)
 			return NullPixmap;
 
 		sna_pixmap_attach(pixmap);
 	} else {
-		struct sna *sna = to_sna_from_screen(screen);
 		struct sna_pixmap *priv;
 
 		pixmap = create_pixmap(sna, screen, 0, 0, depth, usage);
@@ -610,12 +615,11 @@ static PixmapPtr sna_create_pixmap(ScreenPtr screen,
 		pixmap->devKind = pad;
 		pixmap->devPrivate.ptr = NULL;
 
-		priv = sna_pixmap_attach(pixmap);
+		priv = _sna_pixmap_attach(sna, pixmap);
 		if (priv == NULL) {
 			free(pixmap);
 			return create_pixmap(sna, screen,
-					     width, height, depth,
-					     usage);
+					     width, height, depth, usage);
 		}
 
 		priv->stride = pad;
commit b2dc17678fa3a548be61e1055d4d321dbd6494c3
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jan 3 15:50:21 2012 +0000

    sna: Always search for an exact active match first from the bo-cache
    
    And accept second-best only if permitted by flags.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 8812d23..1e4d08f 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -1895,20 +1895,20 @@ struct kgem_bo *kgem_create_2d(struct kgem *kgem,
 	struct kgem_bo *bo, *next;
 	uint32_t pitch, untiled_pitch, tiled_height[3], size;
 	uint32_t handle;
-	int exact = flags & CREATE_EXACT;
 	int i;
 
 	if (tiling < 0)
-		tiling = -tiling, exact = 1;
+		tiling = -tiling, flags |= CREATE_EXACT;
 
 	DBG(("%s(%dx%d, bpp=%d, tiling=%d, exact=%d, inactive=%d, cpu-mapping=%d, gtt-mapping=%d, scanout?=%d)\n", __FUNCTION__,
 	     width, height, bpp, tiling,
-	     !!exact, !!(flags & CREATE_INACTIVE),
+	     !!(flags & CREATE_EXACT),
+	     !!(flags & CREATE_INACTIVE),
 	     !!(flags & CREATE_CPU_MAP),
 	     !!(flags & CREATE_GTT_MAP),
 	     !!(flags & CREATE_SCANOUT)));
 
-	assert(_kgem_can_create_2d(kgem, width, height, bpp, exact ? -tiling : tiling));
+	assert(_kgem_can_create_2d(kgem, width, height, bpp, flags & CREATE_EXACT ? -tiling : tiling));
 	size = kgem_surface_size(kgem,
 				 kgem->has_relaxed_fencing,
 				 flags & CREATE_SCANOUT,
@@ -1972,18 +1972,12 @@ struct kgem_bo *kgem_create_2d(struct kgem *kgem,
 	for (i = 0; i <= I915_TILING_Y; i++)
 		tiled_height[i] = kgem_aligned_height(kgem, height, i);
 
+	next = NULL;
+	cache = active(kgem, size);
 search_active: /* Best active match first */
-	list_for_each_entry(bo, active(kgem, size), list) {
+	list_for_each_entry(bo, cache, list) {
 		uint32_t s;
 
-		if (exact) {
-			if (bo->tiling != tiling)
-				continue;
-		} else {
-			if (bo->tiling > tiling)
-				continue;
-		}
-
 		if (bo->tiling) {
 			if (bo->pitch < pitch) {
 				DBG(("tiled and pitch too small: tiling=%d, (want %d), pitch=%d, need %d\n",
@@ -1996,6 +1990,12 @@ search_active: /* Best active match first */
 
 		s = bo->pitch * tiled_height[bo->tiling];
 		if (s <= bo->size) {
+			if (bo->tiling != tiling) {
+				if (next == NULL && bo->tiling < tiling)
+					next = bo;
+				continue;
+			}
+
 			list_del(&bo->list);
 			if (bo->rq == &_kgem_static_request)
 				list_del(&bo->request);
@@ -2009,7 +2009,7 @@ search_active: /* Best active match first */
 
 			bo->unique_id = kgem_get_unique_id(kgem);
 			bo->delta = 0;
-			DBG(("  from active: pitch=%d, tiling=%d, handle=%d, id=%d\n",
+			DBG(("  1:from active: pitch=%d, tiling=%d, handle=%d, id=%d\n",
 			     bo->pitch, bo->tiling, bo->handle, bo->unique_id));
 			assert(bo->refcnt == 0);
 			assert(bo->reusable);
@@ -2017,6 +2017,25 @@ search_active: /* Best active match first */
 		}
 	}
 
+	if (next && (flags & CREATE_EXACT) == 0) {
+		list_del(&next->list);
+		if (next->rq == &_kgem_static_request)
+			list_del(&next->request);
+
+		if (next->purged && !kgem_bo_clear_purgeable(kgem, next)) {
+			kgem->need_purge |= next->domain == DOMAIN_GPU;
+			kgem_bo_free(kgem, next);
+		} else {
+			next->unique_id = kgem_get_unique_id(kgem);
+			next->delta = 0;
+			DBG(("  2:from active: pitch=%d, tiling=%d, handle=%d, id=%d\n",
+			     next->pitch, next->tiling, next->handle, next->unique_id));
+			assert(next->refcnt == 0);
+			assert(next->reusable);
+			return kgem_bo_reference(next);
+		}
+	}
+
 skip_active_search:
 	/* Now just look for a close match and prefer any currently active */
 	cache = inactive(kgem, size);
commit caf41ae23d263c7baed6b23a80693690c4dfe563
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jan 3 15:11:13 2012 +0000

    sna: Force tiling on medium pitches if not reduced for other reasons
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 3bd65b1..8812d23 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -1814,6 +1814,14 @@ int kgem_choose_tiling(struct kgem *kgem, int tiling, int width, int height, int
 		goto done;
 	}
 
+	if (tiling && width * bpp >= 8 * 4096 / 2) {
+		DBG(("%s: TLB near-miss between lines %dx%d (pitch=%d), forcing tiling %d\n",
+		     __FUNCTION__,
+		     width, height, width*bpp/8,
+		     tiling));
+		return -tiling;
+	}
+
 done:
 	DBG(("%s: %dx%d -> %d\n", __FUNCTION__, width, height, tiling));
 	return tiling;
commit 1b688ca0cfc1e623f896e60a6a6abf724d57efb4
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jan 3 14:18:05 2012 +0000

    sna: Delete the last buffer if destroyed without being used on the GPU
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 7424a8a..3bd65b1 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -2094,10 +2094,49 @@ skip_active_search:
 	return bo;
 }
 
+static void _kgem_bo_delete_partial(struct kgem *kgem, struct kgem_bo *bo)
+{
+	struct kgem_partial_bo *io = (struct kgem_partial_bo *)bo->proxy;
+
+	if (list_is_empty(&io->base.list))
+		    return;
+
+	if (bo->size == io->used) {
+		assert(io->base.exec == NULL);
+		assert(io->base.refcnt >= 2);
+		list_del(&io->base.list);
+		--io->base.refcnt;
+	} else if (bo->delta + bo->size == io->used) {
+		int remain;
+
+		io->used = bo->delta;
+		remain = io->alloc - io->used;
+		while (io->base.list.prev != &kgem->partial) {
+			struct kgem_partial_bo *p;
+
+			p = list_entry(&io->base.list.prev,
+				       struct kgem_partial_bo,
+				       base.list);
+			if (remain < p->alloc - p->used)
+				break;
+
+			io->base.list.prev = p->base.list.prev;
+			p->base.list.prev->next = &io->base.list;
+			p->base.list.prev = &io->base.list;
+
+			p->base.list.next = io->base.list.next;
+			io->base.list.next->prev = &p->base.list;
+			io->base.list.next = &p->base.list;
+		}
+	}
+}
+
 void _kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo)
 {
 	if (bo->proxy) {
 		assert(bo->map == NULL);
+		if (bo->io && bo->exec == NULL)
+			_kgem_bo_delete_partial(kgem, bo);
 		kgem_bo_unref(kgem, bo->proxy);
 		kgem_bo_binding_free(kgem, bo);
 		_list_del(&bo->request);
@@ -2639,6 +2678,7 @@ struct kgem_bo *kgem_create_proxy(struct kgem_bo *target,
 	if (bo == NULL)
 		return NULL;
 
+	bo->io = target->io;
 	bo->reusable = false;
 	bo->proxy = kgem_bo_reference(target);
 	bo->delta = offset;
commit 4a68e7277104d7dccbdc4739eb5651902b9ccc20
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jan 3 12:19:24 2012 +0000

    sna/gen3: Prefer to use the blitter for solid fills
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/gen3_render.c b/src/sna/gen3_render.c
index a4701df..fdd2805 100644
--- a/src/sna/gen3_render.c
+++ b/src/sna/gen3_render.c
@@ -2150,25 +2150,24 @@ gen3_composite_picture(struct sna *sna,
 				    x, y, w, h, dst_x, dst_y);
 }
 
-static inline Bool
+static inline bool
 source_use_blt(struct sna *sna, PicturePtr picture)
 {
+	/* If it is a solid, try to use the BLT paths */
 	if (!picture->pDrawable)
-		return FALSE;
+		return picture->pSourcePict->type == SourcePictTypeSolidFill;
 
-	/* If it is a solid, try to use the render paths */
 	if (picture->pDrawable->width  == 1 &&
 	    picture->pDrawable->height == 1 &&
 	    picture->repeat)
-		return FALSE;
+		return true;
 
-	if (too_large(picture->pDrawable->width,
-		      picture->pDrawable->height))
-		return TRUE;
+	if (too_large(picture->pDrawable->width, picture->pDrawable->height))
+		return true;
 
 	/* If we can sample directly from user-space, do so */
 	if (sna->kgem.has_vmap)
-		return FALSE;
+		return false;
 
 	return is_cpu(picture->pDrawable);
 }
commit 199e357dc693cfe232464e4faa82d9223a8325d6
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jan 3 12:16:48 2012 +0000

    sna/trapezoids: Pass the sna pointer to the callees
    
    Avoid the repeated multiple indirect dereferences.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_trapezoids.c b/src/sna/sna_trapezoids.c
index f7fbdb2..2a48e3d 100644
--- a/src/sna/sna_trapezoids.c
+++ b/src/sna/sna_trapezoids.c
@@ -1966,7 +1966,8 @@ trapezoids_fallback(CARD8 op, PicturePtr src, PicturePtr dst,
 }
 
 static Bool
-composite_aligned_boxes(CARD8 op,
+composite_aligned_boxes(struct sna *sna,
+			CARD8 op,
 			PicturePtr src,
 			PicturePtr dst,
 			PictFormatPtr maskFormat,
@@ -1975,7 +1976,6 @@ composite_aligned_boxes(CARD8 op,
 {
 	BoxRec stack_boxes[64], *boxes, extents;
 	pixman_region16_t region, clip;
-	struct sna *sna;
 	struct sna_composite_op tmp;
 	Bool ret = true;
 	int dx, dy, n, num_boxes;
@@ -2045,7 +2045,6 @@ composite_aligned_boxes(CARD8 op,
 	}
 
 	memset(&tmp, 0, sizeof(tmp));
-	sna = to_sna_from_drawable(dst->pDrawable);
 	if (!sna->render.composite(sna, op, src, NULL, dst,
 				   src_x,  src_y,
 				   0, 0,
@@ -2409,14 +2408,14 @@ composite_unaligned_boxes_fallback(CARD8 op,
 }
 
 static Bool
-composite_unaligned_boxes(CARD8 op,
+composite_unaligned_boxes(struct sna *sna,
+			  CARD8 op,
 			  PicturePtr src,
 			  PicturePtr dst,
 			  PictFormatPtr maskFormat,
 			  INT16 src_x, INT16 src_y,
 			  int ntrap, xTrapezoid *traps)
 {
-	struct sna *sna;
 	BoxRec extents;
 	struct sna_composite_spans_op tmp;
 	pixman_region16_t clip;
@@ -2432,7 +2431,6 @@ composite_unaligned_boxes(CARD8 op,
 	if (ntrap > 1 && maskFormat)
 		return false;
 
-	sna = to_sna_from_drawable(dst->pDrawable);
 	if (!sna->render.composite_spans)
 		return composite_unaligned_boxes_fallback(op, src, dst, src_x, src_y, ntrap, traps);
 
@@ -3606,13 +3604,13 @@ sna_composite_trapezoids(CARD8 op,
 	     __FUNCTION__, rectilinear, pixel_aligned));
 	if (rectilinear) {
 		if (pixel_aligned) {
-			if (composite_aligned_boxes(op, src, dst,
+			if (composite_aligned_boxes(sna, op, src, dst,
 						    maskFormat,
 						    xSrc, ySrc,
 						    ntrap, traps))
 			    return;
 		} else {
-			if (composite_unaligned_boxes(op, src, dst,
+			if (composite_unaligned_boxes(sna, op, src, dst,
 						      maskFormat,
 						      xSrc, ySrc,
 						      ntrap, traps))
commit bd7aa1754dcf9d58d7deb92d99da9b78c91a0eb2
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jan 3 12:46:40 2012 +0000

    sna: Avoid unnecessary call overhead for read-only move-to-cpu
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna.h b/src/sna/sna.h
index feba5b5..f23e6e5 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -433,7 +433,17 @@ struct kgem_bo *sna_pixmap_change_tiling(PixmapPtr pixmap, uint32_t tiling);
 
 #define MOVE_WRITE 0x1
 #define MOVE_READ 0x2
-bool must_check sna_pixmap_move_to_cpu(PixmapPtr pixmap, unsigned flags);
+bool must_check _sna_pixmap_move_to_cpu(PixmapPtr pixmap, unsigned flags);
+static inline bool must_check sna_pixmap_move_to_cpu(PixmapPtr pixmap, unsigned flags)
+{
+	if (flags == MOVE_READ) {
+		struct sna_pixmap *priv = sna_pixmap(pixmap);
+		if (priv == NULL || priv->gpu_damage == NULL)
+			return true;
+	}
+
+	return _sna_pixmap_move_to_cpu(pixmap, flags);
+}
 bool must_check sna_drawable_move_region_to_cpu(DrawablePtr drawable,
 						RegionPtr region,
 						unsigned flags);
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 7a1dc46..e2e90c1 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -658,7 +658,7 @@ static inline bool pixmap_inplace(struct sna *sna,
 }
 
 bool
-sna_pixmap_move_to_cpu(PixmapPtr pixmap, unsigned int flags)
+_sna_pixmap_move_to_cpu(PixmapPtr pixmap, unsigned int flags)
 {
 	struct sna *sna = to_sna_from_pixmap(pixmap);
 	struct sna_pixmap *priv;
@@ -885,7 +885,7 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
 		DBG(("%s: region subsumes drawable\n", __FUNCTION__));
 		if (dx | dy)
 			RegionTranslate(region, -dx, -dy);
-		return sna_pixmap_move_to_cpu(pixmap, flags);
+		return _sna_pixmap_move_to_cpu(pixmap, flags);
 	}
 
 	if ((flags & MOVE_READ) == 0) {
commit 294c8791c435acf5933109fbcab85623a55b2c6c
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jan 3 12:09:51 2012 +0000

    sna: Use a cheaper no-reduction damage check for simply discarding further damage
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 0b9565c..7a1dc46 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -1291,10 +1291,8 @@ _sna_drawable_use_cpu_bo(DrawablePtr drawable,
 		return FALSE;
 
 done:
-	if (sna_damage_contains_box(priv->cpu_damage,
-				    &extents) != PIXMAN_REGION_IN)
-		*damage = &priv->cpu_damage;
-	else
+	*damage = &priv->cpu_damage;
+	if (sna_damage_contains_box__no_reduce(priv->cpu_damage, &extents))
 		*damage = NULL;
 
 	return TRUE;
diff --git a/src/sna/sna_blt.c b/src/sna/sna_blt.c
index 220b900..4c25376 100644
--- a/src/sna/sna_blt.c
+++ b/src/sna/sna_blt.c
@@ -1146,11 +1146,16 @@ has_gpu_area(PixmapPtr pixmap, int x, int y, int w, int h)
 
 	if (priv->cpu_damage == NULL)
 		return TRUE;
+	if (priv->cpu_damage->mode == DAMAGE_ALL)
+		return FALSE;
 
 	area.x1 = x;
 	area.y1 = y;
 	area.x2 = x + w;
 	area.y2 = y + h;
+	if (priv->gpu_damage &&
+	    sna_damage_contains_box__no_reduce(priv->gpu_damage, &area))
+		return TRUE;
 
 	return sna_damage_contains_box(priv->cpu_damage,
 				       &area) == PIXMAN_REGION_OUT;
@@ -1164,16 +1169,19 @@ has_cpu_area(PixmapPtr pixmap, int x, int y, int w, int h)
 
 	if (!priv)
 		return TRUE;
-	if (!priv->gpu_bo)
-		return TRUE;
-
 	if (priv->gpu_damage == NULL)
 		return TRUE;
+	if (priv->gpu_damage->mode == DAMAGE_ALL)
+		return FALSE;
 
 	area.x1 = x;
 	area.y1 = y;
 	area.x2 = x + w;
 	area.y2 = y + h;
+	if (priv->cpu_damage &&
+	    sna_damage_contains_box__no_reduce(priv->cpu_damage, &area))
+		return TRUE;
+
 	return sna_damage_contains_box(priv->gpu_damage,
 				       &area) == PIXMAN_REGION_OUT;
 }
@@ -1185,8 +1193,13 @@ reduce_damage(struct sna_composite_op *op,
 {
 	BoxRec r;
 
-	if (op->damage == NULL)
+	if (op->damage == NULL || *op->damage == NULL)
+		return;
+
+	if ((*op->damage)->mode == DAMAGE_ALL) {
+		op->damage = NULL;
 		return;
+	}
 
 	r.x1 = dst_x + op->dst.x;
 	r.x2 = r.x1 + width;
@@ -1194,7 +1207,7 @@ reduce_damage(struct sna_composite_op *op,
 	r.y1 = dst_y + op->dst.y;
 	r.y2 = r.y1 + height;
 
-	if (sna_damage_contains_box(*op->damage, &r) == PIXMAN_REGION_IN)
+	if (sna_damage_contains_box__no_reduce(*op->damage, &r))
 		op->damage = NULL;
 }
 
diff --git a/src/sna/sna_damage.c b/src/sna/sna_damage.c
index 7431f39..4cccbdc 100644
--- a/src/sna/sna_damage.c
+++ b/src/sna/sna_damage.c
@@ -970,7 +970,7 @@ static bool box_contains(const BoxRec *a, const BoxRec *b)
 	return true;
 }
 
-static inline Bool sna_damage_maybe_contains_box(struct sna_damage *damage,
+static inline Bool sna_damage_maybe_contains_box(const struct sna_damage *damage,
 						 const BoxRec *box)
 {
 	if (box->x2 <= damage->extents.x1 ||
@@ -1190,6 +1190,21 @@ int sna_damage_contains_box(struct sna_damage *damage,
 }
 #endif
 
+bool sna_damage_contains_box__no_reduce(const struct sna_damage *damage,
+					const BoxRec *box)
+{
+	int ret;
+
+	assert(damage && damage->mode != DAMAGE_ALL);
+	if (!sna_damage_maybe_contains_box(damage, box))
+		return false;
+
+	ret = pixman_region_contains_rectangle((RegionPtr)&damage->region,
+					       (BoxPtr)box);
+	return (!damage->dirty || damage->mode == DAMAGE_ADD) &&
+		ret == PIXMAN_REGION_IN;
+}
+
 static Bool _sna_damage_intersect(struct sna_damage *damage,
 				  RegionPtr region, RegionPtr result)
 {
diff --git a/src/sna/sna_damage.h b/src/sna/sna_damage.h
index 8e0c73c..abe222f 100644
--- a/src/sna/sna_damage.h
+++ b/src/sna/sna_damage.h
@@ -124,6 +124,8 @@ Bool sna_damage_intersect(struct sna_damage *damage,
 
 int sna_damage_contains_box(struct sna_damage *damage,
 			    const BoxRec *box);
+bool sna_damage_contains_box__no_reduce(const struct sna_damage *damage,
+					const BoxRec *box);
 
 int sna_damage_get_boxes(struct sna_damage *damage, BoxPtr *boxes);
 
diff --git a/src/sna/sna_render_inline.h b/src/sna/sna_render_inline.h
index 06d1ba3..0369123 100644
--- a/src/sna/sna_render_inline.h
+++ b/src/sna/sna_render_inline.h
@@ -148,7 +148,7 @@ sna_render_reduce_damage(struct sna_composite_op *op,
 	r.y1 = dst_y + op->dst.y;
 	r.y2 = r.y1 + height;
 
-	if (sna_damage_contains_box(*op->damage, &r) == PIXMAN_REGION_IN)
+	if (sna_damage_contains_box__no_reduce(*op->damage, &r))
 		op->damage = NULL;
 }
 
commit 7ff42e9c83cdb17660a64901497704b38032af8c
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jan 3 19:15:07 2012 +0000

    sna/damage: Mark the box as packed so that the embedded_box is aligned correctly
    
    valgrind was complaining about an overlapping memcpy on a 64-bit
    platform as gcc padded the sna_damage_box to 28 bytes...
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_damage.c b/src/sna/sna_damage.c
index 44677ed..7431f39 100644
--- a/src/sna/sna_damage.c
+++ b/src/sna/sna_damage.c
@@ -48,6 +48,11 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  * cheapy discard no-ops.
  */
 
+struct sna_damage_box {
+	struct list list;
+	int size;
+} __attribute__((packed));
+
 static struct sna_damage *__freed_damage;
 
 static inline bool region_is_singular(RegionRec *r)
@@ -182,11 +187,6 @@ static struct sna_damage *_sna_damage_create(void)
 	return damage;
 }
 
-struct sna_damage_box {
-	struct list list;
-	int size;
-};
-
 static bool _sna_damage_create_boxes(struct sna_damage *damage,
 				     int count)
 {
diff --git a/src/sna/sna_damage.h b/src/sna/sna_damage.h
index 67c44c3..8e0c73c 100644
--- a/src/sna/sna_damage.h
+++ b/src/sna/sna_damage.h
@@ -6,8 +6,6 @@
 
 #include "compiler.h"
 
-struct sna_damage_box;
-
 struct sna_damage {
 	BoxRec extents;
 	pixman_region16_t region;
commit 4652a20de5fee0d5d1a8baadc4a93b6a93525564
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jan 3 21:20:09 2012 +0000

    sna/gen3: Check for a non-NULL bo before incrementing its ref in reuse_source()
    
    For gen3, we may reduce a source into a constant operator and so
    dispense with keeping a bo. When duplicated into the mask channel, we
    then need to be careful not to dereference the NULL pointer.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/gen3_render.c b/src/sna/gen3_render.c
index 6174257..a4701df 100644
--- a/src/sna/gen3_render.c
+++ b/src/sna/gen3_render.c
@@ -2399,14 +2399,21 @@ reuse_source(struct sna *sna,
 	     PicturePtr src, struct sna_composite_channel *sc, int src_x, int src_y,
 	     PicturePtr mask, struct sna_composite_channel *mc, int msk_x, int msk_y)
 {
-	if (src->pDrawable == NULL || mask->pDrawable != src->pDrawable)
+	if (src_x != msk_x || src_y != msk_y)
 		return FALSE;
 
-	DBG(("%s: mask reuses source drawable\n", __FUNCTION__));
+	if (mask == src) {
+		*mc = *sc;
+		if (mc->bo)
+			kgem_bo_reference(mc->bo);
+		return TRUE;
+	}
 
-	if (src_x != msk_x || src_y != msk_y)
+	if ((src->pDrawable == NULL || mask->pDrawable != src->pDrawable))
 		return FALSE;
 
+	DBG(("%s: mask reuses source drawable\n", __FUNCTION__));
+
 	if (!sna_transform_equal(src->transform, mask->transform))
 		return FALSE;
 
@@ -2427,7 +2434,8 @@ reuse_source(struct sna *sna,
 	mc->filter = gen3_filter(mask->filter);
 	mc->pict_format = mask->format;
 	gen3_composite_channel_set_format(mc, mask->format);
-	mc->bo = kgem_bo_reference(mc->bo);
+	if (mc->bo)
+		kgem_bo_reference(mc->bo);
 	return TRUE;
 }
 


More information about the xorg-commit mailing list