summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2009-07-23 23:45:01 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2009-07-24 10:44:04 +0100
commit0466053099b7f27065267d49c84e9e24bff6c7a1 (patch)
treef128c7a4a334302c2d19abbbe6078d7fae1d8ab9 /src
parent8b8e03503d7a4fdacfc48e0b35c9b02d7a08c1e2 (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.c35
-rw-r--r--src/cairoint.h1
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;
};