diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2012-12-29 11:41:17 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2012-12-29 14:55:17 +0000 |
commit | 0c84a5474d4e90fc9361ccbb0ebc3d0580bad82b (patch) | |
tree | 3812b28651c61f47060f9f20a339f0284e7a18bc | |
parent | 21db1c99108dc84166cbd9641f3256b22f571ee3 (diff) | |
download | cairo-0c84a5474d4e90fc9361ccbb0ebc3d0580bad82b.tar.gz |
xlib/shm: Rate-limit events and only use as necessary
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | src/cairo-xlib-render-compositor.c | 4 | ||||
-rw-r--r-- | src/cairo-xlib-surface-shm.c | 110 |
2 files changed, 79 insertions, 35 deletions
diff --git a/src/cairo-xlib-render-compositor.c b/src/cairo-xlib-render-compositor.c index e7d7f7987..f0068ae5d 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 8a9e66772..ea047b699 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; |