diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2012-08-17 21:33:54 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2012-08-17 23:43:26 +0100 |
commit | c068691ff57c2f6cd750a54db17393c0e132cb00 (patch) | |
tree | 572c6165864275dc7b1a0d002a80dd88899ef8e9 /src/cairo-xlib-render-compositor.c | |
parent | bc38108947a684fb6e7af99a48ebc8f79d05856a (diff) | |
download | cairo-c068691ff57c2f6cd750a54db17393c0e132cb00.tar.gz |
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@chris-wilson.co.uk>
Diffstat (limited to 'src/cairo-xlib-render-compositor.c')
-rw-r--r-- | src/cairo-xlib-render-compositor.c | 65 |
1 files changed, 62 insertions, 3 deletions
diff --git a/src/cairo-xlib-render-compositor.c b/src/cairo-xlib-render-compositor.c index 1fc1e345e..02cd6a67d 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 |