[gtk/wip/chergert/macos-iosurface] allow drawing cairo without a flip



commit 016f82ffb4f01cce7f4dbfb96fceea7b21894bdd
Author: Christian Hergert <christian hergert me>
Date:   Fri Feb 11 04:00:04 2022 -0800

    allow drawing cairo without a flip
    
    there appears to be some things that can break if stuff starts diving into
    the framebuffers, so just keep it top side up and instead we can use the
    identity/flip transforms

 gdk/macos/GdkMacosLayer.c          | 21 +++++++++++++++++++--
 gdk/macos/GdkMacosLayer.h          |  1 +
 gdk/macos/gdkmacosbuffer-private.h |  3 +++
 gdk/macos/gdkmacosbuffer.c         | 18 ++++++++++++++++++
 gdk/macos/gdkmacoscairocontext.c   |  9 +++------
 gdk/macos/gdkmacosglcontext.c      |  4 ++++
 6 files changed, 48 insertions(+), 8 deletions(-)
---
diff --git a/gdk/macos/GdkMacosLayer.c b/gdk/macos/GdkMacosLayer.c
index b4b7b905a3..d09761a468 100644
--- a/gdk/macos/GdkMacosLayer.c
+++ b/gdk/macos/GdkMacosLayer.c
@@ -166,10 +166,15 @@ fromCGRect (const CGRect rect)
 
 -(void)_applyLayout:(GArray *)tiles
 {
+  CGAffineTransform transform;
   GArray *prev;
   gboolean exhausted;
   guint j = 0;
 
+  if (self->_isFlipped)
+    transform = flipTransform;
+  else
+    transform = CGAffineTransformIdentity;
 
   prev = g_steal_pointer (&self->_tiles);
   self->_tiles = tiles;
@@ -203,13 +208,14 @@ fromCGRect (const CGRect rect)
             {
               info->tile = g_steal_pointer (&other->tile);
               [info->tile setFrame:info->area];
+              [info->tile setAffineTransform:transform];
               continue;
             }
         }
 
       info->tile = [GdkMacosTile layer];
 
-      [info->tile setAffineTransform:flipTransform];
+      [info->tile setAffineTransform:transform];
       [info->tile setContentsScale:1.0f];
       [info->tile setOpaque:info->opaque];
       [info->tile setFrame:info->area];
@@ -322,10 +328,17 @@ fromCGRect (const CGRect rect)
 -(void)swapBuffer:(GdkMacosBuffer *)buffer withDamage:(const cairo_region_t *)damage
 {
   IOSurfaceRef ioSurface = _gdk_macos_buffer_get_native (buffer);
+  gboolean flipped = _gdk_macos_buffer_get_flipped (buffer);
   double scale = _gdk_macos_buffer_get_device_scale (buffer);
   double width = _gdk_macos_buffer_get_width (buffer) / scale;
   double height = _gdk_macos_buffer_get_height (buffer) / scale;
 
+  if (flipped != self->_isFlipped)
+    {
+      self->_isFlipped = flipped;
+      self->_layoutInvalid = TRUE;
+    }
+
   if (self->_layoutInvalid)
     {
       self->_layoutInvalid = FALSE;
@@ -351,7 +364,11 @@ fromCGRect (const CGRect rect)
       area.origin.x = info->area.origin.x / width;
       area.size.width = info->area.size.width / width;
       area.size.height = info->area.size.height / height;
-      area.origin.y = (height - info->area.origin.y - info->area.size.height) / height;
+
+      if (flipped)
+        area.origin.y = (height - info->area.origin.y - info->area.size.height) / height;
+      else
+        area.origin.y = info->area.origin.y / height;
 
       [info->tile swapBuffer:ioSurface withRect:area];
     }
diff --git a/gdk/macos/GdkMacosLayer.h b/gdk/macos/GdkMacosLayer.h
index 18b7d9afae..74ba14ff86 100644
--- a/gdk/macos/GdkMacosLayer.h
+++ b/gdk/macos/GdkMacosLayer.h
@@ -35,6 +35,7 @@
   guint           _opaque : 1;
   guint           _layoutInvalid : 1;
   guint           _inSwapBuffer : 1;
+  guint           _isFlipped : 1;
 };
 
 -(void)setOpaqueRegion:(const cairo_region_t *)opaqueRegion;
diff --git a/gdk/macos/gdkmacosbuffer-private.h b/gdk/macos/gdkmacosbuffer-private.h
index 0b7b12875a..6be201147c 100644
--- a/gdk/macos/gdkmacosbuffer-private.h
+++ b/gdk/macos/gdkmacosbuffer-private.h
@@ -49,6 +49,9 @@ const cairo_region_t *_gdk_macos_buffer_get_damage       (GdkMacosBuffer  *self)
 void                  _gdk_macos_buffer_set_damage       (GdkMacosBuffer  *self,
                                                           cairo_region_t  *damage);
 gpointer              _gdk_macos_buffer_get_data         (GdkMacosBuffer  *self);
+gboolean              _gdk_macos_buffer_get_flipped      (GdkMacosBuffer  *self);
+void                  _gdk_macos_buffer_set_flipped      (GdkMacosBuffer  *self,
+                                                          gboolean         flipped);
 
 G_END_DECLS
 
diff --git a/gdk/macos/gdkmacosbuffer.c b/gdk/macos/gdkmacosbuffer.c
index ace6a0e15d..1612eaa9f6 100644
--- a/gdk/macos/gdkmacosbuffer.c
+++ b/gdk/macos/gdkmacosbuffer.c
@@ -38,6 +38,7 @@ struct _GdkMacosBuffer
   guint            height;
   guint            stride;
   double           device_scale;
+  guint            flipped : 1;
 };
 
 G_DEFINE_TYPE (GdkMacosBuffer, gdk_macos_buffer, G_TYPE_OBJECT)
@@ -234,3 +235,20 @@ _gdk_macos_buffer_get_data (GdkMacosBuffer *self)
 
   return IOSurfaceGetBaseAddress (self->surface);
 }
+
+gboolean
+_gdk_macos_buffer_get_flipped (GdkMacosBuffer *self)
+{
+  g_return_val_if_fail (GDK_IS_MACOS_BUFFER (self), FALSE);
+
+  return self->flipped;
+}
+
+void
+_gdk_macos_buffer_set_flipped (GdkMacosBuffer *self,
+                               gboolean        flipped)
+{
+  g_return_if_fail (GDK_IS_MACOS_BUFFER (self));
+
+  self->flipped = !!flipped;
+}
diff --git a/gdk/macos/gdkmacoscairocontext.c b/gdk/macos/gdkmacoscairocontext.c
index b4fdf717bd..041f1193e6 100644
--- a/gdk/macos/gdkmacoscairocontext.c
+++ b/gdk/macos/gdkmacoscairocontext.c
@@ -152,10 +152,6 @@ _gdk_macos_cairo_context_cairo_create (GdkCairoContext *cairo_context)
       cairo_restore (cr);
     }
 
-  /* Flip contents upside down to match OpenGL */
-  cairo_translate (cr, 0, height/scale);
-  cairo_scale (cr, 1.0, -1.0);
-
 failure:
   cairo_surface_destroy (image_surface);
 
@@ -180,6 +176,7 @@ _gdk_macos_cairo_context_begin_frame (GdkDrawContext *draw_context,
   buffer = _gdk_macos_surface_get_buffer (GDK_MACOS_SURFACE (surface));
 
   _gdk_macos_buffer_set_damage (buffer, region);
+  _gdk_macos_buffer_set_flipped (buffer, FALSE);
 }
 
 static void
@@ -192,9 +189,9 @@ _gdk_macos_cairo_context_end_frame (GdkDrawContext *draw_context,
   g_assert (GDK_IS_MACOS_CAIRO_CONTEXT (draw_context));
 
   surface = gdk_draw_context_get_surface (draw_context);
-  _gdk_macos_surface_swap_buffers (GDK_MACOS_SURFACE (surface), painted);
-
   buffer = _gdk_macos_surface_get_buffer (GDK_MACOS_SURFACE (surface));
+
+  _gdk_macos_surface_swap_buffers (GDK_MACOS_SURFACE (surface), painted);
   _gdk_macos_buffer_set_damage (buffer, NULL);
 
   [CATransaction commit];
diff --git a/gdk/macos/gdkmacosglcontext.c b/gdk/macos/gdkmacosglcontext.c
index 25960026a8..592d3c0bbf 100644
--- a/gdk/macos/gdkmacosglcontext.c
+++ b/gdk/macos/gdkmacosglcontext.c
@@ -425,11 +425,15 @@ gdk_macos_gl_context_begin_frame (GdkDrawContext *context,
                                   cairo_region_t *region)
 {
   GdkMacosGLContext *self = (GdkMacosGLContext *)context;
+  GdkMacosBuffer *buffer;
   GdkSurface *surface;
 
   g_assert (GDK_IS_MACOS_GL_CONTEXT (self));
 
   surface = gdk_draw_context_get_surface (context);
+  buffer = _gdk_macos_surface_get_buffer (GDK_MACOS_SURFACE (surface));
+
+  _gdk_macos_buffer_set_flipped (buffer, TRUE);
 
   g_clear_pointer (&self->damage, cairo_region_destroy);
   self->damage = cairo_region_copy (region);


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