xf86-video-intel: 5 commits - src/sna/kgem.c src/sna/kgem.h src/sna/sna_accel.c test/basic-stippledrect.c test/basic-tiledrect.c test/.gitignore test/Makefile.am test/test_display.c test/test.h test/test_render.c

Chris Wilson ickle at kemper.freedesktop.org
Mon Dec 2 09:15:12 PST 2013


 src/sna/kgem.c            |    6 -
 src/sna/kgem.h            |    1 
 src/sna/sna_accel.c       |  130 ++++++++++++-------------
 test/.gitignore           |    2 
 test/Makefile.am          |    2 
 test/basic-stippledrect.c |  239 ++++++++++++++++++++++++++++++++++++++++++++++
 test/basic-tiledrect.c    |  236 +++++++++++++++++++++++++++++++++++++++++++++
 test/test.h               |    4 
 test/test_display.c       |   16 +--
 test/test_render.c        |    2 
 10 files changed, 558 insertions(+), 80 deletions(-)

New commits:
commit 9a8478dae681212bd7a86640f90e6d47c9393b1a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Dec 2 15:48:50 2013 +0000

    sna: Fix stipple offset for drawing into child windows
    
    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 94d983b..9260ac8 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -12086,9 +12086,17 @@ sna_poly_fill_rect_stippled_8x8_blt(DrawablePtr drawable,
 
 	get_drawable_deltas(drawable, pixmap, &dx, &dy);
 	{
-		unsigned px = (0 - gc->patOrg.x - dx) & 7;
-		unsigned py = (0 - gc->patOrg.y - dy) & 7;
+		int px, py;
+
+		px = (0 - gc->patOrg.x - drawable->x - dx) % 8;
+		if (px < 0)
+			px += 8;
+
+		py = (0 - gc->patOrg.y - drawable->y - dy) % 8;
+		if (py < 0)
+			py += 8;
 		DBG(("%s: pat offset (%d, %d)\n", __FUNCTION__ ,px, py));
+
 		br00 = XY_SCANLINE_BLT | px << 12 | py << 8 | 3 << 20;
 		br13 = bo->pitch;
 		if (sna->kgem.gen >= 040 && bo->tiling) {
@@ -12133,7 +12141,7 @@ sna_poly_fill_rect_stippled_8x8_blt(DrawablePtr drawable,
 			assert(sna->kgem.mode == KGEM_BLT);
 			b = sna->kgem.batch + sna->kgem.nbatch;
 			if (sna->kgem.gen >= 0100) {
-				b[0] = XY_MONO_PAT | (br00 & (BLT_DST_TILED | 0x7<<12 | 0x7<<8)) | 3<<20 | 8;
+				b[0] = XY_MONO_PAT | (br00 & 0x7f00) | 3<<20 | 8;
 				b[1] = br13;
 				b[2] = (r->y + dy) << 16 | (r->x + dx);
 				b[3] = (r->y + r->height + dy) << 16 | (r->x + r->width + dx);
@@ -12149,7 +12157,7 @@ sna_poly_fill_rect_stippled_8x8_blt(DrawablePtr drawable,
 				b[9] = pat[1];
 				sna->kgem.nbatch += 10;
 			} else {
-				b[0] = XY_MONO_PAT | (br00 & (BLT_DST_TILED | 0x7<<12 | 0x7<<8)) | 3<<20 | 7;
+				b[0] = XY_MONO_PAT | (br00 & 0x7f00) | 3<<20 | 7;
 				b[1] = br13;
 				b[2] = (r->y + dy) << 16 | (r->x + dx);
 				b[3] = (r->y + r->height + dy) << 16 | (r->x + r->width + dx);
commit 32b942d0ff4f1d389ac643bfe6b18029d266dc13
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Dec 2 10:43:51 2013 +0000

    tests: Exercise stippled fills
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/test/.gitignore b/test/.gitignore
index 7a36837..979d896 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -4,6 +4,7 @@ basic-fillrect
 basic-putimage
 basic-lines
 basic-stress
+basic-stippledrect
 basic-tiledrect
 render-fill
 render-trapezoid
diff --git a/test/Makefile.am b/test/Makefile.am
index 033afd3..df022e2 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -1,6 +1,7 @@
 stress_TESTS = \
 	basic-fillrect \
 	basic-tiledrect \
+	basic-stippledrect \
 	basic-rectangle \
 	basic-string \
 	basic-copyarea \
diff --git a/test/basic-stippledrect.c b/test/basic-stippledrect.c
new file mode 100644
index 0000000..8a89efd
--- /dev/null
+++ b/test/basic-stippledrect.c
@@ -0,0 +1,239 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "test.h"
+
+static unsigned char bitmap4x4[] = {
+	   0x03, 0x06, 0x0c, 0x09
+};
+
+static unsigned char bitmap8x8[3][8] = {
+	{ 0xcc, 0x66, 0x33, 0x99, 0xcc, 0x66, 0x33, 0x99 },
+	{ 0x00, 0xfe, 0x92, 0x92, 0xfe, 0x92, 0x92, 0xfe },
+	{ 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa },
+};
+
+static void fill_rect(struct test_target *t, uint8_t alu,
+		      XRectangle *clip, int nclip,
+		      uint8_t stipple, uint8_t opaque, int tx, int ty,
+		      int x, int y, int w, int h,
+		      uint32_t fg, uint32_t bg)
+{
+	Display *dpy = t->dpy->dpy;
+	XGCValues val;
+	GC gc;
+
+	val.function = alu;
+	val.foreground = fg;
+	val.background = bg;
+	val.fill_style = opaque ? FillOpaqueStippled : FillStippled;
+	val.ts_x_origin = tx;
+	val.ts_y_origin = ty;
+	if (stipple == 0) {
+		val.stipple = XCreateBitmapFromData(dpy, t->draw, (char *)bitmap4x4, 4, 4);
+	} else {
+		char *b = (char *)bitmap8x8[stipple-1];
+		val.stipple = XCreateBitmapFromData(dpy, t->draw, b, 8, 8);
+	}
+
+	gc = XCreateGC(dpy, t->draw, GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin | GCStipple | GCForeground | GCBackground | GCFunction, &val);
+	if (nclip)
+		XSetClipRectangles(dpy, gc, 0, 0, clip, nclip, Unsorted);
+	XFillRectangle(dpy, t->draw, gc, x, y, w, h);
+	XFreeGC(dpy, gc);
+	XFreePixmap(dpy, val.stipple);
+}
+
+static void clear(struct test_target *tt)
+{
+	XRenderColor render_color = {0};
+	XRenderFillRectangle(tt->dpy->dpy, PictOpClear, tt->picture, &render_color,
+			     0, 0, tt->width, tt->height);
+}
+
+static void unclipped_tests(struct test *t, int reps, int sets, enum target target)
+{
+	struct test_target real, ref;
+	int r, s;
+
+	printf("Testing unclipped stippled fills (%s): ", test_target_name(target));
+	fflush(stdout);
+
+	test_target_create_render(&t->real, target, &real);
+	clear(&real);
+
+	test_target_create_render(&t->ref, target, &ref);
+	clear(&ref);
+
+	for (s = 0; s < sets; s++) {
+		for (r = 0; r < reps; r++) {
+			int x = rand() % real.width;
+			int y = rand() % real.height;
+			int w = rand() % (real.width - x);
+			int h = rand() % (real.height - y);
+			int tx = rand() % (2*real.width) - real.width;
+			int ty = rand() % (2*real.height) - real.height;
+			uint8_t stipple = rand() % 4;
+			uint8_t opaque = rand() % 1;
+			uint8_t alu = rand() % (GXset + 1);
+			uint32_t fg = rand();
+			uint32_t bg = rand();
+
+			fill_rect(&real, alu, NULL, 0,
+				  stipple, opaque, tx, ty,
+				  x, y, w, h,
+				  fg, bg);
+			fill_rect(&ref, alu, NULL, 0,
+				  stipple, opaque, tx, ty,
+				  x, y, w, h,
+				  fg, bg);
+		}
+
+		test_compare(t,
+			     real.draw, real.format,
+			     ref.draw, ref.format,
+			     0, 0, real.width, real.height,
+			     "");
+	}
+
+	printf("passed [%d iterations x %d]\n", reps, sets);
+
+	test_target_destroy_render(&t->real, &real);
+	test_target_destroy_render(&t->ref, &ref);
+}
+
+static void simple_clip_tests(struct test *t, int reps, int sets, enum target target)
+{
+	struct test_target real, ref;
+	int r, s;
+
+	printf("Testing simple clipped stippled fills (%s): ", test_target_name(target));
+	fflush(stdout);
+
+	test_target_create_render(&t->real, target, &real);
+	clear(&real);
+
+	test_target_create_render(&t->ref, target, &ref);
+	clear(&ref);
+
+	for (s = 0; s < sets; s++) {
+		for (r = 0; r < reps; r++) {
+			int x = rand() % (2*real.width) - real.width;
+			int y = rand() % (2*real.height) - real.height;
+			int w = rand() % (2*real.width);
+			int h = rand() % (2*real.height);
+			int tx = rand() % (2*real.width) - real.width;
+			int ty = rand() % (2*real.height) - real.height;
+			uint8_t stipple = rand() % 4;
+			uint8_t opaque = rand() % 1;
+			uint8_t alu = rand() % (GXset + 1);
+			uint32_t fg = rand();
+			uint32_t bg = rand();
+
+			fill_rect(&real, alu, NULL, 0,
+				  stipple, opaque, tx, ty,
+				  x, y, w, h,
+				  fg, bg);
+			fill_rect(&ref, alu, NULL, 0,
+				  stipple, opaque, tx, ty,
+				  x, y, w, h,
+				  fg, bg);
+		}
+
+		test_compare(t,
+			     real.draw, real.format,
+			     ref.draw, ref.format,
+			     0, 0, real.width, real.height,
+			     "");
+	}
+
+	printf("passed [%d iterations x %d]\n", reps, sets);
+
+	test_target_destroy_render(&t->real, &real);
+	test_target_destroy_render(&t->ref, &ref);
+}
+
+static void complex_clip_tests(struct test *t, int reps, int sets, enum target target)
+{
+	struct test_target real, ref;
+	XRectangle *clip;
+	int nclip, r, s;
+
+	printf("Testing complex clipped stippled fills (%s): ", test_target_name(target));
+	fflush(stdout);
+
+	test_target_create_render(&t->real, target, &real);
+	clear(&real);
+
+	test_target_create_render(&t->ref, target, &ref);
+	clear(&ref);
+
+	for (s = 0; s < sets; s++) {
+		nclip = (rand() % 16) + 2;
+		clip = malloc(sizeof(XRectangle)*nclip);
+		for (r = 0; r < nclip; r++) {
+			clip[r].x = rand() % real.width;
+			clip[r].y = rand() % real.height;
+			clip[r].width = rand() % (real.width - clip[r].x);
+			clip[r].height = rand() % (real.height - clip[r].y);
+		}
+
+		for (r = 0; r < reps; r++) {
+			int x = rand() % (2*real.width) - real.width;
+			int y = rand() % (2*real.height) - real.height;
+			int w = rand() % (2*real.width);
+			int h = rand() % (2*real.height);
+			int tx = rand() % (2*real.width) - real.width;
+			int ty = rand() % (2*real.height) - real.height;
+			uint8_t stipple = rand() % 4;
+			uint8_t opaque = rand() % 1;
+			uint8_t alu = rand() % (GXset + 1);
+			uint32_t fg = rand();
+			uint32_t bg = rand();
+
+			fill_rect(&real, alu, clip, nclip,
+				  stipple, opaque, tx, ty,
+				  x, y, w, h,
+				  fg, bg);
+			fill_rect(&ref, alu, clip, nclip,
+				  stipple, opaque, tx, ty,
+				  x, y, w, h,
+				  fg, bg);
+		}
+
+		test_compare(t,
+			     real.draw, real.format,
+			     ref.draw, ref.format,
+			     0, 0, real.width, real.height,
+			     "");
+
+		free(clip);
+	}
+
+	printf("passed [%d iterations x %d]\n", reps, sets);
+
+	test_target_destroy_render(&t->real, &real);
+	test_target_destroy_render(&t->ref, &ref);
+}
+
+int main(int argc, char **argv)
+{
+	struct test test;
+	int i;
+
+	test_init(&test, argc, argv);
+
+	for (i = 0; i <= DEFAULT_ITERATIONS; i++) {
+		int reps = REPS(i), sets = SETS(i);
+		enum target t;
+
+		for (t = TARGET_FIRST; t <= TARGET_LAST; t++) {
+			unclipped_tests(&test, reps, sets, t);
+			simple_clip_tests(&test, reps, sets, t);
+			complex_clip_tests(&test, reps, sets, t);
+		}
+	}
+
+	return 0;
+}
commit 463ab7f4faf46f6530423b6b10f2cd1bb6d0aa83
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Dec 2 11:08:05 2013 +0000

    sna: Fix tile origin for pattern blits
    
    References: https://bugs.freedesktop.org/show_bug.cgi?id=71260
    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 e1487ee..94d983b 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -11310,7 +11310,7 @@ sna_pixmap_get_source_bo(PixmapPtr pixmap)
 	if (priv->cpu_damage && priv->cpu_bo)
 		return kgem_bo_reference(priv->cpu_bo);
 
-	if (!sna_pixmap_force_to_gpu(pixmap, MOVE_READ))
+	if (!sna_pixmap_force_to_gpu(pixmap, MOVE_READ | MOVE_ASYNC_HINT))
 		return NULL;
 
 	return kgem_bo_reference(priv->gpu_bo);
@@ -11343,20 +11343,40 @@ sna_poly_fill_rect_tiled_8x8_blt(DrawablePtr drawable,
 	if (NO_TILE_8x8)
 		return false;
 
-	DBG(("%s x %d [(%d, %d)x(%d, %d)...], clipped=%x\n",
-	     __FUNCTION__, n, r->x, r->y, r->width, r->height, clipped));
+	DBG(("%s x %d [(%d, %d)x(%d, %d)...], clipped=%x, origin=(%d, %d)\n",
+	     __FUNCTION__, n, r->x, r->y, r->width, r->height, clipped, origin->x, origin->y));
+
+	DBG(("%s: tile_bo tiling=%d, pitch=%d\n", __FUNCTION__, tile_bo->tiling, tile_bo->pitch));
+	if (tile_bo->tiling)
+		return false;
+
+	assert(tile_bo->pitch == 8 * drawable->bitsPerPixel >> 3);
 
 	kgem_set_mode(&sna->kgem, KGEM_BLT, bo);
 	if (!kgem_check_batch(&sna->kgem, 10+2*3) ||
 	    !kgem_check_reloc(&sna->kgem, 2) ||
-	    !kgem_check_bo_fenced(&sna->kgem, bo)) {
+	    !kgem_check_many_bo_fenced(&sna->kgem, bo, tile_bo, NULL)) {
 		kgem_submit(&sna->kgem);
-		if (!kgem_check_bo_fenced(&sna->kgem, bo))
+		if (!kgem_check_many_bo_fenced(&sna->kgem, bo, tile_bo, NULL))
 			return false;
 		_kgem_set_mode(&sna->kgem, KGEM_BLT);
 	}
 
+	get_drawable_deltas(drawable, pixmap, &dx, &dy);
+	assert(extents->x1 + dx >= 0);
+	assert(extents->y1 + dy >= 0);
+	assert(extents->x2 + dx <= pixmap->drawable.width);
+	assert(extents->y2 + dy <= pixmap->drawable.height);
+
 	br00 = XY_SCANLINE_BLT;
+	tx = (-drawable->x - dx - origin->x) % 8;
+	if (tx < 0)
+		tx += 8;
+	ty = (-drawable->y - dy - origin->y) % 8;
+	if (ty < 0)
+		ty += 8;
+	br00 |= tx << 12 | ty << 8;
+
 	br13 = bo->pitch;
 	if (sna->kgem.gen >= 040 && bo->tiling) {
 		br00 |= BLT_DST_TILED;
@@ -11365,24 +11385,14 @@ sna_poly_fill_rect_tiled_8x8_blt(DrawablePtr drawable,
 	br13 |= blt_depth(drawable->depth) << 24;
 	br13 |= fill_ROP[gc->alu] << 16;
 
-	get_drawable_deltas(drawable, pixmap, &dx, &dy);
-	assert(extents->x1 + dx >= 0);
-	assert(extents->y1 + dy >= 0);
-	assert(extents->x2 + dx <= pixmap->drawable.width);
-	assert(extents->y2 + dy <= pixmap->drawable.height);
-
 	if (!clipped) {
 		dx += drawable->x;
 		dy += drawable->y;
 
 		sna_damage_add_rectangles(damage, r, n, dx, dy);
 		if (n == 1) {
-			tx = (r->x - origin->x) % 8;
-			if (tx < 0)
-				tx = 8 - tx;
-			ty = (r->y - origin->y) % 8;
-			if (ty < 0)
-				ty = 8 - ty;
+			DBG(("%s: rect=(%d, %d)x(%d, %d) + (%d, %d), tile=(%d, %d)\n",
+			     __FUNCTION__, r->x, r->y, r->width, r->height, dx, dy, tx, ty));
 
 			assert(r->x + dx >= 0);
 			assert(r->y + dy >= 0);
@@ -11392,7 +11402,7 @@ sna_poly_fill_rect_tiled_8x8_blt(DrawablePtr drawable,
 			assert(sna->kgem.mode == KGEM_BLT);
 			b = sna->kgem.batch + sna->kgem.nbatch;
 			if (sna->kgem.gen >= 0100) {
-				b[0] = XY_PAT_BLT | tx << 12 | ty << 8 | 3 << 20 | (br00 & BLT_DST_TILED) | 6;
+				b[0] = XY_PAT_BLT | 3 << 20 | (br00 & 0x7f00) | 6;
 				b[1] = br13;
 				b[2] = (r->y + dy) << 16 | (r->x + dx);
 				b[3] = (r->y + r->height + dy) << 16 | (r->x + r->width + dx);
@@ -11409,7 +11419,7 @@ sna_poly_fill_rect_tiled_8x8_blt(DrawablePtr drawable,
 							 0);
 				sna->kgem.nbatch += 8;
 			} else {
-				b[0] = XY_PAT_BLT | tx << 12 | ty << 8 | 3 << 20 | (br00 & BLT_DST_TILED) | 4;
+				b[0] = XY_PAT_BLT | 3 << 20 | (br00 & 0x7f00) | 4;
 				b[1] = br13;
 				b[2] = (r->y + dy) << 16 | (r->x + dx);
 				b[3] = (r->y + r->height + dy) << 16 | (r->x + r->width + dx);
@@ -11482,14 +11492,7 @@ sna_poly_fill_rect_tiled_8x8_blt(DrawablePtr drawable,
 				assert(r->x + dx + r->width  <= pixmap->drawable.width);
 				assert(r->y + dy + r->height <= pixmap->drawable.height);
 
-				tx = (r->x - origin->x) % 8;
-				if (tx < 0)
-					tx = 8 - tx;
-				ty = (r->y - origin->y) % 8;
-				if (ty < 0)
-					ty = 8 - ty;
-
-				b[0] = br00 | tx << 12 | ty << 8;
+				b[0] = br00;
 				b[1] = (r->y + dy) << 16 | (r->x + dx);
 				b[2] = (r->y + r->height + dy) << 16 | (r->x + r->width + dx);
 				b += 3; r++;
@@ -11554,6 +11557,7 @@ sna_poly_fill_rect_tiled_8x8_blt(DrawablePtr drawable,
 
 		if (clip.data == NULL) {
 			const BoxRec *c = &clip.extents;
+			DBG(("%s: simple clip, %d boxes\n", __FUNCTION__, n));
 			while (n--) {
 				BoxRec box;
 
@@ -11617,17 +11621,12 @@ sna_poly_fill_rect_tiled_8x8_blt(DrawablePtr drawable,
 					assert(box.x2 + dx <= pixmap->drawable.width);
 					assert(box.y2 + dy <= pixmap->drawable.height);
 
-					ty = (box.y1 - drawable->y - origin->y) % 8;
-					if (ty < 0)
-						ty = 8 - ty;
-
-					tx = (box.x1 - drawable->x - origin->x) % 8;
-					if (tx < 0)
-						tx = 8 - tx;
+					DBG(("%s: box=(%d, %d),(%d, %d) + (%d, %d), tile=(%d, %d)\n",
+					     __FUNCTION__, box.x1, box.y1, box.x2, box.y2, dx, dy, tx, ty));
 
 					assert(sna->kgem.mode == KGEM_BLT);
 					b = sna->kgem.batch + sna->kgem.nbatch;
-					b[0] = br00 | tx << 12 | ty << 8;
+					b[0] = br00;
 					b[1] = (box.y1 + dy) << 16 | (box.x1 + dx);
 					b[2] = (box.y2 + dy) << 16 | (box.x2 + dx);
 					sna->kgem.nbatch += 3;
@@ -11638,6 +11637,7 @@ sna_poly_fill_rect_tiled_8x8_blt(DrawablePtr drawable,
 			const BoxRec * const clip_end = clip_start + clip.data->numRects;
 			const BoxRec *c;
 
+			DBG(("%s: complex clip (%ld cliprects), %d boxes\n", __FUNCTION__, (long)clip.data->numRects, n));
 			do {
 				BoxRec box;
 
@@ -11711,17 +11711,9 @@ sna_poly_fill_rect_tiled_8x8_blt(DrawablePtr drawable,
 						assert(bb.x2 + dx <= pixmap->drawable.width);
 						assert(bb.y2 + dy <= pixmap->drawable.height);
 
-						ty = (bb.y1 - drawable->y - origin->y) % 8;
-						if (ty < 0)
-							ty = 8 - ty;
-
-						tx = (bb.x1 - drawable->x - origin->x) % 8;
-						if (tx < 0)
-							tx = 8 - tx;
-
 						assert(sna->kgem.mode == KGEM_BLT);
 						b = sna->kgem.batch + sna->kgem.nbatch;
-						b[0] = br00 | tx << 12 | ty << 8;
+						b[0] = br00;
 						b[1] = (bb.y1 + dy) << 16 | (bb.x1 + dx);
 						b[2] = (bb.y2 + dy) << 16 | (bb.x2 + dx);
 						sna->kgem.nbatch += 3;
@@ -11773,6 +11765,7 @@ sna_poly_fill_rect_tiled_nxm_blt(DrawablePtr drawable,
 	assert(tile->drawable.height && tile->drawable.height <= 8);
 	assert(tile->drawable.width && tile->drawable.width <= 8);
 	assert(has_coherent_ptr(sna, sna_pixmap(tile), MOVE_READ));
+	upload->pitch = 8*tile->drawable.bitsPerPixel >> 3; /* for sanity checks */
 
 	cpp = tile->drawable.bitsPerPixel/8;
 	for (h = 0; h < tile->drawable.height; h++) {
@@ -11848,23 +11841,24 @@ sna_poly_fill_rect_tiled_blt(DrawablePtr drawable,
 		ret = sna_poly_fill_rect_tiled_8x8_blt(drawable, bo, damage,
 						       tile_bo, gc, n, rect,
 						       extents, clipped);
-		kgem_bo_destroy(&sna->kgem, tile_bo);
-
-		return ret;
-	}
-
-	if ((tile->drawable.width | tile->drawable.height) <= 0xc &&
-	    is_power_of_two(tile->drawable.width) &&
-	    is_power_of_two(tile->drawable.height))
-		return sna_poly_fill_rect_tiled_nxm_blt(drawable, bo, damage,
-							gc, n, rect,
-							extents, clipped);
+		if (ret) {
+			kgem_bo_destroy(&sna->kgem, tile_bo);
+			return true;
+		}
+	} else {
+		if ((tile->drawable.width | tile->drawable.height) <= 0xc &&
+				is_power_of_two(tile->drawable.width) &&
+				is_power_of_two(tile->drawable.height))
+			return sna_poly_fill_rect_tiled_nxm_blt(drawable, bo, damage,
+					gc, n, rect,
+					extents, clipped);
 
-	tile_bo = sna_pixmap_get_source_bo(tile);
-	if (tile_bo == NULL) {
-		DBG(("%s: unable to move tile go GPU, fallback\n",
-		     __FUNCTION__));
-		return false;
+		tile_bo = sna_pixmap_get_source_bo(tile);
+		if (tile_bo == NULL) {
+			DBG(("%s: unable to move tile go GPU, fallback\n",
+						__FUNCTION__));
+			return false;
+		}
 	}
 
 	if (!sna_copy_init_blt(&copy, sna, tile, tile_bo, pixmap, bo, alu)) {
commit 6889ba38ab2bb050dec3057dbc584619dbe6d2e2
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Dec 2 14:20:51 2013 +0000

    sna: Drop forced alignment to 64 on pre-gen4 devices
    
    Some linear GPU bo that we create must be naturally aligned, and the
    extra alignment imposed for pure paranoia is counter productive.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 35b76d9..4305c76 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -1258,10 +1258,6 @@ void kgem_init(struct kgem *kgem, int fd, struct pci_device *dev, unsigned gen)
 	DBG(("%s: maximum batch size? %d\n", __FUNCTION__,
 	     kgem->batch_size));
 
-	kgem->min_alignment = 4;
-	if (gen < 040)
-		kgem->min_alignment = 64;
-
 	kgem->half_cpu_cache_pages = cpu_cache_size() >> 13;
 	DBG(("%s: last-level cache size: %d bytes, threshold in pages: %d\n",
 	     __FUNCTION__, cpu_cache_size(), kgem->half_cpu_cache_pages));
@@ -1424,7 +1420,7 @@ inline static uint32_t kgem_pitch_alignment(struct kgem *kgem, unsigned flags)
 		return 256;
 	if (flags & CREATE_SCANOUT)
 		return 64;
-	return kgem->min_alignment;
+	return 4;
 }
 
 void kgem_get_tile_size(struct kgem *kgem, int tiling, int pitch,
diff --git a/src/sna/kgem.h b/src/sna/kgem.h
index d847f3f..14d7d68 100644
--- a/src/sna/kgem.h
+++ b/src/sna/kgem.h
@@ -158,7 +158,6 @@ struct kgem {
 	uint16_t nreloc__self;
 	uint16_t nfence;
 	uint16_t batch_size;
-	uint16_t min_alignment;
 
 	uint32_t flush:1;
 	uint32_t need_expire:1;
commit 49af22ee5533b1afbf30f50fcfd7245f1c8d98bc
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Dec 2 10:43:51 2013 +0000

    tests: Exercise tiled fills
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/test/.gitignore b/test/.gitignore
index 05bb936..7a36837 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -4,6 +4,7 @@ basic-fillrect
 basic-putimage
 basic-lines
 basic-stress
+basic-tiledrect
 render-fill
 render-trapezoid
 render-trapezoid-image
diff --git a/test/Makefile.am b/test/Makefile.am
index 5c2a3e1..033afd3 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -1,5 +1,6 @@
 stress_TESTS = \
 	basic-fillrect \
+	basic-tiledrect \
 	basic-rectangle \
 	basic-string \
 	basic-copyarea \
diff --git a/test/basic-tiledrect.c b/test/basic-tiledrect.c
new file mode 100644
index 0000000..1596c4c
--- /dev/null
+++ b/test/basic-tiledrect.c
@@ -0,0 +1,236 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "test.h"
+
+static unsigned char bitmap4x4[] = {
+	   0x03, 0x06, 0x0c, 0x09
+};
+
+static unsigned char bitmap8x8[3][8] = {
+	{ 0xcc, 0x66, 0x33, 0x99, 0xcc, 0x66, 0x33, 0x99 },
+	{ 0x00, 0xfe, 0x92, 0x92, 0xfe, 0x92, 0x92, 0xfe },
+	{ 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa },
+};
+
+static void fill_rect(struct test_target *t, uint8_t alu,
+		      XRectangle *clip, int nclip,
+		      uint8_t tile, int tx, int ty,
+		      int x, int y, int w, int h,
+		      uint32_t fg, uint32_t bg)
+{
+	Display *dpy = t->dpy->dpy;
+	XGCValues val;
+	GC gc;
+
+	val.function = alu;
+	val.fill_style = FillTiled;
+	val.ts_x_origin = tx;
+	val.ts_y_origin = ty;
+	if (tile == 0) {
+		val.tile = XCreatePixmapFromBitmapData(dpy, t->draw, (char *)bitmap4x4, 4, 4,
+						       fg, bg, t->depth);
+	} else {
+		char *b = (char *)bitmap8x8[tile-1];
+		val.tile = XCreatePixmapFromBitmapData(dpy, t->draw, b, 8, 8,
+						       fg, bg, t->depth);
+	}
+
+	gc = XCreateGC(dpy, t->draw, GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin | GCTile | GCFunction, &val);
+	if (nclip)
+		XSetClipRectangles(dpy, gc, 0, 0, clip, nclip, Unsorted);
+	XFillRectangle(dpy, t->draw, gc, x, y, w, h);
+	XFreeGC(dpy, gc);
+	XFreePixmap(dpy, val.tile);
+}
+
+static void clear(struct test_target *tt)
+{
+	XRenderColor render_color = {0};
+	XRenderFillRectangle(tt->dpy->dpy, PictOpClear, tt->picture, &render_color,
+			     0, 0, tt->width, tt->height);
+}
+
+static void unclipped_tests(struct test *t, int reps, int sets, enum target target)
+{
+	struct test_target real, ref;
+	int r, s;
+
+	printf("Testing unclipped tiled fills (%s): ", test_target_name(target));
+	fflush(stdout);
+
+	test_target_create_render(&t->real, target, &real);
+	clear(&real);
+
+	test_target_create_render(&t->ref, target, &ref);
+	clear(&ref);
+
+	for (s = 0; s < sets; s++) {
+		for (r = 0; r < reps; r++) {
+			int x = rand() % real.width;
+			int y = rand() % real.height;
+			int w = rand() % (real.width - x);
+			int h = rand() % (real.height - y);
+			int tx = rand() % (2*real.width) - real.width;
+			int ty = rand() % (2*real.height) - real.height;
+			uint8_t tile = rand() % 4;
+			uint8_t alu = rand() % (GXset + 1);
+			uint32_t fg = rand();
+			uint32_t bg = rand();
+
+			fill_rect(&real, alu, NULL, 0,
+				  tile, tx, ty,
+				  x, y, w, h,
+				  fg, bg);
+			fill_rect(&ref, alu, NULL, 0,
+				  tile, tx, ty,
+				  x, y, w, h,
+				  fg, bg);
+		}
+
+		test_compare(t,
+			     real.draw, real.format,
+			     ref.draw, ref.format,
+			     0, 0, real.width, real.height,
+			     "");
+	}
+
+	printf("passed [%d iterations x %d]\n", reps, sets);
+
+	test_target_destroy_render(&t->real, &real);
+	test_target_destroy_render(&t->ref, &ref);
+}
+
+static void simple_clip_tests(struct test *t, int reps, int sets, enum target target)
+{
+	struct test_target real, ref;
+	int r, s;
+
+	printf("Testing simple clipped tiled fills (%s): ", test_target_name(target));
+	fflush(stdout);
+
+	test_target_create_render(&t->real, target, &real);
+	clear(&real);
+
+	test_target_create_render(&t->ref, target, &ref);
+	clear(&ref);
+
+	for (s = 0; s < sets; s++) {
+		for (r = 0; r < reps; r++) {
+			int x = rand() % (2*real.width) - real.width;
+			int y = rand() % (2*real.height) - real.height;
+			int w = rand() % (2*real.width);
+			int h = rand() % (2*real.height);
+			int tx = rand() % (2*real.width) - real.width;
+			int ty = rand() % (2*real.height) - real.height;
+			uint8_t tile = rand() % 4;
+			uint8_t alu = rand() % (GXset + 1);
+			uint32_t fg = rand();
+			uint32_t bg = rand();
+
+			fill_rect(&real, alu, NULL, 0,
+				  tile, tx, ty,
+				  x, y, w, h,
+				  fg, bg);
+			fill_rect(&ref, alu, NULL, 0,
+				  tile, tx, ty,
+				  x, y, w, h,
+				  fg, bg);
+		}
+
+		test_compare(t,
+			     real.draw, real.format,
+			     ref.draw, ref.format,
+			     0, 0, real.width, real.height,
+			     "");
+	}
+
+	printf("passed [%d iterations x %d]\n", reps, sets);
+
+	test_target_destroy_render(&t->real, &real);
+	test_target_destroy_render(&t->ref, &ref);
+}
+
+static void complex_clip_tests(struct test *t, int reps, int sets, enum target target)
+{
+	struct test_target real, ref;
+	XRectangle *clip;
+	int nclip, r, s;
+
+	printf("Testing complex clipped tiled fills (%s): ", test_target_name(target));
+	fflush(stdout);
+
+	test_target_create_render(&t->real, target, &real);
+	clear(&real);
+
+	test_target_create_render(&t->ref, target, &ref);
+	clear(&ref);
+
+	for (s = 0; s < sets; s++) {
+		nclip = (rand() % 16) + 2;
+		clip = malloc(sizeof(XRectangle)*nclip);
+		for (r = 0; r < nclip; r++) {
+			clip[r].x = rand() % real.width;
+			clip[r].y = rand() % real.height;
+			clip[r].width = rand() % (real.width - clip[r].x);
+			clip[r].height = rand() % (real.height - clip[r].y);
+		}
+
+		for (r = 0; r < reps; r++) {
+			int x = rand() % (2*real.width) - real.width;
+			int y = rand() % (2*real.height) - real.height;
+			int w = rand() % (2*real.width);
+			int h = rand() % (2*real.height);
+			int tx = rand() % (2*real.width) - real.width;
+			int ty = rand() % (2*real.height) - real.height;
+			uint8_t tile = rand() % 4;
+			uint8_t alu = rand() % (GXset + 1);
+			uint32_t fg = rand();
+			uint32_t bg = rand();
+
+			fill_rect(&real, alu, clip, nclip,
+				  tile, tx, ty,
+				  x, y, w, h,
+				  fg, bg);
+			fill_rect(&ref, alu, clip, nclip,
+				  tile, tx, ty,
+				  x, y, w, h,
+				  fg, bg);
+		}
+
+		test_compare(t,
+			     real.draw, real.format,
+			     ref.draw, ref.format,
+			     0, 0, real.width, real.height,
+			     "");
+
+		free(clip);
+	}
+
+	printf("passed [%d iterations x %d]\n", reps, sets);
+
+	test_target_destroy_render(&t->real, &real);
+	test_target_destroy_render(&t->ref, &ref);
+}
+
+int main(int argc, char **argv)
+{
+	struct test test;
+	int i;
+
+	test_init(&test, argc, argv);
+
+	for (i = 0; i <= DEFAULT_ITERATIONS; i++) {
+		int reps = REPS(i), sets = SETS(i);
+		enum target t;
+
+		for (t = TARGET_FIRST; t <= TARGET_LAST; t++) {
+			unclipped_tests(&test, reps, sets, t);
+			simple_clip_tests(&test, reps, sets, t);
+			complex_clip_tests(&test, reps, sets, t);
+		}
+	}
+
+	return 0;
+}
diff --git a/test/test.h b/test/test.h
index 3cd9457..568e000 100644
--- a/test/test.h
+++ b/test/test.h
@@ -31,7 +31,7 @@ struct test {
 		Window root;
 		XShmSegmentInfo shm;
 		int max_shm_size;
-		int width, height;
+		int width, height, depth;
 		XRenderPictFormat *format;
 	} real, ref;
 };
@@ -82,7 +82,7 @@ struct test_target {
 	GC gc;
 	XRenderPictFormat *format;
 	Picture picture;
-	int width, height;
+	int width, height, depth;
 	enum target target;
 };
 
diff --git a/test/test_display.c b/test/test_display.c
index b5e7e06..36cfe69 100644
--- a/test/test_display.c
+++ b/test/test_display.c
@@ -16,12 +16,12 @@ static Window get_root(struct test_display *t)
 	 * can guarantee we do not get clipped by children.
 	 */
 	attr.override_redirect = 1;
-	w= XCreateWindow(t->dpy, DefaultRootWindow(t->dpy),
-			 0, 0, t->width, t->height, 0,
-			 DefaultDepth(t->dpy, DefaultScreen(t->dpy)),
-			 InputOutput,
-			 DefaultVisual(t->dpy, DefaultScreen(t->dpy)),
-			 CWOverrideRedirect, &attr);
+	w = XCreateWindow(t->dpy, DefaultRootWindow(t->dpy),
+			  0, 0, t->width, t->height, 0,
+			  DefaultDepth(t->dpy, DefaultScreen(t->dpy)),
+			  InputOutput,
+			  DefaultVisual(t->dpy, DefaultScreen(t->dpy)),
+			  CWOverrideRedirect, &attr);
 	XMapWindow(t->dpy, w);
 
 	return w;
@@ -125,6 +125,7 @@ static void default_setup(struct test_display *dpy)
 		XRenderFindVisualFormat(dpy->dpy,
 					DefaultVisual(dpy->dpy,
 						      DefaultScreen(dpy->dpy)));
+	dpy->depth = DefaultDepth(dpy->dpy, DefaultScreen(dpy->dpy));
 }
 
 static void test_get_displays(int argc, char **argv,
@@ -136,8 +137,7 @@ static void test_get_displays(int argc, char **argv,
 	shm_setup(real);
 	real->root = get_root(real);
 
-	ref->dpy = ref_display(real->width, real->height,
-			       DefaultDepth(real->dpy, DefaultScreen(real->dpy)));
+	ref->dpy = ref_display(real->width, real->height, real->depth);
 	default_setup(ref);
 	shm_setup(ref);
 	ref->root = get_root(ref);
diff --git a/test/test_render.c b/test/test_render.c
index 67889ac..926e930 100644
--- a/test/test_render.c
+++ b/test/test_render.c
@@ -31,6 +31,7 @@ void test_target_create_render(struct test_display *dpy,
 	tt->format = dpy->format;
 	tt->width = dpy->width;
 	tt->height = dpy->height;
+	tt->depth = dpy->depth;
 
 	switch (target) {
 	case ROOT:
@@ -56,6 +57,7 @@ void test_target_create_render(struct test_display *dpy,
 		tt->draw = XCreatePixmap(dpy->dpy, tt->draw,
 					 dpy->width, dpy->height,
 					 tt->format->depth);
+		tt->depth = 32;
 		break;
 	}
 


More information about the xorg-commit mailing list