[gtk+/broadway: 13/71] [broadway] Ensure gdk_ref_cairo_surface object can be destroyed



commit db288f32339a0a09effceb8b84662da335871b70
Author: Alexander Larsson <alexl redhat com>
Date:   Tue Nov 16 20:28:54 2010 +0100

    [broadway] Ensure gdk_ref_cairo_surface object can be destroyed
    
    If we return a direct ref that is not possible, since we own a ref to it.
    This is problematic as the gdkwindow.c code uses destruction to track
    outstanding surfaces.
    
    We fix this by returning a subsurface.

 gdk/broadway/gdkdrawable-broadway.c |   45 +++++++++++++++++++++++++++++-----
 gdk/broadway/gdkdrawable-broadway.h |    1 +
 gdk/broadway/gdkwindow-broadway.c   |    6 ++--
 3 files changed, 42 insertions(+), 10 deletions(-)
---
diff --git a/gdk/broadway/gdkdrawable-broadway.c b/gdk/broadway/gdkdrawable-broadway.c
index 8978adf..195d9e6 100644
--- a/gdk/broadway/gdkdrawable-broadway.c
+++ b/gdk/broadway/gdkdrawable-broadway.c
@@ -67,11 +67,18 @@ _gdk_broadway_drawable_finish (GdkDrawable *drawable)
 {
   GdkDrawableImplBroadway *impl = GDK_DRAWABLE_IMPL_BROADWAY (drawable);
 
+  if (impl->ref_surface)
+    {
+      cairo_surface_finish (impl->ref_surface);
+      cairo_surface_set_user_data (impl->ref_surface, &gdk_broadway_cairo_key,
+				   NULL, NULL);
+    }
+
   if (impl->surface)
     {
-      cairo_surface_finish (impl->surface);
+      cairo_surface_destroy (impl->surface);
       impl->surface = NULL;
-      cairo_surface_finish (impl->last_surface);
+      cairo_surface_destroy (impl->last_surface);
       impl->last_surface = NULL;
     }
 }
@@ -103,8 +110,8 @@ _gdk_broadway_drawable_update_size (GdkDrawable *drawable)
 
       /* TODO: copy old contents */
 
-      cairo_surface_finish (old);
-      cairo_surface_finish (last_old);
+      cairo_surface_destroy (old);
+      cairo_surface_destroy (last_old);
     }
 }
 
@@ -112,6 +119,14 @@ _gdk_broadway_drawable_update_size (GdkDrawable *drawable)
  * Broadway specific implementations of generic functions *
  *****************************************************/
 
+static void
+gdk_broadway_cairo_surface_destroy (void *data)
+{
+  GdkDrawableImplBroadway *impl = data;
+
+  impl->ref_surface = NULL;
+}
+
 static cairo_surface_t *
 gdk_broadway_ref_cairo_surface (GdkDrawable *drawable)
 {
@@ -123,10 +138,12 @@ gdk_broadway_ref_cairo_surface (GdkDrawable *drawable)
       GDK_WINDOW_DESTROYED (impl->wrapper))
     return NULL;
 
+  w = gdk_window_get_width (impl->wrapper);
+  h = gdk_window_get_height (impl->wrapper);
+
+  /* Create actual backing store if missing */
   if (!impl->surface)
     {
-      w = gdk_window_get_width (impl->wrapper);
-      h = gdk_window_get_height (impl->wrapper);
       impl->surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, w, h);
       impl->last_surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, w, h);
 
@@ -143,5 +160,19 @@ gdk_broadway_ref_cairo_surface (GdkDrawable *drawable)
       cairo_destroy (cr);
     }
 
-  return cairo_surface_reference (impl->surface);
+  /* Create a destroyable surface referencing the real one */
+  if (!impl->ref_surface)
+    {
+      impl->ref_surface =
+	cairo_surface_create_for_rectangle (impl->surface,
+					    0, 0,
+					    w, h);
+      if (impl->ref_surface)
+	cairo_surface_set_user_data (impl->ref_surface, &gdk_broadway_cairo_key,
+				     drawable, gdk_broadway_cairo_surface_destroy);
+    }
+  else
+    cairo_surface_reference (impl->ref_surface);
+
+  return impl->ref_surface;
 }
diff --git a/gdk/broadway/gdkdrawable-broadway.h b/gdk/broadway/gdkdrawable-broadway.h
index 505a530..2a5b279 100644
--- a/gdk/broadway/gdkdrawable-broadway.h
+++ b/gdk/broadway/gdkdrawable-broadway.h
@@ -53,6 +53,7 @@ struct _GdkDrawableImplBroadway
   GdkScreen *screen;
   cairo_surface_t *surface;
   cairo_surface_t *last_surface;
+  cairo_surface_t *ref_surface;
 };
 
 struct _GdkDrawableImplBroadwayClass
diff --git a/gdk/broadway/gdkwindow-broadway.c b/gdk/broadway/gdkwindow-broadway.c
index 909ad5b..bd0f74f 100644
--- a/gdk/broadway/gdkwindow-broadway.c
+++ b/gdk/broadway/gdkwindow-broadway.c
@@ -230,9 +230,9 @@ _gdk_broadway_window_destroy (GdkWindow *window,
 
 static cairo_surface_t *
 gdk_window_broadway_resize_cairo_surface (GdkWindow       *window,
-                                     cairo_surface_t *surface,
-                                     gint             width,
-                                     gint             height)
+					  cairo_surface_t *surface,
+					  gint             width,
+					  gint             height)
 {
   /* Image surfaces cannot be resized */
   cairo_surface_destroy (surface);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]