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




commit 4a3c40876fc51f5523e17b50197e47d7e9c74496
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]