[cairo-commit] 2 commits - src/cairo-xlib-display.c src/cairo-xlib-surface-shm.c
Chris Wilson
ickle at kemper.freedesktop.org
Tue Aug 21 14:45:51 PDT 2012
src/cairo-xlib-display.c | 2
src/cairo-xlib-surface-shm.c | 106 +++++++++++++++++++++++++++++++++++--------
2 files changed, 89 insertions(+), 19 deletions(-)
New commits:
commit 5c77b4df146796d8280a4f5b16949e3db4a1f84a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Tue Aug 21 21:03:04 2012 +0100
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 at chris-wilson.co.uk>
diff --git a/src/cairo-xlib-display.c b/src/cairo-xlib-display.c
index 12c1623..32e4699 100644
--- a/src/cairo-xlib-display.c
+++ b/src/cairo-xlib-display.c
@@ -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;
}
diff --git a/src/cairo-xlib-private.h b/src/cairo-xlib-private.h
index c7356ec..26bdede 100644
--- a/src/cairo-xlib-private.h
+++ b/src/cairo-xlib-private.h
@@ -228,9 +228,6 @@ 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);
cairo_private cairo_xlib_screen_t *
diff --git a/src/cairo-xlib-surface-shm.c b/src/cairo-xlib-surface-shm.c
index d10e8a6..25e6a87 100644
--- a/src/cairo-xlib-surface-shm.c
+++ b/src/cairo-xlib-surface-shm.c
@@ -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;
commit aa5c7123097c56e2c35bf88b8377bbdd1523fbce
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Tue Aug 21 10:12:06 2012 +0100
xlib/shm: Use a genuine event rather than an open-ended request
Adding lots of requests without popping the replies causes xcb to
continually sort large lists of unprocessed data. Use an event instead
and regularly dequeue them.
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/cairo-xlib-display.c b/src/cairo-xlib-display.c
index 656164a..12c1623 100644
--- a/src/cairo-xlib-display.c
+++ b/src/cairo-xlib-display.c
@@ -372,7 +372,9 @@ _cairo_xlib_display_acquire (cairo_device_t *device, cairo_xlib_display_t **disp
return status;
*display = (cairo_xlib_display_t *) device;
- return status;
+ _cairo_xlib_display_flush_shm (*display);
+
+ return CAIRO_STATUS_SUCCESS;
}
XRenderPictFormat *
diff --git a/src/cairo-xlib-private.h b/src/cairo-xlib-private.h
index 26bdede..c7356ec 100644
--- a/src/cairo-xlib-private.h
+++ b/src/cairo-xlib-private.h
@@ -228,6 +228,9 @@ 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);
cairo_private cairo_xlib_screen_t *
diff --git a/src/cairo-xlib-surface-shm.c b/src/cairo-xlib-surface-shm.c
index 7b27f25..d10e8a6 100644
--- a/src/cairo-xlib-surface-shm.c
+++ b/src/cairo-xlib-surface-shm.c
@@ -103,6 +103,7 @@ struct pqueue {
struct _cairo_xlib_shm_display {
int has_pixmaps;
+ Window window;
cairo_list_t pool;
struct pqueue info;
@@ -285,13 +286,32 @@ can_use_shm (Display *dpy, int *has_pixmap)
return success && ! _x_error_occurred;
}
-static void trigger_event (Display *dpy)
+static inline Display *
+peek_display (cairo_device_t *device)
{
- xReq *req;
+ return ((cairo_xlib_display_t *)device)->display;
+}
- LockDisplay(dpy);
- GetEmptyReq(GetInputFocus, req);
- UnlockDisplay(dpy);
+static inline unsigned long
+peek_processed (cairo_device_t *device)
+{
+ return LastKnownRequestProcessed (peek_display(device));
+}
+
+static void trigger_event (cairo_xlib_display_t *display)
+{
+ cairo_xlib_shm_display_t *shm = display->shm;
+ Display *dpy = display->display;
+ XUnmapEvent ev;
+
+ ev.type = UnmapNotify;
+ ev.event = DefaultRootWindow (dpy);
+ ev.window = shm->window;
+ ev.from_configure = False;
+
+ XSendEvent (dpy, ev.event, False,
+ SubstructureRedirectMask | SubstructureNotifyMask,
+ (XEvent *)&ev);
}
static void
@@ -443,7 +463,7 @@ _cairo_xlib_shm_pool_create(cairo_xlib_display_t *display,
goto cleanup_detach;
cairo_list_add (&pool->link, &display->shm->pool);
- trigger_event (display->display);
+ trigger_event (display);
*ptr = _cairo_mempool_alloc (&pool->mem, size);
assert (*ptr != NULL);
@@ -497,18 +517,6 @@ _cairo_xlib_shm_info_create (cairo_xlib_display_t *display,
return info;
}
-static inline Display *
-peek_display (cairo_device_t *device)
-{
- return ((cairo_xlib_display_t *)device)->display;
-}
-
-static inline unsigned long
-peek_processed (cairo_device_t *device)
-{
- return LastKnownRequestProcessed (peek_display(device));
-}
-
static cairo_status_t
_cairo_xlib_shm_surface_flush (void *abstract_surface, unsigned flags)
{
@@ -696,6 +704,22 @@ 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)
{
@@ -944,7 +968,7 @@ _cairo_xlib_surface_put_shm (cairo_xlib_surface_t *surface)
_cairo_damage_destroy (damage);
shm->active = NextRequest (display->display);
- trigger_event (display->display);
+ trigger_event (display);
_cairo_xlib_surface_put_gc (display, surface, gc);
out:
@@ -1071,7 +1095,7 @@ _cairo_xlib_shm_surface_mark_active (cairo_surface_t *surface)
shm = (cairo_xlib_shm_surface_t *) surface;
shm->active = next_request (surface->device);
- trigger_event (peek_display (surface->device));
+ trigger_event ((cairo_xlib_display_t *)shm->image.base.device);
}
XRenderPictFormat *
@@ -1119,6 +1143,8 @@ _cairo_xlib_display_init_shm (cairo_xlib_display_t *display)
{
int has_pixmap;
cairo_xlib_shm_display_t *shm;
+ XSetWindowAttributes attr;
+ int scr;
display->shm = NULL;
@@ -1134,6 +1160,17 @@ _cairo_xlib_display_init_shm (cairo_xlib_display_t *display)
return;
}
+ scr = DefaultScreen (display->display);
+ attr.event_mask = SubstructureRedirectMask | SubstructureNotifyMask;
+ attr.override_redirect = 1;
+ shm->window = XCreateWindow (display->display,
+ DefaultRootWindow (display->display), -1, -1,
+ 1, 1, 0,
+ DefaultDepth (display->display, scr),
+ InputOutput,
+ DefaultVisual (display->display, scr),
+ CWEventMask | CWOverrideRedirect, &attr);
+
shm->has_pixmaps = has_pixmap ? MIN_PIXMAP_SIZE : 0;
cairo_list_init (&shm->pool);
@@ -1157,6 +1194,9 @@ _cairo_xlib_display_fini_shm (cairo_xlib_display_t *display)
_cairo_xlib_display_shm_pool_destroy (display, pool);
}
+ if (display->display)
+ XDestroyWindow (display->display, shm->window);
+
free (shm);
display->shm = NULL;
}
More information about the cairo-commit
mailing list