[gtk/wip/chergert/macos-iosurface] incremental work on cairo rendering to iosurface
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/chergert/macos-iosurface] incremental work on cairo rendering to iosurface
- Date: Wed, 9 Feb 2022 15:00:35 +0000 (UTC)
commit ca14499f81938b3d323d00809da000ea8b5ed075
Author: Christian Hergert <christian hergert me>
Date: Wed Feb 9 07:00:23 2022 -0800
incremental work on cairo rendering to iosurface
gdk/macos/GdkMacosLayer.c | 339 ++++++++++++++++++++++++++++++++++++
gdk/macos/GdkMacosLayer.h | 43 +++++
gdk/macos/GdkMacosSuperView.c | 81 +++++++++
gdk/macos/GdkMacosSuperView.h | 38 ++++
gdk/macos/GdkMacosTile.c | 56 ++++++
gdk/macos/GdkMacosTile.h | 35 ++++
gdk/macos/GdkMacosWindow.c | 14 +-
gdk/macos/GdkMacosWindow.h | 3 +
gdk/macos/gdkmacosbuffer-private.h | 27 ++-
gdk/macos/gdkmacosbuffer.c | 169 +++++++++++++++---
gdk/macos/gdkmacoscairocontext.c | 188 ++++++++++----------
gdk/macos/gdkmacossurface-private.h | 10 +-
gdk/macos/gdkmacossurface.c | 82 +++++++--
gdk/macos/meson.build | 6 +-
14 files changed, 946 insertions(+), 145 deletions(-)
---
diff --git a/gdk/macos/GdkMacosLayer.c b/gdk/macos/GdkMacosLayer.c
new file mode 100644
index 0000000000..94f3613309
--- /dev/null
+++ b/gdk/macos/GdkMacosLayer.c
@@ -0,0 +1,339 @@
+/* GdkMacosLayer.c
+ *
+ * Copyright © 2022 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#import "GdkMacosLayer.h"
+#import "GdkMacosTile.h"
+
+@implementation GdkMacosLayer
+
+#define TILE_MAX_SIZE 128
+
+typedef struct
+{
+ GdkMacosTile *tile;
+ cairo_rectangle_int_t cr_area;
+ CGRect area;
+ guint opaque : 1;
+} TileInfo;
+
+typedef struct
+{
+ const cairo_region_t *region;
+ guint n_rects;
+ guint iter;
+ cairo_rectangle_int_t rect;
+ cairo_rectangle_int_t stash;
+ guint finished : 1;
+} Tiler;
+
+static void
+tiler_init (Tiler *tiler,
+ const cairo_region_t *region)
+{
+ memset (tiler, 0, sizeof *tiler);
+
+ if (region == NULL)
+ {
+ tiler->finished = TRUE;
+ return;
+ }
+
+ tiler->region = region;
+ tiler->n_rects = cairo_region_num_rectangles (region);
+
+ if (tiler->n_rects > 0)
+ cairo_region_get_rectangle (region, 0, &tiler->rect);
+ else
+ tiler->finished = TRUE;
+}
+
+static gboolean
+tiler_next (Tiler *tiler,
+ cairo_rectangle_int_t *tile)
+{
+ if (tiler->finished)
+ return FALSE;
+
+ if (tiler->rect.width == 0 || tiler->rect.height == 0)
+ {
+ tiler->iter++;
+
+ if (tiler->iter >= tiler->n_rects)
+ {
+ tiler->finished = TRUE;
+ return FALSE;
+ }
+
+ cairo_region_get_rectangle (tiler->region, tiler->iter, &tiler->rect);
+ }
+
+ /* If the next rectangle is too tall, slice the bottom off to
+ * leave just the height we want into tiler->stash.
+ */
+ if (tiler->rect.height > TILE_MAX_SIZE)
+ {
+ tiler->stash = tiler->rect;
+ tiler->stash.y += TILE_MAX_SIZE;
+ tiler->stash.height -= TILE_MAX_SIZE;
+ tiler->rect.height = TILE_MAX_SIZE;
+ }
+
+ /* Now we can take the next horizontal slice */
+ tile->x = tiler->rect.x;
+ tile->y = tiler->rect.y;
+ tile->height = tiler->rect.height;
+ tile->width = MIN (TILE_MAX_SIZE, tiler->rect.width);
+
+ tiler->rect.x += tile->width;
+ tiler->rect.width -= tile->width;
+
+ if (tiler->rect.width == 0)
+ {
+ tiler->rect = tiler->stash;
+ tiler->stash.width = tiler->stash.height = 0;
+ }
+
+ return TRUE;
+}
+
+static inline CGRect
+toCGRect (const cairo_rectangle_int_t *rect)
+{
+ return CGRectMake (rect->x, rect->y, rect->width, rect->height);
+}
+
+static inline cairo_rectangle_int_t
+fromCGRect (const CGRect rect)
+{
+ return (cairo_rectangle_int_t) {
+ rect.origin.x,
+ rect.origin.y,
+ rect.size.width,
+ rect.size.height
+ };
+}
+
+-(id)init
+{
+ self = [super init];
+
+ if (self == NULL)
+ return NULL;
+
+ [self setContentsGravity:kCAGravityCenter];
+ [self setContentsScale:1.0f];
+ [self setGeometryFlipped:YES];
+
+ return self;
+}
+
+-(BOOL)contentsAreFlipped
+{
+ return YES;
+}
+
+-(BOOL)isOpaque
+{
+ return NO;
+}
+
+-(void)_applyLayout:(GArray *)tiles
+{
+ GArray *prev;
+ gboolean exhausted;
+ guint j = 0;
+
+ prev = g_steal_pointer (&self->_tiles);
+ self->_tiles = tiles;
+ exhausted = prev == NULL;
+
+ /* Try to use existing CALayer to avoid creating new layers
+ * as that can be rather expensive.
+ */
+ for (guint i = 0; i < tiles->len; i++)
+ {
+ TileInfo *info = &g_array_index (tiles, TileInfo, i);
+
+ if (!exhausted)
+ {
+ TileInfo *other = NULL;
+
+ for (; j < prev->len; j++)
+ {
+ other = &g_array_index (prev, TileInfo, j);
+
+ if (other->opaque == info->opaque)
+ {
+ j++;
+ break;
+ }
+
+ other = NULL;
+ }
+
+ if (other != NULL)
+ {
+ info->tile = g_steal_pointer (&other->tile);
+ [info->tile setFrame:info->area];
+ continue;
+ }
+ }
+
+ info->tile = [GdkMacosTile layer];
+
+ //[info->tile setContentsGravity:kCAGravityCenter];
+ [info->tile setContentsScale:1.0f];
+ [info->tile setOpaque:info->opaque];
+ [info->tile setFrame:info->area];
+
+ [self addSublayer:info->tile];
+ }
+
+ /* Release all of our old layers */
+ if (prev != NULL)
+ {
+ for (guint i = 0; i < prev->len; i++)
+ {
+ TileInfo *info = &g_array_index (prev, TileInfo, i);
+
+ if (info->tile != NULL)
+ [info->tile removeFromSuperlayer];
+ }
+
+ g_array_unref (prev);
+ }
+}
+
+-(void)layoutSublayers
+{
+ Tiler tiler;
+ GArray *ar;
+ cairo_region_t *transparent;
+ cairo_rectangle_int_t rect;
+
+ if (!self->_inSwapBuffer)
+ return;
+
+ ar = g_array_sized_new (FALSE, FALSE, sizeof (TileInfo), 32);
+
+ rect = fromCGRect ([self bounds]);
+ rect.x = rect.y = 0;
+
+ /* Calculate the transparent region (edges usually) */
+ transparent = cairo_region_create_rectangle (&rect);
+ if (self->_opaqueRegion)
+ cairo_region_subtract (transparent, self->_opaqueRegion);
+
+ self->_opaque = cairo_region_is_empty (transparent);
+
+ /* Track transparent children */
+ tiler_init (&tiler, transparent);
+ while (tiler_next (&tiler, &rect))
+ {
+ TileInfo *info;
+
+ g_array_set_size (ar, ar->len+1);
+
+ info = &g_array_index (ar, TileInfo, ar->len-1);
+ info->tile = NULL;
+ info->opaque = FALSE;
+ info->cr_area = rect;
+ info->area = toCGRect (&info->cr_area);
+ }
+
+ /* Track opaque children */
+ tiler_init (&tiler, self->_opaqueRegion);
+ while (tiler_next (&tiler, &rect))
+ {
+ TileInfo *info;
+
+ g_array_set_size (ar, ar->len+1);
+
+ info = &g_array_index (ar, TileInfo, ar->len-1);
+ info->tile = NULL;
+ info->opaque = TRUE;
+ info->cr_area = rect;
+ info->area = toCGRect (&info->cr_area);
+ }
+
+ cairo_region_destroy (transparent);
+
+ [self _applyLayout:g_steal_pointer (&ar)];
+ [super layoutSublayers];
+}
+
+-(void)setFrame:(NSRect)frame
+{
+ if (CGRectEqualToRect (frame, self.frame))
+ return;
+
+ self->_layoutInvalid = TRUE;
+
+ [super setFrame:frame];
+}
+
+-(void)setOpaqueRegion:(const cairo_region_t *)opaqueRegion
+{
+ g_clear_pointer (&self->_opaqueRegion, cairo_region_destroy);
+ self->_opaqueRegion = cairo_region_copy (opaqueRegion);
+ self->_layoutInvalid = TRUE;
+}
+
+-(void)swapBuffer:(GdkMacosBuffer *)buffer withDamage:(const cairo_region_t *)damage
+{
+ IOSurfaceRef ioSurface = _gdk_macos_buffer_get_native (buffer);
+ double scale = _gdk_macos_buffer_get_device_scale (buffer);
+ size_t width = _gdk_macos_buffer_get_width (buffer) / scale;
+ size_t height = _gdk_macos_buffer_get_height (buffer) / scale;
+
+ if (self->_layoutInvalid)
+ {
+ self->_layoutInvalid = FALSE;
+
+ self->_inSwapBuffer = TRUE;
+ [self layoutSublayers];
+ self->_inSwapBuffer = FALSE;
+ }
+
+ if (self->_tiles == NULL)
+ return;
+
+ for (guint i = 0; i < self->_tiles->len; i++)
+ {
+ const TileInfo *info = &g_array_index (self->_tiles, TileInfo, i);
+ cairo_region_overlap_t overlap;
+ CGRect area;
+
+ overlap = cairo_region_contains_rectangle (damage, &info->cr_area);
+ if (overlap == CAIRO_REGION_OVERLAP_OUT)
+ continue;
+
+ area.origin.x = info->area.origin.x / (double)width;
+ area.origin.y = info->area.origin.y / (double)height;
+ area.size.width = info->area.size.width / (double)width;
+ area.size.height = info->area.size.height / (double)height;
+
+ [info->tile swapBuffer:ioSurface withRect:area];
+ }
+}
+
+@end
diff --git a/gdk/macos/GdkMacosLayer.h b/gdk/macos/GdkMacosLayer.h
new file mode 100644
index 0000000000..18b7d9afae
--- /dev/null
+++ b/gdk/macos/GdkMacosLayer.h
@@ -0,0 +1,43 @@
+/* GdkMacosLayer.h
+ *
+ * Copyright © 2022 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include <QuartzCore/QuartzCore.h>
+#include <IOSurface/IOSurface.h>
+
+#include <cairo.h>
+#include <glib.h>
+
+#include "gdkmacosbuffer-private.h"
+
+#define GDK_IS_MACOS_LAYER(obj) ((obj) && [obj isKindOfClass:[GdkMacosLayer class]])
+
+@interface GdkMacosLayer : CALayer
+{
+ cairo_region_t *_opaqueRegion;
+ GArray *_tiles;
+ guint _opaque : 1;
+ guint _layoutInvalid : 1;
+ guint _inSwapBuffer : 1;
+};
+
+-(void)setOpaqueRegion:(const cairo_region_t *)opaqueRegion;
+-(void)swapBuffer:(GdkMacosBuffer *)buffer withDamage:(const cairo_region_t *)damage;
+
+@end
diff --git a/gdk/macos/GdkMacosSuperView.c b/gdk/macos/GdkMacosSuperView.c
new file mode 100644
index 0000000000..04a0420477
--- /dev/null
+++ b/gdk/macos/GdkMacosSuperView.c
@@ -0,0 +1,81 @@
+/* GdkMacosSuperView.c
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#include <CoreGraphics/CoreGraphics.h>
+
+#import "GdkMacosLayer.h"
+#import "GdkMacosSuperView.h"
+
+@implementation GdkMacosSuperView
+
+-(id)initWithFrame:(NSRect)frame
+{
+ if ((self = [super initWithFrame:frame]))
+ {
+ GdkMacosLayer *layer = [GdkMacosLayer layer];
+
+ [self setLayerContentsRedrawPolicy:NSViewLayerContentsRedrawNever];
+ [self setLayer:layer];
+ [self setWantsLayer:YES];
+ }
+
+ return self;
+}
+
+-(BOOL)isFlipped
+{
+ return YES;
+}
+
+-(BOOL)acceptsFirstMouse
+{
+ return YES;
+}
+
+-(BOOL)mouseDownCanMoveWindow
+{
+ return NO;
+}
+
+-(void)setFrame:(NSRect)rect
+{
+ [super setFrame:rect];
+ self->_nextFrameDirty = TRUE;
+}
+
+-(void)setOpaqueRegion:(const cairo_region_t *)opaqueRegion
+{
+ [(GdkMacosLayer *)[self layer] setOpaqueRegion:opaqueRegion];
+}
+
+-(void)swapBuffer:(GdkMacosBuffer *)buffer withDamage:(const cairo_region_t *)damage
+{
+ if (self->_nextFrameDirty)
+ {
+ self->_nextFrameDirty = FALSE;
+ [[self layer] setFrame:[self frame]];
+ }
+
+ [(GdkMacosLayer *)[self layer] swapBuffer:buffer withDamage:damage];
+}
+
+@end
diff --git a/gdk/macos/GdkMacosSuperView.h b/gdk/macos/GdkMacosSuperView.h
new file mode 100644
index 0000000000..a0a2a198f5
--- /dev/null
+++ b/gdk/macos/GdkMacosSuperView.h
@@ -0,0 +1,38 @@
+/* GdkMacosSuperView.h
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include <cairo.h>
+
+#import "GdkMacosBaseView.h"
+
+#include "gdkmacosbuffer-private.h"
+
+#define GDK_IS_MACOS_SUPER_VIEW(obj) ((obj) && [obj isKindOfClass:[GdkMacosSuperView class]])
+
+@interface GdkMacosSuperView : GdkMacosBaseView
+{
+ NSRect _nextFrame;
+ guint _nextFrameDirty : 1;
+}
+
+-(void)setOpaqueRegion:(const cairo_region_t *)opaqueRegion;
+-(void)swapBuffer:(GdkMacosBuffer *)buffer withDamage:(const cairo_region_t *)damage;
+
+@end
diff --git a/gdk/macos/GdkMacosTile.c b/gdk/macos/GdkMacosTile.c
new file mode 100644
index 0000000000..09e82542c2
--- /dev/null
+++ b/gdk/macos/GdkMacosTile.c
@@ -0,0 +1,56 @@
+/* GdkMacosTile.c
+ *
+ * Copyright © 2022 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#import "GdkMacosTile.h"
+
+@implementation GdkMacosTile
+
+-(BOOL)contentsAreFlipped
+{
+ return YES;
+}
+
+-(BOOL)isOpaque
+{
+ return self->_opaque;
+}
+
+-(void)setOpaque:(BOOL)opaque
+{
+ self->_opaque = opaque;
+}
+
+-(void)swapBuffer:(IOSurfaceRef)buffer withRect:(CGRect)rect
+{
+ CGRect prevRect = [self contentsRect];
+
+ self.contents = nil;
+ self.contents = (id)buffer;
+
+ if (!CGRectEqualToRect (prevRect, rect))
+ self.contentsRect = rect;
+
+ if (self.contentsScale != 1.0f)
+ self.contentsScale = 1.0f;
+}
+
+@end
diff --git a/gdk/macos/GdkMacosTile.h b/gdk/macos/GdkMacosTile.h
new file mode 100644
index 0000000000..09295800fb
--- /dev/null
+++ b/gdk/macos/GdkMacosTile.h
@@ -0,0 +1,35 @@
+/* GdkMacosTile.h
+ *
+ * Copyright © 2022 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include <QuartzCore/QuartzCore.h>
+
+#include "gdkmacosbuffer-private.h"
+
+#define GDK_IS_MACOS_TILE(obj) ((obj) && [obj isKindOfClass:[GdkMacosTile class]])
+
+@interface GdkMacosTile : CALayer
+{
+ guint _opaque : 1;
+};
+
+-(void)setOpaque:(BOOL)opaque;
+-(void)swapBuffer:(IOSurfaceRef)buffer withRect:(CGRect)rect;
+
+@end
diff --git a/gdk/macos/GdkMacosWindow.c b/gdk/macos/GdkMacosWindow.c
index 8dda79ab4d..bb78c9fe87 100644
--- a/gdk/macos/GdkMacosWindow.c
+++ b/gdk/macos/GdkMacosWindow.c
@@ -24,8 +24,8 @@
#include <gdk/gdk.h>
#import "GdkMacosBaseView.h"
-#import "GdkMacosCairoView.h"
#import "GdkMacosGLView.h"
+#import "GdkMacosSuperView.h"
#import "GdkMacosWindow.h"
#include "gdkmacosclipboard-private.h"
@@ -266,7 +266,7 @@ typedef NSString *CALayerContentsGravity;
[[self contentView] setFrame:NSMakeRect (0, 0, surface->width, surface->height)];
- _gdk_surface_update_size (surface);
+ _gdk_macos_surface_update_size (gdk_surface);
gdk_surface_request_layout (surface);
@@ -281,7 +281,7 @@ typedef NSString *CALayerContentsGravity;
defer:(BOOL)flag
screen:(NSScreen *)screen
{
- GdkMacosCairoView *view;
+ GdkMacosSuperView *view;
self = [super initWithContentRect:contentRect
styleMask:styleMask
@@ -292,8 +292,9 @@ typedef NSString *CALayerContentsGravity;
[self setAcceptsMouseMovedEvents:YES];
[self setDelegate:(id<NSWindowDelegate>)self];
[self setReleasedWhenClosed:YES];
+ [self setPreservesContentDuringLiveResize:NO];
- view = [[GdkMacosCairoView alloc] initWithFrame:contentRect];
+ view = [[GdkMacosSuperView alloc] initWithFrame:contentRect];
[self setContentView:view];
[view release];
@@ -852,4 +853,9 @@ typedef NSString *CALayerContentsGravity;
return NO;
}
+-(void)swapBuffer:(GdkMacosBuffer *)buffer withDamage:(const cairo_region_t *)damage
+{
+ [(GdkMacosSuperView *)[self contentView] swapBuffer:buffer withDamage:damage];
+}
+
@end
diff --git a/gdk/macos/GdkMacosWindow.h b/gdk/macos/GdkMacosWindow.h
index 61f546a78b..cb8b2efad1 100644
--- a/gdk/macos/GdkMacosWindow.h
+++ b/gdk/macos/GdkMacosWindow.h
@@ -21,9 +21,11 @@
#import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>
+#import <IOSurface/IOSurface.h>
#include <gdk/gdk.h>
+#include "gdkmacosbuffer-private.h"
#include "gdkmacosdisplay.h"
#include "gdkmacossurface.h"
#include "edgesnapping.h"
@@ -66,5 +68,6 @@
-(BOOL)trackManualMove;
-(BOOL)trackManualResize;
-(void)setDecorated:(BOOL)decorated;
+-(void)swapBuffer:(GdkMacosBuffer *)buffer withDamage:(const cairo_region_t *)damage;
@end
diff --git a/gdk/macos/gdkmacosbuffer-private.h b/gdk/macos/gdkmacosbuffer-private.h
index a7663d8556..ac8ec4e107 100644
--- a/gdk/macos/gdkmacosbuffer-private.h
+++ b/gdk/macos/gdkmacosbuffer-private.h
@@ -20,6 +20,10 @@
#ifndef __GDK_MACOS_BUFFER_PRIVATE_H__
#define __GDK_MACOS_BUFFER_PRIVATE_H__
+#include <CoreGraphics/CoreGraphics.h>
+#include <Foundation/Foundation.h>
+#include <IOSurface/IOSurface.h>
+
#include "gdkmacosdisplay.h"
G_BEGIN_DECLS
@@ -28,12 +32,23 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (GdkMacosBuffer, gdk_macos_buffer, GDK, MACOS_BUFFER, GObject)
-GdkMacosBuffer *_gdk_macos_buffer_new (GdkMacosDisplay *display,
- int width,
- int height,
- int bytes_per_pixel);
-void _gdk_macos_buffer_lock (GdkMacosBuffer *self);
-void _gdk_macos_buffer_unlock (GdkMacosBuffer *self);
+GdkMacosBuffer *_gdk_macos_buffer_new (GdkMacosDisplay *display,
+ int width,
+ int height,
+ double device_scale,
+ int bytes_per_element,
+ int bits_per_pixel);
+IOSurfaceRef _gdk_macos_buffer_get_native (GdkMacosBuffer *self);
+CGContextRef _gdk_macos_buffer_create_context (GdkMacosBuffer *self);
+void _gdk_macos_buffer_lock (GdkMacosBuffer *self);
+void _gdk_macos_buffer_unlock (GdkMacosBuffer *self);
+guint _gdk_macos_buffer_get_width (GdkMacosBuffer *self);
+guint _gdk_macos_buffer_get_height (GdkMacosBuffer *self);
+guint _gdk_macos_buffer_get_stride (GdkMacosBuffer *self);
+double _gdk_macos_buffer_get_device_scale (GdkMacosBuffer *self);
+const cairo_region_t *_gdk_macos_buffer_get_damage (GdkMacosBuffer *self);
+void _gdk_macos_buffer_set_damage (GdkMacosBuffer *self,
+ cairo_region_t *damage);
G_END_DECLS
diff --git a/gdk/macos/gdkmacosbuffer.c b/gdk/macos/gdkmacosbuffer.c
index 8584478c24..7e66b83a09 100644
--- a/gdk/macos/gdkmacosbuffer.c
+++ b/gdk/macos/gdkmacosbuffer.c
@@ -26,10 +26,28 @@
#include "gdkmacosbuffer-private.h"
+CGContextRef CGIOSurfaceContextCreate (IOSurfaceRef io_surface,
+ size_t width,
+ size_t height,
+ size_t bitsPerComponent,
+ size_t bitsPerPixel,
+ CGColorSpaceRef colorSpace,
+ CGBitmapInfo bitmapInfo);
+CGImageRef CGIOSurfaceContextCreateImage (CGContextRef cgContext);
+
struct _GdkMacosBuffer
{
- GObject parent_instance;
- IOSurfaceRef surface;
+ GObject parent_instance;
+ cairo_region_t *damage;
+ CGColorSpaceRef colorspace;
+ IOSurfaceRef surface;
+ int lock_count;
+ guint bytes_per_element;
+ guint bits_per_pixel;
+ guint width;
+ guint height;
+ guint stride;
+ double device_scale;
};
G_DEFINE_TYPE (GdkMacosBuffer, gdk_macos_buffer, G_TYPE_OBJECT)
@@ -38,12 +56,14 @@ static void
gdk_macos_buffer_dispose (GObject *object)
{
GdkMacosBuffer *self = (GdkMacosBuffer *)object;
+
+ if (self->lock_count != 0)
+ g_critical ("Attempt to dispose %s while lock is held",
+ G_OBJECT_TYPE_NAME (self));
- if (self->surface != NULL)
- {
- CFRelease (self->surface);
- self->surface = NULL;
- }
+ g_clear_pointer (&self->surface, CFRelease);
+ g_clear_pointer (&self->colorspace, CGColorSpaceRelease);
+ g_clear_pointer (&self->damage, cairo_region_destroy);
G_OBJECT_CLASS (gdk_macos_buffer_parent_class)->dispose (object);
}
@@ -72,9 +92,10 @@ add_int (CFMutableDictionaryRef dict,
}
static IOSurfaceRef
-create_surface (int width,
- int height,
- int bytes_per_pixel)
+create_surface (int width,
+ int height,
+ int bytes_per_element,
+ guint *stride)
{
CFMutableDictionaryRef props;
IOSurfaceRef ret;
@@ -88,22 +109,22 @@ create_surface (int width,
if (props == NULL)
return NULL;
- add_int (props, kIOSurfaceWidth, width);
- add_int (props, kIOSurfaceHeight, height);
- add_int (props, kIOSurfaceBytesPerElement, bytes_per_pixel);
-
- bytes_per_row = IOSurfaceAlignProperty (kIOSurfaceBytesPerRow, width * bytes_per_pixel);
- add_int (props, kIOSurfaceBytesPerRow, bytes_per_row);
-
+ bytes_per_row = IOSurfaceAlignProperty (kIOSurfaceBytesPerRow, width * bytes_per_element);
total_bytes = IOSurfaceAlignProperty (kIOSurfaceAllocSize, height * bytes_per_row);
+
add_int (props, kIOSurfaceAllocSize, total_bytes);
-
- add_int (props, kIOSurfacePixelFormat, (int)kCVPixelFormatType_32BGRA);
+ add_int (props, kIOSurfaceBytesPerElement, bytes_per_element);
+ add_int (props, kIOSurfaceBytesPerRow, bytes_per_row);
+ add_int (props, kIOSurfaceHeight, height);
+ add_int (props, kIOSurfacePixelFormat, (int)'BGRA');
+ add_int (props, kIOSurfaceWidth, width);
ret = IOSurfaceCreate (props);
CFRelease (props);
+ *stride = bytes_per_row;
+
return ret;
}
@@ -111,32 +132,130 @@ GdkMacosBuffer *
_gdk_macos_buffer_new (GdkMacosDisplay *display,
int width,
int height,
- int bytes_per_pixel)
+ double device_scale,
+ int bytes_per_element,
+ int bits_per_pixel)
{
GdkMacosBuffer *self;
g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (display), NULL);
+ g_return_val_if_fail (width > 0, NULL);
+ g_return_val_if_fail (height > 0, NULL);
self = g_object_new (GDK_TYPE_MACOS_BUFFER, NULL);
- self->surface = create_surface (width, height, bytes_per_pixel);
+ self->colorspace = CGColorSpaceCreateDeviceRGB ();
+ self->bytes_per_element = bytes_per_element;
+ self->bits_per_pixel = bits_per_pixel;
+ self->surface = create_surface (width, height, bytes_per_element, &self->stride);
+ self->width = width;
+ self->height = height;
+ self->device_scale = device_scale;
+ self->lock_count = 0;
if (self->surface == NULL)
- {
- g_object_unref (self);
- return NULL;
- }
+ g_clear_object (&self);
return self;
}
+IOSurfaceRef
+_gdk_macos_buffer_get_native (GdkMacosBuffer *self)
+{
+ g_return_val_if_fail (GDK_IS_MACOS_BUFFER (self), NULL);
+
+ return self->surface;
+}
+
void
_gdk_macos_buffer_lock (GdkMacosBuffer *self)
{
g_return_if_fail (GDK_IS_MACOS_BUFFER (self));
+ g_return_if_fail (self->lock_count == 0);
+
+ self->lock_count++;
+
+ IOSurfaceLock (self->surface, 0, NULL);
}
void
_gdk_macos_buffer_unlock (GdkMacosBuffer *self)
{
g_return_if_fail (GDK_IS_MACOS_BUFFER (self));
+ g_return_if_fail (self->lock_count == 1);
+
+ self->lock_count--;
+
+ IOSurfaceUnlock (self->surface, 0, NULL);
+}
+
+CGContextRef
+_gdk_macos_buffer_create_context (GdkMacosBuffer *self)
+{
+ CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;
+ CGContextRef cg_context;
+
+ g_return_val_if_fail (GDK_IS_MACOS_BUFFER (self), NULL);
+
+ cg_context = CGIOSurfaceContextCreate (self->surface,
+ self->width,
+ self->height,
+ self->bits_per_pixel / 4,
+ self->bits_per_pixel,
+ self->colorspace,
+ bitmapInfo);
+
+ return cg_context;
+}
+
+guint
+_gdk_macos_buffer_get_width (GdkMacosBuffer *self)
+{
+ g_return_val_if_fail (GDK_IS_MACOS_BUFFER (self), 0);
+
+ return self->width;
+}
+
+guint
+_gdk_macos_buffer_get_height (GdkMacosBuffer *self)
+{
+ g_return_val_if_fail (GDK_IS_MACOS_BUFFER (self), 0);
+
+ return self->height;
+}
+
+guint
+_gdk_macos_buffer_get_stride (GdkMacosBuffer *self)
+{
+ g_return_val_if_fail (GDK_IS_MACOS_BUFFER (self), 0);
+
+ return self->stride;
+}
+
+double
+_gdk_macos_buffer_get_device_scale (GdkMacosBuffer *self)
+{
+ g_return_val_if_fail (GDK_IS_MACOS_BUFFER (self), 1.0);
+
+ return self->device_scale;
+}
+
+const cairo_region_t *
+_gdk_macos_buffer_get_damage (GdkMacosBuffer *self)
+{
+ g_return_val_if_fail (GDK_IS_MACOS_BUFFER (self), NULL);
+
+ return self->damage;
+}
+
+void
+_gdk_macos_buffer_set_damage (GdkMacosBuffer *self,
+ cairo_region_t *damage)
+{
+ g_return_if_fail (GDK_IS_MACOS_BUFFER (self));
+
+ if (damage == self->damage)
+ return;
+
+ g_clear_pointer (&self->damage, cairo_region_destroy);
+ self->damage = damage;
}
diff --git a/gdk/macos/gdkmacoscairocontext.c b/gdk/macos/gdkmacoscairocontext.c
index c1dd7f677c..adb5a5994e 100644
--- a/gdk/macos/gdkmacoscairocontext.c
+++ b/gdk/macos/gdkmacoscairocontext.c
@@ -22,19 +22,19 @@
#include "gdkconfig.h"
+#include <cairo.h>
+#include <QuartzCore/QuartzCore.h>
#include <CoreGraphics/CoreGraphics.h>
-#import "GdkMacosCairoView.h"
+#import "GdkMacosSuperView.h"
+#include "gdkmacosbuffer-private.h"
#include "gdkmacoscairocontext-private.h"
#include "gdkmacossurface-private.h"
struct _GdkMacosCairoContext
{
- GdkCairoContext parent_instance;
-
- cairo_surface_t *window_surface;
- cairo_t *cr;
+ GdkCairoContext parent_instance;
};
struct _GdkMacosCairoContextClass
@@ -44,80 +44,97 @@ struct _GdkMacosCairoContextClass
G_DEFINE_TYPE (GdkMacosCairoContext, _gdk_macos_cairo_context, GDK_TYPE_CAIRO_CONTEXT)
-static cairo_surface_t *
-create_cairo_surface_for_surface (GdkSurface *surface)
+static void
+unlock_buffer (gpointer data)
{
- static const cairo_user_data_key_t buffer_key;
- cairo_surface_t *cairo_surface;
- guint8 *data;
- cairo_format_t format;
- size_t size;
- size_t rowstride;
- size_t width;
- size_t height;
- int scale;
-
- g_assert (GDK_IS_MACOS_SURFACE (surface));
-
- /* We use a cairo image surface here instead of a quartz surface because
- * we get strange artifacts with the quartz surface such as empty
- * cross-fades when hovering buttons. For performance, we want to be using
- * GL rendering so there isn't much point here as correctness is better.
- *
- * Additionally, so we can take avantage of faster paths in Core
- * Graphics, we want our data pointer to be 16-byte aligned and our rows
- * to be 16-byte aligned or we risk errors below us. Normally, cairo
- * image surface does not guarantee the later, which means we could end
- * up doing some costly copies along the way to compositing.
- */
-
- if ([GDK_MACOS_SURFACE (surface)->window isOpaque])
- format = CAIRO_FORMAT_RGB24;
- else
- format = CAIRO_FORMAT_ARGB32;
-
- scale = gdk_surface_get_scale_factor (surface);
- width = scale * gdk_surface_get_width (surface);
- height = scale * gdk_surface_get_height (surface);
- rowstride = (cairo_format_stride_for_width (format, width) + 0xF) & ~0xF;
- size = rowstride * height;
- data = g_malloc0 (size);
- cairo_surface = cairo_image_surface_create_for_data (data, format, width, height, rowstride);
- cairo_surface_set_user_data (cairo_surface, &buffer_key, data, g_free);
- cairo_surface_set_device_scale (cairo_surface, scale, scale);
-
- return cairo_surface;
+ GdkMacosBuffer *buffer = data;
+
+ g_assert (GDK_IS_MACOS_BUFFER (buffer));
+
+ _gdk_macos_buffer_unlock (buffer);
+ g_clear_object (&buffer);
}
static cairo_t *
-do_cairo_create (GdkMacosCairoContext *self)
+_gdk_macos_cairo_context_cairo_create (GdkCairoContext *cairo_context)
{
+ GdkMacosCairoContext *self = (GdkMacosCairoContext *)cairo_context;
+ static const cairo_user_data_key_t buffer_key;
+ const cairo_region_t *damage;
+ cairo_surface_t *image_surface;
+ GdkMacosBuffer *back;
+ IOSurfaceRef io_surface;
GdkSurface *surface;
+ gpointer base_address;
+ NSWindow *nswindow;
cairo_t *cr;
+ double scale;
+ guint width;
+ guint height;
+ guint stride;
+ gboolean opaque;
+ double x, y, x2, y2;
g_assert (GDK_IS_MACOS_CAIRO_CONTEXT (self));
surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (self));
- cr = cairo_create (self->window_surface);
- /* Draw upside down as quartz prefers */
- cairo_translate (cr, 0, surface->height);
- cairo_scale (cr, 1.0, -1.0);
+ nswindow = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (surface));
+ opaque = [nswindow isOpaque];
- return cr;
-}
+ back = _gdk_macos_surface_get_back_buffer (GDK_MACOS_SURFACE (surface));
+ io_surface = _gdk_macos_buffer_get_native (back);
+ damage = _gdk_macos_buffer_get_damage (back);
+ width = _gdk_macos_buffer_get_width (back);
+ height = _gdk_macos_buffer_get_height (back);
+ scale = _gdk_macos_buffer_get_device_scale (back);
+ stride = _gdk_macos_buffer_get_stride (back);
+ base_address = IOSurfaceGetBaseAddress (io_surface);
-static cairo_t *
-_gdk_macos_cairo_context_cairo_create (GdkCairoContext *cairo_context)
-{
- GdkMacosCairoContext *self = (GdkMacosCairoContext *)cairo_context;
+ image_surface = cairo_image_surface_create_for_data (base_address,
+ opaque ? CAIRO_FORMAT_RGB24 : CAIRO_FORMAT_ARGB32,
+ width, height, stride);
+ cairo_surface_set_device_scale (image_surface, scale, scale);
- g_assert (GDK_IS_MACOS_CAIRO_CONTEXT (self));
+ _gdk_macos_buffer_lock (back);
+ cairo_surface_set_user_data (image_surface,
+ &buffer_key,
+ g_object_ref (back),
+ unlock_buffer);
+
+ /* TODO: Copy from other image back to this one */
- if (self->cr != NULL)
- return cairo_reference (self->cr);
+ cr = cairo_create (image_surface);
+
+ if (cr != NULL && damage != NULL)
+ {
+ gdk_cairo_region (cr, damage);
+ cairo_clip (cr);
+ }
+
+ if (!opaque)
+ {
+ cairo_region_t *transparent;
- return do_cairo_create (self);
+ cairo_save (cr);
+
+ cairo_clip_extents (cr, &x, &y, &x2, &y2);
+ transparent = cairo_region_create_rectangle (&(cairo_rectangle_int_t) { x, y, x2-x, y2-y });
+ if (surface->opaque_region)
+ cairo_region_subtract (transparent, surface->opaque_region);
+
+ gdk_cairo_region (cr, transparent);
+ cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
+ cairo_fill (cr);
+
+ cairo_region_destroy (transparent);
+
+ cairo_restore (cr);
+ }
+
+ cairo_surface_destroy (image_surface);
+
+ return cr;
}
static void
@@ -126,49 +143,38 @@ _gdk_macos_cairo_context_begin_frame (GdkDrawContext *draw_context,
cairo_region_t *region)
{
GdkMacosCairoContext *self = (GdkMacosCairoContext *)draw_context;
+ const cairo_region_t *front_damage;
+ GdkMacosBuffer *back;
+ GdkMacosBuffer *front;
GdkSurface *surface;
- NSWindow *nswindow;
g_assert (GDK_IS_MACOS_CAIRO_CONTEXT (self));
- surface = gdk_draw_context_get_surface (draw_context);
- nswindow = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (surface));
+ [CATransaction begin];
+ [CATransaction setDisableActions:YES];
- if (self->window_surface == NULL)
- self->window_surface = create_cairo_surface_for_surface (surface);
+ surface = gdk_draw_context_get_surface (draw_context);
+ back = _gdk_macos_surface_get_back_buffer (GDK_MACOS_SURFACE (surface));
+ front = _gdk_macos_surface_get_back_buffer (GDK_MACOS_SURFACE (surface));
- self->cr = do_cairo_create (self);
+ if ((front_damage = _gdk_macos_buffer_get_damage (front)))
+ cairo_region_union (region, front_damage);
- if (![nswindow isOpaque])
- {
- cairo_save (self->cr);
- gdk_cairo_region (self->cr, region);
- cairo_set_source_rgba (self->cr, 0, 0, 0, 0);
- cairo_set_operator (self->cr, CAIRO_OPERATOR_SOURCE);
- cairo_fill (self->cr);
- cairo_restore (self->cr);
- }
+ _gdk_macos_buffer_set_damage (back, cairo_region_copy (region));
}
static void
_gdk_macos_cairo_context_end_frame (GdkDrawContext *draw_context,
cairo_region_t *painted)
{
- GdkMacosCairoContext *self = (GdkMacosCairoContext *)draw_context;
GdkSurface *surface;
- NSView *nsview;
- g_assert (GDK_IS_MACOS_CAIRO_CONTEXT (self));
- g_assert (self->window_surface != NULL);
+ g_assert (GDK_IS_MACOS_CAIRO_CONTEXT (draw_context));
surface = gdk_draw_context_get_surface (draw_context);
- nsview = _gdk_macos_surface_get_view (GDK_MACOS_SURFACE (surface));
-
- g_clear_pointer (&self->cr, cairo_destroy);
+ _gdk_macos_surface_swap_buffers (GDK_MACOS_SURFACE (surface), painted);
- if (GDK_IS_MACOS_CAIRO_VIEW (nsview))
- [(GdkMacosCairoView *)nsview setCairoSurface:self->window_surface
- withDamage:painted];
+ [CATransaction commit];
}
static void
@@ -177,26 +183,20 @@ _gdk_macos_cairo_context_surface_resized (GdkDrawContext *draw_context)
GdkMacosCairoContext *self = (GdkMacosCairoContext *)draw_context;
g_assert (GDK_IS_MACOS_CAIRO_CONTEXT (self));
-
- g_clear_pointer (&self->window_surface, cairo_surface_destroy);
}
static void
_gdk_macos_cairo_context_dispose (GObject *object)
{
- GdkMacosCairoContext *self = (GdkMacosCairoContext *)object;
-
- g_clear_pointer (&self->window_surface, cairo_surface_destroy);
-
G_OBJECT_CLASS (_gdk_macos_cairo_context_parent_class)->dispose (object);
}
static void
_gdk_macos_cairo_context_class_init (GdkMacosCairoContextClass *klass)
{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
GdkCairoContextClass *cairo_context_class = GDK_CAIRO_CONTEXT_CLASS (klass);
GdkDrawContextClass *draw_context_class = GDK_DRAW_CONTEXT_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = _gdk_macos_cairo_context_dispose;
diff --git a/gdk/macos/gdkmacossurface-private.h b/gdk/macos/gdkmacossurface-private.h
index 76cf853c01..e73f2437f6 100644
--- a/gdk/macos/gdkmacossurface-private.h
+++ b/gdk/macos/gdkmacossurface-private.h
@@ -41,8 +41,8 @@ struct _GdkMacosSurface
{
GdkSurface parent_instance;
- GdkMacosBuffer *back;
- GdkMacosBuffer *front;
+ GdkMacosBuffer *buffers[2];
+ GdkMacosBuffer *front_buffer;
GList main;
GList sorted;
@@ -66,6 +66,7 @@ struct _GdkMacosSurface
guint did_initial_present : 1;
guint geometry_dirty : 1;
+ guint back_buffer : 1;
};
struct _GdkMacosSurfaceClass
@@ -135,6 +136,11 @@ void _gdk_macos_surface_set_opacity (GdkMacosSurface
void _gdk_macos_surface_get_root_coords (GdkMacosSurface *self,
int *x,
int *y);
+void _gdk_macos_surface_update_size (GdkMacosSurface *self);
+GdkMacosBuffer *_gdk_macos_surface_get_back_buffer (GdkMacosSurface *self);
+GdkMacosBuffer *_gdk_macos_surface_get_front_buffer (GdkMacosSurface *self);
+void _gdk_macos_surface_swap_buffers (GdkMacosSurface *self,
+ const cairo_region_t *damage);
G_END_DECLS
diff --git a/gdk/macos/gdkmacossurface.c b/gdk/macos/gdkmacossurface.c
index 26e73faad4..5cc9c3c47a 100644
--- a/gdk/macos/gdkmacossurface.c
+++ b/gdk/macos/gdkmacossurface.c
@@ -23,7 +23,7 @@
#include <float.h>
#include <gdk/gdk.h>
-#import "GdkMacosCairoView.h"
+#import "GdkMacosSuperView.h"
#include "gdkmacossurface-private.h"
@@ -112,8 +112,8 @@ gdk_macos_surface_set_opaque_region (GdkSurface *surface,
}
if ((nsview = _gdk_macos_surface_get_view (GDK_MACOS_SURFACE (surface))) &&
- GDK_IS_MACOS_CAIRO_VIEW (nsview))
- [(GdkMacosCairoView *)nsview setOpaqueRegion:region];
+ GDK_IS_MACOS_SUPER_VIEW (nsview))
+ [(GdkMacosSuperView *)nsview setOpaqueRegion:region];
}
static void
@@ -864,20 +864,35 @@ _gdk_macos_surface_synthesize_null_key (GdkMacosSurface *self)
static void
gdk_macos_surface_update_buffers (GdkMacosSurface *self)
{
- GdkMacosBuffer *front;
- GdkDisplay *display;
+ GdkMacosDisplay *display;
+ double scale;
+ guint width;
+ guint height;
g_assert (GDK_IS_MACOS_SURFACE (self));
- display = gdk_surface_get_display (GDK_SURFACE (self));
- front = _gdk_macos_buffer_new (GDK_MACOS_DISPLAY (display),
- GDK_SURFACE (self)->width,
- GDK_SURFACE (self)->height,
- 4);
+ scale = gdk_surface_get_scale_factor (GDK_SURFACE (self));
+ width = GDK_SURFACE (self)->width * scale;
+ height = GDK_SURFACE (self)->height * scale;
+
+ g_print ("Creating new buffers: %dx%d\n", width, height);
- g_print ("Front: %p\n", front);
+ display = GDK_MACOS_DISPLAY (gdk_surface_get_display (GDK_SURFACE (self)));
+
+ for (guint i = 0; i < G_N_ELEMENTS (self->buffers); i++)
+ {
+ GdkMacosBuffer *buffer = _gdk_macos_buffer_new (display, width, height, scale, 4, 32);
+
+ if (buffer != NULL)
+ {
+ g_print ("%p replaced with %p\n", self->buffers[i], buffer);
+ g_clear_object (&self->buffers[i]);
+ self->buffers[i] = buffer;
+ }
+ }
- g_object_unref (front);
+ self->front_buffer = self->buffers[0];
+ self->back_buffer = 1;
}
void
@@ -1017,7 +1032,7 @@ _gdk_macos_surface_monitor_changed (GdkMacosSurface *self)
g_object_unref (monitor);
}
- _gdk_surface_update_size (GDK_SURFACE (self));
+ _gdk_macos_surface_update_size (self);
gdk_surface_invalidate_rect (GDK_SURFACE (self), NULL);
}
@@ -1099,3 +1114,44 @@ _gdk_macos_surface_get_root_coords (GdkMacosSurface *self,
if (y)
*y = out_y;
}
+
+void
+_gdk_macos_surface_update_size (GdkMacosSurface *self)
+{
+ g_return_if_fail (GDK_IS_MACOS_SURFACE (self));
+
+ _gdk_surface_update_size (GDK_SURFACE (self));
+ gdk_macos_surface_update_buffers (self);
+}
+
+GdkMacosBuffer *
+_gdk_macos_surface_get_back_buffer (GdkMacosSurface *self)
+{
+ g_return_val_if_fail (GDK_IS_MACOS_SURFACE (self), NULL);
+
+ return self->buffers[self->back_buffer];
+}
+
+GdkMacosBuffer *
+_gdk_macos_surface_get_front_buffer (GdkMacosSurface *self)
+{
+ g_return_val_if_fail (GDK_IS_MACOS_SURFACE (self), NULL);
+
+ return self->front_buffer;
+}
+
+void
+_gdk_macos_surface_swap_buffers (GdkMacosSurface *self,
+ const cairo_region_t *damage)
+{
+ GdkMacosBuffer *buffer;
+
+ g_return_if_fail (GDK_IS_MACOS_SURFACE (self));
+ g_return_if_fail (damage != NULL);
+
+ buffer = self->buffers[self->back_buffer];
+ self->front_buffer = buffer;
+ //self->back_buffer = (self->back_buffer + 1) % G_N_ELEMENTS (self->buffers);
+
+ [self->window swapBuffer:buffer withDamage:damage];
+}
diff --git a/gdk/macos/meson.build b/gdk/macos/meson.build
index e6e8dd798f..a7f15b4557 100644
--- a/gdk/macos/meson.build
+++ b/gdk/macos/meson.build
@@ -23,10 +23,14 @@ gdk_macos_sources = files([
'gdkmacostoplevelsurface.c',
'GdkMacosBaseView.c',
+ 'GdkMacosLayer.c',
+ 'GdkMacosTile.c',
+ 'GdkMacosSuperView.c',
+ 'GdkMacosWindow.c',
+
'GdkMacosCairoView.c',
'GdkMacosCairoSubview.c',
'GdkMacosGLView.c',
- 'GdkMacosWindow.c',
])
gdk_macos_public_headers = files([
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]