[gtk/gtk-3-24: 9/10] [quartz] Manage implementation surface lifetime.




commit b94ed34f9c1ada2b5a19a1f7f85761ce74d9a6a6
Author: John Ralls <jralls ceridwen us>
Date:   Fri May 13 12:59:09 2022 -0700

    [quartz] Manage implementation surface lifetime.
    
    To prevent leaking cairo surfaces while persisting the parts that
    don't need to be redrawn.

 gdk/quartz/GdkQuartzView.c     |  3 +++
 gdk/quartz/gdkprivate-quartz.h |  2 ++
 gdk/quartz/gdkwindow-quartz.c  | 24 ++++++++++++++++++++++--
 3 files changed, 27 insertions(+), 2 deletions(-)
---
diff --git a/gdk/quartz/GdkQuartzView.c b/gdk/quartz/GdkQuartzView.c
index c08519db71..f7ac47dcc0 100644
--- a/gdk/quartz/GdkQuartzView.c
+++ b/gdk/quartz/GdkQuartzView.c
@@ -448,6 +448,7 @@ copy_rectangle_argb32 (cairo_surface_t *dest, cairo_surface_t *source,
   copy_rectangle_argb32 (cvpb_surface, impl->cairo_surface, &extents);
 
   cairo_surface_destroy (cvpb_surface);
+  _gdk_quartz_unref_cairo_surface (gdk_window);
   CVPixelBufferUnlockBaseAddress (pixels, 0);
   --impl->in_paint_rect_count;
   self.layer.contents = NULL;
@@ -522,6 +523,8 @@ copy_rectangle_argb32 (cairo_surface_t *dest, cairo_surface_t *source,
                             kCVPixelFormatType_32BGRA,
                             cfpb_props, &pixels);
 
+  //Force a new cairo_surface for drawing
+  _gdk_quartz_unref_cairo_surface (gdk_window);
   [super setFrame: frame];
 
   if ([self window])
diff --git a/gdk/quartz/gdkprivate-quartz.h b/gdk/quartz/gdkprivate-quartz.h
index 7900c01b17..a6e644b870 100644
--- a/gdk/quartz/gdkprivate-quartz.h
+++ b/gdk/quartz/gdkprivate-quartz.h
@@ -33,5 +33,7 @@
 
 GdkDisplay *    _gdk_quartz_display_open (const gchar *name);
 
+/* Window Impl */
+void _gdk_quartz_unref_cairo_surface (GdkWindow *window);
 
 #endif /* __GDK_PRIVATE_QUARTZ_H__ */
diff --git a/gdk/quartz/gdkwindow-quartz.c b/gdk/quartz/gdkwindow-quartz.c
index bdb668498c..4419975dc4 100644
--- a/gdk/quartz/gdkwindow-quartz.c
+++ b/gdk/quartz/gdkwindow-quartz.c
@@ -238,7 +238,9 @@ static void
 gdk_quartz_cairo_surface_destroy (void *data)
 {
   GdkQuartzCairoSurfaceData *surface_data = data;
+  cairo_surface_t *surface = surface_data->window_impl->cairo_surface;
 
+  if (!cairo_surface_get_reference_count (surface))
   surface_data->window_impl->cairo_surface = NULL;
 
   g_free (surface_data);
@@ -258,7 +260,6 @@ gdk_quartz_create_cairo_surface (GdkWindowImplQuartz *impl,
   surface_data->cg_context = NULL;
 
   surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
-
   cairo_surface_set_user_data (surface, &gdk_quartz_cairo_key,
                                surface_data,
                                gdk_quartz_cairo_surface_destroy);
@@ -291,11 +292,29 @@ gdk_quartz_ref_cairo_surface (GdkWindow *window)
       cairo_surface_reference (impl->cairo_surface); // The caller will destroy the returned one.
     }
   else
-    cairo_surface_reference (impl->cairo_surface);
+    {
+      cairo_surface_reference (impl->cairo_surface);
+    }
 
   return impl->cairo_surface;
 }
 
+void
+_gdk_quartz_unref_cairo_surface (GdkWindow *window)
+{
+  GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+
+  if (impl->cairo_surface)
+    {
+      cairo_surface_destroy (impl->cairo_surface);
+      if (impl->cairo_surface &&
+          !cairo_surface_get_reference_count (impl->cairo_surface))
+          impl->cairo_surface = NULL;
+    }
+}
+
 static void
 gdk_window_impl_quartz_init (GdkWindowImplQuartz *impl)
 {
@@ -1312,6 +1331,7 @@ move_resize_window_internal (GdkWindow *window,
 
       frame_rect = [impl->toplevel frameRectForContentRect:content_rect];
       [impl->toplevel setFrame:frame_rect display:YES];
+      impl->cairo_surface = gdk_quartz_ref_cairo_surface (window);
     }
   else 
     {


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