[cairo-commit] src/cairo-image-surface.c src/cairo-image-surface-private.h src/win32

Chris Wilson ickle at kemper.freedesktop.org
Wed Feb 15 10:30:58 PST 2012


 src/cairo-image-surface-private.h       |   13 +++++++++++++
 src/cairo-image-surface.c               |    5 +++++
 src/win32/cairo-win32-display-surface.c |    6 +++++-
 3 files changed, 23 insertions(+), 1 deletion(-)

New commits:
commit df608e0fab542562eb00b4f3c84735946289226a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Feb 15 18:25:35 2012 +0000

    win32: Fix lifetime tracking of create_similar_image()
    
    As we return the child image to the user and so perform the reference
    tracking on it and not the parent win32 display surface, we need to add
    a call to destroy the parent from the image surface. This of course
    complicates the normal scenario of destroying the parent first, and so
    in that case we need to unhook the image->parent before freeing the
    surface->image.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-image-surface-private.h b/src/cairo-image-surface-private.h
index 3951793..cef2d75 100644
--- a/src/cairo-image-surface-private.h
+++ b/src/cairo-image-surface-private.h
@@ -50,6 +50,19 @@ struct _cairo_image_surface {
 
     pixman_image_t *pixman_image;
     const cairo_compositor_t *compositor;
+
+    /* Parenting is tricky wrt lifetime tracking...
+     *
+     * One use for tracking the parent of an image surface is for
+     * create_similar_image() where we wish to create a device specific
+     * surface but return an image surface to the user. In such a case,
+     * the image may be owned by the device specific surface, its parent,
+     * but the user lifetime tracking is then performed on the image. So
+     * when the image is then finalized we call cairo_surface_destroy()
+     * on the parent. However, for normal usage where the lifetime tracking
+     * is done on the parent surface, we need to be careful to unhook
+     * the image->parent pointer before finalizing the image.
+     */
     cairo_surface_t *parent;
 
     pixman_format_code_t pixman_format;
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 66f024c..982bf45 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -813,6 +813,11 @@ _cairo_image_surface_finish (void *abstract_surface)
 	surface->data = NULL;
     }
 
+    if (surface->parent) {
+	cairo_surface_destroy (surface->parent);
+	surface->parent = NULL;
+    }
+
     return CAIRO_STATUS_SUCCESS;
 }
 
diff --git a/src/win32/cairo-win32-display-surface.c b/src/win32/cairo-win32-display-surface.c
index 1b5d47e..ac37cbf 100644
--- a/src/win32/cairo-win32-display-surface.c
+++ b/src/win32/cairo-win32-display-surface.c
@@ -405,8 +405,12 @@ _cairo_win32_display_surface_finish (void *abstract_surface)
 {
     cairo_win32_display_surface_t *surface = abstract_surface;
 
-    if (surface->image)
+    if (surface->image) {
+	/* Unhook ourselves first to avoid the double-unref from the image */
+	surface->image->parent = NULL;
+	cairo_surface_finish (surface->image);
 	cairo_surface_destroy (surface->image);
+    }
 
     /* If we created the Bitmap and DC, destroy them */
     if (surface->bitmap) {


More information about the cairo-commit mailing list