macos: double buffer IOSurface
authorChristian Hergert <christian@hergert.me>
Tue, 22 Feb 2022 07:53:55 +0000 (23:53 -0800)
committerChristian Hergert <christian@hergert.me>
Tue, 22 Feb 2022 20:01:29 +0000 (12:01 -0800)
It looks like, particularly on the M1, we might need to double buffer the
contents of the IOSurface<->OpenGL texture bindings. This doesn't appear
to show up on the Intel macbooks I've tried, but I've seen it in the wild
on an M1.

gdk/macos/gdkmacossurface-private.h
gdk/macos/gdkmacossurface.c

index 472058da52f78c0738bfc015779d5b92f8cf0a37..2abc199698a6caade2d55606642774bf10488040 100644 (file)
@@ -47,6 +47,7 @@ struct _GdkMacosSurface
 
   GdkMacosWindow *window;
   GdkMacosBuffer *buffer;
+  GdkMacosBuffer *front;
   GPtrArray *monitors;
   cairo_region_t *opaque_region;
   char *title;
index 5404d1e3b878902c73eab2ad140d96b6b1e09f5b..b49f4bb333b60fdf00aea63c80a6160ea982c409 100644 (file)
@@ -152,6 +152,7 @@ gdk_macos_surface_hide (GdkSurface *surface)
   _gdk_surface_clear_update_area (surface);
 
   g_clear_object (&self->buffer);
+  g_clear_object (&self->front);
 
   if (was_key)
     {
@@ -427,6 +428,9 @@ gdk_macos_surface_destroy (GdkSurface *surface,
 
   g_clear_pointer (&self->monitors, g_ptr_array_unref);
 
+  g_clear_object (&self->buffer);
+  g_clear_object (&self->front);
+
   g_assert (self->sorted.prev == NULL);
   g_assert (self->sorted.next == NULL);
   g_assert (self->frame.prev == NULL);
@@ -781,6 +785,7 @@ _gdk_macos_surface_configure (GdkMacosSurface *self)
       surface->height = content_rect.size.height;
 
       g_clear_object (&self->buffer);
+      g_clear_object (&self->front);
 
       _gdk_surface_update_size (surface);
       gdk_surface_request_layout (surface);
@@ -1032,6 +1037,7 @@ _gdk_macos_surface_monitor_changed (GdkMacosSurface *self)
 
   /* We need to create a new IOSurface for this monitor */
   g_clear_object (&self->buffer);
+  g_clear_object (&self->front);
 
   _gdk_macos_surface_configure (self);
 
@@ -1156,14 +1162,20 @@ void
 _gdk_macos_surface_swap_buffers (GdkMacosSurface      *self,
                                  const cairo_region_t *damage)
 {
+  GdkMacosBuffer *swap;
+
   g_return_if_fail (GDK_IS_MACOS_SURFACE (self));
   g_return_if_fail (damage != NULL);
 
+  swap = self->buffer;
+  self->buffer = self->front;
+  self->front = swap;
+
   /* This code looks like it swaps buffers, but since the IOSurfaceRef
    * appears to be retained on the other side, we really just ask all
    * of the GdkMacosTile CALayer's to update their contents.
    */
-  [self->window swapBuffer:self->buffer withDamage:damage];
+  [self->window swapBuffer:swap withDamage:damage];
 
   /* We might have delayed actually showing the window until the buffer
    * contents are ready to be displayed. Doing so ensures that we don't