[gtk/wip/chergert/gdk-macos-gl-renderer] macos: wip on making GL renderer more compliant



commit 2590c7b3817d49aae02f251fac03ec557c040bde
Author: Christian Hergert <chergert redhat com>
Date:   Thu Oct 22 16:47:40 2020 -0700

    macos: wip on making GL renderer more compliant

 gdk/macos/GdkMacosGLView.c            |  36 +++---
 gdk/macos/gdkmacosglcontext-private.h |  12 +-
 gdk/macos/gdkmacosglcontext.c         | 215 +++++++++++++++++++++-------------
 3 files changed, 161 insertions(+), 102 deletions(-)
---
diff --git a/gdk/macos/GdkMacosGLView.c b/gdk/macos/GdkMacosGLView.c
index 4485bacca5..cab8c66638 100644
--- a/gdk/macos/GdkMacosGLView.c
+++ b/gdk/macos/GdkMacosGLView.c
@@ -35,11 +35,17 @@ G_GNUC_BEGIN_IGNORE_DEPRECATIONS
 +(NSOpenGLPixelFormat *)defaultPixelFormat
 {
   static const NSOpenGLPixelFormatAttribute attrs[] = {
-    NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core,
+    NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
     NSOpenGLPFAAccelerated,
     NSOpenGLPFADoubleBuffer,
+    NSOpenGLPFAColorSize, 24,
+    NSOpenGLPFAAlphaSize, 8,
     NSOpenGLPFADepthSize, 32,
     NSOpenGLPFAStencilSize, 8,
+    NSOpenGLPFAAllowOfflineRenderers,
+    NSOpenGLPFAMultisample,
+    NSOpenGLPFASampleBuffers, 1,
+    NSOpenGLPFASamples, 8,
 
     (NSOpenGLPixelFormatAttribute)nil
   };
@@ -106,19 +112,6 @@ G_GNUC_BEGIN_IGNORE_DEPRECATIONS
     [context setView: self];
 }
 
--(void)viewDidMoveToWindow
-{
-  [super viewDidMoveToWindow];
-
-  if ([self window] == nil)
-    {
-      [[self openGLContext] clearDrawable];
-      return;
-    }
-
-  [[self openGLContext] setView: self];
-}
-
 -(void)update
 {
   [[self openGLContext] update];
@@ -130,13 +123,24 @@ G_GNUC_BEGIN_IGNORE_DEPRECATIONS
 
 -(void)clearGLContext
 {
+  if (_openGLContext != nil)
+    [_openGLContext clearDrawable];
+
   _openGLContext = nil;
 }
 
 -(void)setOpenGLContext:(NSOpenGLContext*)context
 {
-  [context setView:self];
-  _openGLContext = context;
+  if (_openGLContext != context)
+    {
+      if (_openGLContext != nil)
+        [_openGLContext clearDrawable];
+
+      _openGLContext = context;
+
+      if (_openGLContext != nil)
+        [_openGLContext setView:self];
+    }
 }
 
 -(NSOpenGLContext *)openGLContext
diff --git a/gdk/macos/gdkmacosglcontext-private.h b/gdk/macos/gdkmacosglcontext-private.h
index a7417026fb..6a28262118 100644
--- a/gdk/macos/gdkmacosglcontext-private.h
+++ b/gdk/macos/gdkmacosglcontext-private.h
@@ -37,13 +37,13 @@ struct _GdkMacosGLContext
 {
   GdkGLContext parent_instance;
 
-  guint is_attached : 1;
+  G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+  NSOpenGLContext *gl_context;
+  G_GNUC_END_IGNORE_DEPRECATIONS
+
+  NSView *attached;
 
-  struct {
-    int width;
-    int height;
-    guint needed : 1;
-  } resize;
+  guint is_attached : 1;
 };
 
 struct _GdkMacosGLContextClass
diff --git a/gdk/macos/gdkmacosglcontext.c b/gdk/macos/gdkmacosglcontext.c
index d56e0b435f..e5ab1e2fa2 100644
--- a/gdk/macos/gdkmacosglcontext.c
+++ b/gdk/macos/gdkmacosglcontext.c
@@ -39,16 +39,9 @@ static NSOpenGLContext *
 get_ns_open_gl_context (GdkMacosGLContext  *self,
                         GError            **error)
 {
-  NSOpenGLContext *gl_context = nil;
-  GdkSurface *surface;
-  NSView *nsview;
-
   g_assert (GDK_IS_MACOS_GL_CONTEXT (self));
 
-  if (!(surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (self))) ||
-      !(nsview = _gdk_macos_surface_get_view (GDK_MACOS_SURFACE (surface))) ||
-      !GDK_IS_MACOS_GL_VIEW (nsview) ||
-      !(gl_context = [(GdkMacosGLView *)nsview openGLContext]))
+  if (self->gl_context == nil)
     {
       g_set_error_literal (error,
                            GDK_GL_ERROR,
@@ -57,7 +50,36 @@ get_ns_open_gl_context (GdkMacosGLContext  *self,
       return NULL;
     }
 
-  return gl_context;
+  return self->gl_context;
+}
+
+static NSView *
+ensure_gl_view (GdkMacosGLContext *self)
+{
+  GdkMacosSurface *surface;
+  NSWindow *nswindow;
+  NSView *nsview;
+
+  g_assert (GDK_IS_MACOS_GL_CONTEXT (self));
+
+  surface = GDK_MACOS_SURFACE (gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (self)));
+  nsview = _gdk_macos_surface_get_view (surface);
+  nswindow = _gdk_macos_surface_get_native (surface);
+
+  if (!GDK_IS_MACOS_GL_VIEW (nsview))
+    {
+      NSRect frame;
+
+      frame = [[nswindow contentView] bounds];
+      nsview = [[GdkMacosGLView alloc] initWithFrame:frame pixelFormat:pixelFormat];
+      [nsview setWantsBestResolutionOpenGLSurface:YES];
+      [nsview setPostsFrameChangedNotifications: YES];
+      [nsview setNeedsDisplay:YES];
+      [nswindow setContentView:nsview];
+      [nsview release];
+    }
+
+  return [nswindow contentView];
 }
 
 static gboolean
@@ -67,71 +89,94 @@ gdk_macos_gl_context_real_realize (GdkGLContext  *context,
   GdkMacosGLContext *self = (GdkMacosGLContext *)context;
   GdkSurface *surface;
   NSView *nsview;
+  NSOpenGLContext *shared_gl_context = nil;
+  NSOpenGLContext *gl_context;
+  GdkGLContext *shared;
+  GdkGLContext *shared_data;
+  GLint sync_to_framerate = 1;
+  GLint opaque = 0;
+  GLint validate = 0;
 
   g_assert (GDK_IS_MACOS_GL_CONTEXT (self));
 
+  if (self->gl_context != nil)
+    return TRUE;
+
   surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (context));
   nsview = _gdk_macos_surface_get_view (GDK_MACOS_SURFACE (surface));
-
-  if (!GDK_IS_MACOS_GL_VIEW (nsview))
+  shared = gdk_gl_context_get_shared_context (context);
+  shared_data = gdk_surface_get_shared_data_gl_context (surface);
+
+  /* If we are not attached and have a shared context, then we are
+   * trying to draw to our NSView (which must be a GL view). Ensure
+   * that we have that up front to save some checking later.
+   */
+  if (!self->is_attached && shared != NULL)
+    nsview = ensure_gl_view (self);
+
+  /* This can be called with a few modes:
+   * 
+   * 1) GL Paint Context => is_attached=TRUE is used to read back pixels
+   *    into Cairo using gdk_cairo_draw_from_gl().
+   *
+   * 2) GL Context => is_attached=(FALSE) shared=(Paint GL Context)
+   *    This is used by the GskGLRenderer for rendering to the surface.
+   *    But it is also used by GtkGLArea to create a context for the view.
+   *    which should not be rendered to the surface.
+   *
+   * 3) GL Context => is_attached=(FALSE) shared=NULL
+   *    This is used for the "shared data" context for things like glyph
+   *    and icon caches.
+   */
+
+  if (shared != NULL)
     {
-      NSOpenGLContext *shared_gl_context = nil;
-      NSOpenGLContext *gl_context;
-      GdkMacosGLView *gl_view;
-      GdkGLContext *shared;
-      NSWindow *nswindow;
-      NSRect contentRect;
-      GLint sync_to_framerate = 1;
-      GLint opaque = 0;
-
-      if ((shared = gdk_gl_context_get_shared_context (context)))
-        {
-          if (!(shared_gl_context = get_ns_open_gl_context (GDK_MACOS_GL_CONTEXT (shared), error)))
-            return FALSE;
-        }
-
-      if (shared == NULL)
-        {
-          GdkGLContext *shared_data = gdk_surface_get_shared_data_gl_context (surface);
+      if (!(shared_gl_context = get_ns_open_gl_context (GDK_MACOS_GL_CONTEXT (shared), error)))
+        return FALSE;
+    }
+  else
+    {
+      if (shared_data != NULL)
+        shared_gl_context = get_ns_open_gl_context (GDK_MACOS_GL_CONTEXT (shared_data), NULL);
+    }
 
-          if (shared_data != NULL)
-            shared_gl_context = get_ns_open_gl_context (GDK_MACOS_GL_CONTEXT (shared_data), NULL);
-        }
+  gl_context = [[NSOpenGLContext alloc] initWithFormat:pixelFormat
+                                          shareContext:shared_gl_context];
 
-      nswindow = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (surface));
-      gl_context = [[NSOpenGLContext alloc] initWithFormat:pixelFormat
-                                              shareContext:shared_gl_context];
+  if (gl_context == nil)
+    {
+      g_set_error_literal (error,
+                           GDK_GL_ERROR,
+                           GDK_GL_ERROR_NOT_AVAILABLE,
+                           "Failed to create NSOpenGLContext");
+      return FALSE;
+    }
 
-      if (gl_context == nil)
-        {
-          g_set_error_literal (error,
-                               GDK_GL_ERROR,
-                               GDK_GL_ERROR_NOT_AVAILABLE,
-                               "Failed to create NSOpenGLContext");
-          return FALSE;
-        }
+  [gl_context setValues:&sync_to_framerate forParameter:NSOpenGLCPSwapInterval];
+  [gl_context setValues:&opaque forParameter:NSOpenGLCPSurfaceOpacity];
+  [gl_context setValues:&validate forParameter:NSOpenGLContextParameterStateValidation];
 
-      [gl_context setValues:&sync_to_framerate forParameter:NSOpenGLCPSwapInterval];
-      [gl_context setValues:&opaque forParameter:NSOpenGLCPSurfaceOpacity];
+  if (self->is_attached || shared == NULL)
+    {
+      NSRect frame = NSMakeRect (0, 0, 1, 1);
 
-      GDK_NOTE (OPENGL,
-                g_print ("Created NSOpenGLContext[%p]\n", gl_context));
+      self->attached = [[GdkMacosGLView alloc] initWithFrame:frame pixelFormat:pixelFormat];
+      [(GdkMacosGLView *)self->attached setOpenGLContext:gl_context];
+    }
+  else
+    {
+      g_assert (GDK_IS_MACOS_GL_VIEW (nsview));
 
-      contentRect = [[nswindow contentView] bounds];
-      gl_view = [[GdkMacosGLView alloc] initWithFrame:contentRect
-                                          pixelFormat:pixelFormat];
-      [nswindow setContentView:gl_view];
-      [gl_view setOpenGLContext:gl_context];
-      [gl_view setWantsBestResolutionOpenGLSurface:YES];
-      [gl_view setPostsFrameChangedNotifications: YES];
-      [gl_view setNeedsDisplay:YES];
+      [(GdkMacosGLView *)nsview setOpenGLContext:gl_context];
+      [gl_context setView:nsview];
+    }
 
-      [gl_context makeCurrentContext];
+  [gl_context makeCurrentContext];
 
-      [gl_view release];
-    }
+  GDK_NOTE (OPENGL,
+            g_print ("Created NSOpenGLContext[%p]\n", gl_context));
 
-  g_assert (get_ns_open_gl_context (self, NULL) != NULL);
+  self->gl_context = g_steal_pointer (&gl_context);
 
   return TRUE;
 }
@@ -150,21 +195,19 @@ gdk_macos_gl_context_end_frame (GdkDrawContext *context,
                                 cairo_region_t *painted)
 {
   GdkMacosGLContext *self = GDK_MACOS_GL_CONTEXT (context);
-  NSOpenGLContext *gl_context;
+  GdkMacosSurface *surface;
+  NSView *nsview;
 
   g_assert (GDK_IS_MACOS_GL_CONTEXT (self));
+  g_assert (self->gl_context != nil);
 
-  if ((gl_context = get_ns_open_gl_context (self, NULL)))
-    {
-      GdkMacosSurface *surface;
-      NSView *nsview;
+  [self->gl_context flushBuffer];
 
-      surface = GDK_MACOS_SURFACE (gdk_draw_context_get_surface (context));
-      nsview = _gdk_macos_surface_get_view (surface);
-      [(GdkMacosGLView *)nsview invalidateRegion:painted];
+  surface = GDK_MACOS_SURFACE (gdk_draw_context_get_surface (context));
+  nsview = _gdk_macos_surface_get_view (surface);
 
-      [gl_context flushBuffer];
-    }
+  if (nsview == [self->gl_context view])
+    [(GdkMacosGLView *)nsview invalidateRegion:painted];
 }
 
 static void
@@ -177,19 +220,33 @@ gdk_macos_gl_context_surface_resized (GdkDrawContext *draw_context)
 
   surface = gdk_draw_context_get_surface (draw_context);
 
-  self->resize.needed = TRUE;
-  self->resize.width = surface->width;
-  self->resize.height = surface->height;
+  if (self->attached)
+    {
+      NSRect contentRect = NSMakeRect (0, 0, surface->width, surface->height);
+      [self->attached setFrame:contentRect];
+    }
 }
 
 static void
 gdk_macos_gl_context_dispose (GObject *gobject)
 {
   GdkMacosGLContext *self = GDK_MACOS_GL_CONTEXT (gobject);
-  NSOpenGLContext *gl_context;
 
-  if ((gl_context = get_ns_open_gl_context (self, NULL)))
-    [gl_context clearDrawable];
+  if (self->attached != nil)
+    {
+      NSView *nsview = g_steal_pointer (&self->attached);
+
+      [(GdkMacosGLView *)nsview setOpenGLContext:nil];
+      [nsview release];
+    }
+
+  if (self->gl_context != nil)
+    {
+      NSOpenGLContext *gl_context = g_steal_pointer (&self->gl_context);
+
+      [gl_context clearDrawable];
+      [gl_context release];
+    }
 
   G_OBJECT_CLASS (gdk_macos_gl_context_parent_class)->dispose (gobject);
 }
@@ -245,7 +302,7 @@ _gdk_macos_gl_context_new (GdkMacosSurface  *surface,
                           "shared-context", share,
                           NULL);
 
-  context->is_attached = attached;
+  context->is_attached = !!attached;
 
   return GDK_GL_CONTEXT (context);
 }
@@ -253,13 +310,11 @@ _gdk_macos_gl_context_new (GdkMacosSurface  *surface,
 gboolean
 _gdk_macos_gl_context_make_current (GdkMacosGLContext *self)
 {
-  NSOpenGLContext *gl_context;
-
   g_return_val_if_fail (GDK_IS_MACOS_GL_CONTEXT (self), FALSE);
 
-  if ((gl_context = get_ns_open_gl_context (self, NULL)))
+  if (self->gl_context != nil)
     {
-      [gl_context makeCurrentContext];
+      [self->gl_context makeCurrentContext];
       return TRUE;
     }
 


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