From 4d52be39bf36a3557f4e7c61dba764b1c6542c8f Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 22 Jan 2010 16:09:11 +0000 Subject: [PATCH] gstate: Skip ops with a clear mask. As pointed out by Benjamin Otte, these are expensive no-ops that we can trivially detect, just so long as we remember the semantics of extend modes. --- src/cairo-gstate.c | 6 ++++++ src/cairo-pattern.c | 23 +++++++++++++++++++++++ src/cairoint.h | 3 +++ 3 files changed, 32 insertions(+) diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c index 9f0e603d0..52bf2714a 100644 --- a/src/cairo-gstate.c +++ b/src/cairo-gstate.c @@ -1019,6 +1019,12 @@ _cairo_gstate_mask (cairo_gstate_t *gstate, if (_cairo_pattern_is_opaque (mask, NULL)) return _cairo_gstate_paint (gstate); + if (_cairo_pattern_is_clear (mask) && + _cairo_operator_bounded_by_mask (gstate->op)) + { + return CAIRO_STATUS_SUCCESS; + } + _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base); _cairo_gstate_copy_transformed_mask (gstate, &mask_pattern.base, mask); diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c index 5d4ceb7c7..e77f1531d 100644 --- a/src/cairo-pattern.c +++ b/src/cairo-pattern.c @@ -1835,6 +1835,29 @@ _cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern, return FALSE; } +cairo_bool_t +_cairo_pattern_is_clear (const cairo_pattern_t *abstract_pattern) +{ + const cairo_pattern_union_t *pattern; + + if (abstract_pattern->has_component_alpha) + return FALSE; + + pattern = (cairo_pattern_union_t *) abstract_pattern; + switch (pattern->type) { + case CAIRO_PATTERN_TYPE_SOLID: + return pattern->solid.color.alpha_short == 0x0000; + case CAIRO_PATTERN_TYPE_SURFACE: + return pattern->surface.surface->is_clear && + pattern->surface.surface->content & CAIRO_CONTENT_ALPHA; + default: + ASSERT_NOT_REACHED; + case CAIRO_PATTERN_TYPE_LINEAR: + case CAIRO_PATTERN_TYPE_RADIAL: + return FALSE; + } +} + /** * _cairo_pattern_analyze_filter: * @pattern: surface pattern diff --git a/src/cairoint.h b/src/cairoint.h index 401fac6f2..364edf5ba 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -2531,6 +2531,9 @@ cairo_private cairo_bool_t _cairo_pattern_is_opaque (const cairo_pattern_t *pattern, const cairo_rectangle_int_t *extents); +cairo_private cairo_bool_t +_cairo_pattern_is_clear (const cairo_pattern_t *pattern); + enum { CAIRO_PATTERN_ACQUIRE_NONE = 0x0, CAIRO_PATTERN_ACQUIRE_NO_REFLECT = 0x1,