[cairo-commit] 2 commits - src/cairo-analysis-surface.c src/cairo-image-source.c src/cairo-image-surface.c src/cairo-pattern.c src/cairo-pdf-surface.c src/cairo-ps-surface.c src/cairo-script-surface.c src/cairo-surface.c src/cairo-surface-private.h src/cairo-surface-snapshot.c src/cairo-surface-snapshot-inline.h src/cairo-surface-snapshot-private.h src/cairo-surface-subsurface.c src/cairo-traps-compositor.c
Chris Wilson
ickle at kemper.freedesktop.org
Fri Apr 27 06:12:47 PDT 2012
src/cairo-analysis-surface.c | 12 +++---------
src/cairo-image-source.c | 33 ++++++++++++++++++++++++++++-----
src/cairo-image-surface.c | 18 ++++++++++++++++++
src/cairo-pattern.c | 4 +---
src/cairo-pdf-surface.c | 24 ++++++++++++++++--------
src/cairo-ps-surface.c | 33 +++++++++++++++++++++------------
src/cairo-script-surface.c | 5 +++--
src/cairo-surface-private.h | 1 +
src/cairo-surface-snapshot-inline.h | 9 ++++++++-
src/cairo-surface-snapshot-private.h | 2 ++
src/cairo-surface-snapshot.c | 7 ++++++-
src/cairo-surface-subsurface.c | 3 ++-
src/cairo-surface.c | 8 +++++++-
src/cairo-traps-compositor.c | 11 ++---------
14 files changed, 118 insertions(+), 52 deletions(-)
New commits:
commit 7eb33099d34234dcccb8f96caba94b38fa385f16
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri Apr 27 12:39:40 2012 +0100
snapshot: Perform the cow under a mutex
In order to prevent a race between concurrent destroy and use in another
thread, we need to acquire a reference to the snapshot->target under a
mutex. Whilst we hold that reference, it prevents the internal destroy
mechanism from freeing the memory we are using (if we have a pointer to
the original surface) and the client drops their final reference.
Oh boy, talk about opening a can of worms...
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/cairo-analysis-surface.c b/src/cairo-analysis-surface.c
index 5583f25..8516094 100644
--- a/src/cairo-analysis-surface.c
+++ b/src/cairo-analysis-surface.c
@@ -171,11 +171,7 @@ _analyze_recording_surface_pattern (cairo_analysis_surface_t *surface,
cairo_matrix_multiply (&tmp->ctm, &p2d, &surface->ctm);
tmp->has_ctm = ! _cairo_matrix_is_identity (&tmp->ctm);
- if (_cairo_surface_is_snapshot (source))
- source = _cairo_surface_snapshot_get_target (source);
- if (_cairo_surface_is_subsurface (source))
- source = _cairo_surface_subsurface_get_target (source);
-
+ source = _cairo_surface_get_source (source, NULL);
status = _cairo_recording_surface_replay_and_create_regions (source,
&tmp->base);
analysis_status = tmp->has_unsupported ? CAIRO_INT_STATUS_IMAGE_FALLBACK : CAIRO_INT_STATUS_SUCCESS;
@@ -412,8 +408,7 @@ _cairo_analysis_surface_mask (void *abstract_surface,
if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
cairo_surface_t *src_surface = ((cairo_surface_pattern_t *)source)->surface;
- if (_cairo_surface_is_snapshot (src_surface))
- src_surface = _cairo_surface_snapshot_get_target (src_surface);
+ src_surface = _cairo_surface_get_source (src_surface, NULL);
if (_cairo_surface_is_recording (src_surface)) {
backend_source_status =
_analyze_recording_surface_pattern (surface, source);
@@ -424,8 +419,7 @@ _cairo_analysis_surface_mask (void *abstract_surface,
if (mask->type == CAIRO_PATTERN_TYPE_SURFACE) {
cairo_surface_t *mask_surface = ((cairo_surface_pattern_t *)mask)->surface;
- if (_cairo_surface_is_snapshot (mask_surface))
- mask_surface = _cairo_surface_snapshot_get_target (mask_surface);
+ mask_surface = _cairo_surface_get_source (mask_surface, NULL);
if (_cairo_surface_is_recording (mask_surface)) {
backend_mask_status =
_analyze_recording_surface_pattern (surface, mask);
diff --git a/src/cairo-image-source.c b/src/cairo-image-source.c
index ec557c5..c5bd228 100644
--- a/src/cairo-image-source.c
+++ b/src/cairo-image-source.c
@@ -432,6 +432,13 @@ _acquire_source_cleanup (pixman_image_t *pixman_image,
free (data);
}
+static void
+_defer_free_cleanup (pixman_image_t *pixman_image,
+ void *closure)
+{
+ cairo_surface_destroy (closure);
+}
+
static uint16_t
expand_channel (uint16_t v, uint32_t bits)
{
@@ -816,11 +823,14 @@ _pixman_image_for_surface (cairo_image_surface_t *dst,
(! is_mask || ! pattern->base.has_component_alpha ||
(pattern->surface->content & CAIRO_CONTENT_COLOR) == 0))
{
+ cairo_surface_t *defer_free = NULL;
cairo_image_surface_t *source = (cairo_image_surface_t *) pattern->surface;
cairo_surface_type_t type;
- if (_cairo_surface_is_snapshot (&source->base))
- source = (cairo_image_surface_t *) _cairo_surface_snapshot_get_target (&source->base);
+ if (_cairo_surface_is_snapshot (&source->base)) {
+ defer_free = _cairo_surface_snapshot_get_target (&source->base);
+ source = (cairo_image_surface_t *) defer_free;
+ }
type = source->base.backend->type;
if (type == CAIRO_SURFACE_TYPE_IMAGE) {
@@ -839,15 +849,19 @@ _pixman_image_for_surface (cairo_image_surface_t *dst,
sample->x >= source->width ||
sample->y >= source->height)
{
- if (extend == CAIRO_EXTEND_NONE)
+ if (extend == CAIRO_EXTEND_NONE) {
+ cairo_surface_destroy (defer_free);
return _pixman_transparent_image ();
+ }
}
else
{
pixman_image = _pixel_to_solid (source,
sample->x, sample->y);
- if (pixman_image)
+ if (pixman_image) {
+ cairo_surface_destroy (defer_free);
return pixman_image;
+ }
}
}
@@ -858,6 +872,7 @@ _pixman_image_for_surface (cairo_image_surface_t *dst,
pattern->base.filter,
ix, iy))
{
+ cairo_surface_destroy (defer_free);
return pixman_image_ref (source->pixman_image);
}
#endif
@@ -867,8 +882,16 @@ _pixman_image_for_surface (cairo_image_surface_t *dst,
source->height,
(uint32_t *) source->data,
source->stride);
- if (unlikely (pixman_image == NULL))
+ if (unlikely (pixman_image == NULL)) {
+ cairo_surface_destroy (defer_free);
return NULL;
+ }
+
+ if (defer_free) {
+ pixman_image_set_destroy_function (pixman_image,
+ _defer_free_cleanup,
+ defer_free);
+ }
} else if (type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
cairo_surface_subsurface_t *sub;
cairo_bool_t is_contained = FALSE;
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index d21200a..940227d 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -3668,9 +3668,7 @@ _cairo_pattern_get_ink_extents (const cairo_pattern_t *pattern,
(const cairo_surface_pattern_t *) pattern;
cairo_surface_t *surface = surface_pattern->surface;
- if (_cairo_surface_is_snapshot (surface))
- surface = _cairo_surface_snapshot_get_target (surface);
-
+ surface = _cairo_surface_get_source (surface, NULL);
if (_cairo_surface_is_recording (surface)) {
cairo_matrix_t imatrix;
cairo_box_t box;
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 4ff381a..a017601 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1221,23 +1221,28 @@ _get_source_surface_size (cairo_surface_t *source,
*width = extents->width;
*height = extents->height;
} else {
+ cairo_surface_t *free_me = NULL;
cairo_rectangle_int_t surf_extents;
cairo_box_t box;
cairo_bool_t bounded;
if (_cairo_surface_is_snapshot (source))
- source = _cairo_surface_snapshot_get_target (source);
+ free_me = source = _cairo_surface_snapshot_get_target (source);
status = _cairo_recording_surface_get_ink_bbox ((cairo_recording_surface_t *)source,
&box, NULL);
- if (unlikely (status))
+ if (unlikely (status)) {
+ cairo_surface_destroy (free_me);
return status;
-
- _cairo_box_round_to_rectangle (&box, extents);
+ }
bounded = _cairo_surface_get_extents (source, &surf_extents);
+ cairo_surface_destroy (free_me);
+
*width = surf_extents.width;
*height = surf_extents.height;
+
+ _cairo_box_round_to_rectangle (&box, extents);
}
return CAIRO_STATUS_SUCCESS;
@@ -2674,12 +2679,13 @@ _cairo_pdf_surface_emit_recording_surface (cairo_pdf_surface_t *surface,
cairo_box_double_t bbox;
cairo_int_status_t status;
int alpha = 0;
+ cairo_surface_t *free_me = NULL;
cairo_surface_t *source;
assert (pdf_source->type == CAIRO_PATTERN_TYPE_SURFACE);
source = pdf_source->surface;
if (_cairo_surface_is_snapshot (source))
- source = _cairo_surface_snapshot_get_target (source);
+ free_me = source = _cairo_surface_snapshot_get_target (source);
old_width = surface->width;
old_height = surface->height;
@@ -2700,12 +2706,12 @@ _cairo_pdf_surface_emit_recording_surface (cairo_pdf_surface_t *surface,
_get_bbox_from_extents (pdf_source->hash_entry->height, &pdf_source->hash_entry->extents, &bbox);
status = _cairo_pdf_surface_open_content_stream (surface, &bbox, &pdf_source->hash_entry->surface_res, TRUE);
if (unlikely (status))
- return status;
+ goto err;
if (cairo_surface_get_content (source) == CAIRO_CONTENT_COLOR) {
status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
if (unlikely (status))
- return status;
+ goto err;
_cairo_output_stream_printf (surface->output,
"q /a%d gs 0 0 0 rg 0 0 %f %f re f Q\n",
@@ -2720,7 +2726,7 @@ _cairo_pdf_surface_emit_recording_surface (cairo_pdf_surface_t *surface,
CAIRO_RECORDING_REGION_NATIVE);
assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
if (unlikely (status))
- return status;
+ goto err;
status = _cairo_pdf_surface_close_content_stream (surface);
@@ -2731,6 +2737,8 @@ _cairo_pdf_surface_emit_recording_surface (cairo_pdf_surface_t *surface,
old_height);
surface->paginated_mode = old_paginated_mode;
+err:
+ cairo_surface_destroy (free_me);
return status;
}
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index d92029d..1285108 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -1696,16 +1696,19 @@ _cairo_ps_surface_acquire_source_surface_from_pattern (cairo_ps_surface_t
*width = sub->extents.width;
*height = sub->extents.height;
} else {
+ cairo_surface_t *free_me = NULL;
cairo_recording_surface_t *recording_surface;
cairo_box_t bbox;
cairo_rectangle_int_t extents;
recording_surface = (cairo_recording_surface_t *) surf;
- if (_cairo_surface_is_snapshot (&recording_surface->base))
- recording_surface = (cairo_recording_surface_t *)
- _cairo_surface_snapshot_get_target (&recording_surface->base);
+ if (_cairo_surface_is_snapshot (&recording_surface->base)) {
+ free_me = _cairo_surface_snapshot_get_target (&recording_surface->base);
+ recording_surface = (cairo_recording_surface_t *) free_me;
+ }
status = _cairo_recording_surface_get_bbox (recording_surface, &bbox, NULL);
+ cairo_surface_destroy (free_me);
if (unlikely (status))
return status;
@@ -2848,6 +2851,7 @@ _cairo_ps_surface_emit_recording_surface (cairo_ps_surface_t *surface,
cairo_matrix_t old_cairo_to_ps;
cairo_content_t old_content;
cairo_rectangle_int_t old_page_bbox;
+ cairo_surface_t *free_me = NULL;
cairo_surface_clipper_t old_clipper;
cairo_box_t bbox;
cairo_int_status_t status;
@@ -2862,14 +2866,14 @@ _cairo_ps_surface_emit_recording_surface (cairo_ps_surface_t *surface,
_cairo_ps_surface_clipper_intersect_clip_path);
if (_cairo_surface_is_snapshot (recording_surface))
- recording_surface = _cairo_surface_snapshot_get_target (recording_surface);
+ free_me = recording_surface = _cairo_surface_snapshot_get_target (recording_surface);
status =
_cairo_recording_surface_get_bbox ((cairo_recording_surface_t *) recording_surface,
&bbox,
NULL);
if (unlikely (status))
- return status;
+ goto err;
#if DEBUG_PS
_cairo_output_stream_printf (surface->stream,
@@ -2907,11 +2911,11 @@ _cairo_ps_surface_emit_recording_surface (cairo_ps_surface_t *surface,
CAIRO_RECORDING_REGION_NATIVE);
assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
if (unlikely (status))
- return status;
+ goto err;
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (unlikely (status))
- return status;
+ goto err;
_cairo_output_stream_printf (surface->stream, " Q\n");
@@ -2928,7 +2932,9 @@ _cairo_ps_surface_emit_recording_surface (cairo_ps_surface_t *surface,
_cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators,
&surface->cairo_to_ps);
- return CAIRO_STATUS_SUCCESS;
+err:
+ cairo_surface_destroy (free_me);
+ return status;
}
static cairo_int_status_t
@@ -2941,6 +2947,7 @@ _cairo_ps_surface_emit_recording_subsurface (cairo_ps_surface_t *surface,
cairo_content_t old_content;
cairo_rectangle_int_t old_page_bbox;
cairo_surface_clipper_t old_clipper;
+ cairo_surface_t *free_me = NULL;
cairo_int_status_t status;
old_content = surface->content;
@@ -2971,7 +2978,7 @@ _cairo_ps_surface_emit_recording_subsurface (cairo_ps_surface_t *surface,
_cairo_output_stream_printf (surface->stream, " q\n");
if (_cairo_surface_is_snapshot (recording_surface))
- recording_surface = _cairo_surface_snapshot_get_target (recording_surface);
+ free_me = recording_surface = _cairo_surface_snapshot_get_target (recording_surface);
if (recording_surface->content == CAIRO_CONTENT_COLOR) {
surface->content = CAIRO_CONTENT_COLOR;
@@ -2989,11 +2996,11 @@ _cairo_ps_surface_emit_recording_subsurface (cairo_ps_surface_t *surface,
CAIRO_RECORDING_REGION_NATIVE);
assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
if (unlikely (status))
- return status;
+ goto err;
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (unlikely (status))
- return status;
+ goto err;
_cairo_output_stream_printf (surface->stream, " Q\n");
@@ -3010,7 +3017,9 @@ _cairo_ps_surface_emit_recording_subsurface (cairo_ps_surface_t *surface,
_cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators,
&surface->cairo_to_ps);
- return CAIRO_STATUS_SUCCESS;
+err:
+ cairo_surface_destroy (free_me);
+ return status;
}
static void
diff --git a/src/cairo-script-surface.c b/src/cairo-script-surface.c
index e6867c1..ab4dcd6 100644
--- a/src/cairo-script-surface.c
+++ b/src/cairo-script-surface.c
@@ -1549,7 +1549,7 @@ _emit_surface_pattern (cairo_script_surface_t *surface,
{
cairo_script_context_t *ctx = to_context (surface);
cairo_surface_pattern_t *surface_pattern;
- cairo_surface_t *source, *snapshot;
+ cairo_surface_t *source, *snapshot, *free_me = NULL;
cairo_surface_t *take_snapshot = NULL;
cairo_int_status_t status;
@@ -1568,7 +1568,7 @@ _emit_surface_pattern (cairo_script_surface_t *surface,
if (_cairo_surface_snapshot_is_reused (source))
take_snapshot = source;
- source = _cairo_surface_snapshot_get_target (source);
+ free_me = source = _cairo_surface_snapshot_get_target (source);
}
switch ((int) source->backend->type) {
@@ -1585,6 +1585,7 @@ _emit_surface_pattern (cairo_script_surface_t *surface,
status = _emit_image_surface_pattern (surface, source);
break;
}
+ cairo_surface_destroy (free_me);
if (unlikely (status))
return status;
diff --git a/src/cairo-surface-snapshot-inline.h b/src/cairo-surface-snapshot-inline.h
index 5bf3444..7c15b81 100644
--- a/src/cairo-surface-snapshot-inline.h
+++ b/src/cairo-surface-snapshot-inline.h
@@ -47,7 +47,14 @@ _cairo_surface_snapshot_is_reused (cairo_surface_t *surface)
static inline cairo_surface_t *
_cairo_surface_snapshot_get_target (cairo_surface_t *surface)
{
- return ((cairo_surface_snapshot_t *) surface)->target;
+ cairo_surface_snapshot_t *snapshot = (cairo_surface_snapshot_t *) surface;
+ cairo_surface_t *target;
+
+ CAIRO_MUTEX_LOCK (snapshot->mutex);
+ target = cairo_surface_reference (snapshot->target);
+ CAIRO_MUTEX_UNLOCK (snapshot->mutex);
+
+ return target;
}
static inline cairo_bool_t
diff --git a/src/cairo-surface-snapshot-private.h b/src/cairo-surface-snapshot-private.h
index 4c3369b..58bee7b 100644
--- a/src/cairo-surface-snapshot-private.h
+++ b/src/cairo-surface-snapshot-private.h
@@ -36,12 +36,14 @@
#ifndef CAIRO_SURFACE_SNAPSHOT_PRIVATE_H
#define CAIRO_SURFACE_SNAPSHOT_PRIVATE_H
+#include "cairo-mutex-private.h"
#include "cairo-surface-private.h"
#include "cairo-surface-backend-private.h"
struct _cairo_surface_snapshot {
cairo_surface_t base;
+ cairo_mutex_t mutex;
cairo_surface_t *target;
cairo_surface_t *clone;
};
diff --git a/src/cairo-surface-snapshot.c b/src/cairo-surface-snapshot.c
index 2562d12..7b8a9a1 100644
--- a/src/cairo-surface-snapshot.c
+++ b/src/cairo-surface-snapshot.c
@@ -149,6 +149,8 @@ _cairo_surface_snapshot_copy_on_write (cairo_surface_t *surface)
* been lost.
*/
+ CAIRO_MUTEX_LOCK (snapshot->mutex);
+
if (snapshot->target->backend->snapshot != NULL) {
clone = snapshot->target->backend->snapshot (snapshot->target);
if (clone != NULL) {
@@ -165,7 +167,7 @@ _cairo_surface_snapshot_copy_on_write (cairo_surface_t *surface)
if (unlikely (status)) {
snapshot->target = _cairo_surface_create_in_error (status);
status = _cairo_surface_set_error (surface, status);
- return;
+ goto unlock;
}
clone = image->base.backend->snapshot (&image->base);
_cairo_surface_release_source_image (snapshot->target, image, extra);
@@ -174,6 +176,8 @@ done:
status = _cairo_surface_set_error (surface, clone->status);
snapshot->target = snapshot->clone = clone;
snapshot->base.type = clone->type;
+unlock:
+ CAIRO_MUTEX_UNLOCK (snapshot->mutex);
}
/**
@@ -230,6 +234,7 @@ _cairo_surface_snapshot (cairo_surface_t *surface)
surface->content);
snapshot->base.type = surface->type;
+ CAIRO_MUTEX_INIT (snapshot->mutex);
snapshot->target = surface;
snapshot->clone = NULL;
diff --git a/src/cairo-surface-subsurface.c b/src/cairo-surface-subsurface.c
index 97475f2..dfea05c 100644
--- a/src/cairo-surface-subsurface.c
+++ b/src/cairo-surface-subsurface.c
@@ -302,7 +302,8 @@ _cairo_surface_subsurface_source (void *abstract_surface,
cairo_surface_t *source;
source = _cairo_surface_get_source (surface->target, extents);
- *extents = surface->extents;
+ if (extents)
+ *extents = surface->extents;
return source;
}
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 58db7be..46ba256 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -961,6 +961,8 @@ cairo_surface_finish (cairo_surface_t *surface)
/* We have to becareful when decoupling potential reference cycles */
cairo_surface_reference (surface);
_cairo_surface_finish (surface);
+
+ /* XXX need to block and wait for snapshot references */
cairo_surface_destroy (surface);
}
slim_hidden_def (cairo_surface_finish);
@@ -1799,7 +1801,8 @@ cairo_surface_t *
_cairo_surface_default_source (void *surface,
cairo_rectangle_int_t *extents)
{
- _cairo_surface_get_extents(surface, extents);
+ if (extents)
+ _cairo_surface_get_extents(surface, extents);
return surface;
}
diff --git a/src/cairo-traps-compositor.c b/src/cairo-traps-compositor.c
index 519727b..f8308ad 100644
--- a/src/cairo-traps-compositor.c
+++ b/src/cairo-traps-compositor.c
@@ -1127,10 +1127,7 @@ is_recording_pattern (const cairo_pattern_t *pattern)
return FALSE;
surface = ((const cairo_surface_pattern_t *) pattern)->surface;
- if (_cairo_surface_is_paginated (surface))
- surface = _cairo_paginated_surface_get_recording (surface);
- if (_cairo_surface_is_snapshot (surface))
- surface = _cairo_surface_snapshot_get_target (surface);
+ surface = _cairo_surface_get_source (surface, NULL);
return _cairo_surface_is_recording (surface);
}
@@ -1140,11 +1137,7 @@ recording_pattern_get_surface (const cairo_pattern_t *pattern)
cairo_surface_t *surface;
surface = ((const cairo_surface_pattern_t *) pattern)->surface;
- if (_cairo_surface_is_paginated (surface))
- surface = _cairo_paginated_surface_get_recording (surface);
- if (_cairo_surface_is_snapshot (surface))
- surface = _cairo_surface_snapshot_get_target (surface);
- return surface;
+ return _cairo_surface_get_source (surface, NULL);
}
static cairo_bool_t
commit 455b4de1fc6be05f985b43c2f8f83eeed2b2a191
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri Apr 27 11:41:41 2012 +0100
image: Allow a snapshot to steal the original memory upon finish
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 8bbea00..56914b0 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -753,6 +753,24 @@ _cairo_image_surface_snapshot (void *abstract_surface)
cairo_image_surface_t *image = abstract_surface;
cairo_image_surface_t *clone;
+ /* If we own the image, we can simply steal the memory for the snapshot */
+ if (image->owns_data && image->base._finishing) {
+ clone = (cairo_image_surface_t *)
+ _cairo_image_surface_create_for_pixman_image (image->pixman_image,
+ image->pixman_format);
+ if (unlikely (clone->base.status))
+ return &clone->base;
+
+ image->pixman_image = NULL;
+ image->owns_data = FALSE;
+
+ clone->transparency = image->transparency;
+ clone->color = image->color;
+
+ clone->owns_data = FALSE;
+ return &clone->base;
+ }
+
clone = (cairo_image_surface_t *)
_cairo_image_surface_create_with_pixman_format (NULL,
image->pixman_format,
diff --git a/src/cairo-surface-private.h b/src/cairo-surface-private.h
index c4d5de2..d23fc05 100644
--- a/src/cairo-surface-private.h
+++ b/src/cairo-surface-private.h
@@ -65,6 +65,7 @@ struct _cairo_surface {
unsigned int serial;
cairo_damage_t *damage;
+ unsigned _finishing : 1;
unsigned finished : 1;
unsigned is_clear : 1;
unsigned has_font_options : 1;
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 457b3f0..58db7be 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -108,6 +108,7 @@ const cairo_surface_t name = { \
0, /* unique id */ \
0, /* serial */ \
NULL, /* damage */ \
+ FALSE, /* _finishing */ \
FALSE, /* finished */ \
TRUE, /* is_clear */ \
FALSE, /* has_font_options */ \
@@ -905,6 +906,8 @@ _cairo_surface_finish (cairo_surface_t *surface)
cairo_surface_flush (surface);
/* update the snapshots *before* we declare the surface as finished */
+ surface->_finishing = TRUE;
+
_cairo_surface_detach_snapshots (surface);
if (surface->snapshot_of != NULL)
_cairo_surface_detach_snapshot (surface);
More information about the cairo-commit
mailing list