xf86-video-intel: 6 commits - configure.ac src/sna/gen5_render.c src/sna/Makefile.am src/sna/sna_accel.c src/sna/sna_driver.c src/sna/sna.h src/sna/sna_trapezoids.c

Chris Wilson ickle at kemper.freedesktop.org
Fri Sep 9 08:10:58 PDT 2011


 configure.ac             |    8 
 src/sna/Makefile.am      |    7 
 src/sna/gen5_render.c    |    4 
 src/sna/sna.h            |    2 
 src/sna/sna_accel.c      |   47 +++--
 src/sna/sna_driver.c     |   10 +
 src/sna/sna_trapezoids.c |  377 +++++++++++++++++++++++++++++++++++++++++++++--
 7 files changed, 421 insertions(+), 34 deletions(-)

New commits:
commit b6837c21b459a99cb51b0d41906d82604e515dc0
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Sep 9 14:57:09 2011 +0100

    sna/gen5: Prefer BLT for solids
    
    And Ironlake also fails to live up to the promise that its GPU is fast
    enough to run simple programs at memory rates.
    
    x11perf -trap300 5x fold improvement. No obvious improvement elsewhere
    yet.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/gen5_render.c b/src/sna/gen5_render.c
index c7668b9..703b361 100644
--- a/src/sna/gen5_render.c
+++ b/src/sna/gen5_render.c
@@ -2355,7 +2355,7 @@ gen5_render_fill_boxes(struct sna *sna,
 		return FALSE;
 	}
 
-	if (sna->kgem.mode == KGEM_BLT ||
+	if (sna->kgem.mode != KGEM_RENDER ||
 	    dst->drawable.width > 8192 ||
 	    dst->drawable.height > 8192 ||
 	    !gen5_check_dst_format(format)) {
@@ -2497,7 +2497,7 @@ gen5_render_fill(struct sna *sna, uint8_t alu,
 {
 	DBG(("%s(alu=%d, color=%08x)\n", __FUNCTION__, alu, color));
 
-	if (sna->kgem.mode == KGEM_BLT &&
+	if (sna->kgem.mode != KGEM_RENDER &&
 	    sna_blt_fill(sna, alu,
 			 dst_bo, dst->drawable.bitsPerPixel,
 			 color,
commit 27e42b4e1216099f4a6aa7fddeb1e83b87124b6e
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Sep 9 14:06:53 2011 +0100

    sna: Prefer memcpy_blt over fbBlt
    
    We know we have compatible formats since we have a gpu_bo attached to
    the pixmap, so we can use the simpler direct memcpy rather than calling
    fbPutZImage/fbBlt.
    
    On my i3-330m, this improves putimage500 from 730 to 1100 ops/s.
    
    Reported-by: Michael Larabel <Michael at phoronix.com>
    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 a493722..55aeb70 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -982,7 +982,11 @@ sna_put_image_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region,
 	struct sna *sna = to_sna_from_drawable(drawable);
 	PixmapPtr pixmap = get_drawable_pixmap(drawable);
 	struct sna_pixmap *priv = sna_pixmap(pixmap);
+	char *dst_bits;
+	int dst_stride;
+	BoxRec *box;
 	int16_t dx, dy;
+	int n;
 
 	if (!priv->gpu_bo)
 		return false;
@@ -1035,18 +1039,27 @@ sna_put_image_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region,
 	}
 
 	get_drawable_deltas(drawable, pixmap, &dx, &dy);
-	dx += drawable->x;
-	dy += drawable->y;
+	x += dx + drawable->x;
+	y += dx + drawable->y;
+
+	DBG(("%s: upload(%d, %d, %d, %d)\n", __FUNCTION__, x, y, w, h));
+
+	dst_stride = pixmap->devKind;
+	dst_bits = pixmap->devPrivate.ptr;
+
+	/* Region is pre-clipped and translated into pixmap space */
+	box = REGION_RECTS(region);
+	n = REGION_NUM_RECTS(region);
+	do {
+		memcpy_blt(bits, dst_bits,
+			   pixmap->drawable.bitsPerPixel,
+			   stride, dst_stride,
+			   box->x1 - x, box->y1 - y,
+			   box->x1, box->y1,
+			   box->x2 - box->x1, box->y2 - box->y1);
+		box++;
+	} while (--n);
 
-	DBG(("%s: fbPutZImage(%d[+%d], %d[+%d], %d, %d)\n",
-	     __FUNCTION__,
-	     x+dx, pixmap->drawable.x,
-	     y+dy, pixmap->drawable.y,
-	     w, h));
-	fbPutZImage(&pixmap->drawable, region,
-		    GXcopy, ~0U,
-		    x + dx, y + dy, w, h,
-		    (FbStip*)bits, stride/sizeof(FbStip));
 	return true;
 }
 
@@ -1353,6 +1366,8 @@ fallback:
 				box++;
 			} while (--n);
 		} else {
+			DBG(("%s: alu==GXcopy? %d, reverse? %d, upsidedown? %d, bpp? %d\n",
+			     __FUNCTION__, alu == GXcopy, reverse, upsidedown, bpp));
 			dst_bits = dst_pixmap->devPrivate.ptr;
 			src_bits = src_pixmap->devPrivate.ptr;
 
commit 2e1bf7e1b44db16d0c322f17535fc6a6fa07353b
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Sep 9 12:36:32 2011 +0100

    sna: Record git-tree used for compilation
    
    Hopefully, I have all the dependencies correct for auto-updating and
    should continue to work with tarballs...
    
    The next step is to perhaps include it in the usual version number,
    perhaps as patch level?
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/configure.ac b/configure.ac
index fbd46a7..089fbdb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -59,6 +59,14 @@ m4_ifndef([XORG_DRIVER_CHECK_EXT],
 LT_PREREQ([2.2])
 LT_INIT([disable-static])
 
+# Are we in a git checkout?
+dot_git=no
+if test -e .git; then
+	AC_DEFINE(HAVE_DOT_GIT, 1, [Are we in a git checkout?])
+	dot_git=yes
+fi
+AM_CONDITIONAL(HAVE_DOT_GIT, test x$dot_git = xyes)
+
 PKG_CHECK_MODULES(GEN4ASM, [intel-gen4asm >= 1.2], [gen4asm=yes], [gen4asm=no])
 AM_CONDITIONAL(HAVE_GEN4ASM, test x$gen4asm = xyes)
 
diff --git a/src/sna/Makefile.am b/src/sna/Makefile.am
index daf4e98..bacb98f 100644
--- a/src/sna/Makefile.am
+++ b/src/sna/Makefile.am
@@ -99,3 +99,10 @@ libsna_la_SOURCES += \
 	kgem_debug_gen6.c \
 	$(NULL)
 endif
+
+if HAVE_DOT_GIT
+git_version.h: $(top_builddir)/.git/HEAD $(shell sed -e '/ref:/!d' -e 's#ref: *#$(top_builddir)/.git/#' < $(top_builddir)/.git/HEAD)
+	@echo "Recording git-tree used for compilation: `git describe`"
+	@V=`git describe`; echo "static const char git_version[] = \"$$V\";" > git_version.h
+sna_driver.c: git_version.h
+endif
diff --git a/src/sna/sna_driver.c b/src/sna/sna_driver.c
index 107659b..36f4019 100644
--- a/src/sna/sna_driver.c
+++ b/src/sna/sna_driver.c
@@ -71,6 +71,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include <sys/poll.h>
 #include "i915_drm.h"
 
+#if HAVE_DOT_GIT
+#include "git_version.h"
+#endif
+
 #if DEBUG_DRIVER
 #undef DBG
 #define DBG(x) ErrorF x
@@ -1013,6 +1017,12 @@ void sna_init_scrn(ScrnInfoPtr scrn, int entity_num)
 {
 	EntityInfoPtr entity;
 
+#if HAVE_DOT_GIT
+	xf86DrvMsg(scrn->scrnIndex, X_INFO,
+		   "SNA compiled from %s\n",
+		   git_version);
+#endif
+
 	DBG(("%s\n", __FUNCTION__));
 
 	sna_device_key = xf86AllocateEntityPrivateIndex();
commit f73cd955e760064f57f414dce5f39e43022e4ea6
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Sep 9 11:37:32 2011 +0100

    sna/trapezoids: Hook up Imprecise AddTraps in lieu of spans
    
    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 90dbcd7..ac2a6da 100644
--- a/src/sna/sna_trapezoids.c
+++ b/src/sna/sna_trapezoids.c
@@ -2611,6 +2611,143 @@ skip:
 #define pixman_fixed_integer_floor(V) pixman_fixed_to_int(pixman_fixed_floor(V))
 #define pixman_fixed_integer_ceil(V) pixman_fixed_to_int(pixman_fixed_ceil(V))
 
+static void mark_damaged(PixmapPtr pixmap, struct sna_pixmap *priv,
+			 BoxPtr box, int16_t x, int16_t y)
+{
+	if (!priv->gpu_only) {
+		box->x1 += x; box->x2 += x;
+		box->y1 += y; box->y2 += y;
+		if (box->x1 <= 0 && box->y1 <= 0 &&
+		    box->x2 >= pixmap->drawable.width &&
+		    box->y2 >= pixmap->drawable.height) {
+			sna_damage_destroy(&priv->cpu_damage);
+			sna_damage_all(&priv->gpu_damage,
+				       pixmap->drawable.width,
+				       pixmap->drawable.height);
+		} else {
+			sna_damage_add_box(&priv->gpu_damage, box);
+			sna_damage_subtract_box(&priv->cpu_damage, box);
+		}
+	}
+}
+
+static bool
+trap_mask_converter(PicturePtr picture,
+		    INT16 x, INT16 y,
+		    int ntrap, xTrap *trap)
+{
+	struct sna *sna;
+	struct tor tor;
+	ScreenPtr screen = picture->pDrawable->pScreen;
+	PixmapPtr scratch, pixmap;
+	struct sna_pixmap *priv;
+	BoxRec extents;
+	span_func_t span;
+	int16_t dx, dy;
+	int n;
+
+	if (NO_SCAN_CONVERTER)
+		return false;
+
+	pixmap = get_drawable_pixmap(picture->pDrawable);
+	priv = sna_pixmap_move_to_gpu(pixmap);
+
+	/* XXX strict adherence to the Render specification */
+	if (picture->polyMode == PolyModePrecise) {
+		DBG(("%s: fallback -- precise rasterisation requested\n",
+		     __FUNCTION__));
+		return false;
+	}
+
+	extents = *RegionExtents(picture->pCompositeClip);
+	for (n = 0; n < ntrap; n++) {
+		int v;
+
+		v = x + pixman_fixed_integer_floor (MIN(trap[n].top.l, trap[n].bot.l));
+		if (v < extents.x1)
+			extents.x1 = v;
+
+		v = x + pixman_fixed_integer_ceil (MAX(trap[n].top.r, trap[n].bot.r));
+		if (v > extents.x2)
+			extents.x2 = v;
+
+		v = y + pixman_fixed_integer_floor (trap[n].top.y);
+		if (v < extents.y1)
+			extents.y1 = v;
+
+		v = y + pixman_fixed_integer_ceil (trap[n].bot.y);
+		if (v > extents.y2)
+			extents.y2 = v;
+	}
+
+	DBG(("%s: extents (%d, %d), (%d, %d)\n",
+	     __FUNCTION__, extents.x1, extents.y1, extents.x2, extents.y2));
+
+	scratch = sna_pixmap_create_upload(screen,
+					   extents.x2-extents.x1,
+					   extents.y2-extents.y1,
+					   8);
+	if (!scratch)
+		return true;
+
+	dx = picture->pDrawable->x;
+	dy = picture->pDrawable->y;
+	dx *= FAST_SAMPLES_X;
+	dy *= FAST_SAMPLES_Y;
+	if (tor_init(&tor, &extents, 2*ntrap)) {
+		screen->DestroyPixmap(scratch);
+		return true;
+	}
+
+	for (n = 0; n < ntrap; n++) {
+		xTrap t;
+		xPointFixed p1, p2;
+
+		if (!project_trap_onto_grid(&trap[n], dx, dy, &t))
+			continue;
+
+		if (pixman_fixed_to_int(trap[n].top.y) + picture->pDrawable->y >= extents.y2 ||
+		    pixman_fixed_to_int(trap[n].bot.y) + picture->pDrawable->y < extents.y1)
+			continue;
+
+		p1.y = t.top.y;
+		p2.y = t.bot.y;
+		p1.x = t.top.l;
+		p2.x = t.bot.l;
+		polygon_add_line(tor.polygon, &p1, &p2);
+
+		p1.y = t.bot.y;
+		p2.y = t.top.y;
+		p1.x = t.top.r;
+		p2.x = t.bot.r;
+		polygon_add_line(tor.polygon, &p1, &p2);
+	}
+
+	if (picture->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);
+
+	tor_fini(&tor);
+
+	/* XXX clip boxes */
+	get_drawable_deltas(picture->pDrawable, pixmap, &x, &y);
+	sna = to_sna_from_screen(screen);
+	sna->render.copy_boxes(sna, GXcopy,
+			       scratch, sna_pixmap_get_bo(scratch), -extents.x1, -extents.x1,
+			       pixmap, priv->gpu_bo, x, y,
+			       &extents, 1);
+	mark_damaged(pixmap, priv, &extents ,x, y);
+
+	screen->DestroyPixmap(scratch);
+	return true;
+}
+
 static bool
 trap_upload(PicturePtr picture,
 	    INT16 x, INT16 y,
@@ -2681,11 +2818,7 @@ trap_upload(PicturePtr picture,
 			       scratch, sna_pixmap_get_bo(scratch), -extents.x1, -extents.x1,
 			       pixmap, priv->gpu_bo, x, y,
 			       &extents, 1);
-	if (!priv->gpu_only) {
-		extents.x1 += x; extents.x2 += x;
-		extents.y1 += y; extents.y2 += y;
-		sna_damage_add_box(&priv->gpu_damage, &extents);
-	}
+	mark_damaged(pixmap, priv, &extents, x, y);
 
 	screen->DestroyPixmap(scratch);
 	return true;
@@ -2700,6 +2833,9 @@ sna_add_traps(PicturePtr picture, INT16 x, INT16 y, int n, xTrap *t)
 		if (trap_span_converter(picture, x, y, n, t))
 			return;
 
+		if (trap_mask_converter(picture, x, y, n, t))
+			return;
+
 		if (trap_upload(picture, x, y, n, t))
 			return;
 	}
commit adde6eab5d0e532633c864830f8edfa63b36ef4e
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Sep 8 23:35:33 2011 +0100

    sna/trapezoids: Fast upload path for gpu busy bo
    
    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 c7eef03..90dbcd7 100644
--- a/src/sna/sna_trapezoids.c
+++ b/src/sna/sna_trapezoids.c
@@ -2608,6 +2608,89 @@ skip:
 	return true;
 }
 
+#define pixman_fixed_integer_floor(V) pixman_fixed_to_int(pixman_fixed_floor(V))
+#define pixman_fixed_integer_ceil(V) pixman_fixed_to_int(pixman_fixed_ceil(V))
+
+static bool
+trap_upload(PicturePtr picture,
+	    INT16 x, INT16 y,
+	    int ntrap, xTrap *trap)
+{
+	ScreenPtr screen = picture->pDrawable->pScreen;
+	struct sna *sna = to_sna_from_screen(screen);
+	PixmapPtr pixmap = get_drawable_pixmap(picture->pDrawable);
+	PixmapPtr scratch;
+	struct sna_pixmap *priv;
+	BoxRec extents;
+	pixman_image_t *image;
+	int width, height, depth;
+	int n;
+
+	priv = sna_pixmap_move_to_gpu(pixmap);
+	if (priv == NULL)
+		return false;
+
+	extents = *RegionExtents(picture->pCompositeClip);
+	for (n = 0; n < ntrap; n++) {
+		int v;
+
+		v = x + pixman_fixed_integer_floor (MIN(trap[n].top.l, trap[n].bot.l));
+		if (v < extents.x1)
+			extents.x1 = v;
+
+		v = x + pixman_fixed_integer_ceil (MAX(trap[n].top.r, trap[n].bot.r));
+		if (v > extents.x2)
+			extents.x2 = v;
+
+		v = y + pixman_fixed_integer_floor (trap[n].top.y);
+		if (v < extents.y1)
+			extents.y1 = v;
+
+		v = y + pixman_fixed_integer_ceil (trap[n].bot.y);
+		if (v > extents.y2)
+			extents.y2 = v;
+	}
+
+	DBG(("%s: extents (%d, %d), (%d, %d)\n",
+	     __FUNCTION__, extents.x1, extents.y1, extents.x2, extents.y2));
+
+	width  = extents.x2 - extents.x1;
+	height = extents.y2 - extents.y1;
+	depth = picture->pDrawable->depth;
+
+	DBG(("%s: tmp (%dx%d) depth=%d\n",
+	     __FUNCTION__, width, height, depth));
+	scratch = sna_pixmap_create_upload(screen, width, height, depth);
+	if (!scratch)
+		return true;
+
+	memset(scratch->devPrivate.ptr, 0, scratch->devKind*height);
+	image = pixman_image_create_bits(picture->format, width, height,
+					 scratch->devPrivate.ptr,
+					 scratch->devKind);
+	if (image) {
+		pixman_add_traps (image, -extents.x1, -extents.y1,
+				  ntrap, (pixman_trap_t *)trap);
+
+		pixman_image_unref(image);
+	}
+
+	/* XXX clip boxes */
+	get_drawable_deltas(picture->pDrawable, pixmap, &x, &y);
+	sna->render.copy_boxes(sna, GXcopy,
+			       scratch, sna_pixmap_get_bo(scratch), -extents.x1, -extents.x1,
+			       pixmap, priv->gpu_bo, x, y,
+			       &extents, 1);
+	if (!priv->gpu_only) {
+		extents.x1 += x; extents.x2 += x;
+		extents.y1 += y; extents.y2 += y;
+		sna_damage_add_box(&priv->gpu_damage, &extents);
+	}
+
+	screen->DestroyPixmap(scratch);
+	return true;
+}
+
 void
 sna_add_traps(PicturePtr picture, INT16 x, INT16 y, int n, xTrap *t)
 {
@@ -2616,6 +2699,9 @@ sna_add_traps(PicturePtr picture, INT16 x, INT16 y, int n, xTrap *t)
 	if (picture_is_gpu (picture)) {
 		if (trap_span_converter(picture, x, y, n, t))
 			return;
+
+		if (trap_upload(picture, x, y, n, t))
+			return;
 	}
 
 	DBG(("%s -- fallback\n", __FUNCTION__));
commit e9ca05331db9849fba39fbd0583db7052fc80a31
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Sep 8 22:54:22 2011 +0100

    sna/traps: Use the trapezoid path for AddTraps
    
    Usually this will be to CPU-only pixmap, but just on the off-chance that
    we are stalling for a GPU pixmap just the faster path developed for
    Trapezoids.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna.h b/src/sna/sna.h
index 3620173..4e0d710 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -523,6 +523,8 @@ void sna_composite_trapezoids(CARD8 op,
 			      PictFormatPtr maskFormat,
 			      INT16 xSrc, INT16 ySrc,
 			      int ntrap, xTrapezoid *traps);
+void sna_add_traps(PicturePtr picture, INT16 x, INT16 y, int n, xTrap *t);
+
 void sna_composite_triangles(CARD8 op,
 			     PicturePtr src,
 			     PicturePtr dst,
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index f83d8dc..a493722 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -3115,16 +3115,6 @@ static Bool sna_change_window_attributes(WindowPtr win, unsigned long mask)
 }
 
 static void
-sna_add_traps(PicturePtr picture, INT16 x, INT16 y, int n, xTrap *t)
-{
-	DBG(("%s (%d, %d) x %d\n", __FUNCTION__, x, y, n));
-
-	sna_drawable_move_to_cpu(picture->pDrawable, true);
-
-	fbAddTraps(picture, x, y, n, t);
-}
-
-static void
 sna_accel_flush_callback(CallbackListPtr *list,
 			 pointer user_data, pointer call_data)
 {
diff --git a/src/sna/sna_trapezoids.c b/src/sna/sna_trapezoids.c
index 46c1e57..c7eef03 100644
--- a/src/sna/sna_trapezoids.c
+++ b/src/sna/sna_trapezoids.c
@@ -2103,11 +2103,10 @@ choose_span(PicturePtr dst,
 	return span;
 }
 
-
 static bool
-trap_span_converter(CARD8 op, PicturePtr src, PicturePtr dst,
-		    PictFormatPtr maskFormat, INT16 src_x, INT16 src_y,
-		    int ntrap, xTrapezoid *traps)
+trapezoid_span_converter(CARD8 op, PicturePtr src, PicturePtr dst,
+			 PictFormatPtr maskFormat, INT16 src_x, INT16 src_y,
+			 int ntrap, xTrapezoid *traps)
 {
 	struct sna *sna;
 	struct sna_composite_spans_op tmp;
@@ -2265,9 +2264,9 @@ tor_blt_mask_mono(struct sna *sna,
 }
 
 static bool
-trap_mask_converter(CARD8 op, PicturePtr src, PicturePtr dst,
-		    PictFormatPtr maskFormat, INT16 src_x, INT16 src_y,
-		    int ntrap, xTrapezoid *traps)
+trapezoid_mask_converter(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;
@@ -2474,12 +2473,12 @@ sna_composite_trapezoids(CARD8 op,
 		}
 	}
 
-	if (trap_span_converter(op, src, dst, maskFormat,
-				xSrc, ySrc, ntrap, traps))
+	if (trapezoid_span_converter(op, src, dst, maskFormat,
+				     xSrc, ySrc, ntrap, traps))
 		return;
 
-	if (trap_mask_converter(op, src, dst, maskFormat,
-				xSrc, ySrc, ntrap, traps))
+	if (trapezoid_mask_converter(op, src, dst, maskFormat,
+				     xSrc, ySrc, ntrap, traps))
 		return;
 
 fallback:
@@ -2490,6 +2489,140 @@ fallback:
 			    ntrap, traps);
 }
 
+static inline bool
+project_trap_onto_grid(const xTrap *in,
+		       int dx, int dy,
+		       xTrap *out)
+{
+	out->top.l = dx + pixman_fixed_to_grid(in->top.l);
+	out->top.r = dx + pixman_fixed_to_grid(in->top.r);
+	out->top.y = dy + pixman_fixed_to_grid(in->top.y);
+
+	out->bot.l = dx + pixman_fixed_to_grid(in->bot.l);
+	out->bot.r = dx + pixman_fixed_to_grid(in->bot.r);
+	out->bot.y = dy + pixman_fixed_to_grid(in->bot.y);
+
+	return out->bot.y > out->top.y;
+}
+
+static bool
+trap_span_converter(PicturePtr dst,
+		    INT16 src_x, INT16 src_y,
+		    int ntrap, xTrap *trap)
+{
+	struct sna *sna;
+	struct sna_composite_spans_op tmp;
+	struct tor tor;
+	BoxRec extents;
+	PicturePtr src;
+	xRenderColor white;
+	pixman_region16_t *clip;
+	int16_t dx, dy;
+	int n, error;
+
+	if (NO_SCAN_CONVERTER)
+		return false;
+
+	/* XXX strict adherence to the Render specification */
+	if (dst->polyMode == PolyModePrecise) {
+		DBG(("%s: fallback -- precise rasterisation requested\n",
+		     __FUNCTION__));
+		return false;
+	}
+
+	sna = to_sna_from_drawable(dst->pDrawable);
+	if (!sna->render.composite_spans) {
+		DBG(("%s: fallback -- composite spans not supported\n",
+		     __FUNCTION__));
+		return false;
+	}
+
+	DBG(("%s: extents (%d, %d), (%d, %d)\n",
+	     __FUNCTION__, extents.x1, extents.y1, extents.x2, extents.y2));
+
+	clip = dst->pCompositeClip;
+	extents = *RegionExtents(clip);
+	dx = dst->pDrawable->x;
+	dy = dst->pDrawable->y;
+
+	DBG(("%s: after clip -- extents (%d, %d), (%d, %d), delta=(%d, %d)\n",
+	     __FUNCTION__,
+	     extents.x1, extents.y1,
+	     extents.x2, extents.y2,
+	     dx, dy));
+
+	white.red = white.green = white.blue = white.alpha = 0xffff;
+	src = CreateSolidPicture(0, &white, &error);
+	if (src == NULL)
+		return true;
+
+	memset(&tmp, 0, sizeof(tmp));
+	if (!sna->render.composite_spans(sna, PictOpAdd, src, dst,
+					 0, 0,
+					 extents.x1,  extents.y1,
+					 extents.x2 - extents.x1,
+					 extents.y2 - extents.y1,
+					 &tmp)) {
+		DBG(("%s: fallback -- composite spans render op not supported\n",
+		     __FUNCTION__));
+		FreePicture(src, 0);
+		return false;
+	}
+
+	dx *= FAST_SAMPLES_X;
+	dy *= FAST_SAMPLES_Y;
+	if (tor_init(&tor, &extents, 2*ntrap))
+		goto skip;
+
+	for (n = 0; n < ntrap; n++) {
+		xTrap t;
+		xPointFixed p1, p2;
+
+		if (!project_trap_onto_grid(&trap[n], dx, dy, &t))
+			continue;
+
+		if (pixman_fixed_to_int(trap[n].top.y) + dst->pDrawable->y >= extents.y2 ||
+		    pixman_fixed_to_int(trap[n].bot.y) + dst->pDrawable->y < extents.y1)
+			continue;
+
+		p1.y = t.top.y;
+		p2.y = t.bot.y;
+		p1.x = t.top.l;
+		p2.x = t.bot.l;
+		polygon_add_line(tor.polygon, &p1, &p2);
+
+		p1.y = t.bot.y;
+		p2.y = t.top.y;
+		p1.x = t.top.r;
+		p2.x = t.bot.r;
+		polygon_add_line(tor.polygon, &p1, &p2);
+	}
+
+	tor_render(sna, &tor, &tmp, clip,
+		   choose_span(dst, NULL, PictOpAdd, clip), false);
+
+skip:
+	tor_fini(&tor);
+	tmp.done(sna, &tmp);
+	FreePicture(src, 0);
+	return true;
+}
+
+void
+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 (trap_span_converter(picture, x, y, n, t))
+			return;
+	}
+
+	DBG(("%s -- fallback\n", __FUNCTION__));
+	sna_drawable_move_to_cpu(picture->pDrawable, true);
+	fbAddTraps(picture, x, y, n, t);
+}
+
 static inline void
 project_point_onto_grid(const xPointFixed *in,
 			int dx, int dy,


More information about the xorg-commit mailing list