summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrion Vibber <brion@pobox.com>2014-11-15 16:04:58 -0800
committerPhilip Chimento <philip.chimento@gmail.com>2018-05-08 22:41:18 -0700
commit39a28f50a07f2ed4927083e2e7463f7238acf177 (patch)
treec0ce03ee50844b4ad4c94f6aa3246281be8c0223
parent85fa6ba63105e1a857a914bf76798ff1eda9530c (diff)
downloadgtk+-39a28f50a07f2ed4927083e2e7463f7238acf177.tar.gz
quartz: implement GdkGLContext for Quartz backend
Current problems: * other widgets in a GL-painted window are low-resolution on Retina display * something wrong with paint updates; gdkgears demo only updates every couple of seconds but reports ~30fps See: #517
-rw-r--r--gdk/quartz/Makefile.am1
-rw-r--r--gdk/quartz/gdkdisplay-quartz.c2
-rw-r--r--gdk/quartz/gdkglcontext-quartz.c167
-rw-r--r--gdk/quartz/gdkglcontext-quartz.h23
-rw-r--r--gdk/quartz/gdkquartzglcontext.h45
-rw-r--r--gdk/quartz/gdkwindow-quartz.c1
6 files changed, 235 insertions, 4 deletions
diff --git a/gdk/quartz/Makefile.am b/gdk/quartz/Makefile.am
index 3ba039304d..9646f8687c 100644
--- a/gdk/quartz/Makefile.am
+++ b/gdk/quartz/Makefile.am
@@ -64,6 +64,7 @@ libgdkquartzinclude_HEADERS = \
gdkquartzdisplay.h \
gdkquartzdisplaymanager.h \
gdkquartzdnd.h \
+ gdkquartzglcontext.h \
gdkquartzkeys.h \
gdkquartzmonitor.h \
gdkquartzscreen.h \
diff --git a/gdk/quartz/gdkdisplay-quartz.c b/gdk/quartz/gdkdisplay-quartz.c
index d706654813..81a0fc78d5 100644
--- a/gdk/quartz/gdkdisplay-quartz.c
+++ b/gdk/quartz/gdkdisplay-quartz.c
@@ -29,6 +29,7 @@
#include "gdkscreen.h"
#include "gdkmonitorprivate.h"
#include "gdkdisplay-quartz.h"
+#include "gdkglcontext-quartz.h"
static GdkWindow *
@@ -297,6 +298,7 @@ gdk_quartz_display_class_init (GdkQuartzDisplayClass *class)
display_class->get_n_monitors = gdk_quartz_display_get_n_monitors;
display_class->get_monitor = gdk_quartz_display_get_monitor;
display_class->get_primary_monitor = gdk_quartz_display_get_primary_monitor;
+ display_class->make_gl_context_current = gdk_quartz_display_make_gl_context_current;
ProcessSerialNumber psn = { 0, kCurrentProcess };
diff --git a/gdk/quartz/gdkglcontext-quartz.c b/gdk/quartz/gdkglcontext-quartz.c
index a6cc3b6a35..59a97c15a3 100644
--- a/gdk/quartz/gdkglcontext-quartz.c
+++ b/gdk/quartz/gdkglcontext-quartz.c
@@ -24,16 +24,175 @@
#include "gdkglcontext-quartz.h"
+#include "gdkquartzdisplay.h"
+#include "gdkquartzglcontext.h"
+#include "gdkquartzwindow.h"
+#include "gdkprivate-quartz.h"
+
+#include "gdkinternals.h"
+
#include "gdkintl.h"
+G_DEFINE_TYPE (GdkQuartzGLContext, gdk_quartz_gl_context, GDK_TYPE_GL_CONTEXT)
+
+static void gdk_quartz_gl_context_dispose (GObject *gobject);
+
+void
+gdk_quartz_window_invalidate_for_new_frame (GdkWindow *window,
+ cairo_region_t *update_area)
+{
+ cairo_rectangle_int_t window_rect;
+
+ /* Minimal update is ok if we're not drawing with gl */
+ if (window->gl_paint_context == NULL)
+ return;
+
+ window_rect.x = 0;
+ window_rect.y = 0;
+ window_rect.width = gdk_window_get_width (window);
+ window_rect.height = gdk_window_get_height (window);
+
+ /* If nothing else is known, repaint everything so that the back
+ buffer is fully up-to-date for the swapbuffer */
+ cairo_region_union_rectangle (update_area, &window_rect);
+}
+
+static gboolean
+gdk_quartz_gl_context_realize (GdkGLContext *context,
+ GError **error)
+{
+ return TRUE;
+}
+
+static void
+gdk_quartz_gl_context_end_frame (GdkGLContext *context,
+ cairo_region_t *painted,
+ cairo_region_t *damage)
+{
+ GdkQuartzGLContext *context_quartz = GDK_QUARTZ_GL_CONTEXT (context);
+
+ [context_quartz->gl_context flushBuffer];
+}
+
+static void
+gdk_quartz_gl_context_class_init (GdkQuartzGLContextClass *klass)
+{
+ GdkGLContextClass *context_class = GDK_GL_CONTEXT_CLASS (klass);
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ context_class->realize = gdk_quartz_gl_context_realize;
+ context_class->end_frame = gdk_quartz_gl_context_end_frame;
+ gobject_class->dispose = gdk_quartz_gl_context_dispose;
+}
+
+static void
+gdk_quartz_gl_context_init (GdkQuartzGLContext *self)
+{
+}
+
+gboolean
+gdk_quartz_display_init_gl (GdkDisplay *display)
+{
+ return TRUE;
+}
+
GdkGLContext *
gdk_quartz_window_create_gl_context (GdkWindow *window,
gboolean attached,
GdkGLContext *share,
GError **error)
{
- /* FIXME: implement */
- g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE,
- _("Not implemented on OS X"));
- return NULL;
+ GdkDisplay *display = gdk_window_get_display (window);
+ GdkQuartzGLContext *context;
+ NSOpenGLContext *ctx;
+ NSOpenGLPixelFormatAttribute attrs[] =
+ {
+ kCGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
+ NSOpenGLPFADoubleBuffer,
+ NSOpenGLPFAColorSize, 24,
+ NSOpenGLPFAAlphaSize, 8,
+ 0
+ };
+ NSOpenGLPixelFormat* format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
+
+ if (format == NULL)
+ {
+ g_set_error_literal (error, GDK_GL_ERROR,
+ GDK_GL_ERROR_NOT_AVAILABLE,
+ _("Unable to create a GL pixel format"));
+ return NULL;
+ }
+
+ ctx = [[NSOpenGLContext alloc] initWithFormat:format
+ shareContext:share ? GDK_QUARTZ_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"));
+ return NULL;
+ }
+
+ [format release];
+
+ if (attached)
+ {
+ NSView *view = gdk_quartz_window_get_nsview(window);
+
+ if ([view respondsToSelector:@selector(setWantsBestResolutionOpenGLSurface:)])
+ [view setWantsBestResolutionOpenGLSurface:YES];
+
+ GLint sync_to_framerate = 1;
+ [ctx setValues:&sync_to_framerate forParameter:NSOpenGLCPSwapInterval];
+
+ [ctx setView:view];
+ }
+
+ GDK_NOTE (OPENGL,
+ g_print ("Created NSOpenGLContext[%p]\n", ctx));
+
+ context = g_object_new (GDK_TYPE_QUARTZ_GL_CONTEXT,
+ "window", window,
+ "display", display,
+ "shared-context", share,
+ NULL);
+
+ context->gl_context = ctx;
+ context->is_attached = attached;
+
+ return GDK_GL_CONTEXT (context);
+}
+
+static void
+gdk_quartz_gl_context_dispose (GObject *gobject)
+{
+ GdkQuartzGLContext *context_quartz = GDK_QUARTZ_GL_CONTEXT (gobject);
+
+ if (context_quartz->gl_context != NULL)
+ {
+ [context_quartz->gl_context clearDrawable];
+ [context_quartz->gl_context release];
+ context_quartz->gl_context = NULL;
+ }
+
+ G_OBJECT_CLASS (gdk_quartz_gl_context_parent_class)->dispose (gobject);
+}
+
+gboolean
+gdk_quartz_display_make_gl_context_current (GdkDisplay *display,
+ GdkGLContext *context)
+{
+ GdkQuartzGLContext *context_quartz;
+
+ if (context == NULL)
+ {
+ [NSOpenGLContext clearCurrentContext];
+ return TRUE;
+ }
+
+ context_quartz = GDK_QUARTZ_GL_CONTEXT (context);
+
+ [context_quartz->gl_context makeCurrentContext];
+
+ return TRUE;
}
diff --git a/gdk/quartz/gdkglcontext-quartz.h b/gdk/quartz/gdkglcontext-quartz.h
index bc55a57032..b9e5e74dea 100644
--- a/gdk/quartz/gdkglcontext-quartz.h
+++ b/gdk/quartz/gdkglcontext-quartz.h
@@ -24,17 +24,40 @@
#define __GDK_QUARTZ_GL_CONTEXT__
#include "gdkglcontextprivate.h"
+#include "gdkdisplayprivate.h"
#include "gdkvisual.h"
#include "gdkwindow.h"
#include "gdkinternals.h"
#include "gdkmain.h"
+#import <OpenGL/OpenGL.h>
+#import <OpenGL/gl.h>
+#import <AppKit/AppKit.h>
+
G_BEGIN_DECLS
+struct _GdkQuartzGLContext
+{
+ GdkGLContext parent_instance;
+
+ NSOpenGLContext *gl_context;
+ gboolean is_attached;
+};
+
+struct _GdkQuartzGLContextClass
+{
+ GdkGLContextClass parent_class;
+};
+
+gboolean gdk_quartz_display_init_gl (GdkDisplay *display);
GdkGLContext * gdk_quartz_window_create_gl_context (GdkWindow *window,
gboolean attach,
GdkGLContext *share,
GError **error);
+void gdk_quartz_window_invalidate_for_new_frame (GdkWindow *window,
+ cairo_region_t *update_area);
+gboolean gdk_quartz_display_make_gl_context_current (GdkDisplay *display,
+ GdkGLContext *context);
G_END_DECLS
diff --git a/gdk/quartz/gdkquartzglcontext.h b/gdk/quartz/gdkquartzglcontext.h
new file mode 100644
index 0000000000..2839bea4c6
--- /dev/null
+++ b/gdk/quartz/gdkquartzglcontext.h
@@ -0,0 +1,45 @@
+/* GDK - The GIMP Drawing Kit
+ *
+ * gdkquartzglcontext.h: Quartz specific OpenGL wrappers
+ *
+ * Copyright © 2014 Emmanuele Bassi
+ * Copyright © 2014 Brion Vibber
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GDK_QUARTZ_GL_CONTEXT_H__
+#define __GDK_QUARTZ_GL_CONTEXT_H__
+
+#if !defined (__GDKQUARTZ_H_INSIDE__) && !defined (GDK_COMPILATION)
+#error "Only <gdk/gdkquartz.h> can be included directly."
+#endif
+
+#include <gdk/gdk.h>
+
+G_BEGIN_DECLS
+
+#define GDK_TYPE_QUARTZ_GL_CONTEXT (gdk_quartz_gl_context_get_type ())
+#define GDK_QUARTZ_GL_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_QUARTZ_GL_CONTEXT, GdkQuartzGLContext))
+#define GDK_QUARTZ_IS_GL_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_QUARTZ_GL_CONTEXT))
+
+typedef struct _GdkQuartzGLContext GdkQuartzGLContext;
+typedef struct _GdkQuartzGLContextClass GdkQuartzGLContextClass;
+
+GDK_AVAILABLE_IN_3_22
+GType gdk_quartz_gl_context_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __GDK_QUARTZ_GL_CONTEXT_H__ */
diff --git a/gdk/quartz/gdkwindow-quartz.c b/gdk/quartz/gdkwindow-quartz.c
index 4ffbae047d..873fb992e8 100644
--- a/gdk/quartz/gdkwindow-quartz.c
+++ b/gdk/quartz/gdkwindow-quartz.c
@@ -3024,6 +3024,7 @@ gdk_window_impl_quartz_class_init (GdkWindowImplQuartzClass *klass)
impl_class->delete_property = _gdk_quartz_window_delete_property;
impl_class->create_gl_context = gdk_quartz_window_create_gl_context;
+ impl_class->invalidate_for_new_frame = gdk_quartz_window_invalidate_for_new_frame;
impl_quartz_class->get_context = gdk_window_impl_quartz_get_context;
impl_quartz_class->release_context = gdk_window_impl_quartz_release_context;