diff --git a/src/cairo-xcb-private.h b/src/cairo-xcb-private.h index c99f1177b..e87f0e88c 100644 --- a/src/cairo-xcb-private.h +++ b/src/cairo-xcb-private.h @@ -77,6 +77,7 @@ struct _cairo_xcb_shm_info { cairo_xcb_connection_t *connection; uint32_t shm; uint32_t offset; + size_t size; void *mem; cairo_xcb_shm_mem_pool_t *pool; xcb_get_input_focus_cookie_t sync; @@ -307,6 +308,7 @@ _cairo_xcb_connection_destroy (cairo_xcb_connection_t *connection) cairo_private cairo_int_status_t _cairo_xcb_connection_allocate_shm_info (cairo_xcb_connection_t *display, size_t size, + cairo_bool_t might_reuse, cairo_xcb_shm_info_t **shm_info_out); cairo_private void diff --git a/src/cairo-xcb-shm.c b/src/cairo-xcb-shm.c index ffcaec8f1..6972720b0 100644 --- a/src/cairo-xcb-shm.c +++ b/src/cairo-xcb-shm.c @@ -492,6 +492,7 @@ _cairo_xcb_shm_process_pending (cairo_xcb_connection_t *connection, shm_wait_typ cairo_int_status_t _cairo_xcb_connection_allocate_shm_info (cairo_xcb_connection_t *connection, size_t size, + cairo_bool_t might_reuse, cairo_xcb_shm_info_t **shm_info_out) { cairo_xcb_shm_info_t *shm_info; @@ -506,6 +507,22 @@ _cairo_xcb_connection_allocate_shm_info (cairo_xcb_connection_t *connection, CAIRO_MUTEX_LOCK (connection->shm_mutex); _cairo_xcb_shm_process_pending (connection, PENDING_POLL); + if (might_reuse) { + cairo_list_foreach_entry (shm_info, cairo_xcb_shm_info_t, + &connection->shm_pending, pending) { + if (shm_info->size >= size) { + cairo_list_del (&shm_info->pending); + CAIRO_MUTEX_UNLOCK (connection->shm_mutex); + + xcb_discard_reply (connection->xcb_connection, shm_info->sync.sequence); + shm_info->sync.sequence = XCB_NONE; + + *shm_info_out = shm_info; + return CAIRO_STATUS_SUCCESS; + } + } + } + cairo_list_foreach_entry_safe (pool, next, cairo_xcb_shm_mem_pool_t, &connection->shm_pools, link) { @@ -599,6 +616,7 @@ _cairo_xcb_connection_allocate_shm_info (cairo_xcb_connection_t *connection, shm_info->connection = connection; shm_info->pool = pool; shm_info->shm = pool->shmseg; + shm_info->size = size; shm_info->offset = (char *) mem - (char *) pool->base; shm_info->mem = mem; shm_info->sync.sequence = XCB_NONE; diff --git a/src/cairo-xcb-surface-core.c b/src/cairo-xcb-surface-core.c index 20cb5d37d..c28857500 100644 --- a/src/cairo-xcb-surface-core.c +++ b/src/cairo-xcb-surface-core.c @@ -164,8 +164,8 @@ _cairo_xcb_shm_image_create_shm (cairo_xcb_connection_t *connection, if (size <= CAIRO_XCB_SHM_SMALL_IMAGE) return CAIRO_INT_STATUS_UNSUPPORTED; - status = _cairo_xcb_connection_allocate_shm_info (connection, - size, &shm_info); + status = _cairo_xcb_connection_allocate_shm_info (connection, size, + FALSE, &shm_info); if (unlikely (status)) return status; diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c index ebea5ff7b..9639f9162 100644 --- a/src/cairo-xcb-surface.c +++ b/src/cairo-xcb-surface.c @@ -221,6 +221,7 @@ static cairo_surface_t * _cairo_xcb_surface_create_shm_image (cairo_xcb_connection_t *connection, pixman_format_code_t pixman_format, int width, int height, + cairo_bool_t might_reuse, cairo_xcb_shm_info_t **shm_info_out) { cairo_surface_t *image; @@ -234,6 +235,7 @@ _cairo_xcb_surface_create_shm_image (cairo_xcb_connection_t *connection, PIXMAN_FORMAT_BPP (pixman_format)); status = _cairo_xcb_connection_allocate_shm_info (connection, stride * height, + might_reuse, &shm_info); if (unlikely (status)) return _cairo_surface_create_in_error (status); @@ -278,6 +280,7 @@ _get_shm_image (cairo_xcb_surface_t *surface, image = _cairo_xcb_surface_create_shm_image (surface->connection, surface->pixman_format, width, height, + TRUE, &shm_info); if (unlikely (image == NULL || image->status)) goto done;