xf86-video-intel: 8 commits - src/sna/gen2_render.c src/sna/gen3_render.c src/sna/gen4_render.c src/sna/gen5_render.c src/sna/gen6_render.c src/sna/gen7_render.c src/sna/kgem.c src/sna/sna_accel.c src/sna/sna_blt.c src/sna/sna.h src/sna/sna_io.c src/sna/sna_render.c src/sna/sna_render.h

Chris Wilson ickle at kemper.freedesktop.org
Tue Dec 20 15:09:12 PST 2011


 src/sna/gen2_render.c |   15 ++----
 src/sna/gen3_render.c |   15 ++----
 src/sna/gen4_render.c |   15 ++----
 src/sna/gen5_render.c |   15 ++----
 src/sna/gen6_render.c |   14 ++----
 src/sna/gen7_render.c |   14 ++----
 src/sna/kgem.c        |   15 +++---
 src/sna/sna.h         |    1 
 src/sna/sna_accel.c   |   37 +++++++++-------
 src/sna/sna_blt.c     |  114 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/sna/sna_io.c      |    2 
 src/sna/sna_render.c  |   21 ++++++---
 src/sna/sna_render.h  |    4 +
 13 files changed, 195 insertions(+), 87 deletions(-)

New commits:
commit 4d348425592251f49fd31b9259651e8b05e92d1e
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Dec 20 21:35:58 2011 +0000

    sna: Intiialise pixmap size before use
    
    After 0c12f7cb0 we were setting the width/height of the pixmap *after*
    trying to use them to determine if the pixmap could be created on the
    GPU. Normally this would be corrected when we attempt to render, except
    for the core drawing protocol.
    
    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 6c655ca..87c3f3d 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -375,6 +375,7 @@ struct kgem_bo *sna_pixmap_change_tiling(PixmapPtr pixmap, uint32_t tiling)
 static inline void sna_set_pixmap(PixmapPtr pixmap, struct sna_pixmap *sna)
 {
 	dixSetPrivate(&pixmap->devPrivates, &sna_pixmap_index, sna);
+	assert(sna_pixmap(pixmap) == sna);
 }
 
 static struct sna_pixmap *
@@ -592,17 +593,17 @@ static PixmapPtr sna_create_pixmap(ScreenPtr screen,
 		if (pixmap == NullPixmap)
 			return NullPixmap;
 
+		pixmap->drawable.width = width;
+		pixmap->drawable.height = height;
+		pixmap->devKind = pad;
+		pixmap->devPrivate.ptr = NULL;
+
 		if (sna_pixmap_attach(pixmap) == NULL) {
 			free(pixmap);
 			return create_pixmap(sna, screen,
 					     width, height, depth,
 					     usage);
 		}
-
-		pixmap->drawable.width = width;
-		pixmap->drawable.height = height;
-		pixmap->devKind = pad;
-		pixmap->devPrivate.ptr = NULL;
 	}
 
 	return pixmap;
commit e71058c9c81067cd72b1193242acbd85272ab73a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Dec 20 21:20:48 2011 +0000

    sna: Always readback untiled bo in place
    
    We are going to gain no advantage from the kernel detiling the busy
    buffer.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_io.c b/src/sna/sna_io.c
index 4841845..55fb88d 100644
--- a/src/sna/sna_io.c
+++ b/src/sna/sna_io.c
@@ -102,7 +102,7 @@ void sna_read_boxes(struct sna *sna,
 
 	if (DEBUG_NO_IO || kgem->wedged ||
 	    !kgem_bo_is_busy(src_bo) ||
-	    src_bo->tiling == I915_TILING_Y) {
+	    src_bo->tiling != I915_TILING_X) {
 		read_boxes_inplace(kgem,
 				   src_bo, src_dx, src_dy,
 				   dst, dst_dx, dst_dy,
commit 6690ff51ec939367051985172a00bf8ed65ac4e3
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Dec 20 21:09:01 2011 +0000

    sna: Treat all exported bo as potentially active
    
    Don't assume that a read/write will clear the active flag if the bo has
    been exported to another DRI client.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 03b7ceb..53f100c 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -243,7 +243,7 @@ Bool kgem_bo_write(struct kgem *kgem, struct kgem_bo *bo,
 	if (gem_write(kgem->fd, bo->handle, 0, length, data))
 		return FALSE;
 
-	bo->needs_flush = false;
+	bo->needs_flush = !bo->flush;
 	if (bo->domain == DOMAIN_GPU) {
 		kgem->sync = false;
 		kgem_retire(kgem);
@@ -774,6 +774,9 @@ static void __kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo)
 		goto destroy;
 	}
 
+	assert(bo->vmap == false && bo->sync == false);
+	bo->flush = false;
+
 	if (bo->rq) {
 		DBG(("%s: handle=%d -> active\n", __FUNCTION__, bo->handle));
 		list_move(&bo->list, active(kgem, bo->size));
@@ -2247,7 +2250,7 @@ void *kgem_bo_map(struct kgem *kgem, struct kgem_bo *bo, int prot)
 		set_domain.write_domain = I915_GEM_DOMAIN_GTT;
 		drmIoctl(kgem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain);
 
-		bo->needs_flush = false;
+		bo->needs_flush = !bo->flush;
 		if (bo->domain == DOMAIN_GPU) {
 			kgem->sync = false;
 			kgem_retire(kgem);
@@ -2353,7 +2356,7 @@ uint32_t kgem_bo_flink(struct kgem *kgem, struct kgem_bo *bo)
 	/* Henceforth, we need to broadcast all updates to clients and
 	 * flush our rendering before doing so.
 	 */
-	bo->flush = 1;
+	bo->flush = true;
 	if (bo->exec)
 		kgem->flush = 1;
 
@@ -2443,7 +2446,7 @@ void kgem_bo_sync__cpu(struct kgem *kgem, struct kgem_bo *bo)
 
 		drmIoctl(kgem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain);
 		assert(!kgem_busy(kgem, bo->handle));
-		bo->needs_flush = false;
+		bo->needs_flush = !bo->flush;
 		if (bo->domain == DOMAIN_GPU) {
 			kgem->sync = false;
 			kgem_retire(kgem);
@@ -2873,7 +2876,7 @@ void kgem_buffer_read_sync(struct kgem *kgem, struct kgem_bo *_bo)
 			 bo->base.handle, (char *)(bo+1)+offset,
 			 offset, length);
 		assert(!kgem_busy(kgem, bo->base.handle));
-		bo->base.needs_flush = false;
+		bo->base.needs_flush = !bo->base.flush;
 		if (bo->base.domain == DOMAIN_GPU) {
 			kgem->sync = false;
 			kgem_retire(kgem);
commit 743084bbc4c411694190f60cf5161086ada6454f
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Dec 20 20:42:08 2011 +0000

    sna: Only upload tiny pixmaps on the second use
    
    Most small pixmaps appear to be single shot, so amalgamate them into one
    buffer and trim our memory usage.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_render.c b/src/sna/sna_render.c
index 3face43..341cf2c 100644
--- a/src/sna/sna_render.c
+++ b/src/sna/sna_render.c
@@ -315,11 +315,19 @@ move_to_gpu(PixmapPtr pixmap, const BoxRec *box)
 	w = box->x2 - box->x1;
 	h = box->y2 - box->y1;
 	if (w == pixmap->drawable.width && h == pixmap->drawable.height) {
-		DBG(("%s: migrating whole pixmap (%dx%d) for source (%d,%d),(%d,%d)\n",
+		bool upload = true;
+
+		if (pixmap->devKind * pixmap->drawable.height <= 4096) {
+			priv = sna_pixmap(pixmap);
+			upload = priv && priv->source_count++ > SOURCE_BIAS;
+		}
+
+		DBG(("%s: migrating whole pixmap (%dx%d) for source (%d,%d),(%d,%d)? %d\n",
 		     __FUNCTION__,
 		     pixmap->drawable.width, pixmap->drawable.height,
-		     box->x1, box->y1, box->x2, box->y2));
-		return TRUE;
+		     box->x1, box->y1, box->x2, box->y2,
+		     upload));
+		return upload;
 	}
 
 	/* ignore tiny fractions */
commit ca24ffe8b9acef034a5610376c73ebbdce87d41c
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Dec 20 20:11:12 2011 +0000

    sna: Improve a debug message
    
    Give the units when saying the pixmap is too small to bother tiling.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 4ae7d14..03b7ceb 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -1698,7 +1698,7 @@ int kgem_choose_tiling(struct kgem *kgem, int tiling, int width, int height, int
 	}
 
 	if (tiling && ALIGN(height, 2) * ALIGN(width*bpp, 8*64) <= 4096 * 8) {
-		DBG(("%s: too small [%d] for TILING_%c\n", __FUNCTION__,
+		DBG(("%s: too small [%d bytes] for TILING_%c\n", __FUNCTION__,
 		     ALIGN(height, 2) * ALIGN(width*bpp, 8*64) / 8,
 		     tiling == I915_TILING_X ? 'X' : 'Y'));
 		tiling = I915_TILING_NONE;
commit f837b9bcc7d384aeb37c2e9ebdac95571deaedc6
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Dec 20 20:06:25 2011 +0000

    sna/render: If the pixmap already has a GPU bo, use it for the source
    
    The usage hint not to create a GPU bo is obviously superceded if we
    already have a GPU bo.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_render.c b/src/sna/sna_render.c
index 40318aa..3face43 100644
--- a/src/sna/sna_render.c
+++ b/src/sna/sna_render.c
@@ -269,9 +269,6 @@ use_cpu_bo(struct sna *sna, PixmapPtr pixmap, const BoxRec *box)
 		return NULL;
 	}
 
-	if (pixmap->usage_hint)
-		goto done;
-
 	if (priv->gpu_bo) {
 		if (priv->gpu_bo != I915_TILING_NONE &&
 		    priv->cpu_bo->pitch >= 4096) {
@@ -282,6 +279,10 @@ use_cpu_bo(struct sna *sna, PixmapPtr pixmap, const BoxRec *box)
 	} else {
 		int w = box->x2 - box->x1;
 		int h = box->y2 - box->y1;
+
+		if (pixmap->usage_hint)
+			goto done;
+
 		if (priv->source_count*w*h >= pixmap->drawable.width * pixmap->drawable.height &&
 		    I915_TILING_NONE != kgem_choose_tiling(&sna->kgem, I915_TILING_X,
 							   pixmap->drawable.width,
commit dfafe76a57655784c313bc2078d0b28a7ac2675b
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Dec 20 18:39:20 2011 +0000

    sna: Do not use Y-tiling for composite back pixmaps
    
    These are treated by the core drawing routines as replacements for the
    front-buffer attached to Windows, and so expect the usual BLT
    accelerations are available, for example overlapping blits to handle
    scrolling. If we create these pixmaps with Y-tiling and then they are
    pinned by the external compositor we are forced to perform a double copy
    through the 3D pipeline as it does not handle overlapping blits and the
    BLT does not handle Y-tiling.
    
    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 60bd39f..6c655ca 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -291,6 +291,13 @@ static inline uint32_t default_tiling(PixmapPtr pixmap)
 	if (sna->kgem.gen == 21)
 		return I915_TILING_X;
 
+	if (pixmap->usage_hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP) {
+		/* Treat this like a window, and require accelerated
+		 * scrolling i.e. overlapped blits.
+		 */
+		return I915_TILING_X;
+	}
+
 	return sna_damage_is_all(&priv->cpu_damage,
 				 pixmap->drawable.width,
 				 pixmap->drawable.height) ? I915_TILING_Y : sna->default_tiling;
commit 0cda7b4fa82870d57fcd0036a3b734cc73e2bf28
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Dec 20 17:58:33 2011 +0000

    sna: Implement extended fallback handling for src == dst copies
    
    Only marginally better than falling all the way back to using the CPU,
    is to perform a double copy to workaround the overlapping copy.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/gen2_render.c b/src/sna/gen2_render.c
index 373866b..d10f03e 100644
--- a/src/sna/gen2_render.c
+++ b/src/sna/gen2_render.c
@@ -2520,16 +2520,11 @@ gen2_render_copy_boxes(struct sna *sna, uint8_t alu,
 	    too_large(src->drawable.width, src->drawable.height) ||
 	    src_bo->pitch > 8192 ||
 	    too_large(dst->drawable.width, dst->drawable.height) ||
-	    dst_bo->pitch < 8 || dst_bo->pitch > 8192) {
-		if (!sna_blt_compare_depth(&src->drawable, &dst->drawable))
-			return FALSE;
-
-		return sna_blt_copy_boxes(sna, alu,
-					  src_bo, src_dx, src_dy,
-					  dst_bo, dst_dx, dst_dy,
-					  dst->drawable.bitsPerPixel,
-					  box, n);
-	}
+	    dst_bo->pitch < 8 || dst_bo->pitch > 8192)
+		return sna_blt_copy_boxes_fallback(sna, alu,
+						   src, src_bo, src_dx, src_dy,
+						   dst, dst_bo, dst_dx, dst_dy,
+						   box, n);
 
 	if (!kgem_check_bo(&sna->kgem, dst_bo, src_bo, NULL))
 		kgem_submit(&sna->kgem);
diff --git a/src/sna/gen3_render.c b/src/sna/gen3_render.c
index fe3a359..4ada863 100644
--- a/src/sna/gen3_render.c
+++ b/src/sna/gen3_render.c
@@ -3630,16 +3630,11 @@ gen3_render_copy_boxes(struct sna *sna, uint8_t alu,
 	    src_bo->pitch > 8192 ||
 	    too_large(src->drawable.width, src->drawable.height) ||
 	    dst_bo->pitch > 8192 ||
-	    too_large(dst->drawable.width, dst->drawable.height)) {
-		if (!sna_blt_compare_depth(&src->drawable, &dst->drawable))
-			return FALSE;
-
-		return sna_blt_copy_boxes(sna, alu,
-					  src_bo, src_dx, src_dy,
-					  dst_bo, dst_dx, dst_dy,
-					  dst->drawable.bitsPerPixel,
-					  box, n);
-	}
+	    too_large(dst->drawable.width, dst->drawable.height))
+		return sna_blt_copy_boxes_fallback(sna, alu,
+						   src, src_bo, src_dx, src_dy,
+						   dst, dst_bo, dst_dx, dst_dy,
+						   box, n);
 
 	if (!kgem_check_bo(&sna->kgem, dst_bo, src_bo, NULL))
 		kgem_submit(&sna->kgem);
diff --git a/src/sna/gen4_render.c b/src/sna/gen4_render.c
index 1c6c22e..aec5ca0 100644
--- a/src/sna/gen4_render.c
+++ b/src/sna/gen4_render.c
@@ -2279,16 +2279,11 @@ gen4_render_copy_boxes(struct sna *sna, uint8_t alu,
 
 	if (!(alu == GXcopy || alu == GXclear) || src_bo == dst_bo ||
 	    src->drawable.width > 8192 || src->drawable.height > 8192 ||
-	    dst->drawable.width > 8192 || dst->drawable.height > 8192) {
-		if (!sna_blt_compare_depth(&src->drawable, &dst->drawable))
-			return FALSE;
-
-		return sna_blt_copy_boxes(sna, alu,
-					  src_bo, src_dx, src_dy,
-					  dst_bo, dst_dx, dst_dy,
-					  dst->drawable.bitsPerPixel,
-					  box, n);
-	}
+	    dst->drawable.width > 8192 || dst->drawable.height > 8192)
+		return sna_blt_copy_boxes_fallback(sna, alu,
+						   src, src_bo, src_dx, src_dy,
+						   dst, dst_bo, dst_dx, dst_dy,
+						   box, n);
 
 	DBG(("%s (%d, %d)->(%d, %d) x %d\n",
 	     __FUNCTION__, src_dx, src_dy, dst_dx, dst_dy, n));
diff --git a/src/sna/gen5_render.c b/src/sna/gen5_render.c
index 4f5b57c..6d89ca3 100644
--- a/src/sna/gen5_render.c
+++ b/src/sna/gen5_render.c
@@ -2581,16 +2581,11 @@ gen5_render_copy_boxes(struct sna *sna, uint8_t alu,
 
 	if (!(alu == GXcopy || alu == GXclear) || src_bo == dst_bo ||
 	    too_large(src->drawable.width, src->drawable.height) ||
-	    too_large(dst->drawable.width, dst->drawable.height)) {
-		if (!sna_blt_compare_depth(&src->drawable, &dst->drawable))
-			return FALSE;
-
-		return sna_blt_copy_boxes(sna, alu,
-					  src_bo, src_dx, src_dy,
-					  dst_bo, dst_dx, dst_dy,
-					  dst->drawable.bitsPerPixel,
-					  box, n);
-	}
+	    too_large(dst->drawable.width, dst->drawable.height))
+		return sna_blt_copy_boxes_fallback(sna, alu,
+						   src, src_bo, src_dx, src_dy,
+						   dst, dst_bo, dst_dx, dst_dy,
+						   box, n);
 
 	DBG(("%s (%d, %d)->(%d, %d) x %d\n",
 	     __FUNCTION__, src_dx, src_dy, dst_dx, dst_dy, n));
diff --git a/src/sna/gen6_render.c b/src/sna/gen6_render.c
index 8808300..c276f7e 100644
--- a/src/sna/gen6_render.c
+++ b/src/sna/gen6_render.c
@@ -2791,16 +2791,12 @@ gen6_render_copy_boxes(struct sna *sna, uint8_t alu,
 
 	if (!(alu == GXcopy || alu == GXclear) || src_bo == dst_bo ||
 	    too_large(src->drawable.width, src->drawable.height) ||
-	    too_large(dst->drawable.width, dst->drawable.height)) {
-		if (!sna_blt_compare_depth(&src->drawable, &dst->drawable))
-			return FALSE;
+	    too_large(dst->drawable.width, dst->drawable.height))
+		return sna_blt_copy_boxes_fallback(sna, alu,
+						   src, src_bo, src_dx, src_dy,
+						   dst, dst_bo, dst_dx, dst_dy,
+						   box, n);
 
-		return sna_blt_copy_boxes(sna, alu,
-					  src_bo, src_dx, src_dy,
-					  dst_bo, dst_dx, dst_dy,
-					  dst->drawable.bitsPerPixel,
-					  box, n);
-	}
 	tmp.op = alu == GXcopy ? PictOpSrc : PictOpClear;
 
 	tmp.dst.pixmap = dst;
diff --git a/src/sna/gen7_render.c b/src/sna/gen7_render.c
index 0e18bad..dc97d18 100644
--- a/src/sna/gen7_render.c
+++ b/src/sna/gen7_render.c
@@ -2904,16 +2904,12 @@ gen7_render_copy_boxes(struct sna *sna, uint8_t alu,
 
 	if (!(alu == GXcopy || alu == GXclear) || src_bo == dst_bo ||
 	    too_large(src->drawable.width, src->drawable.height) ||
-	    too_large(dst->drawable.width, dst->drawable.height)) {
-		if (!sna_blt_compare_depth(&src->drawable, &dst->drawable))
-			return FALSE;
+	    too_large(dst->drawable.width, dst->drawable.height))
+		return sna_blt_copy_boxes_fallback(sna, alu,
+						   src, src_bo, src_dx, src_dy,
+						   dst, dst_bo, dst_dx, dst_dy,
+						   box, n);
 
-		return sna_blt_copy_boxes(sna, alu,
-					  src_bo, src_dx, src_dy,
-					  dst_bo, dst_dx, dst_dy,
-					  dst->drawable.bitsPerPixel,
-					  box, n);
-	}
 	tmp.op = alu == GXcopy ? PictOpSrc : PictOpClear;
 
 	tmp.dst.pixmap = dst;
diff --git a/src/sna/sna.h b/src/sna/sna.h
index 8deccc1..1fa3122 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -428,6 +428,7 @@ PixmapPtr sna_pixmap_create_upload(ScreenPtr screen,
 
 struct sna_pixmap *sna_pixmap_move_to_gpu(PixmapPtr pixmap);
 struct sna_pixmap *sna_pixmap_force_to_gpu(PixmapPtr pixmap);
+struct kgem_bo *sna_pixmap_change_tiling(PixmapPtr pixmap, uint32_t tiling);
 
 #define MOVE_WRITE 0x1
 #define MOVE_READ 0x2
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 47665dd..60bd39f 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -322,7 +322,7 @@ static uint32_t sna_pixmap_choose_tiling(PixmapPtr pixmap, uint32_t tiling)
 				  pixmap->drawable.bitsPerPixel);
 }
 
-static bool sna_pixmap_change_tiling(PixmapPtr pixmap, uint32_t tiling)
+struct kgem_bo *sna_pixmap_change_tiling(PixmapPtr pixmap, uint32_t tiling)
 {
 	struct sna_pixmap *priv = sna_pixmap(pixmap);
 	struct sna *sna = to_sna_from_pixmap(pixmap);
@@ -335,7 +335,7 @@ static bool sna_pixmap_change_tiling(PixmapPtr pixmap, uint32_t tiling)
 
 	if (priv->pinned) {
 		DBG(("%s: can't convert pinned bo\n", __FUNCTION__));
-		return false;
+		return NULL;
 	}
 
 	bo = kgem_create_2d(&sna->kgem,
@@ -345,7 +345,7 @@ static bool sna_pixmap_change_tiling(PixmapPtr pixmap, uint32_t tiling)
 			    tiling, 0);
 	if (bo == NULL) {
 		DBG(("%s: allocation failed\n", __FUNCTION__));
-		return false;
+		return NULL;
 	}
 
 	box.x1 = box.y1 = 0;
@@ -362,8 +362,7 @@ static bool sna_pixmap_change_tiling(PixmapPtr pixmap, uint32_t tiling)
 	}
 
 	kgem_bo_destroy(&sna->kgem, priv->gpu_bo);
-	priv->gpu_bo = bo;
-	return true;
+	return priv->gpu_bo = bo;
 }
 
 static inline void sna_set_pixmap(PixmapPtr pixmap, struct sna_pixmap *sna)
@@ -7273,11 +7272,9 @@ sna_poly_fill_rect_stippled_blt(DrawablePtr drawable,
 		DBG(("%s: converting bo from Y-tiling\n", __FUNCTION__));
 		/* This is cheating, but only the gpu_bo can be tiled */
 		assert(bo == sna_pixmap(pixmap)->gpu_bo);
-
-		if (!sna_pixmap_change_tiling(pixmap, I915_TILING_X))
+		bo = sna_pixmap_change_tiling(pixmap, I915_TILING_X);
+		if (bo == NULL)
 			return false;
-
-		bo = sna_pixmap(pixmap)->gpu_bo;
 	}
 
 	if (!sna_drawable_move_to_cpu(&stipple->drawable, MOVE_READ))
@@ -7589,11 +7586,11 @@ sna_glyph_blt(DrawablePtr drawable, GCPtr gc,
 	bo = priv->gpu_bo;
 	if (bo->tiling == I915_TILING_Y) {
 		DBG(("%s: converting bo from Y-tiling\n", __FUNCTION__));
-		if (!sna_pixmap_change_tiling(pixmap, I915_TILING_X)) {
+		bo = sna_pixmap_change_tiling(pixmap, I915_TILING_X);
+		if (bo == NULL) {
 			DBG(("%s -- fallback, dst uses Y-tiling\n", __FUNCTION__));
 			return false;
 		}
-		bo = priv->gpu_bo;
 	}
 
 	get_drawable_deltas(drawable, pixmap, &dx, &dy);
diff --git a/src/sna/sna_blt.c b/src/sna/sna_blt.c
index a488102..02ddf3f 100644
--- a/src/sna/sna_blt.c
+++ b/src/sna/sna_blt.c
@@ -1843,3 +1843,117 @@ Bool sna_blt_copy_boxes(struct sna *sna, uint8_t alu,
 
 	return TRUE;
 }
+
+static void box_extents(const BoxRec *box, int n, BoxRec *extents)
+{
+	*extents = *box;
+	while (--n) {
+		box++;
+		if (box->x1 < extents->x1)
+			extents->x1 = box->x1;
+		if (box->y1 < extents->y1)
+			extents->y1 = box->y1;
+
+		if (box->x2 > extents->x2)
+			extents->x2 = box->x2;
+		if (box->y2 > extents->y2)
+			extents->y2 = box->y2;
+	}
+}
+
+Bool sna_blt_copy_boxes_fallback(struct sna *sna, uint8_t alu,
+				 PixmapPtr src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
+				 PixmapPtr dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
+				 const BoxRec *box, int nbox)
+{
+	struct kgem_bo *free_bo = NULL;
+	Bool ret;
+
+	DBG(("%s: alu=%d, n=%d\n", __FUNCTION__, alu, nbox));
+
+	if (!sna_blt_compare_depth(&src->drawable, &dst->drawable)) {
+		DBG(("%s: mismatching depths %d -> %d\n",
+		     __FUNCTION__, src->drawable.depth, dst->drawable.depth));
+		return FALSE;
+	}
+
+	if (src_bo == dst_bo) {
+		DBG(("%s: dst == src\n", __FUNCTION__));
+
+		if (src_bo->tiling == I915_TILING_Y) {
+			struct kgem_bo *bo;
+
+			DBG(("%s: src is Y-tiled\n", __FUNCTION__));
+
+			assert(src_bo == sna_pixmap(src)->gpu_bo);
+			bo = sna_pixmap_change_tiling(src, I915_TILING_X);
+			if (bo == NULL) {
+				BoxRec extents;
+
+				DBG(("%s: y-tiling conversion failed\n",
+				     __FUNCTION__));
+
+				box_extents(box, nbox, &extents);
+				free_bo = kgem_create_2d(&sna->kgem,
+							 extents.x2 - extents.x1,
+							 extents.y2 - extents.y1,
+							 src->drawable.bitsPerPixel,
+							 I915_TILING_X, 0);
+				if (free_bo == NULL) {
+					DBG(("%s: fallback -- temp allocation failed\n",
+					     __FUNCTION__));
+					return FALSE;
+				}
+
+				if (!sna_blt_copy_boxes(sna, GXcopy,
+							src_bo, src_dx, src_dy,
+							free_bo, -extents.x1, -extents.y1,
+							src->drawable.bitsPerPixel,
+							box, nbox)) {
+					DBG(("%s: fallback -- temp copy failed\n",
+					     __FUNCTION__));
+					kgem_bo_destroy(&sna->kgem, free_bo);
+					return FALSE;
+				}
+
+				src_dx = -extents.x1;
+				src_dy = -extents.y1;
+				src_bo = free_bo;
+			} else
+				dst_bo = src_bo = bo;
+		}
+	} else {
+		if (src_bo->tiling == I915_TILING_Y) {
+			DBG(("%s: src is y-tiled\n", __FUNCTION__));
+			assert(src_bo == sna_pixmap(src)->gpu_bo);
+			src_bo = sna_pixmap_change_tiling(src, I915_TILING_X);
+			if (src_bo == NULL) {
+				DBG(("%s: fallback -- src y-tiling conversion failed\n",
+				     __FUNCTION__));
+				return FALSE;
+			}
+		}
+
+		if (dst_bo->tiling == I915_TILING_Y) {
+			DBG(("%s: dst is y-tiled\n", __FUNCTION__));
+			assert(dst_bo == sna_pixmap(dst)->gpu_bo);
+			dst_bo = sna_pixmap_change_tiling(dst, I915_TILING_X);
+			if (dst_bo == NULL) {
+				DBG(("%s: fallback -- dst y-tiling conversion failed\n",
+				     __FUNCTION__));
+				return FALSE;
+			}
+		}
+	}
+
+	ret =  sna_blt_copy_boxes(sna, alu,
+				  src_bo, src_dx, src_dy,
+				  dst_bo, dst_dx, dst_dy,
+				  dst->drawable.bitsPerPixel,
+				  box, nbox);
+
+	if (free_bo)
+		kgem_bo_destroy(&sna->kgem, free_bo);
+
+	return ret;
+}
diff --git a/src/sna/sna_render.h b/src/sna/sna_render.h
index 95720fa..bebbed2 100644
--- a/src/sna/sna_render.h
+++ b/src/sna/sna_render.h
@@ -522,6 +522,10 @@ Bool sna_blt_copy_boxes(struct sna *sna, uint8_t alu,
 			struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
 			int bpp,
 			const BoxRec *box, int n);
+Bool sna_blt_copy_boxes_fallback(struct sna *sna, uint8_t alu,
+				 PixmapPtr src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
+				 PixmapPtr dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
+				 const BoxRec *box, int nbox);
 
 Bool sna_get_pixel_from_rgba(uint32_t *pixel,
 			     uint16_t red,


More information about the xorg-commit mailing list