diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2015-01-29 23:55:19 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2015-01-29 23:55:19 +0000 |
commit | dc51886c0c637a1da94e6379f183fc32ac345df6 (patch) | |
tree | 8a625130cd545383f86e4cb8108754229c415fb3 | |
parent | 1030705cdc7725ee821cf10be9c3cb0aeb31564c (diff) |
sna/dri2: Fix use of stale flip_pending after removing window
Testcase: dri2-race
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | src/sna/sna_dri2.c | 10 | ||||
-rw-r--r-- | test/dri2-race.c | 46 |
2 files changed, 53 insertions, 3 deletions
diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c index 4056fbb5..81ad9c60 100644 --- a/src/sna/sna_dri2.c +++ b/src/sna/sna_dri2.c @@ -1330,6 +1330,9 @@ sna_dri2_event_free(struct sna_dri2_event *info) DrawablePtr draw = info->draw; DBG(("%s(draw?=%d)\n", __FUNCTION__, draw != NULL)); + if (info->sna->dri2.flip_pending == info) + info->sna->dri2.flip_pending = info->chain; + assert(info->sna->dri2.flip_pending != info); if (draw && draw->type == DRAWABLE_WINDOW) sna_dri2_remove_event((WindowPtr)draw, info); @@ -1501,6 +1504,7 @@ void sna_dri2_destroy_window(WindowPtr win) chain = priv->chain; while ((info = chain)) { + assert(info->draw == &win->drawable); info->draw = NULL; info->client = NULL; list_del(&info->link); @@ -2089,9 +2093,9 @@ static void chain_swap(struct sna_dri2_event *chain) if (chain->queued) /* too early! */ return; - assert(chain == dri2_chain(chain->draw)); DBG(("%s: chaining draw=%ld, type=%d\n", __FUNCTION__, (long)chain->draw->id, chain->type)); + assert(chain == dri2_chain(chain->draw)); chain->queued = true; switch (chain->type) { @@ -2392,8 +2396,8 @@ static void chain_flip(struct sna *sna) struct sna_dri2_event *chain = sna->dri2.flip_pending; assert(chain->type == FLIP); - DBG(("%s: chaining type=%d, cancelled?=%d\n", - __FUNCTION__, chain->type, chain->draw == NULL)); + DBG(("%s: chaining type=%d, cancelled?=%d window=%ld\n", + __FUNCTION__, chain->type, chain->draw == NULL, chain->draw ? chain->draw->id : 0)); sna->dri2.flip_pending = NULL; if (chain->draw == NULL) { diff --git a/test/dri2-race.c b/test/dri2-race.c index 8862c84c..4f6d1063 100644 --- a/test/dri2-race.c +++ b/test/dri2-race.c @@ -5,6 +5,10 @@ #include <X11/Xlib.h> #include <X11/Xutil.h> #include <X11/extensions/Xfixes.h> +#include <X11/Xlib-xcb.h> +#include <xcb/xcb.h> +#include <xcb/xcbext.h> +#include <xcb/dri2.h> #include <unistd.h> #include <fcntl.h> #include <string.h> @@ -41,6 +45,25 @@ static int dri2_open(Display *dpy) return fd; } +static void swap_buffers(Display *dpy, Window win, + 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; + + + seq[1] = xcb_dri2_get_buffers_unchecked(c, win, + nattachments, nattachments, + attachments).sequence; + + xcb_flush(c); + xcb_discard_reply(c, seq[0]); + xcb_discard_reply(c, seq[1]); +} + static void run(Display *dpy, int width, int height, unsigned int *attachments, int nattachments, const char *name) @@ -77,6 +100,29 @@ static void run(Display *dpy, int width, int height, XDestroyWindow(dpy, win); } while (--loop); + 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, attachments, nattachments); + XDestroyWindow(dpy, win); + } while (--loop); + XSync(dpy, 1); sleep(2); XSync(dpy, 1); |