[gtk/wip/chergert/gdk-macos-gl-renderer] macos: add more aggressive clip to transparent subview




commit d8192013f3ee1eda0bb9de793acd64b4ef84c1ff
Author: Christian Hergert <chergert redhat com>
Date:   Thu Oct 29 19:37:27 2020 -0700

    macos: add more aggressive clip to transparent subview
    
    The Cairo implementation for the Macos backend uses a toplevel
    window with full transparency and a series of NSView to create opaque
    regions. This improves compositor performance because it allows the
    display server to avoid costly blends.
    
    However, we want to ensure we clip better when exposing the
    transparent region so that we only expose the shadows/corners as
    necessary.

 gdk/macos/GdkMacosCairoSubview.c | 31 +++++++++++++++++++++++++++++++
 gdk/macos/GdkMacosCairoSubview.h |  2 ++
 gdk/macos/GdkMacosCairoView.c    | 12 ++++++++++++
 3 files changed, 45 insertions(+)
---
diff --git a/gdk/macos/GdkMacosCairoSubview.c b/gdk/macos/GdkMacosCairoSubview.c
index 425b52ac78..e52acdf168 100644
--- a/gdk/macos/GdkMacosCairoSubview.c
+++ b/gdk/macos/GdkMacosCairoSubview.c
@@ -32,6 +32,12 @@
 
 @implementation GdkMacosCairoSubview
 
+-(void)dealloc
+{
+  g_clear_pointer (&self->clip, cairo_region_destroy);
+  [super dealloc];
+}
+
 -(BOOL)isOpaque
 {
   return _isOpaque;
@@ -95,6 +101,21 @@
   cr = cairo_create (dest);
   cairo_translate (cr, -abs_bounds.origin.x, -abs_bounds.origin.y);
 
+  /* Apply the clip if provided one */
+  if (self->clip != NULL)
+    {
+      cairo_rectangle_int_t area;
+
+      n_rects = cairo_region_num_rectangles (self->clip);
+      for (guint i = 0; i < n_rects; i++)
+        {
+          cairo_region_get_rectangle (self->clip, i, &area);
+          cairo_rectangle (cr, area.x, area.y, area.width, area.height);
+        }
+
+      cairo_clip (cr);
+    }
+
   /* Clip the cairo context based on the rectangles to be drawn
    * within the bounding box :rect.
    */
@@ -168,4 +189,14 @@
   self->_isOpaque = opaque;
 }
 
+-(void)setClip:(cairo_region_t*)region
+{
+  if (region != self->clip)
+    {
+      g_clear_pointer (&self->clip, cairo_region_destroy);
+      if (region != NULL)
+        self->clip = cairo_region_reference (region);
+    }
+}
+
 @end
diff --git a/gdk/macos/GdkMacosCairoSubview.h b/gdk/macos/GdkMacosCairoSubview.h
index 9255347566..5eae734f8f 100644
--- a/gdk/macos/GdkMacosCairoSubview.h
+++ b/gdk/macos/GdkMacosCairoSubview.h
@@ -26,10 +26,12 @@
 {
   BOOL             _isOpaque;
   cairo_surface_t *cairoSurface;
+  cairo_region_t  *clip;
 }
 
 -(void)setOpaque:(BOOL)opaque;
 -(void)setCairoSurface:(cairo_surface_t *)cairoSurface
             withDamage:(cairo_region_t *)region;
+-(void)setClip:(cairo_region_t*)region;
 
 @end
diff --git a/gdk/macos/GdkMacosCairoView.c b/gdk/macos/GdkMacosCairoView.c
index 2f82488912..81ac8af6a3 100644
--- a/gdk/macos/GdkMacosCairoView.c
+++ b/gdk/macos/GdkMacosCairoView.c
@@ -78,6 +78,7 @@
 
 -(void)setOpaqueRegion:(cairo_region_t *)region
 {
+  cairo_region_t *transparent_clip;
   NSRect abs_bounds;
   guint n_rects;
 
@@ -87,6 +88,17 @@
   abs_bounds = [self convertRect:[self bounds] toView:nil];
   n_rects = cairo_region_num_rectangles (region);
 
+  /* First, we create a clip region for the transparent region to use so that
+   * we dont end up exposing too much other than the corners on CSD.
+   */
+  transparent_clip = cairo_region_create_rectangle (&(cairo_rectangle_int_t) {
+    abs_bounds.origin.x, abs_bounds.origin.y,
+    abs_bounds.size.width, abs_bounds.size.height
+  });
+  cairo_region_subtract (transparent_clip, region);
+  [(GdkMacosCairoSubview *)self->transparent setClip:transparent_clip];
+  cairo_region_destroy (transparent_clip);
+
   /* The common case (at least for opaque windows and CSD) is that we will
    * have either one or two opaque rectangles. If we detect that the same
    * number of them are available as the previous, we can just resize the


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