From b2fd09625c772008af7225b5f71ca172b3445daa Mon Sep 17 00:00:00 2001 From: Christian Hergert Date: Fri, 19 Feb 2021 13:18:42 -0800 Subject: [PATCH] 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];