xf86-video-intel: 3 commits - src/sna/sna_accel.c src/sna/sna_dri2.c src/sna/sna.h test/present-speed.c test/present-test.c

Chris Wilson ickle at kemper.freedesktop.org
Sun Apr 5 03:01:18 PDT 2015


 src/sna/sna.h        |    2 
 src/sna/sna_accel.c  |    3 
 src/sna/sna_dri2.c   |   41 ++++++-----
 test/present-speed.c |   65 +++++++++++++++---
 test/present-test.c  |  178 ++++++++++++++++++++++++++++++++-------------------
 5 files changed, 196 insertions(+), 93 deletions(-)

New commits:
commit af2da325748d238dee42467e4d2295c65cdce18e
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Apr 5 10:50:07 2015 +0100

    test/present-speed: More measurement for different swap methods
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/test/present-speed.c b/test/present-speed.c
index c89af87..5c5b930 100644
--- a/test/present-speed.c
+++ b/test/present-speed.c
@@ -38,6 +38,7 @@
 #include <xcb/xcb.h>
 #include <xcb/present.h>
 #include <xcb/dri3.h>
+#include <xcb/xfixes.h>
 #include <xf86drm.h>
 #include <i915_drm.h>
 
@@ -139,16 +140,21 @@ struct buffer {
 	int busy;
 };
 
-static void run(Display *dpy, Window win, const char *name, int use_dri3)
+#define FENCE 1
+#define NOCOPY 2
+static void run(Display *dpy, Window win, const char *name, unsigned options)
 {
 	xcb_connection_t *c = XGetXCBConnection(dpy);
 	struct timespec start, end;
 #define N_BACK 8
+	char test_name[128];
 	struct buffer buffer[N_BACK];
 	struct list mru;
 	Window root;
 	unsigned int width, height;
 	unsigned border, depth;
+	unsigned present_flags = XCB_PRESENT_OPTION_ASYNC;
+	xcb_xfixes_region_t update = 0;
 	int completed = 0;
 	int queued = 0;
 	uint32_t eid;
@@ -166,7 +172,7 @@ static void run(Display *dpy, Window win, const char *name, int use_dri3)
 		buffer[n].pixmap =
 			XCreatePixmap(dpy, win, width, height, depth);
 		buffer[n].fence.xid = 0;
-		if (use_dri3) {
+		if (options & FENCE) {
 			if (dri3_create_fence(dpy, win, &buffer[n].fence))
 				return;
 			/* start idle */
@@ -175,6 +181,11 @@ static void run(Display *dpy, Window win, const char *name, int use_dri3)
 		buffer[n].busy = 0;
 		list_add(&buffer[n].link, &mru);
 	}
+	if (options & NOCOPY) {
+		update = xcb_generate_id(c);
+		xcb_xfixes_create_region(c, update, 0, NULL);
+		present_flags |= XCB_PRESENT_OPTION_COPY;
+	}
 
 	eid = xcb_generate_id(c);
 	xcb_present_select_input(c, eid, win,
@@ -229,13 +240,13 @@ static void run(Display *dpy, Window win, const char *name, int use_dri3)
 			}
 			xcb_present_pixmap(c, win, b->pixmap, b - buffer,
 					   0, /* valid */
-					   0, /* update */
+					   update, /* update */
 					   0, /* x_off */
 					   0, /* y_off */
 					   None,
 					   None, /* wait fence */
 					   b->fence.xid,
-					   XCB_PRESENT_OPTION_ASYNC,
+					   present_flags,
 					   0, /* target msc */
 					   0, /* divisor */
 					   0, /* remainder */
@@ -270,6 +281,8 @@ static void run(Display *dpy, Window win, const char *name, int use_dri3)
 	}
 	clock_gettime(CLOCK_MONOTONIC, &end);
 
+	if (update)
+		xcb_xfixes_destroy_region(c, update);
 	for (n = 0; n < N_BACK; n++) {
 		if (buffer[n].fence.xid)
 			dri3_fence_free(dpy, &buffer[n].fence);
@@ -284,8 +297,14 @@ static void run(Display *dpy, Window win, const char *name, int use_dri3)
 	XSync(dpy, True);
 	xcb_unregister_for_special_event(c, Q);
 
+	test_name[0] = '\0';
+	if (options) {
+		snprintf(test_name, sizeof(test_name), "(%s%s )",
+			 options & NOCOPY ? " no-copy" : "",
+			 options & FENCE ? " fence" : "");
+	}
 	printf("%s%s: Completed %d presents in %.1fs, %.3fus each (%.1f FPS)\n",
-	       name, use_dri3 ? " (dri3)" : "",
+	       name, test_name,
 	       completed, elapsed(&start, &end) / 1000000,
 	       elapsed(&start, &end) / completed,
 	       completed / (elapsed(&start, &end) / 1000000));
@@ -352,6 +371,26 @@ static int has_dri3(Display *dpy)
 	return major >= 0;
 }
 
+static int has_xfixes(Display *dpy)
+{
+	xcb_connection_t *c = XGetXCBConnection(dpy);
+	const xcb_query_extension_reply_t *ext;
+	void *reply;
+
+	ext = xcb_get_extension_data(c, &xcb_xfixes_id);
+	if (ext == NULL || !ext->present)
+		return 0;
+
+	reply = xcb_xfixes_query_version_reply(c,
+					       xcb_xfixes_query_version(c,
+									XCB_XFIXES_MAJOR_VERSION,
+									XCB_XFIXES_MINOR_VERSION),
+					       NULL);
+	free(reply);
+
+	return reply != NULL;
+}
+
 static inline XRRScreenResources *_XRRGetScreenResourcesCurrent(Display *dpy, Window window)
 {
 	XRRScreenResources *res;
@@ -384,7 +423,7 @@ static void fullscreen(Display *dpy, Window win)
 			(unsigned char *)&atom, 1);
 }
 
-static void loop(Display *dpy, XRRScreenResources *res, int use_dri3)
+static void loop(Display *dpy, XRRScreenResources *res, unsigned options)
 {
 	Window root = DefaultRootWindow(dpy);
 	Window win;
@@ -393,7 +432,7 @@ static void loop(Display *dpy, XRRScreenResources *res, int use_dri3)
 
 	attr.override_redirect = 1;
 
-	run(dpy, root, "off", use_dri3);
+	run(dpy, root, "off", options);
 
 	for (i = 0; i < res->noutput; i++) {
 		XRROutputInfo *output;
@@ -418,7 +457,7 @@ static void loop(Display *dpy, XRRScreenResources *res, int use_dri3)
 			XRRSetCrtcConfig(dpy, res, output->crtcs[c], CurrentTime,
 					 0, 0, output->modes[0], RR_Rotate_0, &res->outputs[i], 1);
 
-			run(dpy, root, "root", use_dri3);
+			run(dpy, root, "root", options);
 
 			win = XCreateWindow(dpy, root,
 					    0, 0, mode->width, mode->height, 0,
@@ -428,7 +467,7 @@ static void loop(Display *dpy, XRRScreenResources *res, int use_dri3)
 					    CWOverrideRedirect, &attr);
 			fullscreen(dpy, win);
 			XMapWindow(dpy, win);
-			run(dpy, win, "fullscreen", use_dri3);
+			run(dpy, win, "fullscreen", options);
 			XDestroyWindow(dpy, win);
 
 			win = XCreateWindow(dpy, root,
@@ -438,7 +477,7 @@ static void loop(Display *dpy, XRRScreenResources *res, int use_dri3)
 					    DefaultVisual(dpy, DefaultScreen(dpy)),
 					    CWOverrideRedirect, &attr);
 			XMapWindow(dpy, win);
-			run(dpy, win, "windowed", use_dri3);
+			run(dpy, win, "windowed", options);
 			XDestroyWindow(dpy, win);
 
 			win = XCreateWindow(dpy, root,
@@ -448,7 +487,7 @@ static void loop(Display *dpy, XRRScreenResources *res, int use_dri3)
 					    DefaultVisual(dpy, DefaultScreen(dpy)),
 					    CWOverrideRedirect, &attr);
 			XMapWindow(dpy, win);
-			run(dpy, win, "half", use_dri3);
+			run(dpy, win, "half", options);
 			XDestroyWindow(dpy, win);
 
 			XRRSetCrtcConfig(dpy, res, output->crtcs[c], CurrentTime,
@@ -495,8 +534,10 @@ int main(void)
 				 0, 0, None, RR_Rotate_0, NULL, 0);
 
 	loop(dpy, res, 0);
+	if (has_xfixes(dpy))
+		loop(dpy, res, NOCOPY);
 	if (has_dri3(dpy))
-		loop(dpy, res, 1);
+		loop(dpy, res, FENCE);
 
 	for (i = 0; i < res->ncrtc; i++)
 		XRRSetCrtcConfig(dpy, res, res->crtcs[i], CurrentTime,
commit fd12095f8994c98c8b30bb7f22d9b06e6f124119
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Apr 5 09:26:50 2015 +0100

    test/present: Also test swaps on windows (as well as full screen flips)
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/test/present-test.c b/test/present-test.c
index 24e876c..0c6743b 100644
--- a/test/present-test.c
+++ b/test/present-test.c
@@ -222,7 +222,7 @@ static void teardown_msc(Display *dpy, void *q)
 	xcb_unregister_for_special_event(XGetXCBConnection(dpy), q);
 }
 
-static int test_whole(Display *dpy)
+static int test_whole(Display *dpy, Window win, const char *phase)
 {
 	xcb_connection_t *c = XGetXCBConnection(dpy);
 	Pixmap pixmap;
@@ -232,19 +232,19 @@ static int test_whole(Display *dpy)
 	unsigned border, depth;
 	int x, y, ret = 1;
 
-	XGetGeometry(dpy, DefaultRootWindow(dpy),
+	XGetGeometry(dpy, win,
 		     &root, &x, &y, &width, &height, &border, &depth);
 
-	if (dri3_create_fence(dpy, root, &fence))
+	if (dri3_create_fence(dpy, win, &fence))
 		return 0;
 
-	printf("Testing whole screen flip: %dx%d\n", width, height);
+	printf("%s: Testing simple flip: %dx%d\n", phase, width, height);
 	_x_error_occurred = 0;
 
 	xshmfence_reset(fence.addr);
 
-	pixmap = XCreatePixmap(dpy, root, width, height, depth);
-	xcb_present_pixmap(c, root, pixmap, 0,
+	pixmap = XCreatePixmap(dpy, win, width, height, depth);
+	xcb_present_pixmap(c, win, pixmap, 0,
 			   0, /* valid */
 			   0, /* update */
 			   0, /* x_off */
@@ -259,8 +259,8 @@ static int test_whole(Display *dpy)
 			   0, NULL);
 	XFreePixmap(dpy, pixmap);
 
-	pixmap = XCreatePixmap(dpy, root, width, height, depth);
-	xcb_present_pixmap(c, root, pixmap, 0,
+	pixmap = XCreatePixmap(dpy, win, width, height, depth);
+	xcb_present_pixmap(c, win, pixmap, 0,
 			   0, /* valid */
 			   0, /* update */
 			   0, /* x_off */
@@ -326,7 +326,7 @@ static uint64_t flush_flips(Display *dpy, Window win, Pixmap pixmap, void *Q, ui
 	return check_msc(dpy, win, Q, msc, ust);
 }
 
-static int test_double(Display *dpy, void *Q)
+static int test_double(Display *dpy, Window win, const char *phase, void *Q)
 {
 #define COUNT (15*60)
 	xcb_connection_t *c = XGetXCBConnection(dpy);
@@ -340,18 +340,18 @@ static int test_double(Display *dpy, void *Q)
 	} frame[COUNT+1];
 	int offset = 0;
 
-	XGetGeometry(dpy, DefaultRootWindow(dpy),
+	XGetGeometry(dpy, win,
 		     &root, &x, &y, &width, &height, &border, &depth);
 
-	printf("Testing whole screen flip double buffering: %dx%d\n", width, height);
+	printf("%s: Testing flip double buffering: %dx%d\n", phase, width, height);
 	_x_error_occurred = 0;
 
-	pixmap = XCreatePixmap(dpy, root, width, height, depth);
-	flush_flips(dpy, root, pixmap, Q, NULL);
+	pixmap = XCreatePixmap(dpy, win, width, height, depth);
+	flush_flips(dpy, win, pixmap, Q, NULL);
 	for (n = 0; n <= COUNT; n++) {
 		int complete;
 
-		xcb_present_pixmap(c, root, pixmap, n,
+		xcb_present_pixmap(c, win, pixmap, n,
 				   0, /* valid */
 				   0, /* update */
 				   0, /* x_off */
@@ -407,7 +407,7 @@ static int test_double(Display *dpy, void *Q)
 	return ret;
 }
 
-static int test_future(Display *dpy, void *Q)
+static int test_future(Display *dpy, Window win, const char *phase, void *Q)
 {
 	xcb_connection_t *c = XGetXCBConnection(dpy);
 	Pixmap pixmap;
@@ -422,21 +422,21 @@ static int test_future(Display *dpy, void *Q)
 	int earliest = 0, latest = 0;
 	uint64_t interval;
 
-	XGetGeometry(dpy, DefaultRootWindow(dpy),
+	XGetGeometry(dpy, win,
 		     &root, &x, &y, &width, &height, &border, &depth);
 
-	if (dri3_create_fence(dpy, root, &fence))
+	if (dri3_create_fence(dpy, win, &fence))
 		return 0;
 
-	printf("Testing whole screen flips into the future: %dx%d\n", width, height);
+	printf("%s: Testing flips into the future: %dx%d\n", phase, width, height);
 	_x_error_occurred = 0;
 
-	interval = msc_interval(dpy, root, Q);
+	interval = msc_interval(dpy, win, Q);
 
-	pixmap = XCreatePixmap(dpy, root, width, height, depth);
-	msc = flush_flips(dpy, root, pixmap, Q, &ust);
+	pixmap = XCreatePixmap(dpy, win, width, height, depth);
+	msc = flush_flips(dpy, win, pixmap, Q, &ust);
 	for (n = 1; n <= 10; n++)
-		xcb_present_pixmap(c, root, pixmap,
+		xcb_present_pixmap(c, win, pixmap,
 				   n, /* serial */
 				   0, /* valid */
 				   0, /* update */
@@ -450,7 +450,7 @@ static int test_future(Display *dpy, void *Q)
 				   0, /* divisor */
 				   0, /* remainder */
 				   0, NULL);
-	xcb_present_pixmap(c, root, pixmap,
+	xcb_present_pixmap(c, win, pixmap,
 			   0xdeadbeef, /* serial */
 			   0, /* valid */
 			   0, /* update */
@@ -523,7 +523,7 @@ static int test_future(Display *dpy, void *Q)
 	return ret;
 }
 
-static int test_exhaustion(Display *dpy, void *Q)
+static int test_exhaustion(Display *dpy, Window win, const char *phase, void *Q)
 {
 #define N_VBLANKS 256 /* kernel event queue length: 128 vblanks */
 	xcb_connection_t *c = XGetXCBConnection(dpy);
@@ -536,25 +536,25 @@ static int test_exhaustion(Display *dpy, void *Q)
 	int x, y, ret = 0, n;
 	uint64_t target, final;
 
-	XGetGeometry(dpy, DefaultRootWindow(dpy),
+	XGetGeometry(dpy, win,
 		     &root, &x, &y, &width, &height, &border, &depth);
 
-	if (dri3_create_fence(dpy, root, &fence[0]) ||
-	    dri3_create_fence(dpy, root, &fence[1]))
+	if (dri3_create_fence(dpy, win, &fence[0]) ||
+	    dri3_create_fence(dpy, win, &fence[1]))
 		return 0;
 
-	printf("Testing whole screen flips with long vblank queues: %dx%d\n", width, height);
+	printf("%s: Testing flips with long vblank queues: %dx%d\n", phase, width, height);
 	_x_error_occurred = 0;
 
 	region = xcb_generate_id(c);
 	xcb_xfixes_create_region(c, region, 0, NULL);
 
-	pixmap = XCreatePixmap(dpy, root, width, height, depth);
+	pixmap = XCreatePixmap(dpy, win, width, height, depth);
 	xshmfence_reset(fence[0].addr);
 	xshmfence_reset(fence[1].addr);
-	target = check_msc(dpy, root, Q, 0, NULL);
+	target = check_msc(dpy, win, Q, 0, NULL);
 	for (n = N_VBLANKS; n--; )
-		xcb_present_pixmap(c, root, pixmap, 0,
+		xcb_present_pixmap(c, win, pixmap, 0,
 				   0, /* valid */
 				   region, /* update */
 				   0, /* x_off */
@@ -567,7 +567,7 @@ static int test_exhaustion(Display *dpy, void *Q)
 				   1, /* divisor */
 				   0, /* remainder */
 				   0, NULL);
-	xcb_present_pixmap(c, root, pixmap, 0,
+	xcb_present_pixmap(c, win, pixmap, 0,
 			   region, /* valid */
 			   region, /* update */
 			   0, /* x_off */
@@ -581,7 +581,7 @@ static int test_exhaustion(Display *dpy, void *Q)
 			   0, /* remainder */
 			   0, NULL);
 	for (n = 1; n < N_VBLANKS; n++)
-		xcb_present_pixmap(c, root, pixmap, 0,
+		xcb_present_pixmap(c, win, pixmap, 0,
 				   region, /* valid */
 				   region, /* update */
 				   0, /* x_off */
@@ -594,7 +594,7 @@ static int test_exhaustion(Display *dpy, void *Q)
 				   0, /* divisor */
 				   0, /* remainder */
 				   0, NULL);
-	xcb_present_pixmap(c, root, pixmap, 0,
+	xcb_present_pixmap(c, win, pixmap, 0,
 			   region, /* valid */
 			   region, /* update */
 			   0, /* x_off */
@@ -610,7 +610,7 @@ static int test_exhaustion(Display *dpy, void *Q)
 	xcb_flush(c);
 
 	ret += !!xshmfence_await(fence[0].addr);
-	final = check_msc(dpy, root, Q, 0, NULL);
+	final = check_msc(dpy, win, Q, 0, NULL);
 	if (final < target) {
 		printf("\tFirst flip too early, MSC was %llu, expected %llu\n",
 		       (long long)final, (long long)target);
@@ -622,7 +622,7 @@ static int test_exhaustion(Display *dpy, void *Q)
 	}
 
 	ret += !!xshmfence_await(fence[1].addr);
-	final = check_msc(dpy, root, Q, 0, NULL);
+	final = check_msc(dpy, win, Q, 0, NULL);
 	if (final < target + N_VBLANKS) {
 		printf("\tLast flip too early, MSC was %llu, expected %llu\n",
 		       (long long)final, (long long)(target + N_VBLANKS));
@@ -633,7 +633,7 @@ static int test_exhaustion(Display *dpy, void *Q)
 		ret++;
 	}
 
-	flush_flips(dpy, root, pixmap, Q, NULL);
+	flush_flips(dpy, win, pixmap, Q, NULL);
 
 	XFreePixmap(dpy, pixmap);
 	xcb_xfixes_destroy_region(c, region);
@@ -647,7 +647,7 @@ static int test_exhaustion(Display *dpy, void *Q)
 #undef N_VBLANKS
 }
 
-static int test_accuracy(Display *dpy, void *Q)
+static int test_accuracy(Display *dpy, Window win, const char *phase, void *Q)
 {
 #define N_VBLANKS (60 * 120) /* ~2 minutes */
 	xcb_connection_t *c = XGetXCBConnection(dpy);
@@ -661,16 +661,16 @@ static int test_accuracy(Display *dpy, void *Q)
 	int earliest = 0, latest = 0;
 	int complete;
 
-	XGetGeometry(dpy, DefaultRootWindow(dpy),
+	XGetGeometry(dpy, win,
 		     &root, &x, &y, &width, &height, &border, &depth);
 
-	printf("Testing whole screen flip accuracy: %dx%d\n", width, height);
+	printf("%s: Testing flip accuracy: %dx%d\n", phase, width, height);
 	_x_error_occurred = 0;
 
-	pixmap = XCreatePixmap(dpy, root, width, height, depth);
-	target = flush_flips(dpy, root, pixmap, Q, NULL);
+	pixmap = XCreatePixmap(dpy, win, width, height, depth);
+	target = flush_flips(dpy, win, pixmap, Q, NULL);
 	for (n = 0; n <= N_VBLANKS; n++)
-		xcb_present_pixmap(c, root, pixmap,
+		xcb_present_pixmap(c, win, pixmap,
 				   n, /* serial */
 				   0, /* valid */
 				   0, /* update */
@@ -684,7 +684,7 @@ static int test_accuracy(Display *dpy, void *Q)
 				   0, /* divisor */
 				   0, /* remainder */
 				   0, NULL);
-	xcb_present_pixmap(c, root, pixmap,
+	xcb_present_pixmap(c, win, pixmap,
 			   0xdeadbeef, /* serial */
 			   0, /* valid */
 			   0, /* update */
@@ -748,7 +748,7 @@ static int test_accuracy(Display *dpy, void *Q)
 #undef N_VBLANKS
 }
 
-static int test_modulus(Display *dpy, void *Q)
+static int test_modulus(Display *dpy, Window win, const char *phase, void *Q)
 {
 	xcb_connection_t *c = XGetXCBConnection(dpy);
 	Pixmap pixmap;
@@ -762,20 +762,20 @@ static int test_modulus(Display *dpy, void *Q)
 	int earliest = 0, latest = 0;
 	int complete;
 
-	XGetGeometry(dpy, DefaultRootWindow(dpy),
+	XGetGeometry(dpy, win,
 		     &root, &x, &y, &width, &height, &border, &depth);
 
-	printf("Testing whole screen flip modulus: %dx%d\n", width, height);
+	printf("%s: Testing flip modulus: %dx%d\n", phase, width, height);
 	_x_error_occurred = 0;
 
 	region = xcb_generate_id(c);
 	xcb_xfixes_create_region(c, region, 0, NULL);
 
-	pixmap = XCreatePixmap(dpy, root, width, height, depth);
-	target = flush_flips(dpy, root, pixmap, Q, NULL);
+	pixmap = XCreatePixmap(dpy, win, width, height, depth);
+	target = flush_flips(dpy, win, pixmap, Q, NULL);
 	for (x = 1; x <= 7; x++) {
 		for (y = 0; y < x; y++) {
-			xcb_present_pixmap(c, root, pixmap,
+			xcb_present_pixmap(c, win, pixmap,
 					   y << 16 | x, /* serial */
 					   region, /* valid */
 					   region, /* update */
@@ -791,7 +791,7 @@ static int test_modulus(Display *dpy, void *Q)
 					   0, NULL);
 		}
 	}
-	xcb_present_pixmap(c, root, pixmap,
+	xcb_present_pixmap(c, win, pixmap,
 			   0xdeadbeef, /* serial */
 			   0, /* valid */
 			   0, /* update */
@@ -1813,23 +1813,75 @@ int main(void)
 	error += test_exhaustion_msc(dpy, queue);
 	last_msc = check_msc(dpy, root, queue, last_msc, NULL);
 
-	error += test_whole(dpy);
-	last_msc = check_msc(dpy, root, queue, last_msc, NULL);
+	for (dummy = 0; dummy < 3; dummy++) {
+		Window win;
+		uint64_t msc = 0;
+		XSetWindowAttributes attr;
+		Visual *visual = DefaultVisual(dpy, DefaultScreen(dpy));
+		unsigned int width, height;
+		unsigned border, depth;
+		const char *phase;
+		int x, y;
+		void *Q;
+
+		attr.override_redirect = 1;
+
+		XGetGeometry(dpy, root, &win, &x, &y,
+			     &width, &height, &border, &depth);
+
+		switch (dummy) {
+		case 0:
+			win = root;
+			phase = "root";
+			break;
+		case 1:
+			win = XCreateWindow(dpy, root,
+					    0, 0, width, height, 0, depth,
+					    InputOutput, visual,
+					    CWOverrideRedirect, &attr);
+			phase = "fullscreen";
+			break;
+		case 2:
+			win = XCreateWindow(dpy, root,
+					    0, 0, width/2, height/2, 0, depth,
+					    InputOutput, visual,
+					    CWOverrideRedirect, &attr);
+			phase = "window";
+			break;
+		default:
+			phase = "broken";
+			win = root;
+			abort();
+			break;
+		}
 
-	error += test_double(dpy, queue);
-	last_msc = check_msc(dpy, root, queue, last_msc, NULL);
+		XMapWindow(dpy, win);
 
-	error += test_future(dpy, queue);
-	last_msc = check_msc(dpy, root, queue, last_msc, NULL);
+		Q = setup_msc(dpy, win);
+		msc = check_msc(dpy, win, Q, msc, NULL);
 
-	error += test_accuracy(dpy, queue);
-	last_msc = check_msc(dpy, root, queue, last_msc, NULL);
+		error += test_whole(dpy, win, phase);
+		msc = check_msc(dpy, win, Q, msc, NULL);
 
-	error += test_modulus(dpy, queue);
-	last_msc = check_msc(dpy, root, queue, last_msc, NULL);
+		error += test_double(dpy, win, phase, Q);
+		msc = check_msc(dpy, win, Q, msc, NULL);
 
-	error += test_exhaustion(dpy, queue);
-	last_msc = check_msc(dpy, root, queue, last_msc, NULL);
+		error += test_future(dpy, win, phase, Q);
+		msc = check_msc(dpy, win, Q, msc, NULL);
+
+		error += test_accuracy(dpy, win, phase, Q);
+		msc = check_msc(dpy, win, Q, msc, NULL);
+
+		error += test_modulus(dpy, win, phase, Q);
+		msc = check_msc(dpy, win, Q, msc, NULL);
+
+		error += test_exhaustion(dpy, win, phase, Q);
+		msc = check_msc(dpy, win, Q, msc, NULL);
+
+		teardown_msc(dpy, Q);
+		if (win != root)
+			XDestroyWindow(dpy, win);
+	}
 
 	error += test_crtc(dpy, queue, last_msc);
 	last_msc = check_msc(dpy, root, queue, last_msc, NULL);
commit 7cf670228eec058a97f6450df46a1a47cb080583
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Apr 4 20:58:24 2015 +0100

    sna/dri2: Prevent the sw cursor from copyig to a buffer as we discard it
    
    During swapbuffers, the sw cursor tries to write to the old buffer.
    Ordinary this is not an issue as we are discarding it, but under
    TearFree that write causes us to instantiate the shadow buffer with a
    possible recursion into set_bo and mayhem.
    
    v2:
    
    commit 226a58bc592d4ed305b7ad0e460f1ee2548e0ddf
    Author: Chris Wilson <chris at chris-wilson.co.uk>
    Date:   Sat Apr 4 20:58:24 2015 +0100
    
        sna/dri2: Prevent the sw cursor from copyig to a buffer as we discard it
    
    Tried to fix it by disabling SourceValidate. However, it a direct hook
    into the Damage code by miSprite that triggers the copy. Since there
    appears to be no way to intervene, we just mark that copy as internal
    and ignore it.
    
    Reported-by: Chris Bainbridge <chris.bainbridge at gmail.com>
    References: https://bugs.freedesktop.org/show_bug.cgi?id=89903
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna.h b/src/sna/sna.h
index a498484..5153399 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -265,6 +265,8 @@ struct sna {
 #define AVX 0x80
 #define AVX2 0x100
 
+	bool ignore_copy_area : 1;
+
 	unsigned watch_flush;
 
 	struct timeval timer_tv;
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 2626988..f76447b 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -7207,6 +7207,9 @@ sna_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc,
 	if (gc->planemask == 0)
 		return NULL;
 
+	if (sna->ignore_copy_area)
+		return NULL;
+
 	DBG(("%s: src=(%d, %d)x(%d, %d)+(%d, %d) -> dst=(%d, %d)+(%d, %d); alu=%d, pm=%lx, depth=%d\n",
 	     __FUNCTION__,
 	     src_x, src_y, width, height, src->x, src->y,
diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c
index 2b7187d..43d4701 100644
--- a/src/sna/sna_dri2.c
+++ b/src/sna/sna_dri2.c
@@ -807,8 +807,8 @@ static void set_bo(PixmapPtr pixmap, struct kgem_bo *bo)
 	struct sna *sna = to_sna_from_pixmap(pixmap);
 	struct sna_pixmap *priv = sna_pixmap(pixmap);
 
-	DBG(("%s: pixmap=%ld, handle=%d\n",
-	     __FUNCTION__, pixmap->drawable.serialNumber, bo->handle));
+	DBG(("%s: pixmap=%ld, handle=%d (old handle=%d)\n",
+	     __FUNCTION__, pixmap->drawable.serialNumber, bo->handle, priv->gpu_bo->handle));
 
 	assert(pixmap->drawable.width * pixmap->drawable.bitsPerPixel <= 8*bo->pitch);
 	assert(pixmap->drawable.height * bo->pitch <= kgem_bo_size(bo));
@@ -818,8 +818,6 @@ static void set_bo(PixmapPtr pixmap, struct kgem_bo *bo)
 	assert(priv->flush);
 
 	if (APPLY_DAMAGE) {
-		ScreenPtr screen = pixmap->drawable.pScreen;
-		SourceValidateProcPtr SourceValidate;
 		RegionRec region;
 
 		/* Post damage on the new front buffer so that listeners, such
@@ -832,17 +830,12 @@ static void set_bo(PixmapPtr pixmap, struct kgem_bo *bo)
 		region.data = NULL;
 
 		/*
-		 * SourceValidate is used by the software cursor code
-		 * to copy the original contents back before the drawing
-		 * operation causing us to instantiate the shadow buffer
-		 * just as we are in the process of swapping it away.
+		 * Eeek, beware the sw cursor copying to the old bo
+		 * causing recursion and mayhem.
 		 */
-		SourceValidate = screen->SourceValidate;
-		screen->SourceValidate = NULL;
-
+		DBG(("%s: marking whole pixmap as damaged\n", __FUNCTION__));
+		sna->ignore_copy_area = true;
 		DamageRegionAppend(&pixmap->drawable, &region);
-
-		screen->SourceValidate = SourceValidate;
 	}
 
 	damage(pixmap, priv, NULL);
@@ -871,8 +864,10 @@ static void set_bo(PixmapPtr pixmap, struct kgem_bo *bo)
 		bo->domain = DOMAIN_NONE;
 	assert(bo->flush);
 
-	if (APPLY_DAMAGE)
+	if (APPLY_DAMAGE) {
 		DamageRegionProcessPending(&pixmap->drawable);
+		sna->ignore_copy_area = false;
+	}
 }
 
 static void sna_dri2_select_mode(struct sna *sna, struct kgem_bo *dst, struct kgem_bo *src, bool sync)
@@ -1163,8 +1158,11 @@ __sna_dri2_copy_region(struct sna *sna, DrawablePtr draw, RegionPtr region,
 		boxes = &clip.extents;
 		n = 1;
 	}
-	if (APPLY_DAMAGE || flags & DRI2_DAMAGE)
+	if (APPLY_DAMAGE || flags & DRI2_DAMAGE) {
+		DBG(("%s: marking region as damaged\n", __FUNCTION__));
+		sna->ignore_copy_area = true;
 		DamageRegionAppend(&pixmap->drawable, region);
+	}
 
 	DBG(("%s: copying [(%d, %d), (%d, %d)]x%d src=(%d, %d), dst=(%d, %d)\n",
 	     __FUNCTION__,
@@ -1194,8 +1192,10 @@ __sna_dri2_copy_region(struct sna *sna, DrawablePtr draw, RegionPtr region,
 		}
 	}
 
-	if (APPLY_DAMAGE || flags & DRI2_DAMAGE)
+	if (APPLY_DAMAGE || flags & DRI2_DAMAGE) {
 		DamageRegionProcessPending(&pixmap->drawable);
+		sna->ignore_copy_area = false;
+	}
 
 	if (clip.data)
 		pixman_region_fini(&clip);
@@ -2045,11 +2045,16 @@ static void sna_dri2_xchg_crtc(struct sna *sna, DrawablePtr draw, xf86CrtcPtr cr
 	     get_window_pixmap(win)->drawable.width,
 	     get_window_pixmap(win)->drawable.height));
 
-	if (APPLY_DAMAGE)
+	if (APPLY_DAMAGE) {
+		DBG(("%s: marking drawable as damaged\n", __FUNCTION__));
+		sna->ignore_copy_area = true;
 		DamageRegionAppend(&win->drawable, &win->clipList);
+	}
 	sna_shadow_set_crtc(sna, crtc, get_private(back)->bo);
-	if (APPLY_DAMAGE)
+	if (APPLY_DAMAGE) {
 		DamageRegionProcessPending(&win->drawable);
+		sna->ignore_copy_area = false;
+	}
 
 	assert(dri2_window(win)->front == NULL);
 


More information about the xorg-commit mailing list