diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2009-07-23 23:45:01 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2009-07-24 10:44:04 +0100 |
commit | 0466053099b7f27065267d49c84e9e24bff6c7a1 (patch) | |
tree | f128c7a4a334302c2d19abbbe6078d7fae1d8ab9 /src | |
parent | 8b8e03503d7a4fdacfc48e0b35c9b02d7a08c1e2 (diff) |
[image] Discard redundant clears
On slow machines the call to pixman_fill_sse2() on similar surfaces that
we know are already zeroed takes a significant amount of time [12.77% of
the profile for a firefox trace, cf to just 3% of the profile is spent
inside memset].
Rather than solve why the pixman_fill_sse2() is so slow, simply skip the
redundant clears.
Diffstat (limited to 'src')
-rw-r--r-- | src/cairo-image-surface.c | 35 | ||||
-rw-r--r-- | src/cairoint.h | 1 |
2 files changed, 35 insertions, 1 deletions
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c index e7efdca1..627f9edd 100644 --- a/src/cairo-image-surface.c +++ b/src/cairo-image-surface.c @@ -172,6 +172,7 @@ _cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image, surface->height = pixman_image_get_height (pixman_image); surface->stride = pixman_image_get_stride (pixman_image); surface->depth = pixman_image_get_depth (pixman_image); + surface->is_clear = FALSE; surface->clip_region = NULL; @@ -358,6 +359,8 @@ _cairo_image_surface_create_with_pixman_format (unsigned char *data, pixman_format); if (cairo_surface_status (surface)) pixman_image_unref (pixman_image); + else + ((cairo_image_surface_t *)surface)->is_clear = TRUE; return surface; } @@ -1113,6 +1116,8 @@ _cairo_image_surface_composite (cairo_operator_t op, _cairo_pattern_release_surface (mask_pattern, &mask->base, &mask_attr); _cairo_pattern_release_surface (src_pattern, &src->base, &src_attr); + if (op != CAIRO_OPERATOR_CLEAR) + dst->is_clear = FALSE; return status; } @@ -1171,6 +1176,9 @@ _cairo_image_surface_fill_rectangles (void *abstract_surface, if (pixman_rects != stack_rects) free (pixman_rects); + if (op != CAIRO_OPERATOR_CLEAR) + surface->is_clear = FALSE; + return status; } @@ -1300,6 +1308,9 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op, pixman_image_unref (mask); + if (op != CAIRO_OPERATOR_CLEAR) + dst->is_clear = FALSE; + if (! _cairo_operator_bounded_by_mask (op)) { status = _cairo_surface_composite_shape_fixup_unbounded (&dst->base, &attributes, @@ -1458,6 +1469,9 @@ _cairo_image_surface_span_renderer_finish (void *abstract_renderer) rects->width, rects->height, dst->clip_region); } + + if (renderer->op != CAIRO_OPERATOR_CLEAR) + dst->is_clear = FALSE; } if (status != CAIRO_STATUS_SUCCESS) return _cairo_span_renderer_set_error (abstract_renderer, @@ -1567,6 +1581,25 @@ _cairo_image_surface_get_font_options (void *abstract_surface, cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_ON); } +static cairo_int_status_t +_cairo_image_surface_paint (void *abstract_surface, + cairo_operator_t op, + const cairo_pattern_t *source, + cairo_clip_t *clip) +{ + /* we know that surfaces are calloc, so ignore any redundant clears */ + if (op == CAIRO_OPERATOR_CLEAR && clip == NULL) { + cairo_image_surface_t *surface = abstract_surface; + + if (surface->is_clear) + return CAIRO_STATUS_SUCCESS; + + surface->is_clear = TRUE; + } + + return CAIRO_INT_STATUS_UNSUPPORTED; +} + /** * _cairo_surface_is_image: * @surface: a #cairo_surface_t @@ -1605,7 +1638,7 @@ const cairo_surface_backend_t _cairo_image_surface_backend = { NULL, /* font_fini */ NULL, /* glyph_fini */ - NULL, /* paint */ + _cairo_image_surface_paint, NULL, /* mask */ NULL, /* stroke */ NULL, /* fill */ diff --git a/src/cairoint.h b/src/cairoint.h index 3cd0cb37..6010e20f 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -857,6 +857,7 @@ struct _cairo_image_surface { pixman_image_t *pixman_image; cairo_region_t *clip_region; + unsigned is_clear : 1; unsigned owns_data : 1; unsigned transparency : 2; }; |