summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2012-12-29 11:41:17 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2012-12-29 14:55:17 +0000
commit0c84a5474d4e90fc9361ccbb0ebc3d0580bad82b (patch)
tree3812b28651c61f47060f9f20a339f0284e7a18bc
parent21db1c99108dc84166cbd9641f3256b22f571ee3 (diff)
downloadcairo-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.c4
-rw-r--r--src/cairo-xlib-surface-shm.c110
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;