Commit f62f8f90 authored by Chris Wilson's avatar Chris Wilson 🤔
Browse files

snapshot: Hold a reference to target whilst querying



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's avatarChris Wilson <chris@chris-wilson.co.uk>
parent af3c8abb
......@@ -58,6 +58,8 @@ _cairo_surface_snapshot_finish (void *abstract_surface)
cairo_surface_destroy (surface->clone);
}
CAIRO_MUTEX_FINI (surface->mutex);
return status;
}
......@@ -65,9 +67,15 @@ 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 *
......@@ -75,27 +83,48 @@ _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
......@@ -103,8 +132,14 @@ _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 = {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment