xf86-video-intel: 3 commits - src/sna/gen2_render.c src/sna/gen3_render.c src/sna/kgem.c src/sna/kgem.h src/sna/sna_render_inline.h src/sna/sna_trapezoids.c

Chris Wilson ickle at kemper.freedesktop.org
Sat Dec 10 05:26:38 PST 2011


 src/sna/gen2_render.c       |   23 ++
 src/sna/gen3_render.c       |   24 ++
 src/sna/kgem.c              |   82 +++++++++
 src/sna/kgem.h              |    8 
 src/sna/sna_render_inline.h |    2 
 src/sna/sna_trapezoids.c    |  373 +++++++++++++++++++++++++++++++++++++++++++-
 6 files changed, 497 insertions(+), 15 deletions(-)

New commits:
commit b5a6bc9e33a2797c926969e1f98b4a9a796248c5
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Dec 10 13:14:45 2011 +0000

    sna/gen[23]: Fixup render targets with pitches below hw minimum
    
    gen2/3 have a restriction that the 3D pipeline cannot render to a pixmap
    with a pitch less than 8/16 respectively. Rather than mandating all
    pixmaps to be created with a stride greater than 16, fixup the bo for
    the rare occasions when it is necessary.
    
    Reported-by: Paul Neumann <paul104x at yahoo.de>
    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=43688
    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 d35f2da..cd2dcf4 100644
--- a/src/sna/gen2_render.c
+++ b/src/sna/gen2_render.c
@@ -1186,7 +1186,8 @@ gen2_composite_picture(struct sna *sna,
 }
 
 static Bool
-gen2_composite_set_target(struct sna_composite_op *op,
+gen2_composite_set_target(struct sna *sna,
+			  struct sna_composite_op *op,
 			  PicturePtr dst)
 {
 	struct sna_pixmap *priv;
@@ -1200,6 +1201,22 @@ gen2_composite_set_target(struct sna_composite_op *op,
 	if (priv == NULL)
 		return FALSE;
 
+	if (priv->gpu_bo->pitch < 8) {
+		struct kgem_bo *bo;
+
+		if (priv->pinned)
+			return FALSE;
+
+		bo = kgem_replace_bo(&sna->kgem, priv->gpu_bo,
+				     op->dst.width, op->dst.height, 16,
+				     op->dst.pixmap->drawable.bitsPerPixel);
+		if (bo == NULL)
+			return FALSE;
+
+		kgem_bo_destroy(&sna->kgem, priv->gpu_bo);
+		priv->gpu_bo = bo;
+	}
+
 	op->dst.bo = priv->gpu_bo;
 	op->damage = &priv->gpu_damage;
 	if (sna_damage_is_all(&priv->gpu_damage, op->dst.width, op->dst.height))
@@ -1396,7 +1413,7 @@ gen2_render_composite(struct sna *sna,
 					    width,  height,
 					    tmp);
 
-	if (!gen2_composite_set_target(tmp, dst)) {
+	if (!gen2_composite_set_target(sna, tmp, dst)) {
 		DBG(("%s: unable to set render target\n",
 		     __FUNCTION__));
 		return FALSE;
@@ -1822,7 +1839,7 @@ gen2_render_composite_spans(struct sna *sna,
 	if (need_tiling(sna, width, height))
 		return FALSE;
 
-	if (!gen2_composite_set_target(&tmp->base, dst)) {
+	if (!gen2_composite_set_target(sna, &tmp->base, dst)) {
 		DBG(("%s: unable to set render target\n",
 		     __FUNCTION__));
 		return FALSE;
diff --git a/src/sna/gen3_render.c b/src/sna/gen3_render.c
index ea9d40a..33bdfd2 100644
--- a/src/sna/gen3_render.c
+++ b/src/sna/gen3_render.c
@@ -2175,7 +2175,9 @@ gen3_align_vertex(struct sna *sna,
 }
 
 static Bool
-gen3_composite_set_target(struct sna_composite_op *op, PicturePtr dst)
+gen3_composite_set_target(struct sna *sna,
+			  struct sna_composite_op *op,
+			  PicturePtr dst)
 {
 	struct sna_pixmap *priv;
 
@@ -2189,6 +2191,22 @@ gen3_composite_set_target(struct sna_composite_op *op, PicturePtr dst)
 	if (priv == NULL)
 		return FALSE;
 
+	if (priv->gpu_bo->pitch < 16) {
+		struct kgem_bo *bo;
+
+		if (priv->pinned)
+			return FALSE;
+
+		bo = kgem_replace_bo(&sna->kgem, priv->gpu_bo,
+				     op->dst.width, op->dst.height, 16,
+				     op->dst.pixmap->drawable.bitsPerPixel);
+		if (bo == NULL)
+			return FALSE;
+
+		kgem_bo_destroy(&sna->kgem, priv->gpu_bo);
+		priv->gpu_bo = bo;
+	}
+
 	op->dst.bo = priv->gpu_bo;
 	op->damage = &priv->gpu_damage;
 	if (sna_damage_is_all(op->damage, op->dst.width, op->dst.height))
@@ -2380,7 +2398,7 @@ gen3_render_composite(struct sna *sna,
 
 	memset(&tmp->u.gen3, 0, sizeof(tmp->u.gen3));
 
-	if (!gen3_composite_set_target(tmp, dst)) {
+	if (!gen3_composite_set_target(sna, tmp, dst)) {
 		DBG(("%s: unable to set render target\n",
 		     __FUNCTION__));
 		return FALSE;
@@ -2913,7 +2931,7 @@ gen3_render_composite_spans(struct sna *sna,
 	if (need_tiling(sna, width, height))
 		return FALSE;
 
-	if (!gen3_composite_set_target(&tmp->base, dst)) {
+	if (!gen3_composite_set_target(sna, &tmp->base, dst)) {
 		DBG(("%s: unable to set render target\n",
 		     __FUNCTION__));
 		return FALSE;
diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 1c9da8e..34ce745 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -2356,3 +2356,85 @@ void kgem_bo_set_binding(struct kgem_bo *bo, uint32_t format, uint16_t offset)
 		bo->binding.next = b;
 	}
 }
+
+struct kgem_bo *
+kgem_replace_bo(struct kgem *kgem,
+		struct kgem_bo *src,
+		uint32_t width,
+		uint32_t height,
+		uint32_t pitch,
+		uint32_t bpp)
+{
+	struct kgem_bo *dst;
+	uint32_t br00, br13;
+	uint32_t handle;
+	uint32_t size;
+	uint32_t *b;
+
+	DBG(("%s: replacing bo handle=%d, size=%dx%d pitch=%d, with pitch=%d\n",
+	     __FUNCTION__, src->handle,  width, height, src->pitch, pitch));
+
+	/* We only expect to be called to fixup small buffers, hence why
+	 * we only attempt to allocate a linear bo.
+	 */
+	assert(src->tiling == I915_TILING_NONE);
+
+	size = height * pitch;
+
+	dst = search_linear_cache(kgem, size, true);
+	if (dst == NULL)
+		dst = search_linear_cache(kgem, size, false);
+	if (dst == NULL) {
+		handle = gem_create(kgem->fd, size);
+		if (handle == 0)
+			return NULL;
+
+		dst = __kgem_bo_alloc(handle, size);
+	}
+	dst->pitch = pitch;
+
+	kgem_set_mode(kgem, KGEM_BLT);
+	if (!kgem_check_batch(kgem, 8) ||
+	    !kgem_check_reloc(kgem, 2) ||
+	    !kgem_check_bo_fenced(kgem, src, dst, NULL)) {
+		_kgem_submit(kgem);
+		_kgem_set_mode(kgem, KGEM_BLT);
+	}
+
+	br00 = XY_SRC_COPY_BLT_CMD;
+	br13 = pitch;
+	pitch = src->pitch;
+	if (kgem->gen >= 40 && src->tiling) {
+		br00 |= BLT_SRC_TILED;
+		pitch >>= 2;
+	}
+
+	br13 |= 0xcc << 16;
+	switch (bpp) {
+	default:
+	case 32: br00 |= BLT_WRITE_ALPHA | BLT_WRITE_RGB;
+		 br13 |= 1 << 25; /* RGB8888 */
+	case 16: br13 |= 1 << 24; /* RGB565 */
+	case 8: break;
+	}
+
+	b = kgem->batch + kgem->nbatch;
+	b[0] = br00;
+	b[1] = br13;
+	b[2] = 0;
+	b[3] = height << 16 | width;
+	b[4] = kgem_add_reloc(kgem, kgem->nbatch + 4, dst,
+			      I915_GEM_DOMAIN_RENDER << 16 |
+			      I915_GEM_DOMAIN_RENDER |
+			      KGEM_RELOC_FENCED,
+			      0);
+	b[5] = 0;
+	b[6] = pitch;
+	b[7] = kgem_add_reloc(kgem, kgem->nbatch + 7, src,
+			      I915_GEM_DOMAIN_RENDER << 16 |
+			      KGEM_RELOC_FENCED,
+			      0);
+	kgem->nbatch += 8;
+
+	return dst;
+}
diff --git a/src/sna/kgem.h b/src/sna/kgem.h
index 14faa70..8649512 100644
--- a/src/sna/kgem.h
+++ b/src/sna/kgem.h
@@ -170,6 +170,14 @@ int kgem_choose_tiling(struct kgem *kgem,
 		       int tiling, int width, int height, int bpp);
 bool kgem_can_create_2d(struct kgem *kgem,
 			int width, int height, int bpp, int tiling);
+
+struct kgem_bo *
+kgem_replace_bo(struct kgem *kgem,
+		struct kgem_bo *src,
+		uint32_t width,
+		uint32_t height,
+		uint32_t pitch,
+		uint32_t bpp);
 enum {
 	CREATE_EXACT = 0x1,
 	CREATE_INACTIVE = 0x2,
commit c0dab7b1cf17fe751c86ad2b3fabce682eb50366
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Dec 10 12:46:46 2011 +0000

    sna/trapezoids: Try to render traps onto a8 destinations in place
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_render_inline.h b/src/sna/sna_render_inline.h
index 6dd93a4..b9997a2 100644
--- a/src/sna/sna_render_inline.h
+++ b/src/sna/sna_render_inline.h
@@ -70,7 +70,7 @@ static inline Bool
 is_gpu(DrawablePtr drawable)
 {
 	struct sna_pixmap *priv = sna_pixmap_from_drawable(drawable);
-	return priv && priv->gpu_bo;
+	return priv && priv->gpu_damage;
 }
 
 static inline Bool
diff --git a/src/sna/sna_trapezoids.c b/src/sna/sna_trapezoids.c
index 7d0a169..b8b7bb1 100644
--- a/src/sna/sna_trapezoids.c
+++ b/src/sna/sna_trapezoids.c
@@ -2992,6 +2992,208 @@ trapezoid_mask_converter(CARD8 op, PicturePtr src, PicturePtr dst,
 	return true;
 }
 
+struct inplace {
+	uint32_t stride;
+	uint8_t *ptr;
+	uint8_t opacity;
+};
+
+static void
+tor_blt_inplace(struct sna *sna,
+		struct sna_composite_spans_op *op,
+		pixman_region16_t *clip,
+		const BoxRec *box,
+		int coverage)
+{
+	struct inplace *in = (struct inplace *)op;
+	uint8_t *ptr = in->ptr;
+	int h, w;
+
+	coverage = (int)coverage * in->opacity / FAST_SAMPLES_XY;
+
+	ptr += box->y1 * in->stride + box->x1;
+
+	h = box->y2 - box->y1;
+	w = box->x2 - box->x1;
+	if ((w | h) == 1) {
+		*ptr = coverage;
+	} else if (w == 1) {
+		do {
+			*ptr = coverage;
+			ptr += in->stride;
+		} while (--h);
+	} else do {
+		memset(ptr, coverage, w);
+		ptr += in->stride;
+	} while (--h);
+}
+
+static void
+tor_blt_inplace_clipped(struct sna *sna,
+			struct sna_composite_spans_op *op,
+			pixman_region16_t *clip,
+			const BoxRec *box,
+			int coverage)
+{
+	pixman_region16_t region;
+	int n;
+
+	pixman_region_init_rects(&region, box, 1);
+	RegionIntersect(&region, &region, clip);
+	n = REGION_NUM_RECTS(&region);
+	box = REGION_RECTS(&region);
+	while (n--){
+		tor_blt_inplace(sna, op, NULL,  box, coverage);
+		box++;
+	}
+	pixman_region_fini(&region);
+}
+
+static void
+tor_blt_inplace_mono(struct sna *sna,
+		     struct sna_composite_spans_op *op,
+		     pixman_region16_t *clip,
+		     const BoxRec *box,
+		     int coverage)
+{
+	tor_blt_inplace(sna, op, clip, box,
+			coverage < FAST_SAMPLES_XY/2 ? 0 : FAST_SAMPLES_XY);
+}
+
+static void
+tor_blt_inplace_clipped_mono(struct sna *sna,
+			     struct sna_composite_spans_op *op,
+			     pixman_region16_t *clip,
+			     const BoxRec *box,
+			     int coverage)
+{
+	tor_blt_inplace_clipped(sna, op, clip, box,
+				coverage < FAST_SAMPLES_XY/2 ? 0 : FAST_SAMPLES_XY);
+}
+
+static bool
+trapezoid_span_inplace(CARD8 op, PicturePtr src, PicturePtr dst,
+		       PictFormatPtr maskFormat, INT16 src_x, INT16 src_y,
+		       int ntrap, xTrapezoid *traps)
+{
+	struct tor tor;
+	struct inplace inplace;
+	span_func_t span;
+	PixmapPtr pixmap;
+	RegionRec region;
+	uint32_t color;
+	int16_t dst_x, dst_y;
+	int dx, dy;
+	int n;
+
+	if (NO_SCAN_CONVERTER)
+		return false;
+
+	if (dst->polyMode == PolyModePrecise) {
+		DBG(("%s: fallback -- precise rasterisation requested\n",
+		     __FUNCTION__));
+		return false;
+	}
+	if (dst->alphaMap || src->alphaMap) {
+		DBG(("%s: fallback -- alphamaps\n",
+		     __FUNCTION__));
+		return false;
+	}
+
+	if (dst->format != PICT_a8 || op != PictOpSrc ||
+	    !sna_picture_is_solid(src, &color)) {
+		DBG(("%s: fallback -- can not perform operation in place\n",
+		     __FUNCTION__));
+		return false;
+	}
+
+	if (maskFormat == NULL && ntrap > 1) {
+		DBG(("%s: individual rasterisation requested\n",
+		     __FUNCTION__));
+		do {
+			/* XXX unwind errors? */
+			if (!trapezoid_span_inplace(op, src, dst, NULL,
+						    src_x, src_y, 1, traps++))
+				return false;
+		} while (--ntrap);
+		return true;
+	}
+
+	miTrapezoidBounds(ntrap, traps, &region.extents);
+	if (region.extents.y1 >= region.extents.y2 ||
+	    region.extents.x1 >= region.extents.x2)
+		return true;
+
+	DBG(("%s: extents (%d, %d), (%d, %d)\n",
+	     __FUNCTION__,
+	     region.extents.x1, region.extents.y1,
+	     region.extents.x2, region.extents.y2));
+
+	if (!sna_compute_composite_extents(&region.extents,
+					   src, NULL, dst,
+					   src_x, src_y,
+					   0, 0,
+					   region.extents.x1, region.extents.y1,
+					   region.extents.x2 - region.extents.x1,
+					   region.extents.y2 - region.extents.y1))
+		return true;
+
+	DBG(("%s: clipped extents (%d, %d), (%d, %d)\n",
+	     __FUNCTION__,
+	     region.extents.x1, region.extents.y1,
+	     region.extents.x2, region.extents.y2));
+
+	if (tor_init(&tor, &region.extents, 2*ntrap))
+		return true;
+
+	dx = dst->pDrawable->x * FAST_SAMPLES_X;
+	dy = dst->pDrawable->y * FAST_SAMPLES_Y;
+
+	for (n = 0; n < ntrap; n++) {
+		xTrapezoid t;
+
+		if (!project_trapezoid_onto_grid(&traps[n], dx, dy, &t))
+			continue;
+
+		if (pixman_fixed_to_int(traps[n].top) >= region.extents.y2 - dst->pDrawable->y ||
+		    pixman_fixed_to_int(traps[n].bottom) < region.extents.y1 - dst->pDrawable->y)
+			continue;
+
+		tor_add_edge(&tor, &t, &t.left, 1);
+		tor_add_edge(&tor, &t, &t.right, -1);
+	}
+
+	if (dst->pCompositeClip->data) {
+		if (maskFormat ? maskFormat->depth < 8 : dst->polyEdge == PolyEdgeSharp)
+			span = tor_blt_inplace_clipped_mono;
+		else
+			span = tor_blt_inplace_clipped;
+	} else {
+		if (maskFormat ? maskFormat->depth < 8 : dst->polyEdge == PolyEdgeSharp)
+			span = tor_blt_inplace_mono;
+		else
+			span = tor_blt_inplace;
+	}
+
+	region.data = NULL;
+	sna_drawable_move_region_to_cpu(dst->pDrawable, &region, true);
+
+	pixmap = get_drawable_pixmap(dst->pDrawable);
+	get_drawable_deltas(dst->pDrawable, pixmap, &dst_x, &dst_y);
+
+	inplace.ptr = pixmap->devPrivate.ptr;
+	inplace.ptr += dst_y * pixmap->devKind + dst_x;
+	inplace.stride = pixmap->devKind;
+	inplace.opacity = color >> 24;
+
+	tor_render(NULL, &tor, (void*)&inplace,
+		   dst->pCompositeClip, span, true);
+
+	tor_fini(&tor);
+
+	return true;
+}
+
 static bool
 trapezoid_span_fallback(CARD8 op, PicturePtr src, PicturePtr dst,
 			PictFormatPtr maskFormat, INT16 src_x, INT16 src_y,
@@ -3167,6 +3369,12 @@ sna_composite_trapezoids(CARD8 op,
 		goto fallback;
 	}
 
+	if (!is_gpu(dst->pDrawable)) {
+		if (trapezoid_span_inplace(op, src, dst, maskFormat,
+					   xSrc, ySrc, ntrap, traps))
+			return;
+	}
+
 	if (too_small(dst->pDrawable) && !picture_is_gpu(src)) {
 		DBG(("%s: fallback -- dst is too small, %dx%d\n",
 		     __FUNCTION__,
@@ -3237,6 +3445,10 @@ sna_composite_trapezoids(CARD8 op,
 		return;
 
 fallback:
+	if (trapezoid_span_inplace(op, src, dst, maskFormat,
+				   xSrc, ySrc, ntrap, traps))
+		return;
+
 	if (trapezoid_span_fallback(op, src, dst, maskFormat,
 				    xSrc, ySrc, ntrap, traps))
 		return;
@@ -3657,7 +3869,7 @@ sna_add_traps(PicturePtr picture, INT16 x, INT16 y, int n, xTrap *t)
 {
 	DBG(("%s (%d, %d) x %d\n", __FUNCTION__, x, y, n));
 
-	if (picture_is_gpu (picture)) {
+	if (is_gpu(picture->pDrawable)) {
 		if (trap_span_converter(picture, x, y, n, t))
 			return;
 
commit c73b14cabb059075af0f1727847074a89941c9df
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Dec 10 11:41:18 2011 +0000

    sna/trapezoids: First try the scan converter for fallbacks
    
    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 4ea1c06..7d0a169 100644
--- a/src/sna/sna_trapezoids.c
+++ b/src/sna/sna_trapezoids.c
@@ -35,6 +35,7 @@
 #include "sna_render.h"
 #include "sna_render_inline.h"
 
+#include <fb.h>
 #include <mipict.h>
 #include <fbpict.h>
 
@@ -2846,17 +2847,17 @@ tor_blt_mask(struct sna *sna,
 
 	h = box->y2 - box->y1;
 	w = box->x2 - box->x1;
-	if (w == 1) {
+	if ((w | h) == 1) {
+		*ptr = coverage;
+	} else if (w == 1) {
 		do {
 			*ptr = coverage;
 			ptr += stride;
 		} while (--h);
-	} else {
-		do {
-			memset(ptr, coverage, w);
-			ptr += stride;
-		} while (--h);
-	}
+	} else do {
+		memset(ptr, coverage, w);
+		ptr += stride;
+	} while (--h);
 }
 
 static void
@@ -2991,6 +2992,146 @@ trapezoid_mask_converter(CARD8 op, PicturePtr src, PicturePtr dst,
 	return true;
 }
 
+static bool
+trapezoid_span_fallback(CARD8 op, PicturePtr src, PicturePtr dst,
+			PictFormatPtr maskFormat, INT16 src_x, INT16 src_y,
+			int ntrap, xTrapezoid *traps)
+{
+	struct tor tor;
+	span_func_t span;
+	ScreenPtr screen = dst->pDrawable->pScreen;
+	PixmapPtr scratch;
+	PicturePtr mask;
+	BoxRec extents;
+	int16_t dst_x, dst_y;
+	int dx, dy;
+	int error, n;
+
+	if (NO_SCAN_CONVERTER)
+		return false;
+
+	if (dst->polyMode == PolyModePrecise) {
+		DBG(("%s: fallback -- precise rasterisation requested\n",
+		     __FUNCTION__));
+		return false;
+	}
+
+	if (maskFormat == NULL && ntrap > 1) {
+		DBG(("%s: individual rasterisation requested\n",
+		     __FUNCTION__));
+		do {
+			/* XXX unwind errors? */
+			if (!trapezoid_span_fallback(op, src, dst, NULL,
+						     src_x, src_y, 1, traps++))
+				return false;
+		} while (--ntrap);
+		return true;
+	}
+
+	miTrapezoidBounds(ntrap, traps, &extents);
+	if (extents.y1 >= extents.y2 || extents.x1 >= extents.x2)
+		return true;
+
+	DBG(("%s: extents (%d, %d), (%d, %d)\n",
+	     __FUNCTION__, extents.x1, extents.y1, extents.x2, extents.y2));
+
+	if (!sna_compute_composite_extents(&extents,
+					   src, NULL, dst,
+					   src_x, src_y,
+					   0, 0,
+					   extents.x1, extents.y1,
+					   extents.x2 - extents.x1,
+					   extents.y2 - extents.y1))
+		return true;
+
+	DBG(("%s: extents (%d, %d), (%d, %d)\n",
+	     __FUNCTION__, extents.x1, extents.y1, extents.x2, extents.y2));
+
+	extents.y2 -= extents.y1;
+	extents.x2 -= extents.x1;
+	extents.x1 -= dst->pDrawable->x;
+	extents.y1 -= dst->pDrawable->y;
+	dst_x = extents.x1;
+	dst_y = extents.y1;
+	dx = -extents.x1 * FAST_SAMPLES_X;
+	dy = -extents.y1 * FAST_SAMPLES_Y;
+	extents.x1 = extents.y1 = 0;
+
+	DBG(("%s: mask (%dx%d), dx=(%d, %d)\n",
+	     __FUNCTION__, extents.x2, extents.y2, dx, dy));
+	scratch = fbCreatePixmap(screen,
+				 extents.x2, extents.y2, 8,
+				 CREATE_PIXMAP_USAGE_SCRATCH);
+	if (!scratch)
+		return true;
+
+	DBG(("%s: created buffer %p, stride %d\n",
+	     __FUNCTION__, scratch->devPrivate.ptr, scratch->devKind));
+
+	if (tor_init(&tor, &extents, 2*ntrap)) {
+		screen->DestroyPixmap(scratch);
+		return true;
+	}
+
+	for (n = 0; n < ntrap; n++) {
+		xTrapezoid t;
+
+		if (!project_trapezoid_onto_grid(&traps[n], dx, dy, &t))
+			continue;
+
+		if (pixman_fixed_to_int(traps[n].top) - dst_y >= extents.y2 ||
+		    pixman_fixed_to_int(traps[n].bottom) - dst_y < 0)
+			continue;
+
+		tor_add_edge(&tor, &t, &t.left, 1);
+		tor_add_edge(&tor, &t, &t.right, -1);
+	}
+
+	if (maskFormat ? maskFormat->depth < 8 : dst->polyEdge == PolyEdgeSharp)
+		span = tor_blt_mask_mono;
+	else
+		span = tor_blt_mask;
+
+	tor_render(NULL, &tor,
+		   scratch->devPrivate.ptr,
+		   (void *)(intptr_t)scratch->devKind,
+		   span, true);
+
+	mask = CreatePicture(0, &scratch->drawable,
+			     PictureMatchFormat(screen, 8, PICT_a8),
+			     0, 0, serverClient, &error);
+	screen->DestroyPixmap(scratch);
+	if (mask) {
+		RegionRec region;
+
+		region.extents.x1 = dst_x;
+		region.extents.y1 = dst_y;
+		region.extents.x2 = dst_x + extents.x2;
+		region.extents.y2 = dst_y + extents.y2;
+		region.data = NULL;
+
+		sna_drawable_move_region_to_cpu(dst->pDrawable, &region, true);
+		if (dst->alphaMap)
+			sna_drawable_move_to_cpu(dst->alphaMap->pDrawable, true);
+		if (src->pDrawable) {
+			sna_drawable_move_to_cpu(src->pDrawable, false);
+			if (src->alphaMap)
+				sna_drawable_move_to_cpu(src->alphaMap->pDrawable, false);
+		}
+
+		fbComposite(op, src, mask, dst,
+			    src_x + dst_x - pixman_fixed_to_int(traps[0].left.p1.x),
+			    src_y + dst_y - pixman_fixed_to_int(traps[0].left.p1.y),
+			    0, 0,
+			    dst_x, dst_y,
+			    extents.x2, extents.y2);
+		FreePicture(mask, 0);
+	}
+	tor_fini(&tor);
+
+	return true;
+}
+
 void
 sna_composite_trapezoids(CARD8 op,
 			 PicturePtr src,
@@ -3096,6 +3237,10 @@ sna_composite_trapezoids(CARD8 op,
 		return;
 
 fallback:
+	if (trapezoid_span_fallback(op, src, dst, maskFormat,
+				    xSrc, ySrc, ntrap, traps))
+		return;
+
 	DBG(("%s: fallback mask=%08x, ntrap=%d\n", __FUNCTION__,
 	     maskFormat ? (unsigned)maskFormat->format : 0, ntrap));
 	trapezoids_fallback(op, src, dst, maskFormat,


More information about the xorg-commit mailing list