diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2011-11-23 18:22:59 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2011-11-23 18:40:02 +0000 |
commit | 6a2b754ec9d2e6dd52b9e51fd674531b3a7e2320 (patch) | |
tree | 7cdbad69f3b46549cae0df28db33fe24d8aea653 /src/cairo-xlib-source.c | |
parent | 49d3a6a95e52876a8660855589d01bd0ec8ab473 (diff) | |
download | cairo-6a2b754ec9d2e6dd52b9e51fd674531b3a7e2320.tar.gz |
xlib: Eliminate redundant copies of subsurfaces
If the sample is wholly contained within the subsurface of the original,
we can simply use the original with an offset; thereby only copying the
data if we are sampling outside the subsurface bounds.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src/cairo-xlib-source.c')
-rw-r--r-- | src/cairo-xlib-source.c | 207 |
1 files changed, 106 insertions, 101 deletions
diff --git a/src/cairo-xlib-source.c b/src/cairo-xlib-source.c index eca4fa9c4..54d87571b 100644 --- a/src/cairo-xlib-source.c +++ b/src/cairo-xlib-source.c @@ -58,18 +58,18 @@ #define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */ -static cairo_surface_t * -unwrap_surface (cairo_surface_t *surface, int *tx, int *ty) +static cairo_xlib_surface_t * +unwrap_surface (cairo_surface_t *surface) { if (_cairo_surface_is_paginated (surface)) surface = _cairo_paginated_surface_get_recording (surface); if (_cairo_surface_is_snapshot (surface)) surface = _cairo_surface_snapshot_get_target (surface); if (_cairo_surface_is_subsurface (surface)) - surface = _cairo_surface_subsurface_get_target_with_offset (surface, tx, ty); + surface = _cairo_surface_subsurface_get_target (surface); if (_cairo_surface_is_observer (surface)) surface = _cairo_surface_observer_get_target (surface); - return surface; + return (cairo_xlib_surface_t *)surface; } static cairo_status_t @@ -542,6 +542,85 @@ solid_source (cairo_xlib_surface_t *dst, } static cairo_surface_t * +embedded_source (cairo_xlib_surface_t *dst, + const cairo_surface_pattern_t *pattern, + cairo_xlib_surface_t *src, + const cairo_rectangle_int_t *extents, + int *src_x, int *src_y) +{ + cairo_xlib_source_t *source; + Display *dpy = dst->display->display; + cairo_int_status_t status; + XTransform xtransform; + XRenderPictureAttributes pa; + unsigned mask = 0; + + /* As these are frequent and meant to be fast, we track pictures for + * native surface and minimise update requests. + */ + source = &src->embedded_source; + if (source->picture == None) { + XRenderPictureAttributes pa; + + _cairo_surface_init (&source->base, + &cairo_xlib_source_backend, + NULL, /* device */ + CAIRO_CONTENT_COLOR_ALPHA); + + pa.subwindow_mode = IncludeInferiors; + source->picture = XRenderCreatePicture (dpy, + src->drawable, + src->xrender_format, + CPSubwindowMode, &pa); + + source->has_component_alpha = 0; + source->has_matrix = 0; + source->filter = CAIRO_FILTER_NEAREST; + source->extend = CAIRO_EXTEND_NONE; + } + + status = _cairo_matrix_to_pixman_matrix_offset (&pattern->base.matrix, + pattern->base.filter, + extents->x + extents->width / 2, + extents->y + extents->height / 2, + (pixman_transform_t *)&xtransform, + src_x, src_y); + + if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) { + if (source->has_matrix) { + source->has_matrix = 0; + memcpy (&xtransform, &identity, sizeof (identity)); + status = CAIRO_INT_STATUS_SUCCESS; + } + } else + source->has_matrix = 1; + if (status == CAIRO_INT_STATUS_SUCCESS) + XRenderSetPictureTransform (dpy, source->picture, &xtransform); + + if (source->filter != pattern->base.filter) { + picture_set_filter (dpy, source->picture, pattern->base.filter); + source->filter = pattern->base.filter; + } + + if (source->has_component_alpha != pattern->base.has_component_alpha) { + pa.component_alpha = pattern->base.has_component_alpha; + mask |= CPComponentAlpha; + source->has_component_alpha = pattern->base.has_component_alpha; + } + + if (source->extend != pattern->base.extend) { + pa.repeat = extend_to_repeat (pattern->base.extend); + mask |= CPRepeat; + source->extend = pattern->base.extend; + } + + if (mask) + XRenderChangePicture (dpy, source->picture, mask, &pa); + + return cairo_surface_reference (&source->base); +} + +static cairo_surface_t * subsurface_source (cairo_xlib_surface_t *dst, const cairo_surface_pattern_t *pattern, cairo_bool_t is_mask, @@ -553,7 +632,6 @@ subsurface_source (cairo_xlib_surface_t *dst, cairo_xlib_surface_t *src; cairo_xlib_source_t *source; Display *dpy = dst->display->display; - cairo_bool_t is_contained = FALSE; cairo_int_status_t status; cairo_surface_pattern_t local_pattern; XTransform xtransform; @@ -566,19 +644,26 @@ subsurface_source (cairo_xlib_surface_t *dst, sample->x + sample->width <= sub->extents.width && sample->y + sample->height <= sub->extents.height) { - is_contained = TRUE; - } - - if (pattern->base.filter == CAIRO_FILTER_NEAREST && is_contained && - _cairo_matrix_is_translation (&pattern->base.matrix)) - { src = (cairo_xlib_surface_t *) sub->target; - _cairo_xlib_surface_ensure_picture (src); - *src_x += pattern->base.matrix.x0 + sub->extents.x; - *src_y += pattern->base.matrix.y0 + sub->extents.y; + if (pattern->base.filter == CAIRO_FILTER_NEAREST && + _cairo_matrix_is_translation (&pattern->base.matrix)) + { + *src_x += pattern->base.matrix.x0 + sub->extents.x; + *src_y += pattern->base.matrix.y0 + sub->extents.y; - return cairo_surface_reference (&src->base); + _cairo_xlib_surface_ensure_picture (src); + return cairo_surface_reference (&src->base); + } + else + { + cairo_surface_pattern_t local_pattern = *pattern; + local_pattern.base.matrix.x0 += sub->extents.x; + local_pattern.base.matrix.y0 += sub->extents.y; + local_pattern.base.extend = CAIRO_EXTEND_NONE; + return embedded_source (dst, &local_pattern, src, extents, + src_x, src_y); + } } if (sub->snapshot) { @@ -669,30 +754,18 @@ native_source (cairo_xlib_surface_t *dst, int *src_x, int *src_y) { cairo_xlib_surface_t *src = (cairo_xlib_surface_t *) pattern->surface; - cairo_xlib_source_t *source; - Display *dpy = dst->display->display; - cairo_bool_t is_contained = FALSE; - cairo_int_status_t status; - XTransform xtransform; - XRenderPictureAttributes pa; - int mask = 0; if (_cairo_surface_is_subsurface (pattern->surface)) return subsurface_source (dst, pattern, is_mask, extents, sample, src_x, src_y); - src = (cairo_xlib_surface_t *) - unwrap_surface (pattern->surface, src_x, src_y); + src = unwrap_surface (pattern->surface); - if (sample->x >= 0 && sample->y >= 0 && + if (pattern->base.filter == CAIRO_FILTER_NEAREST && + sample->x >= 0 && sample->y >= 0 && sample->x + sample->width <= src->width && - sample->y + sample->height <= src->height) - { - is_contained = TRUE; - } - - if (pattern->base.filter == CAIRO_FILTER_NEAREST && is_contained && + sample->y + sample->height <= src->height && _cairo_matrix_is_translation (&pattern->base.matrix)) { *src_x += pattern->base.matrix.x0; @@ -701,74 +774,7 @@ native_source (cairo_xlib_surface_t *dst, return cairo_surface_reference (&src->base); } - /* As these are frequent and meant to be fast, we track pictures for - * native surface and minimise update requests. - */ - source = &src->embedded_source; - if (source->picture == None) { - Picture picture; - XRenderPictureAttributes pa; - int mask = 0; - - pa.subwindow_mode = IncludeInferiors; - mask |= CPSubwindowMode; - - picture = XRenderCreatePicture (dpy, - src->drawable, - src->xrender_format, - mask, &pa); - - _cairo_surface_init (&source->base, - &cairo_xlib_source_backend, - NULL, /* device */ - CAIRO_CONTENT_COLOR_ALPHA); - source->picture = picture; - - source->has_component_alpha = 0; - source->has_matrix = 0; - source->filter = CAIRO_FILTER_NEAREST; - source->extend = CAIRO_EXTEND_NONE; - } - - status = _cairo_matrix_to_pixman_matrix_offset (&pattern->base.matrix, - pattern->base.filter, - extents->x + extents->width / 2, - extents->y + extents->height / 2, - (pixman_transform_t *)&xtransform, - src_x, src_y); - - if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) { - if (source->has_matrix) { - source->has_matrix = 0; - memcpy (&xtransform, &identity, sizeof (identity)); - status = CAIRO_INT_STATUS_SUCCESS; - } - } else - source->has_matrix = 1; - if (status == CAIRO_INT_STATUS_SUCCESS) - XRenderSetPictureTransform (dpy, source->picture, &xtransform); - - if (source->filter != pattern->base.filter) { - picture_set_filter (dpy, source->picture, pattern->base.filter); - source->filter = pattern->base.filter; - } - - if (source->has_component_alpha != pattern->base.has_component_alpha) { - pa.component_alpha = pattern->base.has_component_alpha; - mask |= CPComponentAlpha; - source->has_component_alpha = pattern->base.has_component_alpha; - } - - if (source->extend != pattern->base.extend) { - pa.repeat = extend_to_repeat (pattern->base.extend); - mask |= CPRepeat; - source->extend = pattern->base.extend; - } - - if (mask) - XRenderChangePicture (dpy, source->picture, mask, &pa); - - return cairo_surface_reference (&source->base); + return embedded_source (dst, pattern, src, extents, src_x, src_y); } #if 0 @@ -1016,7 +1022,6 @@ _cairo_xlib_source_create_for_pattern (cairo_surface_t *_dst, int *src_x, int *src_y) { cairo_xlib_surface_t *dst = (cairo_xlib_surface_t *)_dst; - int tx, ty; *src_x = *src_y = 0; @@ -1032,7 +1037,7 @@ _cairo_xlib_source_create_for_pattern (cairo_surface_t *_dst, cairo_surface_pattern_t *spattern = (cairo_surface_pattern_t *)pattern; if (spattern->surface->type == CAIRO_SURFACE_TYPE_XLIB && _cairo_xlib_surface_same_screen (dst, - (cairo_xlib_surface_t *)unwrap_surface (spattern->surface, &tx, &ty))) + unwrap_surface (spattern->surface))) return native_source (dst, spattern, is_mask, extents, sample, src_x, src_y); |