From 4d3632761b928c14fb1ce257af077f45658d8537 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 25 Apr 2010 09:42:13 +0100 Subject: [PATCH] clip: Report the surface offset when retrieving the clip mask Stop the callers from guessing the origin of the clip surface by reporting it explicitly! This enables the clip to bypass any rectangles overlaid on top of the clip surface, which is common when the backends limit the clip to the extents of the operation -- but irrelevant to the actual content of the clip mask --- src/cairo-clip-private.h | 2 +- src/cairo-clip.c | 26 +++++++++++++++++----- src/cairo-image-surface.c | 39 ++++++++++++++++++--------------- src/cairo-surface-fallback.c | 20 ++++++++--------- src/cairo-xcb-surface-render.c | 31 +++++++++++++------------- src/drm/cairo-drm-i915-shader.c | 9 ++++---- src/drm/cairo-drm-i965-shader.c | 7 +++--- 7 files changed, 75 insertions(+), 59 deletions(-) diff --git a/src/cairo-clip-private.h b/src/cairo-clip-private.h index 815fbf864..8e30f13ad 100644 --- a/src/cairo-clip-private.h +++ b/src/cairo-clip-private.h @@ -112,7 +112,7 @@ cairo_private const cairo_rectangle_int_t * _cairo_clip_get_extents (const cairo_clip_t *clip); cairo_private cairo_surface_t * -_cairo_clip_get_surface (cairo_clip_t *clip, cairo_surface_t *dst); +_cairo_clip_get_surface (cairo_clip_t *clip, cairo_surface_t *dst, int *tx, int *ty); cairo_private cairo_status_t _cairo_clip_combine_with_surface (cairo_clip_t *clip, diff --git a/src/cairo-clip.c b/src/cairo-clip.c index fca47597c..ff4aeb636 100644 --- a/src/cairo-clip.c +++ b/src/cairo-clip.c @@ -942,7 +942,8 @@ _cairo_clip_path_to_boxes (cairo_clip_path_t *clip_path, static cairo_surface_t * _cairo_clip_path_get_surface (cairo_clip_path_t *clip_path, - cairo_surface_t *target) + cairo_surface_t *target, + int *tx, int *ty) { const cairo_rectangle_int_t *clip_extents = &clip_path->extents; cairo_bool_t need_translate; @@ -950,9 +951,19 @@ _cairo_clip_path_get_surface (cairo_clip_path_t *clip_path, cairo_clip_path_t *prev; cairo_status_t status; + while (clip_path->prev != NULL && + clip_path->flags & CAIRO_CLIP_PATH_IS_BOX && + clip_path->path.maybe_fill_region) + { + clip_path = clip_path->prev; + } + + clip_extents = &clip_path->extents; if (clip_path->surface != NULL && clip_path->surface->backend == target->backend) { + *tx = clip_extents->x; + *ty = clip_extents->y; return clip_path->surface; } @@ -1046,16 +1057,17 @@ _cairo_clip_path_get_surface (cairo_clip_path_t *clip_path, { cairo_surface_pattern_t pattern; cairo_surface_t *prev_surface; + int prev_tx, prev_ty; - prev_surface = _cairo_clip_path_get_surface (prev, target); + prev_surface = _cairo_clip_path_get_surface (prev, target, &prev_tx, &prev_ty); if (unlikely (prev_surface->status)) goto BAIL; _cairo_pattern_init_for_surface (&pattern, prev_surface); pattern.base.filter = CAIRO_FILTER_NEAREST; cairo_matrix_init_translate (&pattern.base.matrix, - clip_extents->x - prev->extents.x, - clip_extents->y - prev->extents.y); + clip_extents->x - prev_tx, + clip_extents->y - prev_ty); status = _cairo_surface_paint (surface, CAIRO_OPERATOR_IN, &pattern.base, @@ -1071,6 +1083,8 @@ _cairo_clip_path_get_surface (cairo_clip_path_t *clip_path, prev = prev->prev; } + *tx = clip_extents->x; + *ty = clip_extents->y; cairo_surface_destroy (clip_path->surface); return clip_path->surface = surface; @@ -1158,11 +1172,11 @@ _cairo_debug_print_clip (FILE *stream, cairo_clip_t *clip) } cairo_surface_t * -_cairo_clip_get_surface (cairo_clip_t *clip, cairo_surface_t *target) +_cairo_clip_get_surface (cairo_clip_t *clip, cairo_surface_t *target, int *tx, int *ty) { /* XXX is_clear -> all_clipped */ assert (clip->path != NULL); - return _cairo_clip_path_get_surface (clip->path, target); + return _cairo_clip_path_get_surface (clip->path, target, tx, ty); } cairo_status_t diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c index 753882647..36958185d 100644 --- a/src/cairo-image-surface.c +++ b/src/cairo-image-surface.c @@ -1481,13 +1481,14 @@ _cairo_image_surface_fixup_unbounded (cairo_image_surface_t *dst, if (clip != NULL) { cairo_surface_t *clip_surface; + int clip_x, clip_y; - clip_surface = _cairo_clip_get_surface (clip, &dst->base); + clip_surface = _cairo_clip_get_surface (clip, &dst->base, &clip_x, &clip_y); assert (clip_surface->status == CAIRO_STATUS_SUCCESS); mask = ((cairo_image_surface_t *) clip_surface)->pixman_image; - mask_x = -clip->path->extents.x; - mask_y = -clip->path->extents.y; + mask_x = -clip_x; + mask_y = -clip_y; } else { if (rects->bounded.width == rects->unbounded.width && rects->bounded.height == rects->unbounded.height) @@ -1852,6 +1853,7 @@ _clip_and_composite_combine (cairo_clip_t *clip, { pixman_image_t *tmp; cairo_surface_t *clip_surface; + int clip_x, clip_y; cairo_status_t status; tmp = pixman_image_create_bits (dst->pixman_format, @@ -1887,7 +1889,7 @@ _clip_and_composite_combine (cairo_clip_t *clip, goto CLEANUP_SURFACE; assert (clip->path != NULL); - clip_surface = _cairo_clip_get_surface (clip, &dst->base); + clip_surface = _cairo_clip_get_surface (clip, &dst->base, &clip_x, &clip_y); if (unlikely (clip_surface->status)) goto CLEANUP_SURFACE; @@ -1898,8 +1900,8 @@ _clip_and_composite_combine (cairo_clip_t *clip, ((cairo_image_surface_t *) clip_surface)->pixman_image, dst->pixman_image, 0, 0, - extents->x - clip->path->extents.x, - extents->y - clip->path->extents.y, + extents->x - clip_x, + extents->y - clip_y, extents->x, extents->y, extents->width, extents->height); #else @@ -1907,8 +1909,8 @@ _clip_and_composite_combine (cairo_clip_t *clip, pixman_image_composite32 (PIXMAN_OP_OUT_REVERSE, ((cairo_image_surface_t *) clip_surface)->pixman_image, NULL, dst->pixman_image, - extents->x - clip->path->extents.x, - extents->y - clip->path->extents.y, + extents->x - clip_x, + extents->y - clip_y, 0, 0, extents->x, extents->y, extents->width, extents->height); @@ -1919,8 +1921,8 @@ _clip_and_composite_combine (cairo_clip_t *clip, ((cairo_image_surface_t *) clip_surface)->pixman_image, dst->pixman_image, 0, 0, - extents->x - clip->path->extents.x, - extents->y - clip->path->extents.y, + extents->x - clip_x, + extents->y - clip_y, extents->x, extents->y, extents->width, extents->height); #endif @@ -1930,8 +1932,8 @@ _clip_and_composite_combine (cairo_clip_t *clip, ((cairo_image_surface_t *) clip_surface)->pixman_image, dst->pixman_image, 0, 0, - extents->x - clip->path->extents.x, - extents->y - clip->path->extents.y, + extents->x - clip_x, + extents->y - clip_y, extents->x, extents->y, extents->width, extents->height); } @@ -2741,13 +2743,14 @@ _composite_boxes (cairo_image_surface_t *dst, if (need_clip_mask) { cairo_surface_t *clip_surface; + int clip_x, clip_y; - clip_surface = _cairo_clip_get_surface (clip, &dst->base); + clip_surface = _cairo_clip_get_surface (clip, &dst->base, &clip_x, &clip_y); if (unlikely (clip_surface->status)) return clip_surface->status; - mask_x = -clip->path->extents.x; - mask_y = -clip->path->extents.y; + mask_x = -clip_x; + mask_y = -clip_y; if (op == CAIRO_OPERATOR_CLEAR) { pattern = NULL; @@ -2831,9 +2834,9 @@ _clip_and_composite_boxes (cairo_image_surface_t *dst, info.num_traps = traps.num_traps; info.traps = traps.traps; info.antialias = antialias; - status = _clip_and_composite (dst, op, src, - _composite_traps, &info, - extents, clip); + status = _clip_and_composite (dst, op, src, + _composite_traps, &info, + extents, clip); _cairo_traps_fini (&traps); return status; diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c index 7a6932249..f2b017a6d 100644 --- a/src/cairo-surface-fallback.c +++ b/src/cairo-surface-fallback.c @@ -222,6 +222,7 @@ _clip_and_composite_combine (cairo_clip_t *clip, cairo_surface_pattern_t pattern; cairo_surface_pattern_t clip_pattern; cairo_surface_t *clip_surface; + int clip_x, clip_y; cairo_status_t status; /* We'd be better off here creating a surface identical in format @@ -266,7 +267,7 @@ _clip_and_composite_combine (cairo_clip_t *clip, goto CLEANUP_SURFACE; assert (clip->path != NULL); - clip_surface = _cairo_clip_get_surface (clip, dst); + clip_surface = _cairo_clip_get_surface (clip, dst, &clip_x, &clip_y); if (unlikely (clip_surface->status)) goto CLEANUP_SURFACE; @@ -275,8 +276,8 @@ _clip_and_composite_combine (cairo_clip_t *clip, /* Combine that with the clip */ status = _cairo_surface_composite (CAIRO_OPERATOR_DEST_IN, &clip_pattern.base, NULL, intermediate, - extents->x - clip->path->extents.x, - extents->y - clip->path->extents.y, + extents->x - clip_x, + extents->y - clip_y, 0, 0, 0, 0, extents->width, extents->height, @@ -287,8 +288,8 @@ _clip_and_composite_combine (cairo_clip_t *clip, /* Punch the clip out of the destination */ status = _cairo_surface_composite (CAIRO_OPERATOR_DEST_OUT, &clip_pattern.base, NULL, dst, - extents->x - clip->path->extents.x, - extents->y - clip->path->extents.y, + extents->x - clip_x, + extents->y - clip_y, 0, 0, extents->x, extents->y, extents->width, extents->height, @@ -477,9 +478,9 @@ _composite_trap_region (cairo_clip_t *clip, if (clip != NULL) { cairo_surface_t *clip_surface = NULL; - const cairo_rectangle_int_t *clip_extents; + int clip_x, clip_y; - clip_surface = _cairo_clip_get_surface (clip, dst); + clip_surface = _cairo_clip_get_surface (clip, dst, &clip_x, &clip_y); if (unlikely (clip_surface->status)) return clip_surface->status; @@ -489,9 +490,8 @@ _composite_trap_region (cairo_clip_t *clip, } _cairo_pattern_init_for_surface (&mask_pattern, clip_surface); - clip_extents = _cairo_clip_get_extents (clip); - mask_x = extents->x - clip_extents->x; - mask_y = extents->y - clip_extents->y; + mask_x = extents->x - clip_x; + mask_y = extents->y - clip_y; mask = &mask_pattern.base; } diff --git a/src/cairo-xcb-surface-render.c b/src/cairo-xcb-surface-render.c index 9cd51f8a9..5775a9eb6 100644 --- a/src/cairo-xcb-surface-render.c +++ b/src/cairo-xcb-surface-render.c @@ -1894,6 +1894,7 @@ _clip_and_composite_combine (cairo_clip_t *clip, { cairo_xcb_surface_t *tmp; cairo_surface_t *clip_surface; + int clip_x, clip_y; xcb_render_picture_t clip_picture; cairo_status_t status; @@ -1952,7 +1953,7 @@ _clip_and_composite_combine (cairo_clip_t *clip, if (unlikely (status)) goto CLEANUP_SURFACE; - clip_surface = _cairo_clip_get_surface (clip, &dst->base); + clip_surface = _cairo_clip_get_surface (clip, &dst->base, &clip_x, &clip_y); if (unlikely (clip_surface->status)) goto CLEANUP_SURFACE; @@ -1972,8 +1973,8 @@ _clip_and_composite_combine (cairo_clip_t *clip, _cairo_xcb_connection_render_composite (dst->connection, XCB_RENDER_PICT_OP_OUT_REVERSE, clip_picture, XCB_NONE, dst->picture, - extents->x - clip->path->extents.x, - extents->y - clip->path->extents.y, + extents->x - clip_x, + extents->y - clip_y, 0, 0, extents->x, extents->y, extents->width, extents->height); @@ -1983,8 +1984,8 @@ _clip_and_composite_combine (cairo_clip_t *clip, XCB_RENDER_PICT_OP_ADD, tmp->picture, clip_picture, dst->picture, 0, 0, - extents->x - clip->path->extents.x, - extents->y - clip->path->extents.y, + extents->x - clip_x, + extents->y - clip_y, extents->x, extents->y, extents->width, extents->height); } @@ -2182,13 +2183,10 @@ _cairo_xcb_surface_fixup_unbounded_with_mask (cairo_xcb_surface_t *dst, cairo_xcb_surface_t *mask; int mask_x, mask_y; - mask = (cairo_xcb_surface_t *) _cairo_clip_get_surface (clip, &dst->base); + mask = (cairo_xcb_surface_t *) _cairo_clip_get_surface (clip, &dst->base, &mask_x, &mask_y); if (unlikely (mask->base.status)) return mask->base.status; - mask_x = - clip->path->extents.x; - mask_y = - clip->path->extents.y; - /* top */ if (rects->bounded.y != rects->unbounded.y) { int x = rects->unbounded.x; @@ -2199,7 +2197,7 @@ _cairo_xcb_surface_fixup_unbounded_with_mask (cairo_xcb_surface_t *dst, _cairo_xcb_connection_render_composite (dst->connection, XCB_RENDER_PICT_OP_OUT_REVERSE, mask->picture, XCB_NONE, dst->picture, - x + mask_x, y + mask_y, + x - mask_x, y - mask_y, 0, 0, x, y, width, height); @@ -2215,7 +2213,7 @@ _cairo_xcb_surface_fixup_unbounded_with_mask (cairo_xcb_surface_t *dst, _cairo_xcb_connection_render_composite (dst->connection, XCB_RENDER_PICT_OP_OUT_REVERSE, mask->picture, XCB_NONE, dst->picture, - x + mask_x, y + mask_y, + x - mask_x, y - mask_y, 0, 0, x, y, width, height); @@ -2231,7 +2229,7 @@ _cairo_xcb_surface_fixup_unbounded_with_mask (cairo_xcb_surface_t *dst, _cairo_xcb_connection_render_composite (dst->connection, XCB_RENDER_PICT_OP_OUT_REVERSE, mask->picture, XCB_NONE, dst->picture, - x + mask_x, y + mask_y, + x - mask_x, y - mask_y, 0, 0, x, y, width, height); @@ -2247,7 +2245,7 @@ _cairo_xcb_surface_fixup_unbounded_with_mask (cairo_xcb_surface_t *dst, _cairo_xcb_connection_render_composite (dst->connection, XCB_RENDER_PICT_OP_OUT_REVERSE, mask->picture, XCB_NONE, dst->picture, - x + mask_x, y + mask_y, + x - mask_x, y - mask_y, 0, 0, x, y, width, height); @@ -2541,16 +2539,17 @@ _composite_boxes (cairo_xcb_surface_t *dst, if (need_clip_mask) { cairo_surface_t *clip_surface; + int clip_x, clip_y; - clip_surface = _cairo_clip_get_surface (clip, &dst->base); + clip_surface = _cairo_clip_get_surface (clip, &dst->base, &clip_x, &clip_y); if (unlikely (clip_surface->status)) return clip_surface->status; _cairo_pattern_init_for_surface (&mask, clip_surface); mask.base.filter = CAIRO_FILTER_NEAREST; cairo_matrix_init_translate (&mask.base.matrix, - -clip->path->extents.x, - -clip->path->extents.y); + -clip_x, + -clip_y); if (op == CAIRO_OPERATOR_CLEAR) { src = NULL; diff --git a/src/drm/cairo-drm-i915-shader.c b/src/drm/cairo-drm-i915-shader.c index 13f9d85ab..a56513d1f 100644 --- a/src/drm/cairo-drm-i915-shader.c +++ b/src/drm/cairo-drm-i915-shader.c @@ -2403,11 +2403,11 @@ i915_shader_set_clip (i915_shader_t *shader, cairo_clip_t *clip) { cairo_surface_t *clip_surface; - const cairo_rectangle_int_t *clip_extents; + int clip_x, clip_y; union i915_shader_channel *channel; i915_surface_t *s; - clip_surface = _cairo_clip_get_surface (clip, &shader->target->intel.drm.base); + clip_surface = _cairo_clip_get_surface (clip, &shader->target->intel.drm.base, &clip_x, &clip_y); assert (clip_surface->status == CAIRO_STATUS_SUCCESS); assert (clip_surface->type == CAIRO_SURFACE_TYPE_DRM); @@ -2434,13 +2434,12 @@ i915_shader_set_clip (i915_shader_t *shader, SS3_NORMALIZED_COORDS | i915_texture_extend (CAIRO_EXTEND_NONE); - clip_extents = _cairo_clip_get_extents (clip); cairo_matrix_init_scale (&shader->clip.base.matrix, 1. / s->intel.drm.width, 1. / s->intel.drm.height); cairo_matrix_translate (&shader->clip.base.matrix, - NEAREST_BIAS - clip_extents->x, - NEAREST_BIAS - clip_extents->y); + NEAREST_BIAS - clip_x, + NEAREST_BIAS - clip_y); } static cairo_status_t diff --git a/src/drm/cairo-drm-i965-shader.c b/src/drm/cairo-drm-i965-shader.c index fcfec2957..f18494ce0 100644 --- a/src/drm/cairo-drm-i965-shader.c +++ b/src/drm/cairo-drm-i965-shader.c @@ -762,10 +762,11 @@ i965_shader_set_clip (i965_shader_t *shader, cairo_clip_t *clip) { cairo_surface_t *clip_surface; + int clip_x, clip_y; union i965_shader_channel *channel; i965_surface_t *s; - clip_surface = _cairo_clip_get_surface (clip, &shader->target->intel.drm.base); + clip_surface = _cairo_clip_get_surface (clip, &shader->target->intel.drm.base, &clip_x, &clip_y); assert (clip_surface->status == CAIRO_STATUS_SUCCESS); assert (clip_surface->type == CAIRO_SURFACE_TYPE_DRM); s = (i965_surface_t *) clip_surface; @@ -793,8 +794,8 @@ i965_shader_set_clip (i965_shader_t *shader, 1. / s->intel.drm.height); cairo_matrix_translate (&shader->clip.base.matrix, - NEAREST_BIAS - clip->path->extents.x, - NEAREST_BIAS - clip->path->extents.y); + NEAREST_BIAS - clip_x, + NEAREST_BIAS - clip_y); } static cairo_bool_t