Commit 07122f37 authored by Chris Wilson's avatar Chris Wilson 🤔
Browse files

surface: Convert snapshots from an array to a double-linked list.

Saves the memory allocation for the array, and the overhead of
maintaining the area for both insertions and more importantly deletes.
parent 4cb733c2
......@@ -269,11 +269,7 @@ _cairo_recording_surface_acquire_source_image (void *abstract_surface,
return status;
}
status = _cairo_surface_attach_snapshot (&surface->base, image, NULL);
if (unlikely (status)) {
cairo_surface_destroy (image);
return status;
}
_cairo_surface_attach_snapshot (&surface->base, image, NULL);
*image_out = (cairo_image_surface_t *) image;
*image_extra = NULL;
......
......@@ -41,6 +41,7 @@
#include "cairo.h"
#include "cairo-types-private.h"
#include "cairo-list-private.h"
#include "cairo-reference-count-private.h"
#include "cairo-clip-private.h"
......@@ -85,8 +86,8 @@ struct _cairo_surface {
/* A "snapshot" surface is immutable. See _cairo_surface_snapshot. */
cairo_surface_t *snapshot_of;
cairo_surface_func_t snapshot_detach;
/* current snapshots of this surface */
cairo_array_t snapshots;
/* current snapshots of this surface, or place upon snapshot list */
cairo_list_t snapshots;
/*
* Surface font options, falling back to backend's default options,
......
......@@ -228,13 +228,9 @@ _cairo_surface_snapshot (cairo_surface_t *surface)
snapshot->base.device_transform = surface->device_transform;
snapshot->base.device_transform_inverse = surface->device_transform_inverse;
status = _cairo_surface_attach_snapshot (surface,
&snapshot->base,
_cairo_surface_snapshot_copy_on_write);
if (unlikely (status)) {
cairo_surface_destroy (&snapshot->base);
return _cairo_surface_create_in_error (status);
}
_cairo_surface_attach_snapshot (surface,
&snapshot->base,
_cairo_surface_snapshot_copy_on_write);
return &snapshot->base;
}
......@@ -68,11 +68,7 @@ const cairo_surface_t name = { \
0.0, /* y_fallback_resolution */ \
NULL, /* snapshot_of */ \
NULL, /* snapshot_detach */ \
{ 0, /* size */ \
0, /* num_elements */ \
0, /* element_size */ \
NULL, /* elements */ \
}, /* snapshots */ \
{ NULL, NULL }, /* snapshots */ \
{ CAIRO_ANTIALIAS_DEFAULT, /* antialias */ \
CAIRO_SUBPIXEL_ORDER_DEFAULT, /* subpixel_order */ \
CAIRO_HINT_STYLE_DEFAULT, /* hint_style */ \
......@@ -240,30 +236,7 @@ cairo_surface_get_device (cairo_surface_t *surface)
static cairo_bool_t
_cairo_surface_has_snapshots (cairo_surface_t *surface)
{
return surface->snapshots.num_elements != 0;
}
static void
_cairo_surface_detach_snapshots (cairo_surface_t *surface)
{
cairo_surface_t **snapshots;
unsigned int i;
if (! _cairo_surface_has_snapshots (surface))
return;
snapshots = _cairo_array_index (&surface->snapshots, 0);
for (i = 0; i < surface->snapshots.num_elements; i++) {
snapshots[i]->snapshot_of = NULL;
if (snapshots[i]->snapshot_detach != NULL)
snapshots[i]->snapshot_detach (snapshots[i]);
cairo_surface_destroy (snapshots[i]);
}
surface->snapshots.num_elements = 0;
assert (! _cairo_surface_has_snapshots (surface));
return ! cairo_list_is_empty (&surface->snapshots);
}
static cairo_bool_t
......@@ -282,14 +255,43 @@ _cairo_surface_detach_mime_data (cairo_surface_t *surface)
_cairo_user_data_array_init (&surface->mime_data);
}
cairo_status_t
_cairo_surface_attach_snapshot (cairo_surface_t *surface,
cairo_surface_t *snapshot,
cairo_surface_func_t detach_func)
static void
_cairo_surface_detach_snapshots (cairo_surface_t *surface)
{
cairo_status_t status;
if (surface->snapshot_of != NULL)
return;
while (_cairo_surface_has_snapshots (surface)) {
_cairo_surface_detach_snapshot (cairo_list_first_entry (&surface->snapshots,
cairo_surface_t,
snapshots));
}
}
void
_cairo_surface_detach_snapshot (cairo_surface_t *snapshot)
{
assert (snapshot->snapshot_of != NULL);
snapshot->snapshot_of = NULL;
cairo_list_del (&snapshot->snapshots);
if (snapshot->snapshot_detach != NULL)
snapshot->snapshot_detach (snapshot);
cairo_surface_destroy (snapshot);
}
void
_cairo_surface_attach_snapshot (cairo_surface_t *surface,
cairo_surface_t *snapshot,
cairo_surface_func_t detach_func)
{
assert (surface != snapshot);
assert (surface->snapshot_of == NULL);
assert (snapshot->snapshot_of != surface);
cairo_surface_reference (snapshot);
if (snapshot->snapshot_of != NULL)
_cairo_surface_detach_snapshot (snapshot);
......@@ -297,61 +299,28 @@ _cairo_surface_attach_snapshot (cairo_surface_t *surface,
snapshot->snapshot_of = surface;
snapshot->snapshot_detach = detach_func;
status = _cairo_array_append (&surface->snapshots, &snapshot);
if (unlikely (status))
return status;
cairo_list_add (&snapshot->snapshots, &surface->snapshots);
cairo_surface_reference (snapshot);
return CAIRO_STATUS_SUCCESS;
assert (_cairo_surface_has_snapshot (surface, snapshot->backend) == snapshot);
}
cairo_surface_t *
_cairo_surface_has_snapshot (cairo_surface_t *surface,
const cairo_surface_backend_t *backend)
{
cairo_surface_t **snapshots;
unsigned int i;
cairo_surface_t *snapshot;
/* XXX is_similar? */
snapshots = _cairo_array_index (&surface->snapshots, 0);
for (i = 0; i < surface->snapshots.num_elements; i++) {
if (snapshots[i]->backend == backend)
return snapshots[i];
cairo_list_foreach_entry (snapshot, cairo_surface_t,
&surface->snapshots, snapshots)
{
/* XXX is_similar? */
if (snapshot->backend == backend)
return snapshot;
}
return NULL;
}
void
_cairo_surface_detach_snapshot (cairo_surface_t *snapshot)
{
cairo_surface_t *surface;
cairo_surface_t **snapshots;
unsigned int i;
assert (snapshot->snapshot_of != NULL);
surface = snapshot->snapshot_of;
snapshots = _cairo_array_index (&surface->snapshots, 0);
for (i = 0; i < surface->snapshots.num_elements; i++) {
if (snapshots[i] == snapshot)
break;
}
assert (i < surface->snapshots.num_elements);
surface->snapshots.num_elements--;
memmove (&snapshots[i],
&snapshots[i+1],
sizeof (cairo_surface_t *)*(surface->snapshots.num_elements - i));
snapshot->snapshot_of = NULL;
if (snapshot->snapshot_detach != NULL)
snapshot->snapshot_detach (snapshot);
cairo_surface_destroy (snapshot);
}
static cairo_bool_t
_cairo_surface_is_writable (cairo_surface_t *surface)
{
......@@ -403,7 +372,7 @@ _cairo_surface_init (cairo_surface_t *surface,
surface->x_fallback_resolution = CAIRO_SURFACE_FALLBACK_RESOLUTION_DEFAULT;
surface->y_fallback_resolution = CAIRO_SURFACE_FALLBACK_RESOLUTION_DEFAULT;
_cairo_array_init (&surface->snapshots, sizeof (cairo_surface_t *));
cairo_list_init (&surface->snapshots);
surface->snapshot_of = NULL;
surface->has_font_options = FALSE;
......@@ -630,7 +599,6 @@ cairo_surface_destroy (cairo_surface_t *surface)
_cairo_user_data_array_fini (&surface->user_data);
_cairo_user_data_array_fini (&surface->mime_data);
_cairo_array_fini (&surface->snapshots);
free (surface);
}
......@@ -1532,11 +1500,7 @@ _cairo_recording_surface_clone_similar (cairo_surface_t *surface,
return status;
}
status = _cairo_surface_attach_snapshot (src, similar, NULL);
if (unlikely (status)) {
cairo_surface_destroy (similar);
return status;
}
_cairo_surface_attach_snapshot (src, similar, NULL);
src_x = src_y = 0;
}
......
......@@ -982,12 +982,8 @@ _vg_setup_surface_source (cairo_vg_context_t *context,
return status;
}
status = _cairo_surface_attach_snapshot (spat->surface, &clone->base,
_vg_surface_remove_from_cache);
if (unlikely (status)) {
cairo_surface_destroy (&clone->base);
return status;
}
_cairo_surface_attach_snapshot (spat->surface, &clone->base,
_vg_surface_remove_from_cache);
DONE:
cairo_surface_destroy (&context->source->base);
......
......@@ -405,11 +405,7 @@ _cairo_xcb_surface_pixmap (cairo_xcb_surface_t *target,
if (unlikely (pixmap->base.status))
return pixmap;
status = _cairo_surface_attach_snapshot (source, &pixmap->base, NULL);
if (unlikely (status)) {
cairo_surface_destroy (&pixmap->base);
return (cairo_xcb_pixmap_t *) _cairo_surface_create_in_error (status);
}
_cairo_surface_attach_snapshot (source, &pixmap->base, NULL);
if (pattern->base.extend != CAIRO_EXTEND_NONE) {
if (extents->x < 0 || extents->y < 0 ||
......
......@@ -1367,13 +1367,9 @@ _cairo_xcb_surface_picture (cairo_xcb_surface_t *target,
return (cairo_xcb_picture_t *) _cairo_surface_create_in_error (status);
}
status = _cairo_surface_attach_snapshot (source,
&picture->base,
cairo_surface_finish);
if (unlikely (status)) {
cairo_surface_destroy (&picture->base);
return (cairo_xcb_picture_t *) _cairo_surface_create_in_error (status);
}
_cairo_surface_attach_snapshot (source,
&picture->base,
cairo_surface_finish);
setup_picture:
filter = pattern->base.filter;
......
......@@ -553,11 +553,7 @@ _cairo_xcb_surface_acquire_source_image (void *abstract_surface,
if (unlikely (status))
return status;
status = _cairo_surface_attach_snapshot (&surface->base, &image->base, NULL);
if (unlikely (status)) {
cairo_surface_destroy (&image->base);
return status;
}
_cairo_surface_attach_snapshot (&surface->base, &image->base, NULL);
DONE:
*image_out = image;
......@@ -704,9 +700,9 @@ _cairo_xcb_surface_flush (void *abstract_surface)
}
if (status == CAIRO_STATUS_SUCCESS) {
status = _cairo_surface_attach_snapshot (&surface->base,
surface->fallback,
cairo_surface_finish);
_cairo_surface_attach_snapshot (&surface->base,
surface->fallback,
cairo_surface_finish);
}
}
......
......@@ -2033,7 +2033,7 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
cairo_private cairo_surface_t *
_cairo_surface_snapshot (cairo_surface_t *surface);
cairo_private cairo_status_t
cairo_private void
_cairo_surface_attach_snapshot (cairo_surface_t *surface,
cairo_surface_t *snapshot,
cairo_surface_func_t detach_func);
......
......@@ -1281,17 +1281,16 @@ i915_surface_clone (i915_device_t *device,
if (unlikely (clone->intel.drm.base.status))
return clone->intel.drm.base.status;
status = _cairo_surface_attach_snapshot (&image->base,
&clone->intel.drm.base,
intel_surface_detach_snapshot);
if (likely (status == CAIRO_STATUS_SUCCESS))
status = intel_snapshot_cache_insert (&device->intel, &clone->intel);
status = intel_snapshot_cache_insert (&device->intel, &clone->intel);
if (unlikely (status)) {
cairo_surface_destroy (&clone->intel.drm.base);
return status;
}
_cairo_surface_attach_snapshot (&image->base,
&clone->intel.drm.base,
intel_surface_detach_snapshot);
*clone_out = clone;
return CAIRO_STATUS_SUCCESS;
}
......
......@@ -282,17 +282,16 @@ i965_surface_clone (i965_device_t *device,
return status;
}
status = _cairo_surface_attach_snapshot (&image->base,
&clone->intel.drm.base,
intel_surface_detach_snapshot);
if (likely (status == CAIRO_STATUS_SUCCESS))
status = intel_snapshot_cache_insert (&device->intel, &clone->intel);
status = intel_snapshot_cache_insert (&device->intel, &clone->intel);
if (unlikely (status)) {
cairo_surface_destroy (&clone->intel.drm.base);
return status;
}
_cairo_surface_attach_snapshot (&image->base,
&clone->intel.drm.base,
intel_surface_detach_snapshot);
*clone_out = clone;
return CAIRO_STATUS_SUCCESS;
}
......
......@@ -90,13 +90,7 @@ intel_surface_acquire_source_image (void *abstract_surface,
if (unlikely (status))
return status;
status = _cairo_surface_attach_snapshot (&surface->drm.base,
image,
cairo_surface_destroy);
if (unlikely (status)) {
cairo_surface_destroy (image);
return status;
}
_cairo_surface_attach_snapshot (&surface->drm.base, image, cairo_surface_destroy);
DONE:
*image_out = (cairo_image_surface_t *) cairo_surface_reference (image);
......
......@@ -106,13 +106,7 @@ radeon_surface_acquire_source_image (void *abstract_surface,
if (unlikely (status))
return status;
status = _cairo_surface_attach_snapshot (&surface->base.base,
image,
cairo_surface_destroy);
if (unlikely (status)) {
cairo_surface_destroy (image);
return status;
}
_cairo_surface_attach_snapshot (&surface->base.base, image, cairo_surface_destroy);
DONE:
*image_out = (cairo_image_surface_t *) cairo_surface_reference (image);
......
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