[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