[cairo-commit] src/cairo-xlib-render-compositor.c src/cairo-xlib-surface-shm.c

Chris Wilson ickle at kemper.freedesktop.org
Sat Dec 29 06:55:27 PST 2012


 src/cairo-xlib-render-compositor.c |    4 -
 src/cairo-xlib-surface-shm.c       |  110 +++++++++++++++++++++++++------------
 2 files changed, 79 insertions(+), 35 deletions(-)

New commits:
commit 0c84a5474d4e90fc9361ccbb0ebc3d0580bad82b
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Dec 29 11:41:17 2012 +0000

    xlib/shm: Rate-limit events and only use as necessary
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-xlib-render-compositor.c b/src/cairo-xlib-render-compositor.c
index e7d7f79..f0068ae 100644
--- a/src/cairo-xlib-render-compositor.c
+++ b/src/cairo-xlib-render-compositor.c
@@ -1485,12 +1485,12 @@ check_composite_glyphs (const cairo_composite_rectangles_t *extents,
 			cairo_glyph_t *glyphs,
 			int *num_glyphs)
 {
-    TRACE ((stderr, "%s\n", __FUNCTION__));
-
     cairo_xlib_surface_t *dst = (cairo_xlib_surface_t *)extents->surface;
     cairo_xlib_display_t *display = dst->display;
     int max_request_size, size;
 
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
     if (! CAIRO_RENDER_SUPPORTS_OPERATOR (display, extents->op))
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
diff --git a/src/cairo-xlib-surface-shm.c b/src/cairo-xlib-surface-shm.c
index 8a9e667..ea047b6 100644
--- a/src/cairo-xlib-surface-shm.c
+++ b/src/cairo-xlib-surface-shm.c
@@ -206,6 +206,8 @@ struct _cairo_xlib_shm_display {
     int event;
 
     Window window;
+    unsigned long last_request;
+    unsigned long last_event;
 
     cairo_list_t surfaces;
 
@@ -216,7 +218,7 @@ struct _cairo_xlib_shm_display {
 static inline cairo_bool_t
 seqno_passed (unsigned long a, unsigned long b)
 {
-    return (long)(b - a) > 0;
+    return (long)(b - a) >= 0;
 }
 
 static inline cairo_status_t
@@ -421,6 +423,43 @@ _cairo_xlib_display_shm_pool_destroy (cairo_xlib_display_t *display,
     free (pool);
 }
 
+static void send_event(cairo_xlib_display_t *display,
+		       cairo_xlib_shm_info_t *info,
+		       unsigned long seqno)
+{
+    XShmCompletionEvent ev;
+
+    if (seqno_passed (seqno, display->shm->last_event))
+	return;
+
+    ev.type = display->shm->event;
+    ev.send_event = 1; /* XXX or lie? */
+    ev.serial = NextRequest (display->display);
+    ev.drawable = display->shm->window;
+    ev.major_code = display->shm->opcode;
+    ev.minor_code = X_ShmPutImage;
+    ev.shmseg = info->pool->shm.shmid;
+    ev.offset = (char *)info->mem - (char *)info->pool->shm.shmaddr;
+
+    XSendEvent (display->display, ev.drawable, False, 0, (XEvent *)&ev);
+
+    display->shm->last_event = ev.serial;
+}
+
+static void sync (cairo_xlib_display_t *display)
+{
+    cairo_xlib_shm_info_t *info;
+    struct pqueue *pq = &display->shm->info;
+
+    XSync (display->display, False);
+
+    while ((info = PQ_TOP(pq))) {
+	_cairo_mempool_free (&info->pool->mem, info->mem);
+	_pqueue_pop (&display->shm->info);
+	free (info);
+    }
+}
+
 static void
 _cairo_xlib_shm_info_cleanup (cairo_xlib_display_t *display)
 {
@@ -437,8 +476,10 @@ _cairo_xlib_shm_info_cleanup (cairo_xlib_display_t *display)
 
     info = PQ_TOP(pq);
     do {
-	if (! seqno_passed (info->last_request, processed))
-	    break;
+	if (! seqno_passed (info->last_request, processed)) {
+	    send_event (display, info, display->shm->last_request);
+	    return;
+	}
 
 	_cairo_mempool_free (&info->pool->mem, info->mem);
 	_pqueue_pop (&display->shm->info);
@@ -446,9 +487,9 @@ _cairo_xlib_shm_info_cleanup (cairo_xlib_display_t *display)
     } while ((info = PQ_TOP(pq)));
 }
 
-static cairo_xlib_shm_info_t *
-_cairo_xlib_shm_info_find (cairo_xlib_display_t *display,
-			   size_t size, unsigned long *last_request)
+static cairo_xlib_shm_t *
+_cairo_xlib_shm_info_find (cairo_xlib_display_t *display, size_t size,
+			   void **ptr, unsigned long *last_request)
 {
     cairo_xlib_shm_info_t *info;
     struct pqueue *pq = &display->shm->info;
@@ -458,14 +499,21 @@ _cairo_xlib_shm_info_find (cairo_xlib_display_t *display,
 
     info = PQ_TOP(pq);
     do {
-	_pqueue_pop (&display->shm->info);
-
-	if (info->size >= size && size <= 2*info->size)
-	    return info;
+	cairo_xlib_shm_t *pool = info->pool;
 
 	*last_request = info->last_request;
+
+	_pqueue_pop (&display->shm->info);
 	_cairo_mempool_free (&info->pool->mem, info->mem);
 	free (info);
+
+	if (pool->mem.free_bytes >= size) {
+	    void *mem = _cairo_mempool_alloc (&pool->mem, size);
+	    if (mem != NULL) {
+		*ptr = mem;
+		return pool;
+	    }
+	}
     } while ((info = PQ_TOP(pq)));
 
     return NULL;
@@ -582,15 +630,12 @@ _cairo_xlib_shm_info_create (cairo_xlib_display_t *display,
     unsigned long last_request = 0;
     void *mem = NULL;
 
-    if (will_sync) {
-	info = _cairo_xlib_shm_info_find (display, size, &last_request);
-	if (info)
-	    return info;
-    }
-
     _cairo_xlib_shm_info_cleanup (display);
     pool = _cairo_xlib_shm_pool_find (display, size, &mem);
     _cairo_xlib_shm_pool_cleanup (display);
+
+    if (pool == NULL && will_sync)
+	pool = _cairo_xlib_shm_info_find (display, size, &mem, &last_request);
     if (pool == NULL)
 	pool = _cairo_xlib_shm_pool_create (display, size, &mem);
     if (pool == NULL)
@@ -617,6 +662,7 @@ _cairo_xlib_shm_surface_flush (void *abstract_surface, unsigned flags)
 {
     cairo_xlib_shm_surface_t *shm = abstract_surface;
     cairo_xlib_display_t *display;
+    Display *dpy;
     cairo_status_t status;
 
     if (shm->active == 0)
@@ -634,10 +680,15 @@ _cairo_xlib_shm_surface_flush (void *abstract_surface, unsigned flags)
     if (unlikely (status))
 	return status;
 
-    XEventsQueued (display->display, QueuedAfterReading);
-    if (!seqno_passed (shm->active,
-		       LastKnownRequestProcessed (display->display)))
-	XSync (display->display, False);
+    send_event (display, shm->info, shm->active);
+
+    dpy = display->display;
+    XEventsQueued (dpy, QueuedAfterReading);
+    while (! seqno_passed (shm->active, LastKnownRequestProcessed (dpy))) {
+	LockDisplay(dpy);
+	_XReadEvents(dpy);
+	UnlockDisplay(dpy);
+    }
 
     cairo_device_release (&display->base);
     shm->active = 0;
@@ -649,7 +700,7 @@ static inline cairo_bool_t
 active (cairo_xlib_shm_surface_t *shm, Display *dpy)
 {
     return (shm->active &&
-	    !seqno_passed (shm->active, LastKnownRequestProcessed (dpy)));
+	    ! seqno_passed (shm->active, LastKnownRequestProcessed (dpy)));
 }
 
 static cairo_status_t
@@ -669,6 +720,8 @@ _cairo_xlib_shm_surface_finish (void *abstract_surface)
     if (active (shm, display->display)) {
 	shm->info->last_request = shm->active;
 	_pqueue_push (&display->shm->info, shm->info);
+	if (! seqno_passed (display->shm->last_request, shm->active))
+	    display->shm->last_request = shm->active;
     } else {
 	_cairo_mempool_free (&shm->info->pool->mem, shm->info->mem);
 	free (shm->info);
@@ -884,7 +937,7 @@ _cairo_xlib_surface_update_shm (cairo_xlib_surface_t *surface)
 	XChangeGC (display->display, gc, GCSubwindowMode, &gcv);
     }
 
-    XSync (display->display, False);
+    sync (display);
     shm->active = 0;
     shm->idle--;
 
@@ -1130,19 +1183,8 @@ _cairo_xlib_shm_surface_mark_active (cairo_surface_t *_shm)
 {
     cairo_xlib_shm_surface_t *shm = (cairo_xlib_shm_surface_t *) _shm;
     cairo_xlib_display_t *display = (cairo_xlib_display_t *) _shm->device;
-    XShmCompletionEvent ev;
-
-    ev.type = display->shm->event;
-    ev.send_event = 1; /* XXX or lie? */
-    ev.serial = NextRequest (display->display) - 1;
-    ev.drawable = display->shm->window;
-    ev.major_code = display->shm->opcode;
-    ev.minor_code = X_ShmPutImage;
-    ev.shmseg = shm->info->pool->shm.shmid;
-    ev.offset = (char *)shm->info->mem - (char *)shm->info->pool->shm.shmaddr;
 
     shm->active = NextRequest (display->display);
-    XSendEvent (display->display, ev.drawable, False, 0, (XEvent *)&ev);
 }
 
 void
@@ -1356,6 +1398,8 @@ _cairo_xlib_display_init_shm (cairo_xlib_display_t *display)
 				 InputOutput,
 				 DefaultVisual (display->display, scr),
 				 CWOverrideRedirect, &attr);
+    shm->last_event = 0;
+    shm->last_request = 0;
 
     if (xorg_has_buggy_send_shm_completion_event(display, shm))
 	has_pixmap = 0;


More information about the cairo-commit mailing list