summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cairo-gl-surface.c2
-rw-r--r--src/cairo-image-surface.c47
-rw-r--r--src/cairo-surface-private.h6
-rw-r--r--src/cairo-surface.c66
-rw-r--r--src/cairoint.h1
5 files changed, 68 insertions, 54 deletions
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 64ae29ba..5d4853dd 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -527,6 +527,8 @@ cairo_gl_surface_create (cairo_gl_context_t *ctx,
glClear (GL_COLOR_BUFFER_BIT);
_cairo_gl_context_release (ctx);
+ surface->base.is_clear = TRUE;
+
return &surface->base;
}
slim_hidden_def (cairo_gl_surface_create);
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 4dbc2fee..d4b607e1 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -190,7 +190,6 @@ _cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image,
surface->height = height;
surface->stride = pixman_image_get_stride (pixman_image);
surface->depth = pixman_image_get_depth (pixman_image);
- surface->is_clear = FALSE;
surface->clip_region = NULL;
@@ -393,7 +392,7 @@ _cairo_image_surface_create_with_pixman_format (unsigned char *data,
}
/* we can not make any assumptions about the initial state of user data */
- ((cairo_image_surface_t *) surface)->is_clear = data == NULL;
+ surface->is_clear = data == NULL;
return surface;
}
@@ -1154,8 +1153,6 @@ _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;
}
@@ -1214,9 +1211,6 @@ _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;
}
@@ -1345,9 +1339,6 @@ _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,
@@ -1506,9 +1497,6 @@ _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,
@@ -1615,35 +1603,6 @@ _cairo_image_surface_get_font_options (void *abstract_surface,
cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_ON);
}
-static cairo_status_t
-_cairo_image_surface_mark_dirty_rectangle (void *abstract_surface,
- int x, int y,
- int width, int height)
-{
- cairo_image_surface_t *surface = abstract_surface;
- surface->is_clear = FALSE;
- return CAIRO_STATUS_SUCCESS;
-}
-
-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
@@ -1678,11 +1637,11 @@ const cairo_surface_backend_t _cairo_image_surface_backend = {
NULL, /* old_show_glyphs */
_cairo_image_surface_get_font_options,
NULL, /* flush */
- _cairo_image_surface_mark_dirty_rectangle,
+ NULL, /* mark dirty */
NULL, /* font_fini */
NULL, /* glyph_fini */
- _cairo_image_surface_paint,
+ NULL, /* paint */
NULL, /* mask */
NULL, /* stroke */
NULL, /* fill */
diff --git a/src/cairo-surface-private.h b/src/cairo-surface-private.h
index 5c80d43f..994df0e5 100644
--- a/src/cairo-surface-private.h
+++ b/src/cairo-surface-private.h
@@ -58,9 +58,12 @@ struct _cairo_surface {
cairo_reference_count_t ref_count;
cairo_status_t status;
- cairo_bool_t finished;
unsigned int unique_id;
+ unsigned finished : 1;
+ unsigned is_clear : 1;
+ unsigned has_font_options : 1;
+
cairo_user_data_array_t user_data;
cairo_user_data_array_t mime_data;
@@ -89,7 +92,6 @@ struct _cairo_surface {
* and set using _cairo_surface_set_font_options(), and propagated by
* cairo_surface_create_similar().
*/
- cairo_bool_t has_font_options;
cairo_font_options_t font_options;
};
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index e080c31e..aaab3134 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -51,8 +51,10 @@ const cairo_surface_t name = { \
CAIRO_CONTENT_COLOR, /* content */ \
CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */ \
status, /* status */ \
- FALSE, /* finished */ \
0, /* unique id */ \
+ FALSE, /* finished */ \
+ TRUE, /* is_clear */ \
+ FALSE, /* has_font_options */ \
{ 0, 0, 0, NULL, }, /* user_data */ \
{ 0, 0, 0, NULL, }, /* mime_data */ \
{ 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, /* device_transform */ \
@@ -68,7 +70,6 @@ const cairo_surface_t name = { \
0, /* element_size */ \
NULL, /* elements */ \
}, /* snapshots */ \
- FALSE, /* has_font_options */ \
{ CAIRO_ANTIALIAS_DEFAULT, /* antialias */ \
CAIRO_SUBPIXEL_ORDER_DEFAULT, /* subpixel_order */ \
CAIRO_HINT_STYLE_DEFAULT, /* hint_style */ \
@@ -343,8 +344,9 @@ _cairo_surface_init (cairo_surface_t *surface,
CAIRO_REFERENCE_COUNT_INIT (&surface->ref_count, 1);
surface->status = CAIRO_STATUS_SUCCESS;
- surface->finished = FALSE;
surface->unique_id = _cairo_surface_allocate_unique_id ();
+ surface->finished = FALSE;
+ surface->is_clear = FALSE;
_cairo_user_data_array_init (&surface->user_data);
_cairo_user_data_array_init (&surface->mime_data);
@@ -1030,6 +1032,8 @@ cairo_surface_mark_dirty_rectangle (cairo_surface_t *surface,
* call mark_dirty()). */
assert (! _cairo_surface_has_snapshots (surface));
+ surface->is_clear = FALSE;
+
if (surface->backend->mark_dirty_rectangle != NULL) {
/* XXX: FRAGILE: We're ignoring the scaling component of
* device_transform here. I don't know what the right thing to
@@ -1924,6 +1928,14 @@ _cairo_surface_paint (cairo_surface_t *surface,
if (clip && clip->all_clipped)
return CAIRO_STATUS_SUCCESS;
+ if (op == CAIRO_OPERATOR_CLEAR) {
+ if (surface->is_clear)
+ return CAIRO_STATUS_SUCCESS;
+
+ if (clip == NULL)
+ surface->is_clear = TRUE;
+ }
+
_cairo_surface_begin_modification (surface);
if (surface->backend->paint != NULL) {
@@ -1935,6 +1947,8 @@ _cairo_surface_paint (cairo_surface_t *surface,
status = _cairo_surface_fallback_paint (surface, op, source, clip);
FINISH:
+ surface->is_clear &= op == CAIRO_OPERATOR_CLEAR;
+
return _cairo_surface_set_error (surface, status);
}
@@ -1953,6 +1967,16 @@ _cairo_surface_mask (cairo_surface_t *surface,
if (clip && clip->all_clipped)
return CAIRO_STATUS_SUCCESS;
+ if (op == CAIRO_OPERATOR_CLEAR && surface->is_clear)
+ return CAIRO_STATUS_SUCCESS;
+
+ /* If the mask is blank, this is just an expensive no-op */
+ if (mask->type == CAIRO_PATTERN_TYPE_SURFACE) {
+ const cairo_surface_pattern_t *spattern = (cairo_surface_pattern_t *) mask;
+ if (spattern->surface->is_clear)
+ return CAIRO_STATUS_SUCCESS;
+ }
+
_cairo_surface_begin_modification (surface);
if (surface->backend->mask != NULL) {
@@ -1964,6 +1988,8 @@ _cairo_surface_mask (cairo_surface_t *surface,
status = _cairo_surface_fallback_mask (surface, op, source, mask, clip);
FINISH:
+ surface->is_clear &= op == CAIRO_OPERATOR_CLEAR;
+
return _cairo_surface_set_error (surface, status);
}
@@ -1992,6 +2018,13 @@ _cairo_surface_fill_stroke (cairo_surface_t *surface,
if (clip && clip->all_clipped)
return CAIRO_STATUS_SUCCESS;
+ if (surface->is_clear &&
+ fill_op == CAIRO_OPERATOR_CLEAR &&
+ stroke_op == CAIRO_OPERATOR_CLEAR)
+ {
+ return CAIRO_STATUS_SUCCESS;
+ }
+
_cairo_surface_begin_modification (surface);
if (surface->backend->fill_stroke) {
@@ -2009,23 +2042,27 @@ _cairo_surface_fill_stroke (cairo_surface_t *surface,
clip);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- return _cairo_surface_set_error (surface, status);
+ goto FINISH;
}
status = _cairo_surface_fill (surface, fill_op, fill_source, path,
fill_rule, fill_tolerance, fill_antialias,
clip);
if (unlikely (status))
- return _cairo_surface_set_error (surface, status);
+ goto FINISH;
status = _cairo_surface_stroke (surface, stroke_op, stroke_source, path,
stroke_style, stroke_ctm, stroke_ctm_inverse,
stroke_tolerance, stroke_antialias,
clip);
if (unlikely (status))
- return _cairo_surface_set_error (surface, status);
+ goto FINISH;
- return CAIRO_STATUS_SUCCESS;
+ FINISH:
+ surface->is_clear &= fill_op == CAIRO_OPERATOR_CLEAR;
+ surface->is_clear &= stroke_op == CAIRO_OPERATOR_CLEAR;
+
+ return _cairo_surface_set_error (surface, status);
}
cairo_status_t
@@ -2048,6 +2085,9 @@ _cairo_surface_stroke (cairo_surface_t *surface,
if (clip && clip->all_clipped)
return CAIRO_STATUS_SUCCESS;
+ if (op == CAIRO_OPERATOR_CLEAR && surface->is_clear)
+ return CAIRO_STATUS_SUCCESS;
+
_cairo_surface_begin_modification (surface);
if (surface->backend->stroke != NULL) {
@@ -2068,6 +2108,8 @@ _cairo_surface_stroke (cairo_surface_t *surface,
clip);
FINISH:
+ surface->is_clear &= op == CAIRO_OPERATOR_CLEAR;
+
return _cairo_surface_set_error (surface, status);
}
@@ -2089,6 +2131,9 @@ _cairo_surface_fill (cairo_surface_t *surface,
if (clip && clip->all_clipped)
return CAIRO_STATUS_SUCCESS;
+ if (op == CAIRO_OPERATOR_CLEAR && surface->is_clear)
+ return CAIRO_STATUS_SUCCESS;
+
_cairo_surface_begin_modification (surface);
if (surface->backend->fill != NULL) {
@@ -2107,6 +2152,8 @@ _cairo_surface_fill (cairo_surface_t *surface,
clip);
FINISH:
+ surface->is_clear &= op == CAIRO_OPERATOR_CLEAR;
+
return _cairo_surface_set_error (surface, status);
}
@@ -2408,6 +2455,9 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface,
if (clip && clip->all_clipped)
return CAIRO_STATUS_SUCCESS;
+ if (op == CAIRO_OPERATOR_CLEAR && surface->is_clear)
+ return CAIRO_STATUS_SUCCESS;
+
_cairo_surface_begin_modification (surface);
if (_cairo_surface_has_device_transform (surface) &&
@@ -2504,6 +2554,8 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface,
if (dev_scaled_font != scaled_font)
cairo_scaled_font_destroy (dev_scaled_font);
+ surface->is_clear &= op == CAIRO_OPERATOR_CLEAR;
+
return _cairo_surface_set_error (surface, status);
}
diff --git a/src/cairoint.h b/src/cairoint.h
index b9139138..fc1046e3 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -861,7 +861,6 @@ 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;
};