From e5329805394c94c915e43a0040b51d5019b4a90e Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 5 May 2010 09:17:51 +0100 Subject: [PATCH] recording: Avoid refcycles by always copying the command array. Short-term solution to avoid the refleaks and to make the test suite happy. A more elegant solution would be to track the references and avoid the substantial memory overhead of copying the recording surfaces. Thanks to Benjamin Otte for pointing out the solution to avoiding refcycles. --- src/cairo-recording-surface-private.h | 1 - src/cairo-recording-surface.c | 23 ++++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/cairo-recording-surface-private.h b/src/cairo-recording-surface-private.h index 4a5c9dbd6..4ec5f88b4 100644 --- a/src/cairo-recording-surface-private.h +++ b/src/cairo-recording-surface-private.h @@ -132,7 +132,6 @@ typedef struct _cairo_recording_surface { cairo_clip_t clip; cairo_array_t commands; - cairo_surface_t *commands_owner; int replay_start_idx; } cairo_recording_surface_t; diff --git a/src/cairo-recording-surface.c b/src/cairo-recording-surface.c index 5a2f80447..d3866ed6f 100644 --- a/src/cairo-recording-surface.c +++ b/src/cairo-recording-surface.c @@ -154,7 +154,6 @@ cairo_recording_surface_create (cairo_content_t content, } _cairo_array_init (&recording_surface->commands, sizeof (cairo_command_t *)); - recording_surface->commands_owner = NULL; recording_surface->replay_start_idx = 0; @@ -182,12 +181,6 @@ _cairo_recording_surface_finish (void *abstract_surface) cairo_command_t **elements; int i, num_elements; - if (recording_surface->commands_owner) { - cairo_surface_destroy (recording_surface->commands_owner); - _cairo_clip_fini (&recording_surface->clip); - return CAIRO_STATUS_SUCCESS; - } - num_elements = recording_surface->commands.num_elements; elements = _cairo_array_index (&recording_surface->commands, 0); for (i = 0; i < num_elements; i++) { @@ -613,6 +606,7 @@ _cairo_recording_surface_snapshot (void *abstract_other) { cairo_recording_surface_t *other = abstract_other; cairo_recording_surface_t *recording_surface; + cairo_status_t status; recording_surface = malloc (sizeof (cairo_recording_surface_t)); if (unlikely (recording_surface == NULL)) @@ -626,14 +620,21 @@ _cairo_recording_surface_snapshot (void *abstract_other) recording_surface->extents_pixels = other->extents_pixels; recording_surface->extents = other->extents; recording_surface->unbounded = other->unbounded; - recording_surface->replay_start_idx = other->replay_start_idx; recording_surface->content = other->content; - _cairo_array_init_snapshot (&recording_surface->commands, &other->commands); - recording_surface->commands_owner = cairo_surface_reference (&other->base); - _cairo_clip_init_copy (&recording_surface->clip, &other->clip); + /* XXX We should in theory be able to reuse the original array, but we + * need to handle reference cycles during subsurface and self-copy. + */ + recording_surface->replay_start_idx = 0; + _cairo_array_init (&recording_surface->commands, sizeof (cairo_command_t *)); + status = _cairo_recording_surface_replay (&other->base, &recording_surface->base); + if (unlikely (status)) { + cairo_surface_destroy (&recording_surface->base); + return _cairo_surface_create_in_error (status); + } + return &recording_surface->base; }