[cairo-commit] 5 commits - src/cairo-image-source.c src/cairo-recording-surface.c src/cairo-surface-snapshot.c src/cairo-surface-subsurface.c test/reference
Chris Wilson
ickle at kemper.freedesktop.org
Fri Feb 24 05:58:30 PST 2012
src/cairo-image-source.c | 89 +++++++++++++-
src/cairo-recording-surface.c | 31 ++++
src/cairo-surface-snapshot.c | 7 +
src/cairo-surface-subsurface.c | 9 +
test/reference/mask-transformed-similar.recording.ref.png |binary
test/reference/source-clip-scale.recording.ref.png |binary
6 files changed, 133 insertions(+), 3 deletions(-)
New commits:
commit 61050f5445000be014764cedb6da36cb357bf434
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri Feb 24 13:56:41 2012 +0000
test: Add a couple of reference images for the recording surface
In tests where we apply a scale factor to a similar source, the
recording surface will produce different results to image as the scaling
of the source is performed on the geometry and not on a raster image and
so avoids scaling artefacts.
diff --git a/test/reference/mask-transformed-similar.recording.ref.png b/test/reference/mask-transformed-similar.recording.ref.png
new file mode 100644
index 0000000..33ec279
Binary files /dev/null and b/test/reference/mask-transformed-similar.recording.ref.png differ
diff --git a/test/reference/source-clip-scale.recording.ref.png b/test/reference/source-clip-scale.recording.ref.png
new file mode 100644
index 0000000..bbf7c9b
Binary files /dev/null and b/test/reference/source-clip-scale.recording.ref.png differ
commit c39cb77d64afdeff522a74d31af6386f5fd3c10f
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri Feb 24 13:00:44 2012 +0000
subsurface: Fix typo in snapshot creation
I need to remember that the translation for the pattern matrix is the
inverse of the translation for drawing.
Fixes: subsurface-modify-parent
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/cairo-surface-subsurface.c b/src/cairo-surface-subsurface.c
index bced245..8590bf0 100644
--- a/src/cairo-surface-subsurface.c
+++ b/src/cairo-surface-subsurface.c
@@ -368,7 +368,7 @@ _cairo_surface_subsurface_snapshot (void *abstract_surface)
_cairo_pattern_init_for_surface (&pattern, surface->target);
cairo_matrix_init_translate (&pattern.base.matrix,
- -surface->extents.x, -surface->extents.y);
+ surface->extents.x, surface->extents.y);
pattern.base.filter = CAIRO_FILTER_NEAREST;
status = _cairo_surface_paint (clone,
CAIRO_OPERATOR_SOURCE,
commit b2cb9ec31ea580164a3d5a267bff334a0c6b4dc5
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri Feb 24 13:45:44 2012 +0000
recording: Optimize a copy of one recording surface onto another
Rather than store a command to copy from a reference of another recording
surface onto this, just replay the other recording surface.
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/cairo-recording-surface.c b/src/cairo-recording-surface.c
index 2e83a9c..601eb0f 100644
--- a/src/cairo-recording-surface.c
+++ b/src/cairo-recording-surface.c
@@ -677,6 +677,21 @@ _cairo_recording_surface_reset (cairo_recording_surface_t *surface)
_cairo_array_init (&surface->commands, sizeof (cairo_command_t *));
}
+static cairo_bool_t
+is_identity_recording_pattern (const cairo_pattern_t *pattern)
+{
+ cairo_surface_t *surface;
+
+ if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE)
+ return FALSE;
+
+ if (!_cairo_matrix_is_identity(&pattern->matrix))
+ return FALSE;
+
+ surface = ((cairo_surface_pattern_t *)pattern)->surface;
+ return surface->backend->type == CAIRO_SURFACE_TYPE_RECORDING;
+}
+
static cairo_int_status_t
_cairo_recording_surface_paint (void *abstract_surface,
cairo_operator_t op,
@@ -698,12 +713,16 @@ _cairo_recording_surface_paint (void *abstract_surface,
}
if (clip == NULL && surface->optimize_clears &&
- source->type == CAIRO_PATTERN_TYPE_SOLID &&
(op == CAIRO_OPERATOR_SOURCE ||
(op == CAIRO_OPERATOR_OVER &&
(surface->base.is_clear || _cairo_pattern_is_opaque_solid (source)))))
{
_cairo_recording_surface_reset (surface);
+ if (is_identity_recording_pattern (source)) {
+ cairo_surface_t *src = ((cairo_surface_pattern_t *)source)->surface;
+ _cairo_recording_surface_reset (surface);
+ return _cairo_recording_surface_replay (src, &surface->base);
+ }
}
status = _cairo_composite_rectangles_init_for_paint (&composite,
commit 8028f04a919d1e6afe95c21cd16172c367f05392
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri Feb 24 13:46:54 2012 +0000
debug: Add some TRACE statements for recording surfaces and snapshots
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/cairo-recording-surface.c b/src/cairo-recording-surface.c
index 3b626cc..2e83a9c 100644
--- a/src/cairo-recording-surface.c
+++ b/src/cairo-recording-surface.c
@@ -688,6 +688,8 @@ _cairo_recording_surface_paint (void *abstract_surface,
cairo_command_paint_t *command;
cairo_composite_rectangles_t composite;
+ TRACE ((stderr, "%s: surface=%d\n", __FUNCTION__, surface->base.unique_id));
+
if (op == CAIRO_OPERATOR_CLEAR && clip == NULL) {
if (surface->optimize_clears) {
_cairo_recording_surface_reset (surface);
@@ -758,6 +760,8 @@ _cairo_recording_surface_mask (void *abstract_surface,
cairo_command_mask_t *command;
cairo_composite_rectangles_t composite;
+ TRACE ((stderr, "%s: surface=%d\n", __FUNCTION__, surface->base.unique_id));
+
status = _cairo_composite_rectangles_init_for_mask (&composite,
&surface->base,
op, source, mask,
@@ -823,6 +827,8 @@ _cairo_recording_surface_stroke (void *abstract_surface,
cairo_command_stroke_t *command;
cairo_composite_rectangles_t composite;
+ TRACE ((stderr, "%s: surface=%d\n", __FUNCTION__, surface->base.unique_id));
+
status = _cairo_composite_rectangles_init_for_stroke (&composite,
&surface->base,
op, source,
@@ -898,6 +904,8 @@ _cairo_recording_surface_fill (void *abstract_surface,
cairo_command_fill_t *command;
cairo_composite_rectangles_t composite;
+ TRACE ((stderr, "%s: surface=%d\n", __FUNCTION__, surface->base.unique_id));
+
status = _cairo_composite_rectangles_init_for_fill (&composite,
&surface->base,
op, source, path,
@@ -975,6 +983,8 @@ _cairo_recording_surface_show_text_glyphs (void *abstract_surface,
cairo_command_show_text_glyphs_t *command;
cairo_composite_rectangles_t composite;
+ TRACE ((stderr, "%s: surface=%d\n", __FUNCTION__, surface->base.unique_id));
+
status = _cairo_composite_rectangles_init_for_glyphs (&composite,
&surface->base,
op, source,
diff --git a/src/cairo-surface-snapshot.c b/src/cairo-surface-snapshot.c
index 6952374..c197e71 100644
--- a/src/cairo-surface-snapshot.c
+++ b/src/cairo-surface-snapshot.c
@@ -49,6 +49,8 @@ _cairo_surface_snapshot_finish (void *abstract_surface)
cairo_surface_snapshot_t *surface = abstract_surface;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ TRACE ((stderr, "%s\n", __FUNCTION__));
+
if (surface->clone != NULL) {
cairo_surface_finish (surface->clone);
status = surface->clone->status;
@@ -138,6 +140,9 @@ _cairo_surface_snapshot_copy_on_write (cairo_surface_t *surface)
void *extra;
cairo_status_t status;
+ TRACE ((stderr, "%s: target=%d\n",
+ __FUNCTION__, snapshot->target->unique_id));
+
/* We need to make an image copy of the original surface since the
* snapshot may exceed the lifetime of the original device, i.e.
* when we later need to use the snapshot the data may have already
@@ -196,6 +201,8 @@ _cairo_surface_snapshot (cairo_surface_t *surface)
cairo_surface_snapshot_t *snapshot;
cairo_status_t status;
+ TRACE ((stderr, "%s: target=%d\n", __FUNCTION__, surface->unique_id));
+
if (unlikely (surface->status))
return _cairo_surface_create_in_error (surface->status);
diff --git a/src/cairo-surface-subsurface.c b/src/cairo-surface-subsurface.c
index 4d80cfd..bced245 100644
--- a/src/cairo-surface-subsurface.c
+++ b/src/cairo-surface-subsurface.c
@@ -357,6 +357,8 @@ _cairo_surface_subsurface_snapshot (void *abstract_surface)
cairo_surface_t *clone;
cairo_status_t status;
+ TRACE ((stderr, "%s: target=%d\n", __FUNCTION__, surface->target->unique_id));
+
clone = _cairo_surface_create_similar_scratch (surface->target,
surface->target->content,
surface->extents.width,
@@ -541,6 +543,8 @@ _cairo_surface_subsurface_detach_snapshot (cairo_surface_t *surface)
{
cairo_surface_subsurface_t *ss = (cairo_surface_subsurface_t *) surface;
+ TRACE ((stderr, "%s: target=%d\n", __FUNCTION__, ss->target->unique_id));
+
cairo_surface_destroy (ss->snapshot);
ss->snapshot = NULL;
}
@@ -551,6 +555,9 @@ _cairo_surface_subsurface_set_snapshot (cairo_surface_t *surface,
{
cairo_surface_subsurface_t *ss = (cairo_surface_subsurface_t *) surface;
+ TRACE ((stderr, "%s: target=%d, snapshot=%d\n", __FUNCTION__,
+ ss->target->unique_id, snapshot->unique_id));
+
if (ss->snapshot)
_cairo_surface_detach_snapshot (ss->snapshot);
commit 6b5199645af00a11e445e0ebdf74d8a9f6a3718a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri Feb 24 13:44:52 2012 +0000
image: Handle recursive drawing of recording surface
Borrow the technique for installing a proxy-snapshot developed for
acquiring the image from a recording surface.
This prevents the cairo from exploding and using up all memory due to
infinite recursion, but it does break a few tests that perform
self-copies with differing transformations.
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/cairo-image-source.c b/src/cairo-image-source.c
index 3fa75e5..c3fc7d7 100644
--- a/src/cairo-image-source.c
+++ b/src/cairo-image-source.c
@@ -606,6 +606,82 @@ _pixman_image_set_properties (pixman_image_t *pixman_image,
return TRUE;
}
+struct proxy {
+ cairo_surface_t base;
+ cairo_surface_t *image;
+};
+
+static cairo_status_t
+proxy_acquire_source_image (void *abstract_surface,
+ cairo_image_surface_t **image_out,
+ void **image_extra)
+{
+ struct proxy *proxy = abstract_surface;
+ return _cairo_surface_acquire_source_image (proxy->image, image_out, image_extra);
+}
+
+static void
+proxy_release_source_image (void *abstract_surface,
+ cairo_image_surface_t *image,
+ void *image_extra)
+{
+ struct proxy *proxy = abstract_surface;
+ _cairo_surface_release_source_image (proxy->image, image, image_extra);
+}
+
+static cairo_status_t
+proxy_finish (void *abstract_surface)
+{
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static const cairo_surface_backend_t proxy_backend = {
+ CAIRO_INTERNAL_SURFACE_TYPE_NULL,
+ proxy_finish,
+ NULL,
+
+ NULL, /* create similar */
+ NULL, /* create similar image */
+ NULL, /* map to image */
+ NULL, /* unmap image */
+
+ _cairo_surface_default_source,
+ proxy_acquire_source_image,
+ proxy_release_source_image,
+};
+
+static cairo_surface_t *
+attach_proxy (cairo_surface_t *source,
+ cairo_surface_t *image)
+{
+ struct proxy *proxy;
+
+ proxy = malloc (sizeof (*proxy));
+ if (unlikely (proxy == NULL))
+ return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
+
+ _cairo_surface_init (&proxy->base, &proxy_backend, NULL, image->content);
+
+ proxy->image = image;
+ _cairo_surface_attach_snapshot (source, &proxy->base, NULL);
+
+ return &proxy->base;
+}
+
+static void
+detach_proxy (cairo_surface_t *source,
+ cairo_surface_t *proxy)
+{
+ cairo_surface_finish (proxy);
+ cairo_surface_destroy (proxy);
+}
+
+static cairo_surface_t *
+get_proxy (cairo_surface_t *proxy)
+{
+ return ((struct proxy *)proxy)->image;
+}
+
static pixman_image_t *
_pixman_image_for_recording (cairo_image_surface_t *dst,
const cairo_surface_pattern_t *pattern,
@@ -614,7 +690,7 @@ _pixman_image_for_recording (cairo_image_surface_t *dst,
const cairo_rectangle_int_t *sample,
int *ix, int *iy)
{
- cairo_surface_t *source, *clone;
+ cairo_surface_t *source, *clone, *proxy;
cairo_rectangle_int_t limit;
pixman_image_t *pixman_image;
cairo_status_t status;
@@ -659,6 +735,13 @@ _pixman_image_for_recording (cairo_image_surface_t *dst,
}
}
+ /* XXX transformations! */
+ proxy = _cairo_surface_has_snapshot (source, &proxy_backend);
+ if (proxy != NULL) {
+ clone = cairo_surface_reference (get_proxy (proxy));
+ goto done;
+ }
+
if (dst->base.content == source->content)
clone = cairo_image_surface_create (dst->format,
limit.width, limit.height);
@@ -678,12 +761,16 @@ _pixman_image_for_recording (cairo_image_surface_t *dst,
/* XXX extract scale factor for repeating patterns */
}
+ /* Handle recursion by returning future reads from the current image */
+ proxy = attach_proxy (source, clone);
status = _cairo_recording_surface_replay_with_clip (source, m, clone, NULL);
+ detach_proxy (source, proxy);
if (unlikely (status)) {
cairo_surface_destroy (clone);
return NULL;
}
+done:
pixman_image = pixman_image_ref (((cairo_image_surface_t *)clone)->pixman_image);
cairo_surface_destroy (clone);
More information about the cairo-commit
mailing list