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.
This commit is contained in:
Christian Hergert 2020-10-29 19:37:27 -07:00
parent 8ed1f51f7f
commit d8192013f3
3 changed files with 45 additions and 0 deletions

View File

@ -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

View File

@ -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

View File

@ -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