[gtk/wip/chergert/macos-iosurface] start porting to GL with IOSurface



commit b00b83f230ef7e102abdb30a7b3c3684bc9cb6be
Author: Christian Hergert <christian hergert me>
Date:   Thu Feb 10 18:51:58 2022 -0800

    start porting to GL with IOSurface
    
    stuff stil doesn't work, however, still need to figure out the process
    for GL_TEXTURE_RECTANGLE_ARB and how to make that work
    with newer GL, even if only when rendering to it as a FBO.

 gdk/macos/GdkMacosGLView.c            | 125 --------
 gdk/macos/GdkMacosGLView.h            |  41 ---
 gdk/macos/GdkMacosWindow.c            |   4 +-
 gdk/macos/gdkmacosglcontext-private.h |  17 +-
 gdk/macos/gdkmacosglcontext.c         | 575 +++++++++++++++++++---------------
 gdk/macos/meson.build                 |   2 -
 6 files changed, 338 insertions(+), 426 deletions(-)
---
diff --git a/gdk/macos/GdkMacosWindow.c b/gdk/macos/GdkMacosWindow.c
index 9ed2147ed8..8401f45860 100644
--- a/gdk/macos/GdkMacosWindow.c
+++ b/gdk/macos/GdkMacosWindow.c
@@ -24,7 +24,6 @@
 #include <gdk/gdk.h>
 
 #import "GdkMacosBaseView.h"
-#import "GdkMacosGLView.h"
 #import "GdkMacosView.h"
 #import "GdkMacosWindow.h"
 
@@ -150,8 +149,7 @@ typedef NSString *CALayerContentsGravity;
       _gdk_macos_display_break_all_grabs (GDK_MACOS_DISPLAY (display), time);
 
       /* Reset gravity */
-      if (GDK_IS_MACOS_GL_VIEW ([self contentView]))
-        [[[self contentView] layer] setContentsGravity:kCAGravityBottomLeft];
+      [[[self contentView] layer] setContentsGravity:kCAGravityBottomLeft];
 
       break;
     }
diff --git a/gdk/macos/gdkmacosglcontext-private.h b/gdk/macos/gdkmacosglcontext-private.h
index 781035677a..9d9b378b16 100644
--- a/gdk/macos/gdkmacosglcontext-private.h
+++ b/gdk/macos/gdkmacosglcontext-private.h
@@ -29,7 +29,7 @@
 #include "gdkmacossurface.h"
 
 #import <OpenGL/OpenGL.h>
-#import <OpenGL/gl.h>
+#import <OpenGL/gl3.h>
 #import <AppKit/AppKit.h>
 
 G_BEGIN_DECLS
@@ -38,17 +38,15 @@ struct _GdkMacosGLContext
 {
   GdkGLContext parent_instance;
 
+  cairo_region_t *damage;
+
   G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-  NSOpenGLContext *gl_context;
+  CGLContextObj cgl_context;
   G_GNUC_END_IGNORE_DEPRECATIONS
 
-  NSWindow *dummy_window;
-  NSView *dummy_view;
-
-  cairo_region_t *damage;
-
-  guint is_attached : 1;
-  guint needs_resize : 1;
+  GLuint texture;
+  GLuint target;
+  GLuint fbo;
 };
 
 struct _GdkMacosGLContextClass
@@ -56,7 +54,6 @@ struct _GdkMacosGLContextClass
   GdkGLContextClass parent_class;
 };
 
-
 G_END_DECLS
 
 #endif /* __GDK_MACOS_GL_CONTEXT_PRIVATE_H__ */
diff --git a/gdk/macos/gdkmacosglcontext.c b/gdk/macos/gdkmacosglcontext.c
index 1800815786..0686ae048c 100644
--- a/gdk/macos/gdkmacosglcontext.c
+++ b/gdk/macos/gdkmacosglcontext.c
@@ -25,14 +25,108 @@
 
 #include "gdkintl.h"
 
-#include <OpenGL/gl.h>
+#include <OpenGL/gl3.h>
+#include <OpenGL/glext.h>
+#include <OpenGL/CGLIOSurface.h>
 
-#import "GdkMacosGLView.h"
+#include "gdkmacosbuffer-private.h"
 
 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
 
 G_DEFINE_TYPE (GdkMacosGLContext, gdk_macos_gl_context, GDK_TYPE_GL_CONTEXT)
 
+static inline gboolean
+_CHECK (GError     **error,
+        const char  *location,
+        CGLError     cgl_error)
+{
+  if (cgl_error != kCGLNoError)
+    {
+      g_log ("Core OpenGL",
+             G_LOG_LEVEL_CRITICAL,
+             "%s: %s",
+             location, CGLErrorString (cgl_error));
+      g_set_error (error,
+                   GDK_GL_ERROR,
+                   GDK_GL_ERROR_NOT_AVAILABLE,
+                   "%s",
+                   CGLErrorString (cgl_error));
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+static inline gboolean
+_CHECK_GL (GError     **error,
+           const char  *location,
+           GLenum       gl_error)
+{
+  const char *msg;
+
+  switch (gl_error)
+    {
+    case GL_INVALID_ENUM:
+      msg = "invalid enum";
+      break;
+    case GL_INVALID_VALUE:
+      msg = "invalid value";
+      break;
+    case GL_INVALID_OPERATION:
+      msg = "invalid operation";
+      break;
+    case GL_INVALID_FRAMEBUFFER_OPERATION:
+      msg = "invalid framebuffer operation";
+      break;
+    case GL_OUT_OF_MEMORY:
+      msg = "out of memory";
+      break;
+    default:
+      msg = "unknown error";
+      break;
+    }
+
+  if (gl_error != GL_NO_ERROR)
+    {
+      g_log ("OpenGL",
+             G_LOG_LEVEL_CRITICAL,
+             "%s: %s", location, msg);
+      g_set_error (error,
+                   GDK_GL_ERROR,
+                   GDK_GL_ERROR_NOT_AVAILABLE,
+                   "%s", msg);
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+#define CHECK(error,cgl_error) _CHECK(error, G_STRLOC, cgl_error)
+#define CHECK_GL(error,func) _CHECK_GL(error, G_STRLOC, ({ func; glGetError(); }))
+
+static inline gboolean
+is_opaque_surface (GdkMacosGLContext *self)
+{
+  GdkSurface *surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (self));
+  cairo_region_t *region = GDK_MACOS_SURFACE (surface)->opaque_region;
+
+  if (region != NULL && cairo_region_num_rectangles (region) == 1)
+    {
+      cairo_rectangle_int_t extents;
+
+      cairo_region_get_extents (region, &extents);
+
+      if (extents.x == 0 &&
+          extents.y == 0 &&
+          extents.width == surface->width &&
+          extents.height == surface->height)
+        return TRUE;
+    }
+
+  return FALSE;
+}
+
+
 static const char *
 get_renderer_name (GLint id)
 {
@@ -72,95 +166,166 @@ get_renderer_name (GLint id)
   }
 }
 
-static NSOpenGLContext *
-get_ns_open_gl_context (GdkMacosGLContext  *self,
-                        GError            **error)
+static GLuint
+create_texture (GLuint target)
 {
-  g_assert (GDK_IS_MACOS_GL_CONTEXT (self));
-
-  if (self->gl_context == nil)
+  GLuint texture = 0;
+
+  if (!CHECK_GL (NULL, glGenTextures (1, &texture)) ||
+      !CHECK_GL (NULL, glBindTexture (target, texture)) ||
+      !CHECK_GL (NULL, glTexParameteri (target, GL_TEXTURE_BASE_LEVEL, 0)) ||
+      !CHECK_GL (NULL, glTexParameteri (target, GL_TEXTURE_MIN_FILTER, GL_NEAREST)) ||
+      !CHECK_GL (NULL, glTexParameteri (target, GL_TEXTURE_MAG_FILTER, GL_NEAREST)) ||
+      !CHECK_GL (NULL, glTexParameteri (target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)) ||
+      !CHECK_GL (NULL, glTexParameteri (target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE)) ||
+      !CHECK_GL (NULL, glTexParameteri (target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)))
     {
-      g_set_error_literal (error,
-                           GDK_GL_ERROR,
-                           GDK_GL_ERROR_NOT_AVAILABLE,
-                           "Cannot access NSOpenGLContext for surface");
-      return NULL;
+      glDeleteTextures (1, &texture);
+      return 0;
     }
 
-  return self->gl_context;
+  return texture;
 }
 
-static NSOpenGLPixelFormat *
-create_pixel_format (int      major,
-                     int      minor,
-                     GError **error)
+static void
+gdk_macos_gl_context_allocate (GdkMacosGLContext *self)
 {
-  NSOpenGLPixelFormatAttribute attrs[] = {
-    NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersionLegacy,
-    NSOpenGLPFAAccelerated,
-    NSOpenGLPFADoubleBuffer,
-    NSOpenGLPFABackingStore,
-    NSOpenGLPFAColorSize, 24,
-    NSOpenGLPFAAlphaSize, 8,
-    0
-  };
+  GdkSurface *surface;
 
-  if (major == 3 && minor == 2)
-    attrs[1] = NSOpenGLProfileVersion3_2Core;
-  else if (major == 4 && minor == 1)
-    attrs[1] = NSOpenGLProfileVersion4_1Core;
+  g_assert (GDK_IS_MACOS_GL_CONTEXT (self));
+  g_assert (self->cgl_context != NULL);
 
-  NSOpenGLPixelFormat *format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
+  if (!(surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (self))))
+    return;
 
-  if (format == NULL)
-    g_set_error (error,
-                 GDK_GL_ERROR,
-                 GDK_GL_ERROR_NOT_AVAILABLE,
-                 "Failed to create pixel format");
+  if (self->texture == 0)
+    {
+      GdkMacosBuffer *buffer;
+      IOSurfaceRef io_surface;
+      guint width;
+      guint height;
+
+      buffer = _gdk_macos_surface_get_buffer (GDK_MACOS_SURFACE (surface));
+      io_surface = _gdk_macos_buffer_get_native (buffer);
+      width = _gdk_macos_buffer_get_width (buffer);
+      height = _gdk_macos_buffer_get_height (buffer);
+
+      self->texture = create_texture (self->target);
+      if (!CHECK_GL (NULL, glGenFramebuffers (1, &self->fbo)) ||
+          !CHECK_GL (NULL, glBindFramebuffer (GL_FRAMEBUFFER, self->fbo)) ||
+          !CHECK_GL (NULL, glBindTexture (self->target, self->texture)))
+        return;
+
+      if (!CHECK (NULL, CGLTexImageIOSurface2D (self->cgl_context,
+                                                self->target,
+                                                GL_RGBA,
+                                                width,
+                                                height,
+                                                GL_BGRA,
+                                                GL_UNSIGNED_INT_8_8_8_8_REV,
+                                                io_surface,
+                                                0)))
+        return;
+    }
 
-  return g_steal_pointer (&format);
+  glBindTexture (self->target, self->texture);
+  glBindFramebuffer (GL_FRAMEBUFFER, self->fbo);
+
+  if (!CHECK_GL (NULL, glFramebufferTexture2D (GL_FRAMEBUFFER,
+                                               GL_COLOR_ATTACHMENT0,
+                                               self->target,
+                                               self->texture,
+                                               0)))
+    return;
+
+  switch (glCheckFramebufferStatus (GL_FRAMEBUFFER))
+    {
+    case GL_FRAMEBUFFER_COMPLETE:
+      break;
+
+    case GL_FRAMEBUFFER_UNDEFINED:
+      g_critical ("Framebuffer is undefined");
+      break;
+
+    case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
+      g_critical ("Framebuffer has incomplete attachment");
+      break;
+
+    case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
+      g_critical ("Framebuffer has missing attachment");
+      break;
+
+    case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
+      g_critical ("Framebuffer has incomplete draw buffer");
+      break;
+
+    case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
+      g_critical ("Framebuffer has incomplete read buffer");
+      break;
+
+    case GL_FRAMEBUFFER_UNSUPPORTED:
+      g_critical ("Framebuffer is unsupported");
+      break;
+
+    case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
+      g_critical ("Framebuffer has incomplete multisample");
+      break;
+
+    default:
+      g_critical ("Framebuffer has unknown error");
+      break;
+    }
 }
 
-static NSView *
-ensure_gl_view (GdkMacosGLContext *self)
+static void
+gdk_macos_gl_context_release (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);
+  glBindTexture (self->target, 0);
 
-  if G_UNLIKELY (!GDK_IS_MACOS_GL_VIEW (nsview))
+  if (self->fbo != 0)
     {
-      NSRect frame;
-
-      frame = [[nswindow contentView] bounds];
-      nsview = [[GdkMacosGLView alloc] initWithFrame:frame];
-      [nsview setWantsBestResolutionOpenGLSurface:YES];
-      [nsview setPostsFrameChangedNotifications: YES];
-      [nsview setNeedsDisplay:YES];
-      [nswindow setContentView:nsview];
-      [nswindow makeFirstResponder:nsview];
-      [nsview release];
-
-      if (self->dummy_view != NULL)
-        {
-          NSView *dummy_view = g_steal_pointer (&self->dummy_view);
-          [dummy_view release];
-        }
+      glDeleteFramebuffers (1, &self->fbo);
+      self->fbo = 0;
+    }
 
-      if (self->dummy_window != NULL)
-        {
-          NSWindow *dummy_window = g_steal_pointer (&self->dummy_window);
-          [dummy_window release];
-        }
+  if (self->texture != 0)
+    {
+      glDeleteTextures (1, &self->texture);
+      self->texture = 0;
     }
+}
+
+static CGLPixelFormatObj
+create_pixel_format (int      major,
+                     int      minor,
+                     GError **error)
+{
+  CGLPixelFormatAttribute attrs[] = {
+    kCGLPFAOpenGLProfile, (CGLPixelFormatAttribute)kCGLOGLPVersion_Legacy,
+    kCGLPFAAccelerated,
+    //kCGLPFAAllowOfflineRenderers,
+    //kCGLPFADoubleBuffer,
+    //kCGLPFABackingStore,
+    kCGLPFAColorSize, 24,
+    kCGLPFAAlphaSize, 8,
+    0
+  };
+  CGLPixelFormatObj format = NULL;
+  GLint n_format = 1;
 
-  return [nswindow contentView];
+  if (major == 3 && minor == 2)
+    attrs[1] = (CGLPixelFormatAttribute)kCGLOGLPVersion_GL3_Core;
+  else if (major == 4 && minor == 1)
+    attrs[1] = (CGLPixelFormatAttribute)kCGLOGLPVersion_GL4_Core;
+
+  g_print (">>> GL %d.%d\n", major, minor);
+
+  if (!CHECK (error, CGLChoosePixelFormat (attrs, &format, &n_format)))
+    return NULL;
+
+  return g_steal_pointer (&format);
 }
 
 static GdkGLAPI
@@ -170,26 +335,25 @@ gdk_macos_gl_context_real_realize (GdkGLContext  *context,
   GdkMacosGLContext *self = (GdkMacosGLContext *)context;
   GdkSurface *surface;
   GdkDisplay *display;
-  NSOpenGLContext *shared_gl_context = nil;
-  NSOpenGLContext *gl_context;
-  NSOpenGLPixelFormat *pixelFormat;
+  CGLPixelFormatObj pixelFormat;
+  CGLContextObj shared_gl_context = nil;
   CGLContextObj cgl_context;
+  CGLContextObj existing;
   GdkGLContext *shared;
-  NSOpenGLContext *existing;
   GLint sync_to_framerate = 1;
   GLint validate = 0;
-  GLint swapRect[4];
+  GLint renderer_id = 0;
   int major, minor;
 
   g_assert (GDK_IS_MACOS_GL_CONTEXT (self));
 
-  if (self->gl_context != nil)
+  if (self->cgl_context != nil)
     return GDK_GL_API_GL;
 
   if (!gdk_gl_context_is_api_allowed (context, GDK_GL_API_GL, error))
     return 0;
 
-  existing = [NSOpenGLContext currentContext];
+  existing = CGLGetCurrentContext ();
 
   gdk_gl_context_get_required_version (context, &major, &minor);
 
@@ -199,99 +363,59 @@ gdk_macos_gl_context_real_realize (GdkGLContext  *context,
 
   if (shared != NULL)
     {
-      if (!(shared_gl_context = get_ns_open_gl_context (GDK_MACOS_GL_CONTEXT (shared), error)))
-        return 0;
+      if (!(shared_gl_context = GDK_MACOS_GL_CONTEXT (shared)->cgl_context))
+        {
+          g_set_error_literal (error,
+                               GDK_GL_ERROR,
+                               GDK_GL_ERROR_NOT_AVAILABLE,
+                               "Cannot access shared CGLContextObj");
+          return 0;
+        }
     }
 
   GDK_DISPLAY_NOTE (display,
                     OPENGL,
-                    g_message ("Creating NSOpenGLContext (version %d.%d)",
+                    g_message ("Creating CGLContextObj (version %d.%d)",
                                major, minor));
 
   if (!(pixelFormat = create_pixel_format (major, minor, error)))
     return 0;
 
-  gl_context = [[NSOpenGLContext alloc] initWithFormat:pixelFormat
-                                          shareContext:shared_gl_context];
-
-  [pixelFormat release];
-
-  if (gl_context == nil)
+  if (!CHECK (error, CGLCreateContext (pixelFormat, shared_gl_context, &cgl_context)))
     {
-      g_set_error_literal (error,
-                           GDK_GL_ERROR,
-                           GDK_GL_ERROR_NOT_AVAILABLE,
-                           "Failed to create NSOpenGLContext");
+      CGLReleasePixelFormat (pixelFormat);
       return 0;
     }
 
-  cgl_context = [gl_context CGLContextObj];
+  CGLSetCurrentContext (cgl_context);
+  CGLReleasePixelFormat (pixelFormat);
 
-  swapRect[0] = 0;
-  swapRect[1] = 0;
-  swapRect[2] = surface ? surface->width : 0;
-  swapRect[3] = surface ? surface->height : 0;
-
-  CGLSetParameter (cgl_context, kCGLCPSwapRectangle, swapRect);
-  CGLSetParameter (cgl_context, kCGLCPSwapInterval, &sync_to_framerate);
-
-  CGLEnable (cgl_context, kCGLCESwapRectangle);
   if (validate)
-    CGLEnable (cgl_context, kCGLCEStateValidation);
+    CHECK (NULL, CGLEnable (cgl_context, kCGLCEStateValidation));
 
-  self->dummy_window = [[NSWindow alloc] initWithContentRect:NSZeroRect
-                                                   styleMask:0
-                                                     backing:NSBackingStoreBuffered
-                                                       defer:NO
-                                                      screen:nil];
-  self->dummy_view = [[NSView alloc] initWithFrame:NSZeroRect];
-  [self->dummy_window setContentView:self->dummy_view];
-  [gl_context setView:self->dummy_view];
+  if (!CHECK (error, CGLSetParameter (cgl_context, kCGLCPSwapInterval, &sync_to_framerate)) ||
+      !CHECK (error, CGLGetParameter (cgl_context, kCGLCPCurrentRendererID, &renderer_id)))
+   {
+      CGLReleaseContext (cgl_context);
+      return 0;
+   }
 
-  GLint renderer_id = 0;
-  [gl_context getValues:&renderer_id forParameter:NSOpenGLContextParameterCurrentRendererID];
   GDK_DISPLAY_NOTE (display,
                     OPENGL,
-                    g_message ("Created NSOpenGLContext[%p] using %s",
-                               gl_context,
+                    g_message ("Created CGLContextObj@%p using %s",
+                               cgl_context,
                                get_renderer_name (renderer_id)));
 
-  self->gl_context = g_steal_pointer (&gl_context);
+  self->cgl_context = g_steal_pointer (&cgl_context);
+
+  gdk_macos_gl_context_allocate (self);
 
   if (existing != NULL)
-    [existing makeCurrentContext];
+    CGLSetCurrentContext (existing);
 
   return GDK_GL_API_GL;
 }
 
-static gboolean
-opaque_region_covers_surface (GdkMacosGLContext *self)
-{
-  GdkSurface *surface;
-  cairo_region_t *region;
-
-  g_assert (GDK_IS_MACOS_GL_CONTEXT (self));
-
-  surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (self));
-  region = GDK_MACOS_SURFACE (surface)->opaque_region;
-
-  if (region != NULL &&
-      cairo_region_num_rectangles (region) == 1)
-    {
-      cairo_rectangle_int_t extents;
-
-      cairo_region_get_extents (region, &extents);
-
-      if (extents.x == 0 &&
-          extents.y == 0 &&
-          extents.width == surface->width &&
-          extents.height == surface->height)
-        return TRUE;
-    }
-
-  return FALSE;
-}
-
 static void
 gdk_macos_gl_context_begin_frame (GdkDrawContext *context,
                                   gboolean        prefers_high_depth,
@@ -299,66 +423,32 @@ gdk_macos_gl_context_begin_frame (GdkDrawContext *context,
 {
   GdkMacosGLContext *self = (GdkMacosGLContext *)context;
   GdkSurface *surface;
+  GLint opaque;
 
   g_assert (GDK_IS_MACOS_GL_CONTEXT (self));
 
-  surface = gdk_draw_context_get_surface (context);
+  g_print ("Begin frame\n");
+
+  gdk_gl_context_make_current (GDK_GL_CONTEXT (self));
 
   g_clear_pointer (&self->damage, cairo_region_destroy);
   self->damage = cairo_region_copy (painted);
 
-  /* If begin frame is called, that means we are trying to draw to
-   * the NSWindow using our view. That might be a GdkMacosCairoView
-   * but we need it to be a GL view. Also, only in this case do we
-   * want to replace our damage region for the next frame (to avoid
-   * doing it multiple times).
-   */
-  ensure_gl_view (self);
-
-  if (self->needs_resize)
-    {
-      CGLContextObj cgl_context = [self->gl_context CGLContextObj];
-      GLint opaque;
-
-      self->needs_resize = FALSE;
-
-      if (self->dummy_view != NULL)
-        {
-          NSRect frame = NSMakeRect (0, 0, surface->width, surface->height);
-
-          [self->dummy_window setFrame:frame display:NO];
-          [self->dummy_view setFrame:frame];
-        }
-
-      /* Possibly update our opaque setting depending on a resize. We can
-       * rely on getting a resize if decoarated is changed, so this reduces
-       * how much we adjust the parameter.
-       */
-      if (GDK_IS_MACOS_TOPLEVEL_SURFACE (surface))
-        opaque = GDK_MACOS_TOPLEVEL_SURFACE (surface)->decorated;
-      else
-        opaque = FALSE;
+  surface = gdk_draw_context_get_surface (context);
+  opaque = is_opaque_surface (self);
 
-      /* If we are maximized, we might be able to make it opaque */
-      if (opaque == FALSE)
-        opaque = opaque_region_covers_surface (self);
+  /* If the whole surface is opaque, we can help CGL out a bit */
+  if (!CHECK (NULL, CGLSetParameter (self->cgl_context, kCGLCPSurfaceOpacity, &opaque)))
+    return;
 
-      CGLSetParameter (cgl_context, kCGLCPSurfaceOpacity, &opaque);
+  gdk_macos_gl_context_allocate (self);
 
-      [self->gl_context update];
-    }
+  //if (!CHECK (NULL, CGLUpdateContext (self->cgl_context)))
+    //return;
 
   GDK_DRAW_CONTEXT_CLASS (gdk_macos_gl_context_parent_class)->begin_frame (context, prefers_high_depth, 
painted);
 
-  if (!self->is_attached)
-    {
-      NSView *nsview = _gdk_macos_surface_get_view (GDK_MACOS_SURFACE (surface));
-
-      g_assert (self->gl_context != NULL);
-      g_assert (GDK_IS_MACOS_GL_VIEW (nsview));
-
-      [(GdkMacosGLView *)nsview setOpenGLContext:self->gl_context];
-    }
+  g_print ("Begin frame\n");
 }
 
 static void
@@ -366,32 +456,34 @@ gdk_macos_gl_context_end_frame (GdkDrawContext *context,
                                 cairo_region_t *painted)
 {
   GdkMacosGLContext *self = GDK_MACOS_GL_CONTEXT (context);
+  GdkSurface *surface;
+  cairo_rectangle_int_t flush_rect;
+  GLint swapRect[4];
 
   g_assert (GDK_IS_MACOS_GL_CONTEXT (self));
-  g_assert (self->gl_context != nil);
+  g_assert (self->cgl_context != nil);
 
   GDK_DRAW_CONTEXT_CLASS (gdk_macos_gl_context_parent_class)->end_frame (context, painted);
 
-  if (!self->is_attached)
-    {
-      GdkSurface *surface = gdk_draw_context_get_surface (context);
-      CGLContextObj glctx = [self->gl_context CGLContextObj];
-      cairo_rectangle_int_t flush_rect;
-      GLint swapRect[4];
-
-      /* Coordinates are in display coordinates, where as flush_rect is
-       * in GDK coordinates. Must flip Y to match display coordinates where
-       * 0,0 is the bottom-left corner.
-       */
-      cairo_region_get_extents (painted, &flush_rect);
-      swapRect[0] = flush_rect.x;                   /* left */
-      swapRect[1] = surface->height - flush_rect.y; /* bottom */
-      swapRect[2] = flush_rect.width;               /* width */
-      swapRect[3] = flush_rect.height;              /* height */
-      CGLSetParameter (glctx, kCGLCPSwapRectangle, swapRect);
-
-      [self->gl_context flushBuffer];
-    }
+  surface = gdk_draw_context_get_surface (context);
+
+  /* Coordinates are in display coordinates, where as flush_rect is
+  * in GDK coordinates. Must flip Y to match display coordinates where
+  * 0,0 is the bottom-left corner.
+  */
+  cairo_region_get_extents (painted, &flush_rect);
+  swapRect[0] = flush_rect.x;                   /* left */
+  swapRect[1] = surface->height - flush_rect.y; /* bottom */
+  swapRect[2] = flush_rect.width;               /* width */
+  swapRect[3] = flush_rect.height;              /* height */
+  CGLSetParameter (self->cgl_context, kCGLCPSwapRectangle, swapRect);
+  CGLEnable (self->cgl_context, kCGLCESwapRectangle);
+
+  glFlush ();
+
+  g_print ("End frame\n");
+
+  _gdk_macos_surface_swap_buffers (GDK_MACOS_SURFACE (surface), painted);
 }
 
 static void
@@ -401,7 +493,10 @@ gdk_macos_gl_context_surface_resized (GdkDrawContext *draw_context)
 
   g_assert (GDK_IS_MACOS_GL_CONTEXT (self));
 
-  self->needs_resize = TRUE;
+  gdk_gl_context_make_current (GDK_GL_CONTEXT (self));
+
+  gdk_macos_gl_context_release (self);
+  gdk_macos_gl_context_allocate (self);
 
   g_clear_pointer (&self->damage, cairo_region_destroy);
 }
@@ -410,22 +505,13 @@ static gboolean
 gdk_macos_gl_context_clear_current (GdkGLContext *context)
 {
   GdkMacosGLContext *self = GDK_MACOS_GL_CONTEXT (context);
-  NSOpenGLContext *current;
 
   g_return_val_if_fail (GDK_IS_MACOS_GL_CONTEXT (self), FALSE);
 
-  current = [NSOpenGLContext currentContext];
-
-  if (self->gl_context == current)
+  if (self->cgl_context == CGLGetCurrentContext ())
     {
-      /* The OpenGL mac programming guide suggests that glFlush() is called
-       * before switching current contexts to ensure that the drawing commands
-       * are submitted.
-       */
-      if (current != NULL)
-        glFlush ();
-
-      [NSOpenGLContext clearCurrentContext];
+      glFlush ();
+      CGLSetCurrentContext (NULL);
     }
 
   return TRUE;
@@ -436,22 +522,26 @@ gdk_macos_gl_context_make_current (GdkGLContext *context,
                                    gboolean      surfaceless)
 {
   GdkMacosGLContext *self = GDK_MACOS_GL_CONTEXT (context);
-  NSOpenGLContext *current;
+  CGLContextObj current;
 
   g_return_val_if_fail (GDK_IS_MACOS_GL_CONTEXT (self), FALSE);
 
-  current = [NSOpenGLContext currentContext];
+  current = CGLGetCurrentContext ();
 
-  if (self->gl_context != current)
+  if (self->cgl_context != current)
     {
       /* The OpenGL mac programming guide suggests that glFlush() is called
        * before switching current contexts to ensure that the drawing commands
        * are submitted.
+       *
+       * TODO: investigate if we need this because we may switch contexts
+       *       durring composition and only need it when returning to a
+       *       previous context that uses the other context.
        */
       if (current != NULL)
         glFlush ();
 
-      [self->gl_context makeCurrentContext];
+      CGLSetCurrentContext (self->cgl_context);
     }
 
   return TRUE;
@@ -475,27 +565,18 @@ gdk_macos_gl_context_dispose (GObject *gobject)
 {
   GdkMacosGLContext *self = GDK_MACOS_GL_CONTEXT (gobject);
 
-  if (self->dummy_view != nil)
-    {
-      NSView *nsview = g_steal_pointer (&self->dummy_view);
-      [nsview release];
-    }
-
-  if (self->dummy_window != nil)
-    {
-      NSWindow *nswindow = g_steal_pointer (&self->dummy_window);
-      [nswindow release];
-    }
+  self->texture = 0;
+  self->fbo = 0;
 
-  if (self->gl_context != nil)
+  if (self->cgl_context != nil)
     {
-      NSOpenGLContext *gl_context = g_steal_pointer (&self->gl_context);
+      CGLContextObj cgl_context = g_steal_pointer (&self->cgl_context);
 
-      if (gl_context == [NSOpenGLContext currentContext])
-        [NSOpenGLContext clearCurrentContext];
+      if (cgl_context == CGLGetCurrentContext ())
+        CGLSetCurrentContext (NULL);
 
-      [gl_context clearDrawable];
-      [gl_context release];
+      CGLClearDrawable (cgl_context);
+      CGLDestroyContext (cgl_context);
     }
 
   g_clear_pointer (&self->damage, cairo_region_destroy);
@@ -527,6 +608,10 @@ gdk_macos_gl_context_class_init (GdkMacosGLContextClass *klass)
 static void
 gdk_macos_gl_context_init (GdkMacosGLContext *self)
 {
+  /* We must use GL_TEXTURE_RECTANGLE_ARB to be able to bind an
+   * IOSurfaceRef to the GL texture/framebuffer.
+   */
+  self->target = GL_TEXTURE_RECTANGLE_ARB;
 }
 
 G_GNUC_END_IGNORE_DEPRECATIONS
diff --git a/gdk/macos/meson.build b/gdk/macos/meson.build
index f42914a9d0..86f20bd2ea 100644
--- a/gdk/macos/meson.build
+++ b/gdk/macos/meson.build
@@ -26,8 +26,6 @@ gdk_macos_sources = files([
   'GdkMacosTile.c',
   'GdkMacosView.c',
   'GdkMacosWindow.c',
-
-  'GdkMacosGLView.c',
 ])
 
 gdk_macos_public_headers = files([


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