[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