[gtk/wip/chergert/macos-gl-opaque-context: 5/5] macos: make OpenGL context opaque when possible




commit b2fd09625c772008af7225b5f71ca172b3445daa
Author: Christian Hergert <chergert redhat com>
Date:   Fri Feb 19 13:18:42 2021 -0800

    macos: make OpenGL context opaque when possible
    
    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       | 32 ++++++++++++++++++++++++++++++++
 gdk/macos/gdkmacossurface-private.h |  1 +
 gdk/macos/gdkmacossurface.c         | 10 +++++++++-
 3 files changed, 42 insertions(+), 1 deletion(-)
---
diff --git a/gdk/macos/gdkmacosglcontext.c b/gdk/macos/gdkmacosglcontext.c
index f50e837465..a8b28b05be 100644
--- a/gdk/macos/gdkmacosglcontext.c
+++ b/gdk/macos/gdkmacosglcontext.c
@@ -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];
diff --git a/gdk/macos/gdkmacossurface-private.h b/gdk/macos/gdkmacossurface-private.h
index c366c0b4e6..8a5ee526fa 100644
--- a/gdk/macos/gdkmacossurface-private.h
+++ b/gdk/macos/gdkmacossurface-private.h
@@ -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;
diff --git a/gdk/macos/gdkmacossurface.c b/gdk/macos/gdkmacossurface.c
index 61e249497e..5fe5bb38e7 100644
--- a/gdk/macos/gdkmacossurface.c
+++ b/gdk/macos/gdkmacossurface.c
@@ -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];


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