xf86-video-intel: 6 commits - src/sna/sna_display.c src/sna/sna_dri2.c test/dri2-race.c test/present-test.c

Chris Wilson ickle at kemper.freedesktop.org
Wed Feb 11 05:41:42 PST 2015


 src/sna/sna_display.c |   55 ++++++++++++++++----
 src/sna/sna_dri2.c    |  125 +++++++++++++++++++++++++----------------------
 test/dri2-race.c      |  132 ++++++++++++++++++++++++++++++++++++++++++++++----
 test/present-test.c   |    2 
 4 files changed, 233 insertions(+), 81 deletions(-)

New commits:
commit 6b6ab5407219ba29bae19386067a9eefe355ad03
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Feb 11 12:32:53 2015 +0000

    sna/dri2: Refactor immediate swap scheduling
    
    Allow a request to swap on the next frame to be considered by the
    immediate handling code by refactoring the target msc computation.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c
index 9213a5b..840459e 100644
--- a/src/sna/sna_dri2.c
+++ b/src/sna/sna_dri2.c
@@ -2573,12 +2573,18 @@ static int use_triple_buffer(struct sna *sna, ClientPtr client, bool async)
 }
 
 static bool immediate_swap(struct sna *sna,
-			   uint64_t target_msc,
-			   uint64_t divisor,
 			   DrawablePtr draw,
 			   xf86CrtcPtr crtc,
+			   uint64_t *target_msc,
+			   uint64_t divisor,
+			   uint64_t remainder,
 			   uint64_t *current_msc)
 {
+	/*
+	 * If divisor is zero, or current_msc is smaller than target_msc
+	 * we just need to make sure target_msc passes before initiating
+	 * the swap.
+	 */
 	if (divisor == 0) {
 		*current_msc = -1;
 
@@ -2587,39 +2593,47 @@ static bool immediate_swap(struct sna *sna,
 			return true;
 		}
 
-		if (target_msc)
+		if (*target_msc)
 			*current_msc = get_current_msc(sna, draw, crtc);
 
 		DBG(("%s: current_msc=%ld, target_msc=%ld -- %s\n",
 		     __FUNCTION__, (long)*current_msc, (long)target_msc,
-		     (*current_msc >= target_msc - 1) ? "yes" : "no"));
-		return *current_msc >= target_msc - 1;
+		     (*current_msc >= *target_msc - 1) ? "yes" : "no"));
+		return *current_msc >= *target_msc - 1;
 	}
 
 	DBG(("%s: explicit waits requests, divisor=%ld\n",
 	     __FUNCTION__, (long)divisor));
 	*current_msc = get_current_msc(sna, draw, crtc);
-	if (sna->mode.flip_active) {
-		DBG(("%s: %d flips still active, bumping current_msc\n",
-		     __FUNCTION__, sna->mode.flip_active));
-		*current_msc += 1;
+	if (*current_msc >= *target_msc) {
+		DBG(("%s: missed target, queueing event for next: current=%lld, target=%lld, divisor=%lld, remainder=%lld\n",
+		     __FUNCTION__,
+		     (long long)*current_msc,
+		     (long long)*target_msc,
+		     (long long)divisor,
+		     (long long)remainder));
+
+		*target_msc = *current_msc + remainder - *current_msc % divisor;
+		if (*target_msc <= *current_msc)
+			*target_msc += divisor;
 	}
-	DBG(("%s: target_msc=%lld, current_msc=%lld\n",
-	     __FUNCTION__, (long long)target_msc, (long long)*current_msc));
-	return false;
+
+	DBG(("%s: target_msc=%lld, current_msc=%lld, immediate?=%d\n",
+	     __FUNCTION__, (long long)*target_msc, (long long)*current_msc,
+	     *current_msc >= *target_msc - 1));
+	return *current_msc >= *target_msc - 1;
 }
 
 static bool
 sna_dri2_schedule_flip(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
 		       DRI2BufferPtr front, DRI2BufferPtr back,
-		       CARD64 *target_msc, CARD64 divisor, CARD64 remainder,
+		       bool immediate, CARD64 *target_msc, CARD64 current_msc,
 		       DRI2SwapEventPtr func, void *data)
 {
 	struct sna *sna = to_sna_from_drawable(draw);
 	struct sna_dri2_event *info;
-	uint64_t current_msc;
 
-	if (immediate_swap(sna, *target_msc, divisor, draw, crtc, &current_msc)) {
+	if (immediate) {
 		info = sna->dri2.flip_pending;
 		DBG(("%s: performing immediate swap on pipe %d, pending? %d, mode: %d, continuation? %d\n",
 		     __FUNCTION__, sna_crtc_to_pipe(crtc),
@@ -2716,24 +2730,6 @@ queue:
 	info->front = sna_dri2_reference_buffer(front);
 	info->back = sna_dri2_reference_buffer(back);
 
-	/*
-	 * If divisor is zero, or current_msc is smaller than target_msc
-	 * we just need to make sure target_msc passes before initiating
-	 * the swap.
-	 */
-	if (divisor && current_msc >= *target_msc) {
-		DBG(("%s: missed target, queueing event for next: current=%lld, target=%lld, divisor=%lld, remainder=%lld\n",
-		     __FUNCTION__,
-		     (long long)current_msc,
-		     (long long)*target_msc,
-		     (long long)divisor,
-		     (long long)remainder));
-
-		*target_msc = current_msc + remainder - current_msc % divisor;
-		if (*target_msc <= current_msc)
-			*target_msc += divisor;
-	}
-
 	if (*target_msc <= current_msc + 1 && sna_dri2_flip(info)) {
 		*target_msc = current_msc + 1;
 	} else {
@@ -2764,14 +2760,13 @@ queue:
 static bool
 sna_dri2_schedule_xchg(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
 		       DRI2BufferPtr front, DRI2BufferPtr back,
-		       CARD64 *target_msc, CARD64 divisor, CARD64 remainder,
+		       bool immediate, CARD64 *target_msc, CARD64 current_msc,
 		       DRI2SwapEventPtr func, void *data)
 {
 	struct sna *sna = to_sna_from_drawable(draw);
-	uint64_t current_msc;
 	bool sync, event;
 
-	if (!immediate_swap(sna, *target_msc, divisor, draw, crtc, &current_msc))
+	if (!immediate)
 		return false;
 
 	sync = current_msc < *target_msc && xorg_can_triple_buffer();
@@ -2827,14 +2822,13 @@ complete:
 static bool
 sna_dri2_schedule_xchg_crtc(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
 			    DRI2BufferPtr front, DRI2BufferPtr back,
-			    CARD64 *target_msc, CARD64 divisor, CARD64 remainder,
+			    bool immediate, CARD64 *target_msc, CARD64 current_msc,
 			    DRI2SwapEventPtr func, void *data)
 {
 	struct sna *sna = to_sna_from_drawable(draw);
-	uint64_t current_msc;
 	bool sync, event;
 
-	if (!immediate_swap(sna, *target_msc, divisor, draw, crtc, &current_msc))
+	if (!immediate)
 		return false;
 
 	sync = current_msc < *target_msc && xorg_can_triple_buffer();
@@ -2926,6 +2920,7 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 	struct sna_dri2_event *info = NULL;
 	int type = DRI2_EXCHANGE_COMPLETE;
 	CARD64 current_msc;
+	bool immediate;
 
 	DBG(("%s: draw=%lu %dx%d, pixmap=%ld %dx%d, back=%u (refs=%d/%d, flush=%d) , front=%u (refs=%d/%d, flush=%d)\n",
 	     __FUNCTION__,
@@ -3005,21 +3000,25 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 		sna_mode_wakeup(sna);
 	}
 
+	immediate = immediate_swap(sna, draw, crtc,
+				   target_msc, divisor, remainder,
+				   &current_msc);
+
 	if (can_xchg(sna, draw, front, back) &&
 	    sna_dri2_schedule_xchg(client, draw, crtc, front, back,
-				   target_msc, divisor, remainder,
+				   immediate, target_msc, current_msc,
 				   func, data))
 		return TRUE;
 
 	if (can_xchg_crtc(sna, draw, front, back, crtc) &&
 	    sna_dri2_schedule_xchg_crtc(client, draw, crtc, front, back,
-					target_msc, divisor, remainder,
+					immediate, target_msc, current_msc,
 					func, data))
 		return TRUE;
 
 	if (can_flip(sna, draw, front, back, crtc) &&
 	    sna_dri2_schedule_flip(client, draw, crtc, front, back,
-				  target_msc, divisor, remainder,
+				  immediate, target_msc, current_msc,
 				  func, data))
 		return TRUE;
 
@@ -3036,7 +3035,7 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 	info->front = sna_dri2_reference_buffer(front);
 	info->back = sna_dri2_reference_buffer(back);
 
-	if (immediate_swap(sna, *target_msc, divisor, draw, crtc, &current_msc)) {
+	if (immediate) {
 		bool sync = current_msc < *target_msc;
 		if (!sna_dri2_immediate_blit(sna, info, sync, true))
 			sna_dri2_event_free(info);
@@ -3049,25 +3048,8 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 		DRM_VBLANK_EVENT;
 	vbl.request.signal = (uintptr_t)info;
 
-	/*
-	 * If divisor is zero, or current_msc is smaller than target_msc
-	 * we just need to make sure target_msc passes before initiating
-	 * the swap.
-	 */
 	info->type = SWAP;
 	info->queued = true;
-	if (divisor && current_msc >= *target_msc) {
-		DBG(("%s: missed target, queueing event for next: current=%lld, target=%lld, divisor=%lld, remainder=%lld\n",
-		     __FUNCTION__,
-		     (long long)current_msc,
-		     (long long)*target_msc,
-		     (long long)divisor,
-		     (long long)remainder));
-
-		*target_msc = current_msc + remainder - current_msc % divisor;
-		if (*target_msc <= current_msc)
-			*target_msc += divisor;
-	}
 	vbl.request.sequence = draw_target_seq(draw, *target_msc - 1);
 	if (*target_msc <= current_msc + 1) {
 		DBG(("%s: performing blit before queueing\n", __FUNCTION__));
commit 7e1671b15e8e480457a31036e105f3691c0964d6
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Feb 11 11:26:35 2015 +0000

    sna/dri2: Queue a flip via a vblank event if we have outstanding flips
    
    If we swap between Clients, or even Windows, then we may have a flip
    still pending completion in hardware but no longer tracked in order to
    release the freed state. In this scenario, queue the flip via a vblank
    event.
    
    Testcase: dri2-race with non-immediate flips
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c
index f4e2ced..9213a5b 100644
--- a/src/sna/sna_dri2.c
+++ b/src/sna/sna_dri2.c
@@ -1542,6 +1542,12 @@ sna_dri2_flip(struct sna_dri2_event *info)
 	assert(get_drawable_pixmap(info->draw)->drawable.height * bo->pitch <= kgem_bo_size(bo));
 	assert(bo->refcnt);
 
+	if (info->sna->mode.flip_active) {
+		DBG(("%s: %d flips still active, aborting\n",
+		     __FUNCTION__, info->sna->mode.flip_active));
+		return false;
+	}
+
 	if (!sna_page_flip(info->sna, bo, sna_dri2_flip_handler,
 			   info->type == FLIP_ASYNC ? NULL : info))
 		return false;
@@ -2365,6 +2371,9 @@ sna_dri2_flip_continue(struct sna_dri2_event *info)
 
 	info->type = info->flip_continue;
 
+	if (info->sna->mode.front_active == 0)
+		return false;
+
 	if (bo != sna_pixmap(info->sna->front)->gpu_bo)
 		return false;
 
@@ -2388,6 +2397,9 @@ sna_dri2_flip_keepalive(struct sna_dri2_event *info)
 	if (!--info->keepalive)
 		return false;
 
+	if (info->draw == NULL)
+		return false;
+
 	info->flip_continue = FLIP_COMPLETE;
 	return sna_dri2_flip_continue(info);
 }
@@ -2587,6 +2599,13 @@ static bool immediate_swap(struct sna *sna,
 	DBG(("%s: explicit waits requests, divisor=%ld\n",
 	     __FUNCTION__, (long)divisor));
 	*current_msc = get_current_msc(sna, draw, crtc);
+	if (sna->mode.flip_active) {
+		DBG(("%s: %d flips still active, bumping current_msc\n",
+		     __FUNCTION__, sna->mode.flip_active));
+		*current_msc += 1;
+	}
+	DBG(("%s: target_msc=%lld, current_msc=%lld\n",
+	     __FUNCTION__, (long long)target_msc, (long long)*current_msc));
 	return false;
 }
 
@@ -2650,6 +2669,10 @@ sna_dri2_schedule_flip(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
 			sna->dri2.flip_pending = info;
 			assert(!info->queued);
 			current_msc++;
+		} else if (sna->mode.flip_active) {
+			DBG(("%s: %d outstanding flips from old client, queueing\n",
+			     __FUNCTION__, sna->mode.flip_active));
+			goto queue;
 		} else {
 			info->type = use_triple_buffer(sna, client, *target_msc == 0);
 			if (!sna_dri2_flip(info)) {
@@ -2675,6 +2698,12 @@ out:
 		return true;
 	}
 
+queue:
+	if (KEEPALIVE > 1 && sna->dri2.flip_pending) {
+		info = sna->dri2.flip_pending;
+		info->keepalive = 1;
+	}
+
 	info = sna_dri2_add_event(sna, draw, client);
 	if (info == NULL)
 		return false;
@@ -2705,11 +2734,7 @@ out:
 			*target_msc += divisor;
 	}
 
-	if (*target_msc <= current_msc + 1) {
-		if (!sna_dri2_flip(info)) {
-			sna_dri2_event_free(info);
-			return false;
-		}
+	if (*target_msc <= current_msc + 1 && sna_dri2_flip(info)) {
 		*target_msc = current_msc + 1;
 	} else {
 		union drm_wait_vblank vbl;
commit 8b8b1021f45ea7e47c1825f88b50bda98a28d47c
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Feb 11 11:14:33 2015 +0000

    test/dri2-race: Mix immediate flips with delayed flips
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/test/dri2-race.c b/test/dri2-race.c
index 0c500f8..c589f2b 100644
--- a/test/dri2-race.c
+++ b/test/dri2-race.c
@@ -55,14 +55,14 @@ static int dri2_open(Display *dpy)
 	return fd;
 }
 
-static void swap_buffers(Display *dpy, Window win,
+static void swap_buffers(Display *dpy, Window win, int divisor,
 			 unsigned int *attachments, int nattachments)
 {
 	xcb_connection_t *c = XGetXCBConnection(dpy);
 	unsigned int seq[2];
 
 	seq[0] = xcb_dri2_swap_buffers_unchecked(c, win,
-						 0, 0, 0, 0, 0, 0).sequence;
+						 0, 0, 0, divisor, 0, 0).sequence;
 
 
 	seq[1] = xcb_dri2_get_buffers_unchecked(c, win,
@@ -133,7 +133,57 @@ static void race_window(Display *dpy, int width, int height,
 
 		free(buffers);
 		for (count = 0; count < loop; count++)
-			swap_buffers(dpy, win, attachments, nattachments);
+			DRI2SwapBuffers(dpy, win, 0, 1, 0);
+		XDestroyWindow(dpy, win);
+		printf("."); fflush(stdout);
+	} while (--loop);
+	printf("*\n");
+
+	loop = 100;
+	do {
+		win = XCreateWindow(dpy, DefaultRootWindow(dpy),
+				    0, 0, width, height, 0,
+				    DefaultDepth(dpy, DefaultScreen(dpy)),
+				    InputOutput,
+				    DefaultVisual(dpy, DefaultScreen(dpy)),
+				    CWOverrideRedirect, &attr);
+		XMapWindow(dpy, win);
+
+		DRI2CreateDrawable(dpy, win);
+
+		buffers = DRI2GetBuffers(dpy, win, &width, &height,
+					 attachments, nattachments, &count);
+		if (count != nattachments)
+			return;
+
+		free(buffers);
+		for (count = 0; count < loop; count++)
+			swap_buffers(dpy, win, 0, attachments, nattachments);
+		XDestroyWindow(dpy, win);
+		printf("."); fflush(stdout);
+	} while (--loop);
+	printf("*\n");
+
+	loop = 100;
+	do {
+		win = XCreateWindow(dpy, DefaultRootWindow(dpy),
+				    0, 0, width, height, 0,
+				    DefaultDepth(dpy, DefaultScreen(dpy)),
+				    InputOutput,
+				    DefaultVisual(dpy, DefaultScreen(dpy)),
+				    CWOverrideRedirect, &attr);
+		XMapWindow(dpy, win);
+
+		DRI2CreateDrawable(dpy, win);
+
+		buffers = DRI2GetBuffers(dpy, win, &width, &height,
+					 attachments, nattachments, &count);
+		if (count != nattachments)
+			return;
+
+		free(buffers);
+		for (count = 0; count < loop; count++)
+			swap_buffers(dpy, win, 1, attachments, nattachments);
 		XDestroyWindow(dpy, win);
 		printf("."); fflush(stdout);
 	} while (--loop);
@@ -228,7 +278,32 @@ static void race_client(int width, int height,
 			return;
 
 		for (count = 0; count < loop; count++)
-			swap_buffers(dpy, win, attachments, nattachments);
+			swap_buffers(dpy, win, 0, attachments, nattachments);
+		XCloseDisplay(dpy);
+		printf("."); fflush(stdout);
+	} while (--loop);
+	printf("*\n");
+
+	loop = 100;
+	do {
+		Display *dpy = XOpenDisplay(NULL);
+		Window win = XCreateWindow(dpy, DefaultRootWindow(dpy),
+					   0, 0, width, height, 0,
+					   DefaultDepth(dpy, DefaultScreen(dpy)),
+					   InputOutput,
+					   DefaultVisual(dpy, DefaultScreen(dpy)),
+					   CWOverrideRedirect, &attr);
+
+		XMapWindow(dpy, win);
+
+		DRI2CreateDrawable(dpy, win);
+		free(DRI2GetBuffers(dpy, win, &width, &height,
+				    attachments, nattachments, &count));
+		if (count != nattachments)
+			return;
+
+		for (count = 0; count < loop; count++)
+			swap_buffers(dpy, win, 1, attachments, nattachments);
 		XCloseDisplay(dpy);
 		printf("."); fflush(stdout);
 	} while (--loop);
commit fc010846b13dcb757f030c06f25415c200f61f71
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Feb 11 11:05:12 2015 +0000

    test/dri2-race: Actually queue a number of future WaitMSC
    
    In order to have outstanding WaitMSC when the Client quits or the Window
    is destroyed, we need to use the xcb version so as not to immediately
    block on the play.
    
    And also print keepalive dots to console as test progresses.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/test/dri2-race.c b/test/dri2-race.c
index 5235317..0c500f8 100644
--- a/test/dri2-race.c
+++ b/test/dri2-race.c
@@ -21,6 +21,16 @@
 
 #define COUNT 60
 
+static uint32_t upper_32_bits(uint64_t val)
+{
+	return val >> 32;
+}
+
+static uint32_t lower_32_bits(uint64_t val)
+{
+	return val & 0xffffffff;
+}
+
 static int dri2_open(Display *dpy)
 {
 	drm_auth_t auth;
@@ -73,6 +83,8 @@ static void race_window(Display *dpy, int width, int height,
 	int count, loop;
 	DRI2Buffer *buffers;
 
+	printf("%s(%s)\n", __func__, name);
+
 	/* Be nasty and install a fullscreen window on top so that we
 	 * can guarantee we do not get clipped by children.
 	 */
@@ -98,7 +110,9 @@ static void race_window(Display *dpy, int width, int height,
 		for (count = 0; count < loop; count++)
 			DRI2SwapBuffers(dpy, win, 0, 0, 0);
 		XDestroyWindow(dpy, win);
+		printf("."); fflush(stdout);
 	} while (--loop);
+	printf("*\n");
 
 	loop = 100;
 	do {
@@ -121,11 +135,14 @@ static void race_window(Display *dpy, int width, int height,
 		for (count = 0; count < loop; count++)
 			swap_buffers(dpy, win, attachments, nattachments);
 		XDestroyWindow(dpy, win);
+		printf("."); fflush(stdout);
 	} while (--loop);
+	printf("*\n");
 
 	loop = 100;
 	do {
-		uint64_t ignore;
+		uint64_t ignore, msc;
+		xcb_connection_t *c = XGetXCBConnection(dpy);
 
 		win = XCreateWindow(dpy, DefaultRootWindow(dpy),
 				    0, 0, width, height, 0,
@@ -136,12 +153,18 @@ static void race_window(Display *dpy, int width, int height,
 		XMapWindow(dpy, win);
 
 		DRI2CreateDrawable(dpy, win);
-
+		DRI2GetMSC(dpy, win, &ignore, &msc, &ignore);
 		for (count = 0; count < loop; count++)
-			DRI2WaitMSC(dpy, win, 0, 1, 0,
-				    &ignore, &ignore, &ignore);
+			xcb_discard_reply(c,
+					  xcb_dri2_wait_msc(c, win,
+							    upper_32_bits(msc + count + 1),
+							    lower_32_bits(msc + count + 1),
+							    0, 1, 0, 0).sequence);
+		XFlush(dpy);
 		XDestroyWindow(dpy, win);
+		printf("."); fflush(stdout);
 	} while (--loop);
+	printf("*\n");
 
 	XSync(dpy, 1);
 	sleep(2);
@@ -155,6 +178,8 @@ static void race_client(int width, int height,
 	XSetWindowAttributes attr;
 	int count, loop;
 
+	printf("%s(%s)\n", __func__, name);
+
 	/* Be nasty and install a fullscreen window on top so that we
 	 * can guarantee we do not get clipped by children.
 	 */
@@ -180,7 +205,9 @@ static void race_client(int width, int height,
 		for (count = 0; count < loop; count++)
 			DRI2SwapBuffers(dpy, win, 0, 0, 0);
 		XCloseDisplay(dpy);
+		printf("."); fflush(stdout);
 	} while (--loop);
+	printf("*\n");
 
 	loop = 100;
 	do {
@@ -203,12 +230,15 @@ static void race_client(int width, int height,
 		for (count = 0; count < loop; count++)
 			swap_buffers(dpy, win, attachments, nattachments);
 		XCloseDisplay(dpy);
+		printf("."); fflush(stdout);
 	} while (--loop);
+	printf("*\n");
 
 	loop = 100;
 	do {
-		uint64_t ignore;
+		uint64_t ignore, msc;
 		Display *dpy = XOpenDisplay(NULL);
+		xcb_connection_t *c = XGetXCBConnection(dpy);
 		Window win = XCreateWindow(dpy, DefaultRootWindow(dpy),
 					   0, 0, width, height, 0,
 					   DefaultDepth(dpy, DefaultScreen(dpy)),
@@ -219,11 +249,18 @@ static void race_client(int width, int height,
 		XMapWindow(dpy, win);
 
 		DRI2CreateDrawable(dpy, win);
+		DRI2GetMSC(dpy, win, &ignore, &msc, &ignore);
 		for (count = 0; count < loop; count++)
-			DRI2WaitMSC(dpy, win, 0, 1, 0,
-				    &ignore, &ignore, &ignore);
+			xcb_discard_reply(c,
+					  xcb_dri2_wait_msc(c, win,
+							    upper_32_bits(msc + count + 1),
+							    lower_32_bits(msc + count + 1),
+							    0, 1, 0, 0).sequence);
+		XFlush(dpy);
 		XCloseDisplay(dpy);
+		printf("."); fflush(stdout);
 	} while (--loop);
+	printf("*\n");
 }
 
 int main(void)
commit 4f5d7825dfc57a5f892f3f903cbfa36abf3c13ca
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Feb 11 10:34:47 2015 +0000

    test/present: Return the correct error counter from for_each_crtc
    
    When the xserver is fixed and we no longer block for ever inside the
    test, we can see that the test itself falsely reports failure!
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/test/present-test.c b/test/present-test.c
index e90ef47..6f6d6a8 100644
--- a/test/present-test.c
+++ b/test/present-test.c
@@ -434,7 +434,7 @@ static int for_each_crtc(Display *dpy,
 	free(original_crtc);
 	XRRFreeScreenResources(res);
 
-	return j;
+	return err;
 }
 
 struct test_crtc {
commit 7671e5cb7b0b8c7d914b8e659d9deddad2c55bb2
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Feb 11 10:26:13 2015 +0000

    sna: Handle double failure to flip
    
    During flip failure recovery, we try to queue a second flip in order to
    generate the flip completion event. If that fails, we need to abort the
    flip entirely.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index db4dc9b..95c1b31 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -5331,6 +5331,37 @@ sna_crtc_flip(struct sna *sna, struct sna_crtc *crtc, struct kgem_bo *bo, int x,
 	return true;
 }
 
+static void sna_mode_restore(struct sna *sna)
+{
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+	int error = 0;
+	int i;
+
+	assert(!sna->mode.hidden);
+
+	for (i = 0; i < sna->mode.num_real_crtc; i++) {
+		xf86CrtcPtr crtc = config->crtc[i];
+
+		assert(to_sna_crtc(crtc) != NULL);
+		if (to_sna_crtc(crtc)->bo == NULL)
+			continue;
+
+		assert(crtc->enabled);
+		if (!__sna_crtc_set_mode(crtc)) {
+			sna_crtc_disable(crtc, false);
+			error++;
+		}
+	}
+	sna_mode_wakeup(sna);
+	update_flush_interval(sna);
+	sna_cursors_reload(sna);
+	sna->mode.dirty = false;
+
+	if (error)
+		xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR,
+			   "Failed to restore display configuration\n");
+}
+
 int
 sna_page_flip(struct sna *sna,
 	      struct kgem_bo *bo,
@@ -5410,12 +5441,8 @@ fixup_flip:
 
 				/* queue a flip in order to send the event */
 			} else {
-				if (count && !xf86SetDesiredModes(sna->scrn)) {
-					xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR,
-						   "failed to restore display configuration\n");
-					for (; i < sna->mode.num_real_crtc; i++)
-						sna_crtc_disable(config->crtc[i], false);
-				}
+				if (count)
+					sna_mode_restore(sna);
 				return 0;
 			}
 		}
@@ -5463,11 +5490,17 @@ retry_flip:
 				goto retry_flip;
 			}
 
-			xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR,
-				   "page flipping failed, on CRTC:%d (pipe=%d), disabling %s page flips\n",
-				   crtc->id, crtc->pipe, data ? "synchronous": "asynchronous");
-			sna->flags &= ~(data ? SNA_HAS_FLIP : SNA_HAS_ASYNC_FLIP);
-			goto fixup_flip;
+			if (sna->flags & (data ? SNA_HAS_FLIP : SNA_HAS_ASYNC_FLIP)) {
+				xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR,
+					   "page flipping failed, on CRTC:%d (pipe=%d), disabling %s page flips\n",
+					   crtc->id, crtc->pipe, data ? "synchronous": "asynchronous");
+				sna->flags &= ~(data ? SNA_HAS_FLIP : SNA_HAS_ASYNC_FLIP);
+				goto fixup_flip;
+			}
+
+			if (count)
+				sna_mode_restore(sna);
+			return 0;
 		}
 
 		if (data) {


More information about the xorg-commit mailing list