[gtk/wip/chergert/quartz4u: 116/116] macos: start on GL context



commit 481a5c39f6c2902219cdd50ff5945b44626a5fc3
Author: Christian Hergert <chergert redhat com>
Date:   Wed Jun 24 16:04:08 2020 -0700

    macos: start on GL context
    
    Not working or anything at this point, just landing some bits
    so that we can do some exploration on how to merge this
    Rube Goldberg machine.
    
    What seems difficult right now is to implement the drawing
    (such as GdkSurface::render) from the drawInOpenGL
    position of the layer. So we'll probably have to come up with
    a way to render to an FBO/texture and then draw that from
    the layer.

 gdk/macos/gdkmacos.h                  |   1 +
 gdk/macos/gdkmacosdisplay.c           |  12 +++
 gdk/macos/gdkmacosglcontext-private.h |  60 +++++++++++++
 gdk/macos/gdkmacosglcontext.c         | 153 ++++++++++++++++++++++++++++++++++
 gdk/macos/gdkmacosglcontext.h         |  43 ++++++++++
 gdk/macos/gdkmacossurface.c           |  16 ++++
 gdk/macos/meson.build                 |   2 +
 gsk/gskrenderer.c                     |   7 ++
 8 files changed, 294 insertions(+)
---
diff --git a/gdk/macos/gdkmacos.h b/gdk/macos/gdkmacos.h
index d04d46067d..7d7d348752 100644
--- a/gdk/macos/gdkmacos.h
+++ b/gdk/macos/gdkmacos.h
@@ -24,6 +24,7 @@
 
 #include "gdkmacosdevice.h"
 #include "gdkmacosdisplay.h"
+#include "gdkmacosglcontext.h"
 #include "gdkmacoskeymap.h"
 #include "gdkmacosmonitor.h"
 #include "gdkmacossurface.h"
diff --git a/gdk/macos/gdkmacosdisplay.c b/gdk/macos/gdkmacosdisplay.c
index 043cea4edb..800696eb09 100644
--- a/gdk/macos/gdkmacosdisplay.c
+++ b/gdk/macos/gdkmacosdisplay.c
@@ -31,6 +31,7 @@
 #include "gdkmacoscairocontext-private.h"
 #include "gdkmacoseventsource-private.h"
 #include "gdkmacosdisplay-private.h"
+#include "gdkmacosglcontext-private.h"
 #include "gdkmacoskeymap-private.h"
 #include "gdkmacosmonitor-private.h"
 #include "gdkmacosseat-private.h"
@@ -606,6 +607,16 @@ gdk_macos_display_load_clipboard (GdkMacosDisplay *self)
   GDK_DISPLAY (self)->clipboard = _gdk_macos_clipboard_new (self);
 }
 
+static gboolean
+gdk_macos_display_make_gl_context_current (GdkDisplay   *display,
+                                           GdkGLContext *gl_context)
+{
+  g_assert (GDK_IS_MACOS_DISPLAY (display));
+  g_assert (GDK_IS_MACOS_GL_CONTEXT (gl_context));
+
+  return _gdk_macos_gl_context_make_current (GDK_MACOS_GL_CONTEXT (gl_context));
+}
+
 static void
 gdk_macos_display_finalize (GObject *object)
 {
@@ -649,6 +660,7 @@ gdk_macos_display_class_init (GdkMacosDisplayClass *klass)
   display_class->get_name = gdk_macos_display_get_name;
   display_class->get_setting = gdk_macos_display_get_setting;
   display_class->has_pending = gdk_macos_display_has_pending;
+  display_class->make_gl_context_current = gdk_macos_display_make_gl_context_current;
   display_class->notify_startup_complete = gdk_macos_display_notify_startup_complete;
   display_class->queue_events = gdk_macos_display_queue_events;
   display_class->sync = gdk_macos_display_sync;
diff --git a/gdk/macos/gdkmacosglcontext-private.h b/gdk/macos/gdkmacosglcontext-private.h
new file mode 100644
index 0000000000..e976939eb1
--- /dev/null
+++ b/gdk/macos/gdkmacosglcontext-private.h
@@ -0,0 +1,60 @@
+/* gdkmacosglcontext-private.h
+ *
+ * Copyright (C) 2020 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/>.
+ */
+
+#ifndef __GDK_MACOS_GL_CONTEXT_PRIVATE_H__
+#define __GDK_MACOS_GL_CONTEXT_PRIVATE_H__
+
+#include "gdkglcontextprivate.h"
+#include "gdkdisplayprivate.h"
+#include "gdksurface.h"
+#include "gdkinternals.h"
+
+#include "gdkmacosglcontext.h"
+#include "gdkmacossurface.h"
+
+#import <OpenGL/OpenGL.h>
+#import <OpenGL/gl.h>
+#import <AppKit/AppKit.h>
+
+G_BEGIN_DECLS
+
+struct _GdkMacosGLContext
+{
+  GdkGLContext parent_instance;
+
+  G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+  NSOpenGLContext *gl_context;
+  G_GNUC_END_IGNORE_DEPRECATIONS
+
+  gboolean is_attached;
+};
+
+struct _GdkMacosGLContextClass
+{
+  GdkGLContextClass parent_class;
+};
+
+GdkGLContext *_gdk_macos_gl_context_new          (GdkMacosSurface    *surface,
+                                                  gboolean            attached,
+                                                  GdkGLContext       *share,
+                                                  GError            **error);
+gboolean      _gdk_macos_gl_context_make_current (GdkMacosGLContext  *self);
+
+G_END_DECLS
+
+#endif /* __GDK_MACOS_GL_CONTEXT_PRIVATE_H__ */
diff --git a/gdk/macos/gdkmacosglcontext.c b/gdk/macos/gdkmacosglcontext.c
new file mode 100644
index 0000000000..0d1e03e1d2
--- /dev/null
+++ b/gdk/macos/gdkmacosglcontext.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright © 2020 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.1 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 "gdkmacosglcontext-private.h"
+#include "gdkmacossurface-private.h"
+
+#include "gdkinternals.h"
+#include "gdkintl.h"
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+
+G_DEFINE_TYPE (GdkMacosGLContext, gdk_macos_gl_context, GDK_TYPE_GL_CONTEXT)
+
+static void
+gdk_macos_gl_context_end_frame (GdkDrawContext *context,
+                                cairo_region_t *painted)
+{
+  GdkMacosGLContext *self = GDK_MACOS_GL_CONTEXT (context);
+
+  g_assert (GDK_IS_MACOS_GL_CONTEXT (self));
+
+  [self->gl_context flushBuffer];
+}
+
+static void
+gdk_macos_gl_context_dispose (GObject *gobject)
+{
+  GdkMacosGLContext *context_macos = GDK_MACOS_GL_CONTEXT (gobject);
+
+  if (context_macos->gl_context != NULL)
+    {
+      [context_macos->gl_context clearDrawable];
+      [context_macos->gl_context release];
+      context_macos->gl_context = NULL;
+    }
+
+  G_OBJECT_CLASS (gdk_macos_gl_context_parent_class)->dispose (gobject);
+}
+
+static void
+gdk_macos_gl_context_class_init (GdkMacosGLContextClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GdkDrawContextClass *draw_context_class = GDK_DRAW_CONTEXT_CLASS (klass);
+
+  object_class->dispose = gdk_macos_gl_context_dispose;
+
+  draw_context_class->end_frame = gdk_macos_gl_context_end_frame;
+}
+
+static void
+gdk_macos_gl_context_init (GdkMacosGLContext *self)
+{
+}
+
+GdkGLContext *
+_gdk_macos_gl_context_new (GdkMacosSurface  *surface,
+                           gboolean          attached,
+                           GdkGLContext     *share,
+                           GError          **error)
+{
+  static const NSOpenGLPixelFormatAttribute attrs[] = {
+    NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
+    NSOpenGLPFADoubleBuffer,
+    NSOpenGLPFAColorSize, 24,
+    NSOpenGLPFAAlphaSize, 8,
+    0
+  };
+
+  NSOpenGLPixelFormat *format;
+  GdkMacosGLContext *context = NULL;
+  NSOpenGLContext *ctx;
+  GdkDisplay *display;
+  NSView *nsview;
+  GLint sync_to_framerate = 1;
+
+  g_return_val_if_fail (GDK_IS_MACOS_SURFACE (surface), NULL);
+  g_return_val_if_fail (!share || GDK_IS_MACOS_GL_CONTEXT (share), NULL);
+
+  display = gdk_surface_get_display (GDK_SURFACE (surface));
+
+  if (!(format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs]))
+    {
+      g_set_error_literal (error,
+                           GDK_GL_ERROR,
+                           GDK_GL_ERROR_NOT_AVAILABLE,
+                           _("Unable to create a GL pixel format"));
+      goto failure;
+    }
+
+  ctx = [[NSOpenGLContext alloc] initWithFormat:format
+                                 shareContext:share ? GDK_MACOS_GL_CONTEXT (share)->gl_context : nil];
+  if (ctx == NULL)
+    {
+      g_set_error_literal (error,
+                           GDK_GL_ERROR,
+                           GDK_GL_ERROR_NOT_AVAILABLE,
+                           _("Unable to create a GL context"));
+      goto failure;
+    }
+
+  nsview = _gdk_macos_surface_get_view (surface);
+  [nsview setWantsBestResolutionOpenGLSurface:YES];
+  [ctx setValues:&sync_to_framerate forParameter:NSOpenGLCPSwapInterval];
+  [ctx setView:nsview];
+
+  GDK_NOTE (OPENGL,
+            g_print ("Created NSOpenGLContext[%p]\n", ctx));
+
+  context = g_object_new (GDK_TYPE_MACOS_GL_CONTEXT,
+                          "surface", surface,
+                          "shared-context", share,
+                          NULL);
+
+  context->gl_context = ctx;
+  context->is_attached = attached;
+
+failure:
+  if (format != NULL)
+    [format release];
+
+  return GDK_GL_CONTEXT (context);
+}
+
+gboolean
+_gdk_macos_gl_context_make_current (GdkMacosGLContext *self)
+{
+  g_return_val_if_fail (GDK_IS_MACOS_GL_CONTEXT (self), FALSE);
+
+  [self->gl_context makeCurrentContext];
+
+  return TRUE;
+}
+
+G_GNUC_END_IGNORE_DEPRECATIONS
diff --git a/gdk/macos/gdkmacosglcontext.h b/gdk/macos/gdkmacosglcontext.h
new file mode 100644
index 0000000000..e4add89502
--- /dev/null
+++ b/gdk/macos/gdkmacosglcontext.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright © 2020 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.1 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
+ */
+
+#ifndef __GDK_MACOS_GL_CONTEXT_H__
+#define __GDK_MACOS_GL_CONTEXT_H__
+
+#if !defined (__GDKMACOS_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gdk/macos/gdkmacos.h> can be included directly."
+#endif
+
+#include <gdk/gdk.h>
+
+G_BEGIN_DECLS
+
+#define GDK_TYPE_MACOS_GL_CONTEXT    (gdk_macos_gl_context_get_type ())
+#define GDK_MACOS_GL_CONTEXT(obj)    (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_MACOS_GL_CONTEXT, 
GdkMacosGLContext))
+#define GDK_IS_MACOS_GL_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_MACOS_GL_CONTEXT))
+
+typedef struct _GdkMacosGLContext      GdkMacosGLContext;
+typedef struct _GdkMacosGLContextClass GdkMacosGLContextClass;
+
+GDK_AVAILABLE_IN_ALL
+GType gdk_macos_gl_context_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __GDK_MACOS_GL_CONTEXT_H__ */
diff --git a/gdk/macos/gdkmacossurface.c b/gdk/macos/gdkmacossurface.c
index 1e1e1b5be8..83fad33ffd 100644
--- a/gdk/macos/gdkmacossurface.c
+++ b/gdk/macos/gdkmacossurface.c
@@ -35,6 +35,7 @@
 #include "gdkmacosdisplay-private.h"
 #include "gdkmacosdrag-private.h"
 #include "gdkmacosdragsurface-private.h"
+#include "gdkmacosglcontext-private.h"
 #include "gdkmacosmonitor-private.h"
 #include "gdkmacospopupsurface-private.h"
 #include "gdkmacossurface-private.h"
@@ -337,6 +338,20 @@ gdk_macos_surface_drag_begin (GdkSurface         *surface,
   return GDK_DRAG (g_steal_pointer (&drag));
 }
 
+static GdkGLContext *
+gdk_macos_surface_create_gl_context (GdkSurface    *surface,
+                                     gboolean       attached,
+                                     GdkGLContext  *share,
+                                     GError       **error)
+{
+  GdkMacosSurface *self = (GdkMacosSurface *)surface;
+
+  g_assert (GDK_IS_MACOS_SURFACE (self));
+  g_assert (!share || GDK_IS_GL_CONTEXT (share));
+
+  return _gdk_macos_gl_context_new (self, attached, share, error);
+}
+
 static void
 gdk_macos_surface_destroy (GdkSurface *surface,
                            gboolean    foreign_destroy)
@@ -448,6 +463,7 @@ gdk_macos_surface_class_init (GdkMacosSurfaceClass *klass)
   object_class->get_property = gdk_macos_surface_get_property;
   object_class->set_property = gdk_macos_surface_set_property;
 
+  surface_class->create_gl_context = gdk_macos_surface_create_gl_context;
   surface_class->destroy = gdk_macos_surface_destroy;
   surface_class->drag_begin = gdk_macos_surface_drag_begin;
   surface_class->get_device_state = gdk_macos_surface_get_device_state;
diff --git a/gdk/macos/meson.build b/gdk/macos/meson.build
index d96f1f78a1..ef9f21ea85 100644
--- a/gdk/macos/meson.build
+++ b/gdk/macos/meson.build
@@ -11,6 +11,7 @@ gdk_macos_sources = files([
   'gdkmacosdisplay-translate.c',
   'gdkmacosdrag.c',
   'gdkmacosdragsurface.c',
+  'gdkmacosglcontext.c',
   'gdkmacoseventsource.c',
   'gdkmacoskeymap.c',
   'gdkmacosmonitor.c',
@@ -29,6 +30,7 @@ gdk_macos_sources = files([
 gdk_macos_public_headers = files([
   'gdkmacosdevice.h',
   'gdkmacosdisplay.h',
+  'gdkmacosglcontext.h',
   'gdkmacoskeymap.h',
   'gdkmacosmonitor.h',
   'gdkmacossurface.h',
diff --git a/gsk/gskrenderer.c b/gsk/gskrenderer.c
index 7563c5bb6f..5f4b1deeb8 100644
--- a/gsk/gskrenderer.c
+++ b/gsk/gskrenderer.c
@@ -60,6 +60,9 @@
 #ifdef GDK_RENDERING_VULKAN
 #include "vulkan/gskvulkanrenderer.h"
 #endif
+#ifdef GDK_WINDOWING_MACOS
+#include <gdk/macos/gdkmacos.h>
+#endif
 
 typedef struct
 {
@@ -555,6 +558,10 @@ get_renderer_for_backend (GdkSurface *surface)
   if (GDK_IS_BROADWAY_SURFACE (surface))
     return GSK_TYPE_BROADWAY_RENDERER;
 #endif
+#ifdef GDK_WINDOWING_MACOS
+  if (GDK_IS_MACOS_SURFACE (surface))
+    return GSK_TYPE_GL_RENDERER;
+#endif
 
   return G_TYPE_INVALID;
 }


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