[cairo-commit] 6 commits - src/cairo-xlib-fallback-compositor.c src/cairo-xlib-private.h src/cairo-xlib-render-compositor.c src/cairo-xlib-surface.c src/cairo-xlib-surface-shm.c
Chris Wilson
ickle at kemper.freedesktop.org
Fri Aug 17 16:25:04 PDT 2012
src/cairo-xlib-fallback-compositor.c | 14 +++--
src/cairo-xlib-private.h | 14 +++--
src/cairo-xlib-render-compositor.c | 97 +++++++++++++++++++++++++++++++++--
src/cairo-xlib-surface-shm.c | 69 ++++++++++++++++++------
src/cairo-xlib-surface.c | 9 +--
5 files changed, 167 insertions(+), 36 deletions(-)
New commits:
commit 1bc9f673b61aa48369329606acc13aa5bce94a0a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri Aug 17 23:38:10 2012 +0100
xlib/shm: Avoid using a synchronous ShmCreatePixmap if evading the readback
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/cairo-xlib-surface-shm.c b/src/cairo-xlib-surface-shm.c
index 5932def..ad36ce1 100644
--- a/src/cairo-xlib-surface-shm.c
+++ b/src/cairo-xlib-surface-shm.c
@@ -804,6 +804,7 @@ _cairo_xlib_surface_get_shm (cairo_xlib_surface_t *surface,
if (surface->shm == NULL) {
pixman_format_code_t pixman_format;
+ cairo_bool_t will_sync;
if (! has_shm_pixmaps (surface))
return NULL;
@@ -815,10 +816,12 @@ _cairo_xlib_surface_get_shm (cairo_xlib_surface_t *surface,
if (pixman_format == 0)
return NULL;
+ will_sync = !surface->base.is_clear && !overwrite;
+
surface->shm =
&_cairo_xlib_shm_surface_create (surface, pixman_format,
surface->width, surface->height,
- TRUE, 1)->image.base;
+ will_sync, 1)->image.base;
if (surface->shm == NULL)
return NULL;
commit 3da2d8a1e277ae76ea2ba2533850b1901c6b3b29
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri Aug 17 23:37:31 2012 +0100
xlib: Only use CopyArea if the ShmPixmap and destination are the same depth
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 02cd6a6..8baeaf3 100644
--- a/src/cairo-xlib-render-compositor.c
+++ b/src/cairo-xlib-render-compositor.c
@@ -138,6 +138,8 @@ copy_image_boxes (void *_dst,
GC gc;
int i, j;
+ assert (image->depth == dst->depth);
+
status = acquire (dst);
if (unlikely (status))
return status;
@@ -240,6 +242,7 @@ draw_image_boxes (void *_dst,
int i;
if (image->base.device == dst->base.device &&
+ image->depth == dst->depth &&
_cairo_xlib_shm_surface_get_pixmap (&image->base))
return copy_image_boxes (dst, image, boxes, dx, dy);
@@ -287,7 +290,8 @@ draw_image_boxes (void *_dst,
return CAIRO_INT_STATUS_NOTHING_TO_DO;
}
- if (((cairo_xlib_display_t *)dst->display)->shm) {
+ if (image->depth == dst->depth &&
+ ((cairo_xlib_display_t *)dst->display)->shm) {
cairo_box_t extents;
cairo_rectangle_int_t r;
commit 94815189a42e52a82c602e8f23e69e1826f51ce7
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri Aug 17 22:17:41 2012 +0100
xlib/shm: Clear the similar image surface
The upper layers check that the surface returned to userspace is
cleared; make it so.
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/cairo-xlib-surface-shm.c b/src/cairo-xlib-surface-shm.c
index c8a8ebd..5932def 100644
--- a/src/cairo-xlib-surface-shm.c
+++ b/src/cairo-xlib-surface-shm.c
@@ -776,6 +776,7 @@ _cairo_xlib_surface_clear_shm (cairo_xlib_surface_t *surface)
surface->base.damage = _cairo_damage_create();
memset (shm->image.data, 0, shm->image.stride * shm->image.height);
+ shm->image.base.is_clear = TRUE;
}
static void inc_idle (cairo_surface_t *surface)
@@ -977,7 +978,14 @@ _cairo_xlib_surface_create_similar_shm (void *other,
surface = _cairo_xlib_surface_create_shm (other,
_cairo_format_to_pixman_format_code (format),
width, height);
- if (surface == NULL)
+ if (surface) {
+ if (! surface->is_clear) {
+ cairo_xlib_shm_surface_t *shm = (cairo_xlib_shm_surface_t *) surface;
+ assert (shm->active == 0);
+ memset (shm->image.data, 0, shm->image.stride * shm->image.height);
+ shm->image.base.is_clear = TRUE;
+ }
+ } else
surface = cairo_image_surface_create (format, width, height);
return surface;
commit c068691ff57c2f6cd750a54db17393c0e132cb00
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri Aug 17 21:33:54 2012 +0100
xlib/shm: Use an impromptu upload ShmSegment
Reduce the number of copies required for uploading large image data.
Ultimately we want the client to allocate the similar-image itself to
acheive zero copy, this is just an intermediate step for legacy clients.
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/cairo-xlib-private.h b/src/cairo-xlib-private.h
index b704c6b..26bdede 100644
--- a/src/cairo-xlib-private.h
+++ b/src/cairo-xlib-private.h
@@ -411,9 +411,14 @@ cairo_private cairo_int_status_t
_cairo_xlib_surface_put_shm (cairo_xlib_surface_t *surface);
cairo_private cairo_surface_t *
-_cairo_xlib_surface_create_shm_image (cairo_xlib_surface_t *surface,
- pixman_format_code_t format,
- int width, int height);
+_cairo_xlib_surface_create_shm (cairo_xlib_surface_t *other,
+ pixman_format_code_t format,
+ int width, int height);
+
+cairo_private cairo_surface_t *
+_cairo_xlib_surface_create_shm__image (cairo_xlib_surface_t *surface,
+ pixman_format_code_t format,
+ int width, int height);
cairo_private void
_cairo_xlib_shm_surface_get_ximage (cairo_surface_t *surface,
diff --git a/src/cairo-xlib-render-compositor.c b/src/cairo-xlib-render-compositor.c
index 1fc1e34..02cd6a6 100644
--- a/src/cairo-xlib-render-compositor.c
+++ b/src/cairo-xlib-render-compositor.c
@@ -236,6 +236,7 @@ draw_image_boxes (void *_dst,
cairo_xlib_surface_t *dst = _dst;
struct _cairo_boxes_chunk *chunk;
cairo_image_surface_t *shm;
+ cairo_int_status_t status;
int i;
if (image->base.device == dst->base.device &&
@@ -286,6 +287,60 @@ draw_image_boxes (void *_dst,
return CAIRO_INT_STATUS_NOTHING_TO_DO;
}
+ if (((cairo_xlib_display_t *)dst->display)->shm) {
+ cairo_box_t extents;
+ cairo_rectangle_int_t r;
+
+ _cairo_boxes_extents (boxes, &extents);
+ _cairo_box_round_to_rectangle (&extents, &r);
+
+ shm = (cairo_image_surface_t *)
+ _cairo_xlib_surface_create_shm (dst, image->pixman_format,
+ r.width, r.height);
+ if (shm) {
+ int tx = -r.x, ty = -r.y;
+
+ assert (shm->pixman_format == image->pixman_format);
+ for (chunk = &boxes->chunks; chunk; chunk = chunk->next) {
+ for (i = 0; i < chunk->count; i++) {
+ cairo_box_t *b = &chunk->base[i];
+
+ r.x = _cairo_fixed_integer_part (b->p1.x);
+ r.y = _cairo_fixed_integer_part (b->p1.y);
+ r.width = _cairo_fixed_integer_part (b->p2.x) - r.x;
+ r.height = _cairo_fixed_integer_part (b->p2.y) - r.y;
+
+ if (! pixman_blt ((uint32_t *)image->data, (uint32_t *)shm->data,
+ image->stride / sizeof (uint32_t),
+ shm->stride / sizeof (uint32_t),
+ PIXMAN_FORMAT_BPP (image->pixman_format),
+ PIXMAN_FORMAT_BPP (shm->pixman_format),
+ r.x + dx, r.y + dy,
+ r.x + tx, r.y + ty,
+ r.width, r.height))
+ {
+ pixman_image_composite32 (PIXMAN_OP_SRC,
+ image->pixman_image, NULL, shm->pixman_image,
+ r.x + dx, r.y + dy,
+ 0, 0,
+ r.x + tx, r.y + ty,
+ r.width, r.height);
+ }
+ }
+ }
+
+ dx = tx;
+ dy = ty;
+ image = shm;
+
+ if (_cairo_xlib_shm_surface_get_pixmap (&image->base)) {
+ status = copy_image_boxes (dst, image, boxes, dx, dy);
+ goto out;
+ }
+ }
+ }
+
+ status = CAIRO_STATUS_SUCCESS;
for (chunk = &boxes->chunks; chunk; chunk = chunk->next) {
for (i = 0; i < chunk->count; i++) {
cairo_box_t *b = &chunk->base[i];
@@ -296,12 +351,16 @@ draw_image_boxes (void *_dst,
if ( _cairo_xlib_surface_draw_image (dst, image,
x1 + dx, y1 + dy,
x2 - x1, y2 - y1,
- x1, y1))
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ x1, y1)) {
+ status = CAIRO_INT_STATUS_UNSUPPORTED;
+ goto out;
+ }
}
}
- return CAIRO_STATUS_SUCCESS;
+out:
+ cairo_surface_destroy (&shm->base);
+ return status;
}
static cairo_int_status_t
diff --git a/src/cairo-xlib-surface-shm.c b/src/cairo-xlib-surface-shm.c
index cdb91c8..c8a8ebd 100644
--- a/src/cairo-xlib-surface-shm.c
+++ b/src/cairo-xlib-surface-shm.c
@@ -561,9 +561,7 @@ _cairo_xlib_shm_surface_finish (void *abstract_surface)
shm->info->last_request = shm->active;
_pqueue_push (&display->shm->info, shm->info);
} else {
- cairo_xlib_shm_t *pool = shm->info->pool;
-
- _cairo_mempool_free (&pool->mem, shm->info->mem);
+ _cairo_mempool_free (&shm->info->pool->mem, shm->info->mem);
free (shm->info);
_cairo_xlib_shm_pool_cleanup (display);
@@ -673,6 +671,8 @@ _cairo_xlib_shm_surface_create (cairo_xlib_surface_t *other,
shm->active = shm->info->last_request;
shm->idle = -5;
+ assert (shm->active == 0 || will_sync);
+
cairo_device_release (&display->base);
return shm;
@@ -939,9 +939,25 @@ out:
}
cairo_surface_t *
-_cairo_xlib_surface_create_shm_image (cairo_xlib_surface_t *surface,
- pixman_format_code_t format,
- int width, int height)
+_cairo_xlib_surface_create_shm (cairo_xlib_surface_t *other,
+ pixman_format_code_t format,
+ int width, int height)
+{
+ cairo_surface_t *surface;
+
+ surface = NULL;
+ if (has_shm (other))
+ surface = &_cairo_xlib_shm_surface_create (other, format,
+ width, height, FALSE,
+ has_shm_pixmaps (other))->image.base;
+
+ return surface;
+}
+
+cairo_surface_t *
+_cairo_xlib_surface_create_shm__image (cairo_xlib_surface_t *surface,
+ pixman_format_code_t format,
+ int width, int height)
{
if (! has_shm(surface))
return NULL;
@@ -958,13 +974,10 @@ _cairo_xlib_surface_create_similar_shm (void *other,
{
cairo_surface_t *surface;
- surface = NULL;
- if (has_shm (other))
- surface = &_cairo_xlib_shm_surface_create (other,
- _cairo_format_to_pixman_format_code (format),
- width, height, FALSE,
- has_shm_pixmaps (other))->image.base;
- if (surface == NULL)
+ surface = _cairo_xlib_surface_create_shm (other,
+ _cairo_format_to_pixman_format_code (format),
+ width, height);
+ if (surface == NULL)
surface = cairo_image_surface_create (format, width, height);
return surface;
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index ff4117c..6127e07 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -762,8 +762,8 @@ _get_image_surface (cairo_xlib_surface_t *surface,
pixman_format = _pixman_format_for_xlib_surface (surface);
if (try_shm && pixman_format) {
image = (cairo_image_surface_t *)
- _cairo_xlib_surface_create_shm_image (surface, pixman_format,
- extents->width, extents->height);
+ _cairo_xlib_surface_create_shm__image (surface, pixman_format,
+ extents->width, extents->height);
if (image && image->base.status == CAIRO_STATUS_SUCCESS) {
cairo_xlib_error_func_t old_handler;
XImage shm_image;
@@ -1104,7 +1104,6 @@ _cairo_xlib_surface_draw_image (cairo_xlib_surface_t *surface,
ximage.bits_per_pixel = image_masks.bpp;
ximage.bytes_per_line = image->stride;
ximage.data = (char *)image->data;
- ximage.obdata = NULL;
if (image->base.device == surface->base.device)
ximage.obdata = _cairo_xlib_shm_surface_get_obdata (&image->base);
own_data = FALSE;
commit bc38108947a684fb6e7af99a48ebc8f79d05856a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri Aug 17 20:57:04 2012 +0100
xlib/shm: Limit use of the impromptu fallback pixmap for uploads
We want to avoid unnecessary readback and so only want to use the
ShmPixmap when uploading the complete surface.
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/cairo-xlib-fallback-compositor.c b/src/cairo-xlib-fallback-compositor.c
index d573276..ed2845d 100644
--- a/src/cairo-xlib-fallback-compositor.c
+++ b/src/cairo-xlib-fallback-compositor.c
@@ -74,10 +74,14 @@ _cairo_xlib_shm_compositor_paint (const cairo_compositor_t *_compositor,
cairo_xlib_surface_t *xlib = (cairo_xlib_surface_t *)extents->surface;
cairo_int_status_t status;
cairo_surface_t *shm;
+ cairo_bool_t overwrite;
TRACE ((stderr, "%s\n", __FUNCTION__));
- shm = _cairo_xlib_surface_get_shm (xlib);
+ overwrite =
+ extents->op <= CAIRO_OPERATOR_SOURCE && unclipped (xlib, extents->clip);
+
+ shm = _cairo_xlib_surface_get_shm (xlib, overwrite);
if (shm == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -105,7 +109,7 @@ _cairo_xlib_shm_compositor_mask (const cairo_compositor_t *_compositor,
TRACE ((stderr, "%s\n", __FUNCTION__));
- shm = _cairo_xlib_surface_get_shm (xlib);
+ shm = _cairo_xlib_surface_get_shm (xlib, FALSE);
if (shm == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -139,7 +143,7 @@ _cairo_xlib_shm_compositor_stroke (const cairo_compositor_t *_compositor,
TRACE ((stderr, "%s\n", __FUNCTION__));
- shm = _cairo_xlib_surface_get_shm (xlib);
+ shm = _cairo_xlib_surface_get_shm (xlib, FALSE);
if (shm == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -174,7 +178,7 @@ _cairo_xlib_shm_compositor_fill (const cairo_compositor_t *_compositor,
TRACE ((stderr, "%s\n", __FUNCTION__));
- shm = _cairo_xlib_surface_get_shm (xlib);
+ shm = _cairo_xlib_surface_get_shm (xlib, FALSE);
if (shm == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -207,7 +211,7 @@ _cairo_xlib_shm_compositor_glyphs (const cairo_compositor_t *_compositor,
TRACE ((stderr, "%s\n", __FUNCTION__));
- shm = _cairo_xlib_surface_get_shm (xlib);
+ shm = _cairo_xlib_surface_get_shm (xlib, FALSE);
if (shm == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
diff --git a/src/cairo-xlib-private.h b/src/cairo-xlib-private.h
index 8e9c044..b704c6b 100644
--- a/src/cairo-xlib-private.h
+++ b/src/cairo-xlib-private.h
@@ -404,7 +404,8 @@ _cairo_xlib_surface_create_similar_shm (void *surface,
int width, int height);
cairo_private cairo_surface_t *
-_cairo_xlib_surface_get_shm (cairo_xlib_surface_t *surface);
+_cairo_xlib_surface_get_shm (cairo_xlib_surface_t *surface,
+ cairo_bool_t overwrite);
cairo_private cairo_int_status_t
_cairo_xlib_surface_put_shm (cairo_xlib_surface_t *surface);
diff --git a/src/cairo-xlib-render-compositor.c b/src/cairo-xlib-render-compositor.c
index f76db24..1fc1e34 100644
--- a/src/cairo-xlib-render-compositor.c
+++ b/src/cairo-xlib-render-compositor.c
@@ -205,6 +205,28 @@ copy_image_boxes (void *_dst,
return CAIRO_STATUS_SUCCESS;
}
+static cairo_bool_t
+boxes_cover_surface (cairo_boxes_t *boxes,
+ cairo_xlib_surface_t *surface)
+{
+ cairo_box_t *b;
+
+ if (boxes->num_boxes != 1)
+ return FALSE;
+
+ b = &boxes->chunks.base[0];
+
+ if (_cairo_fixed_integer_part (b->p1.x) > 0 ||
+ _cairo_fixed_integer_part (b->p1.y) > 0)
+ return FALSE;
+
+ if (_cairo_fixed_integer_part (b->p2.x) < surface->width ||
+ _cairo_fixed_integer_part (b->p2.y) < surface->height)
+ return FALSE;
+
+ return TRUE;
+}
+
static cairo_int_status_t
draw_image_boxes (void *_dst,
cairo_image_surface_t *image,
@@ -220,7 +242,11 @@ draw_image_boxes (void *_dst,
_cairo_xlib_shm_surface_get_pixmap (&image->base))
return copy_image_boxes (dst, image, boxes, dx, dy);
- shm = (cairo_image_surface_t *) _cairo_xlib_surface_get_shm (dst);
+ shm = NULL;
+ if (boxes_cover_surface (boxes, dst))
+ shm = (cairo_image_surface_t *) _cairo_xlib_surface_get_shm (dst, TRUE);
+ if (shm == NULL && dst->shm)
+ shm = (cairo_image_surface_t *) _cairo_xlib_surface_get_shm (dst, FALSE);
if (shm) {
for (chunk = &boxes->chunks; chunk; chunk = chunk->next) {
for (i = 0; i < chunk->count; i++) {
diff --git a/src/cairo-xlib-surface-shm.c b/src/cairo-xlib-surface-shm.c
index 7d9a3e1..cdb91c8 100644
--- a/src/cairo-xlib-surface-shm.c
+++ b/src/cairo-xlib-surface-shm.c
@@ -791,7 +791,8 @@ static void dec_idle (cairo_surface_t *surface)
}
cairo_surface_t *
-_cairo_xlib_surface_get_shm (cairo_xlib_surface_t *surface)
+_cairo_xlib_surface_get_shm (cairo_xlib_surface_t *surface,
+ cairo_bool_t overwrite)
{
if (surface->fallback) {
assert (surface->base.damage);
@@ -836,6 +837,11 @@ _cairo_xlib_surface_get_shm (cairo_xlib_surface_t *surface)
surface->shm->damage = _cairo_damage_create ();
}
+ if (overwrite) {
+ _cairo_damage_destroy (surface->base.damage);
+ surface->base.damage = _cairo_damage_create ();
+ }
+
if (!surface->base.is_clear && surface->base.damage->dirty)
_cairo_xlib_surface_update_shm (surface);
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index aeff746..ff4117c 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -1317,7 +1317,7 @@ _cairo_xlib_surface_acquire_source_image (void *abstract_surf
*image_extra = NULL;
*image_out = (cairo_image_surface_t *)
- _cairo_xlib_surface_get_shm (abstract_surface);
+ _cairo_xlib_surface_get_shm (abstract_surface, FALSE);
if (*image_out)
return (*image_out)->base.status;
@@ -1363,7 +1363,7 @@ _cairo_xlib_surface_map_to_image (void *abstract_surface,
cairo_xlib_surface_t *surface = abstract_surface;
cairo_surface_t *image;
- image = _cairo_xlib_surface_get_shm (abstract_surface);
+ image = _cairo_xlib_surface_get_shm (abstract_surface, FALSE);
if (image) {
assert (surface->base.damage);
surface->fallback++;
commit 4af7a1c8637f3008a2265e063ab990eec07e02dd
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri Aug 17 23:17:43 2012 +0100
xlib/shm: Propagate the last-request to the synchronous create
If we optimise away the pending frees we must be careful to propagate
the implied sync.
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/cairo-xlib-surface-shm.c b/src/cairo-xlib-surface-shm.c
index 5c23c9b..7d9a3e1 100644
--- a/src/cairo-xlib-surface-shm.c
+++ b/src/cairo-xlib-surface-shm.c
@@ -328,7 +328,8 @@ _cairo_xlib_shm_info_cleanup (cairo_xlib_display_t *display)
}
static cairo_xlib_shm_info_t *
-_cairo_xlib_shm_info_find (cairo_xlib_display_t *display, size_t size)
+_cairo_xlib_shm_info_find (cairo_xlib_display_t *display,
+ size_t size, unsigned long *last_request)
{
cairo_xlib_shm_info_t *info;
struct pqueue *pq = &display->shm->info;
@@ -343,6 +344,7 @@ _cairo_xlib_shm_info_find (cairo_xlib_display_t *display, size_t size)
if (info->size >= size && size <= 2*info->size)
return info;
+ *last_request = info->last_request;
_cairo_mempool_free (&info->pool->mem, info->mem);
free (info);
} while ((info = PQ_TOP(pq)));
@@ -456,10 +458,11 @@ _cairo_xlib_shm_info_create (cairo_xlib_display_t *display,
{
cairo_xlib_shm_info_t *info;
cairo_xlib_shm_t *pool;
+ unsigned long last_request = 0;
void *mem = NULL;
if (will_sync) {
- info = _cairo_xlib_shm_info_find (display, size);
+ info = _cairo_xlib_shm_info_find (display, size, &last_request);
if (info)
return info;
}
@@ -483,7 +486,7 @@ _cairo_xlib_shm_info_create (cairo_xlib_display_t *display,
info->pool = pool;
info->mem = mem;
info->size = size;
- info->last_request = 0;
+ info->last_request = last_request;
return info;
}
More information about the cairo-commit
mailing list