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.
This commit is contained in:
Chris Wilson 2010-05-05 09:17:51 +01:00
parent 6a06e0ef7b
commit e532980539
2 changed files with 12 additions and 12 deletions

View file

@ -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;

View file

@ -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;
}