Skip to content

Commit

Permalink
snapshot: Hold a reference to target whilst querying
Browse files Browse the repository at this point in the history
Due to race with cow and accessing target from multiple threads, we need
to be careful that we always acquire a reference for our access to
the snapshot target.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
  • Loading branch information
Chris Wilson committed May 1, 2012
1 parent af3c8ab commit f62f8f9
Showing 1 changed file with 43 additions and 8 deletions.
51 changes: 43 additions & 8 deletions src/cairo-surface-snapshot.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,53 +58,88 @@ _cairo_surface_snapshot_finish (void *abstract_surface)
cairo_surface_destroy (surface->clone);
}

CAIRO_MUTEX_FINI (surface->mutex);

return status;
}

static cairo_status_t
_cairo_surface_snapshot_flush (void *abstract_surface)
{
cairo_surface_snapshot_t *surface = abstract_surface;
cairo_surface_t *target;
cairo_status_t status;

cairo_surface_flush (surface->target);
return surface->target->status;
target = _cairo_surface_snapshot_get_target (&surface->base);
cairo_surface_flush (target);
status = target->status;
cairo_surface_destroy (target);

return status;
}

static cairo_surface_t *
_cairo_surface_snapshot_source (void *abstract_surface,
cairo_rectangle_int_t *extents)
{
cairo_surface_snapshot_t *surface = abstract_surface;
return _cairo_surface_get_source (surface->target, extents);
return _cairo_surface_get_source (surface->target, extents); /* XXX racy */
}

struct snapshot_extra {
cairo_surface_t *target;
void *extra;
};

static cairo_status_t
_cairo_surface_snapshot_acquire_source_image (void *abstract_surface,
cairo_image_surface_t **image_out,
void **extra_out)
{
cairo_surface_snapshot_t *surface = abstract_surface;
struct snapshot_extra *extra;
cairo_status_t status;

return _cairo_surface_acquire_source_image (surface->target, image_out, extra_out);
extra = malloc (sizeof (*extra));
if (unlikely (extra == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);

extra->target = _cairo_surface_snapshot_get_target (&surface->base);
status = _cairo_surface_acquire_source_image (extra->target, image_out, &extra->extra);
if (unlikely (status)) {
cairo_surface_destroy (extra->target);
free (extra);
}

*extra_out = extra;
return status;
}

static void
_cairo_surface_snapshot_release_source_image (void *abstract_surface,
cairo_image_surface_t *image,
void *extra)
void *_extra)
{
cairo_surface_snapshot_t *surface = abstract_surface;
struct snapshot_extra *extra = _extra;

_cairo_surface_release_source_image (surface->target, image, extra);
_cairo_surface_release_source_image (extra->target, image, extra->extra);
cairo_surface_destroy (extra->target);
free (extra);
}

static cairo_bool_t
_cairo_surface_snapshot_get_extents (void *abstract_surface,
cairo_rectangle_int_t *extents)
{
cairo_surface_snapshot_t *surface = abstract_surface;
cairo_surface_t *target;
cairo_bool_t bounded;

target = _cairo_surface_snapshot_get_target (&surface->base);
bounded = _cairo_surface_get_extents (target, extents);
cairo_surface_destroy (target);

return _cairo_surface_get_extents (surface->target, extents);
return bounded;
}

static const cairo_surface_backend_t _cairo_surface_snapshot_backend = {
Expand Down

0 comments on commit f62f8f9

Please sign in to comment.