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