summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Bragg <robert@linux.intel.com>2012-01-16 11:32:28 +0000
committerRobert Bragg <robert@linux.intel.com>2012-01-16 11:32:28 +0000
commitb6b29aa310a2de8013de0b4458d3765145cbcbec (patch)
treef3f9ee8653df8609f5a3df3491ff67495adc7dcb
parent83b7ff8bdcc66bd467df671898b1eed5f9d72543 (diff)
downloadcogl-wip/osx.tar.gz
stash: Adds initial osx backendwip/osx
-rw-r--r--cogl/Makefile.am7
-rw-r--r--cogl/cogl-renderer.c6
-rw-r--r--cogl/cogl-renderer.h1
-rw-r--r--cogl/winsys/cogl-winsys-osx.m470
-rw-r--r--configure.ac35
5 files changed, 516 insertions, 3 deletions
diff --git a/cogl/Makefile.am b/cogl/Makefile.am
index 0c223b86..288ef521 100644
--- a/cogl/Makefile.am
+++ b/cogl/Makefile.am
@@ -34,6 +34,8 @@ AM_CPPFLAGS = \
AM_CFLAGS = $(COGL_DEP_CFLAGS) $(COGL_EXTRA_CFLAGS) $(MAINTAINER_CFLAGS)
+AM_OBJCFLAGS= $(COGL_OBJCFLAGS) $(COGL_DEP_CFLAGS) $(COGL_EXTRA_CFLAGS) $(MAINTAINER_CFLAGS)
+
BUILT_SOURCES += cogl-defines.h
DISTCLEANFILES += cogl-defines.h
EXTRA_DIST += cogl-defines.h.in
@@ -432,6 +434,11 @@ cogl_sources_c += \
$(srcdir)/winsys/cogl-winsys-sdl.c
endif
+if OS_OSX
+cogl_sources_c += \
+ $(srcdir)/winsys/cogl-winsys-osx.m
+endif
+
EXTRA_DIST += stb_image.c
# glib-mkenums rules
diff --git a/cogl/cogl-renderer.c b/cogl/cogl-renderer.c
index 1a01b594..55b5cb08 100644
--- a/cogl/cogl-renderer.c
+++ b/cogl/cogl-renderer.c
@@ -77,6 +77,9 @@ extern const CoglWinsysVtable *_cogl_winsys_wgl_get_vtable (void);
#ifdef COGL_HAS_SDL_SUPPORT
extern const CoglWinsysVtable *_cogl_winsys_sdl_get_vtable (void);
#endif
+#ifdef COGL_HAS_OSX_SUPPORT
+extern const CoglWinsysVtable *_cogl_winsys_osx_get_vtable (void);
+#endif
typedef const CoglWinsysVtable *(*CoglWinsysVtableGetter) (void);
@@ -109,6 +112,9 @@ static CoglWinsysVtableGetter _cogl_winsys_vtable_getters[] =
#ifdef COGL_HAS_SDL_SUPPORT
_cogl_winsys_sdl_get_vtable,
#endif
+#ifdef COGL_HAS_OSX_SUPPORT
+ _cogl_winsys_osx_get_vtable,
+#endif
_cogl_winsys_stub_get_vtable,
};
diff --git a/cogl/cogl-renderer.h b/cogl/cogl-renderer.h
index 94d4de9d..d7f0768a 100644
--- a/cogl/cogl-renderer.h
+++ b/cogl/cogl-renderer.h
@@ -72,6 +72,7 @@ cogl_renderer_new (void);
* @COGL_WINSYS_ID_EGL_ANDROID: Use EGL with the Android platform
* @COGL_WINSYS_ID_WGL: Use the Microsoft Windows WGL binding API
* @COGL_WINSYS_ID_SDL: Use the SDL window system
+ * @COGL_WINSYS_ID_OSX: Use the OSX window system
*
* Identifies specific window system backends that Cogl supports.
*
diff --git a/cogl/winsys/cogl-winsys-osx.m b/cogl/winsys/cogl-winsys-osx.m
new file mode 100644
index 00000000..6ebaf871
--- /dev/null
+++ b/cogl/winsys/cogl-winsys-osx.m
@@ -0,0 +1,470 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * Copyright (C) 2011 Intel Corporation.
+ *
+ * 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/>.
+ *
+ *
+ * Authors:
+ * Neil Roberts <neil@linux.intel.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "cogl-renderer-private.h"
+#include "cogl-display-private.h"
+#include "cogl-framebuffer-private.h"
+#include "cogl-swap-chain-private.h"
+#include "cogl-onscreen-template-private.h"
+#include "cogl-context-private.h"
+#include "cogl-onscreen-private.h"
+
+#import <AppKit/AppKit.h>
+
+/* might need this */
+#if 0
+@class NSOpenGLPixelFormat, NSOpenGLContext;
+#endif
+
+typedef struct _CoglRendererOSX
+{
+ int stub;
+} CoglRendererOSX;
+
+typedef struct _CoglDisplayOSX
+{
+ NSOpenGLPixelFormat *ns_pixel_format;
+ NSOpenGLView *ns_dummy_view;
+ NSWindow *ns_dummy_window;
+ NSOpenGLContext *ns_context;
+} CoglDisplayOSX;
+
+typedef struct _CoglOnscreenOSX
+{
+ NSOpenGLPixelFormat *ns_pixel_format;
+ NSOpenGLView *ns_view;
+ NSWindow *ns_window;
+} CoglOnscreenOSX;
+
+#if 0
+@interface CoglOSXOpenGLView : NSOpenGLView
+{
+ CoglOnscreen *onscreen;
+}
+- (id) initWithContext: (CoglContext *) context: (int) width: (int) height;
+//- (void) drawRect: (NSRect) bounds;
+@end
+#endif
+
+static CoglFuncPtr
+_cogl_winsys_renderer_get_proc_address (CoglRenderer *renderer,
+ const char *name)
+{
+ static GModule *module = NULL;
+
+ /* this should find the right function if the program is linked against a
+ * library providing it */
+ if (G_UNLIKELY (module == NULL))
+ module = g_module_open (NULL, 0);
+
+ if (module)
+ {
+ void *symbol;
+
+ if (g_module_symbol (module, name, &symbol))
+ return symbol;
+ }
+
+ return NULL;
+}
+
+static void
+_cogl_winsys_renderer_disconnect (CoglRenderer *renderer)
+{
+ g_slice_free (CoglRendererOSX, renderer->winsys);
+}
+
+static gboolean
+_cogl_winsys_renderer_connect (CoglRenderer *renderer,
+ GError **error)
+{
+ NSAutoreleasePool *autorelease_pool = [[NSAutoreleasePool alloc] init];
+ NSApplication *myApplication;
+
+ /* XXX: Hack to trick gnustep into initializing its backend including the
+ * GSDisplayServer which we require to access GLX. */
+ if (!NSApp)
+ myApplication = [NSApplication sharedApplication];
+
+ [autorelease_pool release];
+
+ if (renderer->driver != COGL_DRIVER_GL)
+ {
+ g_set_error (error, COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_INIT,
+ "The OSX winsys only supports the GL driver");
+ return FALSE;
+ }
+
+ renderer->winsys = g_slice_new0 (CoglRendererOSX);
+ return TRUE;
+}
+
+static void
+_cogl_winsys_display_destroy (CoglDisplay *display)
+{
+ CoglDisplayOSX *ns_display = display->winsys;
+
+ _COGL_RETURN_IF_FAIL (ns_display != NULL);
+
+ if (ns_display->ns_context)
+ [ns_display->ns_context release];
+
+ if (ns_display->ns_pixel_format)
+ [ns_display->ns_pixel_format release];
+
+ g_slice_free (CoglDisplayOSX, display->winsys);
+ display->winsys = NULL;
+}
+
+#define MAX_PIXEL_FORMAT_ATTRIBS 30
+
+static NSOpenGLPixelFormat *
+ns_pixel_format_from_framebuffer_config (CoglFramebufferConfig *config)
+{
+ NSOpenGLPixelFormatAttribute attrs[MAX_PIXEL_FORMAT_ATTRIBS];
+ int i = 0;
+
+ attrs[i++] = NSOpenGLPFAMinimumPolicy;
+
+ if (config->swap_chain->length >= 1)
+ attrs[i++] = NSOpenGLPFADoubleBuffer;
+
+ if (config->need_stencil)
+ {
+ attrs[i++] = NSOpenGLPFAStencilSize;
+ attrs[i++] = 8;
+ }
+
+ if (config->swap_chain->has_alpha)
+ {
+ attrs[i++] = NSOpenGLPFAAlphaSize;
+ attrs[i++] = 1;
+ }
+
+ attrs[i++] = NSOpenGLPFADepthSize;
+ attrs[i++] = 24;
+
+ if (config->samples_per_pixel)
+ {
+ attrs[i++] = NSOpenGLPFAMultisample;
+ attrs[i++] = NSOpenGLPFASampleBuffers;
+ attrs[i++] = 1;
+ attrs[i++] = NSOpenGLPFASamples;
+ attrs[i++] = config->samples_per_pixel;
+ }
+
+ attrs[i++] = 0;
+
+ g_assert (i < MAX_PIXEL_FORMAT_ATTRIBS);
+
+ return [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
+}
+
+static gboolean
+create_context (CoglDisplay *display,
+ GError **error)
+{
+ CoglDisplayOSX *ns_display = display->winsys;
+ CoglFramebufferConfig *config;
+#ifndef USING_GNUSTEP
+ const long sw = 1;
+#endif
+ gboolean status = TRUE;
+ NSRect rect;
+
+ NSAutoreleasePool *autorelease_pool = [[NSAutoreleasePool alloc] init];
+
+ config = &display->onscreen_template->config;
+ ns_display->ns_pixel_format =
+ ns_pixel_format_from_framebuffer_config (config);
+ if (!ns_display->ns_pixel_format)
+ {
+ g_set_error (error, COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_CREATE_CONTEXT,
+ "Unable to find suitable GL pixel format");
+ status = FALSE;
+ goto done;
+ }
+
+ config = &display->onscreen_template->config;
+ ns_display->ns_context =
+ [[NSOpenGLContext alloc] initWithFormat: ns_display->ns_pixel_format
+ shareContext: nil];
+ if (!ns_display->ns_context)
+ {
+ g_set_error (error, COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_CREATE_CONTEXT,
+ "Unable to create suitable GL context");
+ status = FALSE;
+ goto done;
+ }
+
+#ifndef USING_GNUSTEP
+ /* Enable vblank sync - http://developer.apple.com/qa/qa2007/qa1521.html */
+ [ns_display->ns_context setValues:&sw forParameter: NSOpenGLCPSwapInterval];
+#endif
+
+ rect = NSMakeRect (0, 0, 1, 1);
+
+ ns_display->ns_dummy_view = [[NSOpenGLView alloc]
+ initWithFrame: rect
+ pixelFormat: ns_display->ns_pixel_format];
+ if (!ns_display->ns_dummy_view)
+ {
+ g_set_error (error, COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_CREATE_ONSCREEN,
+ "Unable to create suitable NSView");
+ status = FALSE;
+ goto done;
+ }
+
+ ns_display->ns_dummy_window = [[NSWindow alloc]
+ initWithContentRect: [ns_display->ns_dummy_view frame]
+ styleMask: NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask
+ backing: NSBackingStoreBuffered
+ defer: NO];
+ if (!ns_display->ns_dummy_window)
+ {
+ g_set_error (error, COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_CREATE_ONSCREEN,
+ "Unable to create suitable NSWindow");
+ status = FALSE;
+ goto done;
+ }
+ [ns_display->ns_dummy_window setContentView:ns_display->ns_dummy_view];
+ [ns_display->ns_dummy_window useOptimizedDrawing:YES];
+
+ [ns_display->ns_dummy_view setOpenGLContext:ns_display->ns_context];
+
+ [ns_display->ns_context setView: ns_display->ns_dummy_view];
+ [ns_display->ns_context makeCurrentContext];
+
+done:
+ [autorelease_pool release];
+ return status;
+}
+
+static gboolean
+_cogl_winsys_display_setup (CoglDisplay *display,
+ GError **error)
+{
+ CoglDisplayOSX *ns_display;
+
+ _COGL_RETURN_VAL_IF_FAIL (display->winsys == NULL, FALSE);
+
+ ns_display = g_slice_new0 (CoglDisplayOSX);
+ display->winsys = ns_display;
+
+ if (!create_context (display, error))
+ goto error;
+
+ return TRUE;
+error:
+ _cogl_winsys_display_destroy (display);
+ return FALSE;
+}
+
+static gboolean
+_cogl_winsys_context_init (CoglContext *context, GError **error)
+{
+ return _cogl_context_update_features (context, error);
+}
+
+static void
+_cogl_winsys_context_deinit (CoglContext *context)
+{
+}
+
+static void
+_cogl_winsys_onscreen_bind (CoglOnscreen *onscreen)
+{
+ CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
+ CoglDisplay *display = context->display;
+ CoglDisplayOSX *ns_display = display->winsys;
+ CoglOnscreenOSX *ns_onscreen = onscreen->winsys;
+
+ NSAutoreleasePool *autorelease_pool = [[NSAutoreleasePool alloc] init];
+
+ [ns_display->ns_context setView: ns_onscreen->ns_view];
+
+ [autorelease_pool release];
+}
+
+static void
+_cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen)
+{
+}
+
+static gboolean
+_cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
+ GError **error)
+{
+ CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
+ CoglContext *context = framebuffer->context;
+ CoglDisplay *display = context->display;
+ CoglDisplayOSX *ns_display = display->winsys;
+ CoglOnscreenOSX *ns_onscreen;
+ int width, height;
+ NSRect rect;
+ gboolean status = TRUE;
+
+ NSAutoreleasePool *autorelease_pool = [[NSAutoreleasePool alloc] init];
+
+ ns_onscreen = g_slice_new0 (CoglOnscreenOSX);
+ onscreen->winsys = ns_onscreen;
+
+ ns_onscreen->ns_pixel_format =
+ ns_pixel_format_from_framebuffer_config (&framebuffer->config);
+ if (!ns_onscreen->ns_pixel_format)
+ {
+ g_set_error (error, COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_CREATE_ONSCREEN,
+ "Unable to create suitable NSOpenGLPixelFormat");
+ status = FALSE;
+ goto done;
+ }
+
+ width = cogl_framebuffer_get_width (framebuffer);
+ height = cogl_framebuffer_get_height (framebuffer);
+
+ rect = NSMakeRect (0, 0, width, height);
+
+ ns_onscreen->ns_view = [[NSOpenGLView alloc]
+ initWithFrame: rect
+ pixelFormat: ns_onscreen->ns_pixel_format];
+ if (!ns_onscreen->ns_view)
+ {
+ g_set_error (error, COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_CREATE_ONSCREEN,
+ "Unable to create suitable NSView");
+ status = FALSE;
+ goto done;
+ }
+ [ns_onscreen->ns_view setOpenGLContext:ns_display->ns_context];
+
+ ns_onscreen->ns_window = [[NSWindow alloc]
+ initWithContentRect: [ns_onscreen->ns_view frame]
+ styleMask: NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask
+ backing: NSBackingStoreBuffered
+ defer: NO];
+ if (!ns_onscreen->ns_window)
+ {
+ g_set_error (error, COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_CREATE_ONSCREEN,
+ "Unable to create suitable NSWindow");
+ status = FALSE;
+ goto done;
+ }
+
+ [ns_onscreen->ns_window setContentView:ns_onscreen->ns_view];
+ [ns_onscreen->ns_window useOptimizedDrawing:YES];
+
+ //[ns_onscreen->ns_view setOpenGLContext:ns_display->ns_context];
+#if 0
+
+ [ns_display->ns_context setView: ns_onscreen->ns_view];
+ [ns_display->ns_context makeCurrentContext];
+#endif
+
+done:
+ [autorelease_pool release];
+ return status;
+}
+
+static void
+_cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
+{
+ CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
+ CoglDisplay *display = context->display;
+ CoglDisplayOSX *ns_display = display->winsys;
+
+ [ns_display->ns_context flushBuffer];
+}
+
+static void
+_cogl_winsys_onscreen_update_swap_throttled (CoglOnscreen *onscreen)
+{
+ /* OSX doesn't appear to provide a way to set this per window */
+}
+
+static void
+_cogl_winsys_onscreen_set_visibility (CoglOnscreen *onscreen,
+ gboolean visibility)
+{
+ CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
+ CoglDisplay *display = context->display;
+ CoglDisplayOSX *ns_display = display->winsys;
+ CoglOnscreenOSX *ns_onscreen = onscreen->winsys;
+
+ NSAutoreleasePool *autorelease_pool = [[NSAutoreleasePool alloc] init];
+ if (visibility)
+ [ns_onscreen->ns_window makeKeyAndOrderFront: nil];
+ else
+ [ns_onscreen->ns_window orderOut: nil];
+
+ /* XXX: HACK */
+ [ns_display->ns_context setView: ns_onscreen->ns_view];
+ [ns_display->ns_context makeCurrentContext];
+
+ [autorelease_pool release];
+}
+
+const CoglWinsysVtable *
+_cogl_winsys_osx_get_vtable (void)
+{
+ static gboolean vtable_inited = FALSE;
+ static CoglWinsysVtable vtable;
+
+ if (!vtable_inited)
+ {
+ memset (&vtable, 0, sizeof (vtable));
+
+ vtable.id = COGL_WINSYS_ID_SDL;
+ vtable.name = "OSX";
+ vtable.renderer_get_proc_address = _cogl_winsys_renderer_get_proc_address;
+ vtable.renderer_connect = _cogl_winsys_renderer_connect;
+ vtable.renderer_disconnect = _cogl_winsys_renderer_disconnect;
+ vtable.display_setup = _cogl_winsys_display_setup;
+ vtable.display_destroy = _cogl_winsys_display_destroy;
+ vtable.context_init = _cogl_winsys_context_init;
+ vtable.context_deinit = _cogl_winsys_context_deinit;
+ vtable.onscreen_init = _cogl_winsys_onscreen_init;
+ vtable.onscreen_deinit = _cogl_winsys_onscreen_deinit;
+ vtable.onscreen_bind = _cogl_winsys_onscreen_bind;
+ vtable.onscreen_swap_buffers = _cogl_winsys_onscreen_swap_buffers;
+ vtable.onscreen_update_swap_throttled =
+ _cogl_winsys_onscreen_update_swap_throttled;
+ vtable.onscreen_set_visibility = _cogl_winsys_onscreen_set_visibility;
+
+ vtable_inited = TRUE;
+ }
+
+ return &vtable;
+}
diff --git a/configure.ac b/configure.ac
index 755cb5f2..877850cb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -159,8 +159,7 @@ AS_CASE([$host],
AC_MSG_RESULT([$platform_win32])
AM_CONDITIONAL(OS_WIN32, [test "$platform_win32" = "yes"])
-AC_CHECK_HEADER([OpenGL/gl.h], [platform_quartz=yes], [platform_quartz=no])
-AM_CONDITIONAL(OS_QUARTZ, [test "$platform_quartz" = "yes"])
+AC_CHECK_HEADER([OpenGL/gl.h], [platform_osx=yes], [platform_osx=no])
dnl ================================================================
dnl Handle extra configure options
@@ -318,6 +317,26 @@ AS_CASE([$enable_deprecated],
# strip leading spaces
COGL_EXTRA_CFLAGS="$COGL_EXTRA_CFLAGS ${DEPRECATED_CFLAGS#* }"
+COGL_OBJCFLAGS=""
+AC_ARG_ENABLE(
+ [osx],
+ [AC_HELP_STRING([--enable-osx=@<:@no/yes@:>@], [Enable the osx winsys (also works with gnustep) @<:@default=auto@:>@])],
+ [platform_osx=$enable_osx],
+)
+if test "x$platform_osx" = "xyes"; then
+ AC_CHECK_PROG(platform_gnustep, gnustep-config, yes, no)
+ AC_PROG_OBJC
+ COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_OSX_SUPPORT"
+ GL_WINSYS_APIS="$GL_WINSYS_APIS osx"
+fi
+if test "x$platform_gnustep" = "xyes"; then
+ COGL_OBJCFLAGS=`gnustep-config --objc-flags`
+ COGL_EXTRA_LDFLAGS="$COGL_EXTRA_LDFLAGS `gnustep-config --gui-libs`"
+ AC_DEFINE([USING_GNUSTEP], 1, [Using the gnustep build environment])
+fi
+AM_CONDITIONAL(OS_OSX, [test "$platform_osx" = "yes"])
+AC_SUBST(COGL_OBJCFLAGS)
+
dnl ============================================================
dnl Choose image loading backend
dnl ============================================================
@@ -565,7 +584,7 @@ AS_IF([test "x$enable_gl" = "xyes"],
cogl_gl_headers="GL/gl.h"
- AS_IF([test "x$platform_quartz" = "xyes"],
+ AS_IF([test "x$platform_osx" = "xyes" -a "x$platform_gnustep" != "xyes"],
[
cogl_gl_headers="OpenGL/gl.h"
COGL_EXTRA_LDFLAGS="$COGL_EXTRA_LDFLAGS -framework OpenGL"
@@ -573,6 +592,16 @@ AS_IF([test "x$enable_gl" = "xyes"],
dnl no need to dlopen it separately
GL_LIBRARY_DIRECTLY_LINKED=yes
COGL_GL_LIBNAME=""
+ ALLOW_GLX=no
+ ],
+
+ [test "x$platform_gnustep" = "xyes"],
+ [
+ COGL_EXTRA_LDFLAGS="$COGL_EXTRA_LDFLAGS -framework OpenGL"
+ dnl The GL API is being directly linked in so there is
+ dnl no need to dlopen it separately
+ GL_LIBRARY_DIRECTLY_LINKED=yes
+ COGL_GL_LIBNAME=""
],
[test "x$platform_win32" = "xyes"],