xf86-video-intel: 4 commits - src/uxa/intel_display.c src/uxa/intel_dri.c src/uxa/intel.h test/dri2-race.c

Chris Wilson ickle at kemper.freedesktop.org
Fri Jan 30 06:49:19 PST 2015


 src/uxa/intel.h         |    4 -
 src/uxa/intel_display.c |   60 +++++++++++++-----------
 src/uxa/intel_dri.c     |   39 +++++++++-------
 test/dri2-race.c        |  116 +++++++++++++++++++++++++++++++++++++++++++++---
 4 files changed, 166 insertions(+), 53 deletions(-)

New commits:
commit e427bb4e4187a9fd251ddeb420a1e26ca281cbff
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Jan 30 14:08:54 2015 +0000

    test/dri2-race: Race against CloseDisplay and also test WaitMSC
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/test/dri2-race.c b/test/dri2-race.c
index 4f6d106..5235317 100644
--- a/test/dri2-race.c
+++ b/test/dri2-race.c
@@ -64,9 +64,9 @@ static void swap_buffers(Display *dpy, Window win,
 	xcb_discard_reply(c, seq[1]);
 }
 
-static void run(Display *dpy, int width, int height,
-		unsigned int *attachments, int nattachments,
-		const char *name)
+static void race_window(Display *dpy, int width, int height,
+			unsigned int *attachments, int nattachments,
+			const char *name)
 {
 	Window win;
 	XSetWindowAttributes attr;
@@ -123,11 +123,109 @@ static void run(Display *dpy, int width, int height,
 		XDestroyWindow(dpy, win);
 	} while (--loop);
 
+	loop = 100;
+	do {
+		uint64_t ignore;
+
+		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);
+
+		for (count = 0; count < loop; count++)
+			DRI2WaitMSC(dpy, win, 0, 1, 0,
+				    &ignore, &ignore, &ignore);
+		XDestroyWindow(dpy, win);
+	} while (--loop);
+
 	XSync(dpy, 1);
 	sleep(2);
 	XSync(dpy, 1);
 }
 
+static void race_client(int width, int height,
+			unsigned int *attachments, int nattachments,
+			const char *name)
+{
+	XSetWindowAttributes attr;
+	int count, loop;
+
+	/* Be nasty and install a fullscreen window on top so that we
+	 * can guarantee we do not get clipped by children.
+	 */
+	attr.override_redirect = 1;
+	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++)
+			DRI2SwapBuffers(dpy, win, 0, 0, 0);
+		XCloseDisplay(dpy);
+	} while (--loop);
+
+	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, attachments, nattachments);
+		XCloseDisplay(dpy);
+	} while (--loop);
+
+	loop = 100;
+	do {
+		uint64_t ignore;
+		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);
+		for (count = 0; count < loop; count++)
+			DRI2WaitMSC(dpy, win, 0, 1, 0,
+				    &ignore, &ignore, &ignore);
+		XCloseDisplay(dpy);
+	} while (--loop);
+}
+
 int main(void)
 {
 	Display *dpy;
@@ -147,13 +245,17 @@ int main(void)
 
 	width = WidthOfScreen(DefaultScreenOfDisplay(dpy));
 	height = HeightOfScreen(DefaultScreenOfDisplay(dpy));
-	run(dpy, width, height, attachments, 1, "fullscreen");
-	run(dpy, width, height, attachments, 2, "fullscreen (with front)");
+	race_window(dpy, width, height, attachments, 1, "fullscreen");
+	race_window(dpy, width, height, attachments, 2, "fullscreen (with front)");
+	race_client(width, height, attachments, 1, "fullscreen");
+	race_client(width, height, attachments, 2, "fullscreen (with front)");
 
 	width /= 2;
 	height /= 2;
-	run(dpy, width, height, attachments, 1, "windowed");
-	run(dpy, width, height, attachments, 2, "windowed (with front)");
+	race_window(dpy, width, height, attachments, 1, "windowed");
+	race_window(dpy, width, height, attachments, 2, "windowed (with front)");
+	race_client(width, height, attachments, 1, "windowed");
+	race_client(width, height, attachments, 2, "windowed (with front)");
 
 	return 0;
 }
commit d909c460743a0cabc5c0ed30e063e99af7b26b17
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Jan 30 13:24:42 2015 +0000

    uxa: Fix error handling for failed pageflips
    
    Lots of issues found when trying dri2-race, mostly resulting from
    queueing too many flips at one - which itself is buggy. However, we
    crashed whilst trying to recover from the kernel reporting the error.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/uxa/intel_display.c b/src/uxa/intel_display.c
index 7b4d4e0..d5dce8e 100644
--- a/src/uxa/intel_display.c
+++ b/src/uxa/intel_display.c
@@ -89,9 +89,11 @@ struct intel_mode {
 	struct list outputs;
 	struct list crtcs;
 
-	void *pageflip_data;
-	intel_pageflip_handler_proc pageflip_handler;
-	intel_pageflip_abort_proc pageflip_abort;
+	struct {
+		intel_pageflip_handler_proc handler;
+		intel_pageflip_abort_proc abort;
+		void *data;
+	} pageflip;
 
 	Bool delete_dp_12_displays;
 };
@@ -1671,23 +1673,30 @@ intel_do_pageflip(intel_screen_private *intel,
 	uint32_t new_fb_id;
 	uint32_t flags;
 	uint32_t seq;
+	int err = 0;
 	int i;
 
 	/*
+	 * We only have a single length queue in the kernel, so any
+	 * attempts to schedule a second flip before processing the first
+	 * is a bug. Punt it back to the caller.
+	 */
+	if (mode->pageflip.handler)
+		return FALSE;
+
+	/*
 	 * Create a new handle for the back buffer
 	 */
 	if (drmModeAddFB(mode->fd, scrn->virtualX, scrn->virtualY,
 			 scrn->depth, scrn->bitsPerPixel, pitch,
-			 new_front->handle, &new_fb_id))
+			 new_front->handle, &new_fb_id)) {
+		err = errno;
 		goto error_out;
+	}
 
 	drm_intel_bo_disable_reuse(new_front);
         intel_flush(intel);
 
-	mode->pageflip_data = pageflip_data;
-	mode->pageflip_handler = pageflip_handler;
-	mode->pageflip_abort = pageflip_abort;
-
 	/*
 	 * Queue flips on all enabled CRTCs
 	 * Note that if/when we get per-CRTC buffers, we'll have to update this.
@@ -1711,8 +1720,7 @@ intel_do_pageflip(intel_screen_private *intel,
 
 		flip = calloc(1, sizeof(struct intel_pageflip));
 		if (flip == NULL) {
-			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
-				   "flip queue: carrier alloc failed.\n");
+			err = errno;
 			goto error_undo;
 		}
 
@@ -1724,25 +1732,17 @@ intel_do_pageflip(intel_screen_private *intel,
 
 		seq = intel_drm_queue_alloc(scrn, config->crtc[i], flip, intel_pageflip_handler, intel_pageflip_abort);
 		if (!seq) {
+			err = errno;
 			free(flip);
 			goto error_undo;
 		}
 
-again:
 		if (drmModePageFlip(mode->fd,
 				    crtc_id(crtc),
 				    new_fb_id,
 				    flags, (void *)(uintptr_t)seq)) {
-			if (intel_mode_read_drm_events(intel)) {
-				xf86DrvMsg(scrn->scrnIndex, X_WARNING,
-					   "flip queue retry\n");
-				goto again;
-			}
-			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
-				   "flip queue failed: %s\n", strerror(errno));
-			if (seq)
-				intel_drm_abort_seq(scrn, seq);
-			free(flip);
+			err = errno;
+			intel_drm_abort_seq(scrn, seq);
 			goto error_undo;
 		}
 		mode->flip_count++;
@@ -1751,6 +1751,10 @@ again:
 	mode->old_fb_id = mode->fb_id;
 	mode->fb_id = new_fb_id;
 
+	mode->pageflip.data = pageflip_data;
+	mode->pageflip.handler = pageflip_handler;
+	mode->pageflip.abort = pageflip_abort;
+
 	if (!mode->flip_count)
 		intel_pageflip_complete(mode);
 
@@ -1765,7 +1769,7 @@ error_undo:
 
 error_out:
 	xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Page flip failed: %s\n",
-		   strerror(errno));
+		   strerror(err));
 
 	mode->flip_count = 0;
 	return FALSE;
@@ -2001,11 +2005,12 @@ intel_pageflip_complete(struct intel_mode *mode)
 	/* Release framebuffer */
 	drmModeRmFB(mode->fd, mode->old_fb_id);
 
-	if (!mode->pageflip_handler)
+	if (!mode->pageflip.handler)
 		return;
 
-	mode->pageflip_handler(mode->fe_msc, mode->fe_usec,
-			       mode->pageflip_data);
+	mode->pageflip.handler(mode->fe_msc, mode->fe_usec,
+			       mode->pageflip.data);
+	memset(&mode->pageflip, 0, sizeof(mode->pageflip));
 }
 
 /*
@@ -2063,10 +2068,11 @@ intel_pageflip_abort(ScrnInfoPtr scrn, xf86CrtcPtr crtc, void *data)
 	/* Release framebuffer */
 	drmModeRmFB(mode->fd, mode->old_fb_id);
 
-	if (!mode->pageflip_abort)
+	if (!mode->pageflip.abort)
 		return;
 
-	mode->pageflip_abort(mode->pageflip_data);
+	mode->pageflip.abort(mode->pageflip.data);
+	memset(&mode->pageflip, 0, sizeof(mode->pageflip));
 }
 
 /*
commit c2f30a539cfb5808dbee19b7cc5d878bb7381a60
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Jan 30 13:12:20 2015 +0000

    uxa/dri2: Make vblank/flip handlers static
    
    These are no longer called directly from outside intel_dri.c and so we
    can make them static.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/uxa/intel.h b/src/uxa/intel.h
index 1b7e533..b4ad292 100644
--- a/src/uxa/intel.h
+++ b/src/uxa/intel.h
@@ -456,10 +456,6 @@ extern xf86CrtcPtr intel_covering_crtc(ScrnInfoPtr scrn, BoxPtr box,
 
 Bool I830DRI2ScreenInit(ScreenPtr pScreen);
 void I830DRI2CloseScreen(ScreenPtr pScreen);
-void I830DRI2FrameEventHandler(unsigned int frame, unsigned int tv_sec,
-			       unsigned int tv_usec, DRI2FrameEventPtr flip_info);
-void I830DRI2FlipEventHandler(unsigned int frame, unsigned int tv_sec,
-			      unsigned int tv_usec, DRI2FrameEventPtr flip_info);
 
 /* intel_dri3.c */
 Bool intel_dri3_screen_init(ScreenPtr screen);
diff --git a/src/uxa/intel_dri.c b/src/uxa/intel_dri.c
index e7080dc..5170c6d 100644
--- a/src/uxa/intel_dri.c
+++ b/src/uxa/intel_dri.c
@@ -81,6 +81,11 @@ static DevPrivateKeyRec i830_client_key;
 static int i830_client_key;
 #endif
 
+static void I830DRI2FlipEventHandler(unsigned int frame,
+				     unsigned int tv_sec,
+				     unsigned int tv_usec,
+				     DRI2FrameEventPtr flip_info);
+
 static uint32_t pixmap_flink(PixmapPtr pixmap)
 {
 	struct intel_uxa_pixmap *priv = intel_uxa_get_pixmap_private(pixmap);
@@ -889,8 +894,10 @@ can_exchange(DrawablePtr drawable, DRI2BufferPtr front, DRI2BufferPtr back)
 	return TRUE;
 }
 
-void I830DRI2FrameEventHandler(unsigned int frame, unsigned int tv_sec,
-			       unsigned int tv_usec, DRI2FrameEventPtr swap_info)
+static void I830DRI2FrameEventHandler(unsigned int frame,
+				      unsigned int tv_sec,
+				      unsigned int tv_usec,
+				      DRI2FrameEventPtr swap_info)
 {
 	intel_screen_private *intel = swap_info->intel;
 	DrawablePtr drawable;
@@ -939,8 +946,10 @@ void I830DRI2FrameEventHandler(unsigned int frame, unsigned int tv_sec,
 	i830_dri2_del_frame_event(swap_info);
 }
 
-void I830DRI2FlipEventHandler(unsigned int frame, unsigned int tv_sec,
-			      unsigned int tv_usec, DRI2FrameEventPtr flip_info)
+static void I830DRI2FlipEventHandler(unsigned int frame,
+				     unsigned int tv_sec,
+				     unsigned int tv_usec,
+				     DRI2FrameEventPtr flip_info)
 {
 	struct intel_screen_private *intel = flip_info->intel;
 	DrawablePtr drawable;
commit fa5a8c61d1ac6f90b1f4544e1734308fbdba3c0d
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Jan 30 13:10:55 2015 +0000

    uxa/dri2: Reset swap_info->type after a failed flip submission
    
    As we set the type prior to attempting to queue a flip, we need to then
    reset the type if that attempt fails and we need to fall back to a
    vblank handler.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/uxa/intel_dri.c b/src/uxa/intel_dri.c
index e9f3174..e7080dc 100644
--- a/src/uxa/intel_dri.c
+++ b/src/uxa/intel_dri.c
@@ -1130,8 +1130,6 @@ I830DRI2ScheduleSwap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 	    flip = 1;
 	}
 
-	swap_info->type = swap_type;
-
 	/* Correct target_msc by 'flip' if swap_type == DRI2_FLIP.
 	 * Do it early, so handling of different timing constraints
 	 * for divisor, remainder and msc vs. target_msc works.
@@ -1140,20 +1138,22 @@ I830DRI2ScheduleSwap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 		*target_msc -= flip;
 
 	/*
+	 * If we can, schedule the flip directly from here rather
+	 * than waiting for an event from the kernel for the current
+	 * (or a past) MSC.
+	 */
+	if (flip && divisor == 0 && current_msc >= *target_msc &&
+	    I830DRI2ScheduleFlip(intel, draw, swap_info))
+		return TRUE;
+
+	swap_info->type = swap_type;
+
+	/*
 	 * 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 < *target_msc) {
-		/*
-		 * If we can, schedule the flip directly from here rather
-		 * than waiting for an event from the kernel for the current
-		 * (or a past) MSC.
-		 */
-		if (flip && divisor == 0 && current_msc >= *target_msc &&
-		    I830DRI2ScheduleFlip(intel, draw, swap_info))
-			return TRUE;
-
 		vbl.request.type =
 			DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT | pipe_select(pipe);
 


More information about the xorg-commit mailing list