macos: make OpenGL context opaque when possible
authorChristian Hergert <chergert@redhat.com>
Fri, 19 Feb 2021 21:18:42 +0000 (13:18 -0800)
committerChristian Hergert <chergert@redhat.com>
Fri, 19 Feb 2021 21:23:26 +0000 (13:23 -0800)
If our opaque region is the entire surface, then we can make the OpenGL
context opaque like we do for decorated windows. This improves performance
as the compositor does not need to blend the surface with the contents
behind the window.

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

index f50e837465d9ba0c8219b8c50fd8357a3a72a608..a8b28b05be263e0987d4c4cd8b020d51d0563faa 100644 (file)
@@ -267,6 +267,34 @@ gdk_macos_gl_context_real_realize (GdkGLContext  *context,
   return TRUE;
 }
 
+static gboolean
+opaque_region_covers_surface (GdkMacosGLContext *self)
+{
+  GdkSurface *surface;
+  cairo_region_t *region;
+
+  g_assert (GDK_IS_MACOS_GL_CONTEXT (self));
+
+  surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (self));
+  region = GDK_MACOS_SURFACE (surface)->opaque_region;
+
+  if (region != NULL &&
+      cairo_region_num_rectangles (region) == 1)
+    {
+      cairo_rectangle_int_t extents;
+
+      cairo_region_get_extents (region, &extents);
+
+      if (extents.x == 0 &&
+          extents.y == 0 &&
+          extents.width == surface->width &&
+          extents.height == surface->height)
+        return TRUE;
+    }
+
+  return FALSE;
+}
+
 static void
 gdk_macos_gl_context_begin_frame (GdkDrawContext *context,
                                   cairo_region_t *painted)
@@ -315,6 +343,10 @@ gdk_macos_gl_context_begin_frame (GdkDrawContext *context,
       else
         opaque = FALSE;
 
+      /* If we are maximized, we might be able to make it opaque */
+      if (opaque == FALSE)
+        opaque = opaque_region_covers_surface (self);
+
       CGLSetParameter (cgl_context, kCGLCPSurfaceOpacity, &opaque);
 
       [self->gl_context update];
index c366c0b4e6fb72697266dbc50f3bc1cc5c80d865..8a5ee526fa91737cd7aaf757d45c93474be0a9f7 100644 (file)
@@ -48,6 +48,7 @@ struct _GdkMacosSurface
   GdkMacosWindow *window;
   GPtrArray *monitors;
   cairo_region_t *input_region;
+  cairo_region_t *opaque_region;
   char *title;
 
   int root_x;
index 61e249497ef737c96fa803d1840c876254cba2a1..5fe5bb38e71195fb36a1a4bfbbccaa2deccf4692 100644 (file)
@@ -98,9 +98,16 @@ static void
 gdk_macos_surface_set_opaque_region (GdkSurface     *surface,
                                      cairo_region_t *region)
 {
+  GdkMacosSurface *self = (GdkMacosSurface *)surface;
   NSView *nsview;
 
-  g_assert (GDK_IS_MACOS_SURFACE (surface));
+  g_assert (GDK_IS_MACOS_SURFACE (self));
+
+  if (region != self->opaque_region)
+    {
+      g_clear_pointer (&self->opaque_region, cairo_region_destroy);
+      self->opaque_region = cairo_region_copy (region);
+    }
 
   if ((nsview = _gdk_macos_surface_get_view (GDK_MACOS_SURFACE (surface))) &&
       GDK_IS_MACOS_CAIRO_VIEW (nsview))
@@ -386,6 +393,7 @@ gdk_macos_surface_destroy (GdkSurface *surface,
     }
 
   g_clear_pointer (&self->title, g_free);
+  g_clear_pointer (&self->opaque_region, cairo_region_destroy);
 
   if (window != NULL)
     [window close];