diff options
-rw-r--r-- | src/cairo-gl-surface.c | 2 | ||||
-rw-r--r-- | src/cairo-image-surface.c | 47 | ||||
-rw-r--r-- | src/cairo-surface-private.h | 6 | ||||
-rw-r--r-- | src/cairo-surface.c | 66 | ||||
-rw-r--r-- | src/cairoint.h | 1 |
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; }; |