xlib/shm: Only check if we are expecting an event

As the XCheckWindowEvent() has the unwanted side-effect of flushing the
output queue when there is no event available (libX11 seems to be
entirely anti-performant), we need to roll our own that only checks the
already available event queue.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
Chris Wilson 2012-08-21 21:03:04 +01:00
parent aa5c712309
commit 5c77b4df14
3 changed files with 46 additions and 21 deletions

View file

@ -372,8 +372,6 @@ _cairo_xlib_display_acquire (cairo_device_t *device, cairo_xlib_display_t **disp
return status;
*display = (cairo_xlib_display_t *) device;
_cairo_xlib_display_flush_shm (*display);
return CAIRO_STATUS_SUCCESS;
}

View file

@ -227,9 +227,6 @@ _cairo_xlib_device_create (Display *display);
cairo_private void
_cairo_xlib_display_init_shm (cairo_xlib_display_t *display);
cairo_private void
_cairo_xlib_display_flush_shm (cairo_xlib_display_t *display);
cairo_private void
_cairo_xlib_display_fini_shm (cairo_xlib_display_t *display);

View file

@ -105,6 +105,9 @@ struct _cairo_xlib_shm_display {
int has_pixmaps;
Window window;
unsigned pending_events;
unsigned last_event;
cairo_list_t pool;
struct pqueue info;
};
@ -298,20 +301,61 @@ peek_processed (cairo_device_t *device)
return LastKnownRequestProcessed (peek_display(device));
}
static void
flush_events (cairo_xlib_display_t *display)
{
cairo_xlib_shm_display_t *shm;
Display *dpy;
_XQEvent *prev, *qelt, *next;
shm = display->shm;
if (shm == NULL)
return;
if (shm->pending_events == 0)
return;
dpy = display->display;
if (QLength (dpy) == 0)
return;
LockDisplay(dpy);
for (prev = NULL, qelt = dpy->head; qelt; qelt = next) {
next = qelt->next;
if (qelt->event.xany.window == shm->window) {
_XDeq(dpy, prev, qelt);
if (! --shm->pending_events)
break;
continue;
}
prev = qelt;
}
UnlockDisplay(dpy);
/* Did somebody else eat all of our events? */
if (seqno_passed (shm->last_event, LastKnownRequestProcessed (dpy)))
shm->pending_events = 0;
}
static void trigger_event (cairo_xlib_display_t *display)
{
cairo_xlib_shm_display_t *shm = display->shm;
Display *dpy = display->display;
XUnmapEvent ev;
flush_events (display);
ev.type = UnmapNotify;
ev.event = DefaultRootWindow (dpy);
ev.window = shm->window;
ev.from_configure = False;
shm->last_event = NextRequest (dpy);
XSendEvent (dpy, ev.event, False,
SubstructureRedirectMask | SubstructureNotifyMask,
(XEvent *)&ev);
shm->pending_events++;
}
static void
@ -704,22 +748,6 @@ cleanup_shm:
return NULL;
}
void
_cairo_xlib_display_flush_shm (cairo_xlib_display_t *display)
{
cairo_xlib_shm_display_t *shm;
XEvent ev;
shm = display->shm;
if (shm == NULL)
return;
while (XCheckWindowEvent (display->display, shm->window,
SubstructureRedirectMask | SubstructureNotifyMask,
&ev))
;
}
static void
_cairo_xlib_surface_update_shm (cairo_xlib_surface_t *surface)
{
@ -1160,6 +1188,8 @@ _cairo_xlib_display_init_shm (cairo_xlib_display_t *display)
return;
}
shm->pending_events = 0;
scr = DefaultScreen (display->display);
attr.event_mask = SubstructureRedirectMask | SubstructureNotifyMask;
attr.override_redirect = 1;