From 029a2e8ab09d5ba7fd17100c5ed15a7deb0934f8 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Tue, 1 Oct 2013 17:11:53 +0300 Subject: [PATCH] Add OpenGL context support on OS X --- Build | 4 ++ source/graphics/cgl/cocoaglcontext.h | 24 ++++++++ source/graphics/cgl/cocoaglcontext.m | 46 ++++++++++++++ source/graphics/cgl/cocoapixelformat.h | 28 +++++++++ source/graphics/cgl/cocoapixelformat.m | 31 ++++++++++ source/graphics/cgl/glcontext.cpp | 83 ++++++++++++++++++++++++++ 6 files changed, 216 insertions(+) create mode 100644 source/graphics/cgl/cocoaglcontext.h create mode 100644 source/graphics/cgl/cocoaglcontext.m create mode 100644 source/graphics/cgl/cocoapixelformat.h create mode 100644 source/graphics/cgl/cocoapixelformat.m create mode 100644 source/graphics/cgl/glcontext.cpp diff --git a/Build b/Build index 9e564ff..0eac10a 100644 --- a/Build +++ b/Build @@ -82,6 +82,10 @@ package "mspgui" if_arch "darwin" { overlay "cocoa"; + if_feature "opengl" + { + overlay "cgl"; + }; }; if_arch "!windows" { diff --git a/source/graphics/cgl/cocoaglcontext.h b/source/graphics/cgl/cocoaglcontext.h new file mode 100644 index 0000000..4a1fcca --- /dev/null +++ b/source/graphics/cgl/cocoaglcontext.h @@ -0,0 +1,24 @@ +#ifndef MSP_GRAPHICS_COCOAGLCONTEXT_H_ +#define MSP_GRAPHICS_COCOAGLCONTEXT_H_ + +#include "cocoapixelformat.h" +#include "cocoawindow.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct _CocoaGLContext; +typedef struct _CocoaGLContext CocoaGLContext; + +CocoaGLContext *create_gl_context(CocoaPixelFormat *); +void destroy_gl_context(CocoaGLContext *); +void attach_gl_context_to_window(CocoaGLContext *, CocoaWindow *); +void make_gl_context_current(CocoaGLContext *); +void flush_gl_buffer(CocoaGLContext *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/graphics/cgl/cocoaglcontext.m b/source/graphics/cgl/cocoaglcontext.m new file mode 100644 index 0000000..7bd8056 --- /dev/null +++ b/source/graphics/cgl/cocoaglcontext.m @@ -0,0 +1,46 @@ +#import +#import +#include +#include "cocoaglcontext.h" + +NSOpenGLPixelFormat *get_native_pixel_format(CocoaPixelFormat *); +NSWindow *get_native_window(CocoaWindow *); + +struct _CocoaGLContext +{ + NSOpenGLContext *context; +}; + +CocoaGLContext *create_gl_context(CocoaPixelFormat *format) +{ + NSOpenGLContext *ctx = [NSOpenGLContext alloc]; + ctx = [ctx initWithFormat:get_native_pixel_format(format) shareContext:nil]; + if(!ctx) + return NULL; + + CocoaGLContext *wrapper = (CocoaGLContext *)malloc(sizeof(CocoaGLContext)); + wrapper->context = ctx; + return wrapper; +} + +void destroy_gl_context(CocoaGLContext *context) +{ + [context->context release]; + free(context); +} + +void attach_gl_context_to_window(CocoaGLContext *context, CocoaWindow *window) +{ + NSWindow *nswindow = get_native_window(window); + [context->context setView:[nswindow contentView]]; +} + +void make_gl_context_current(CocoaGLContext *context) +{ + [context->context makeCurrentContext]; +} + +void flush_gl_buffer(CocoaGLContext *context) +{ + [context->context flushBuffer]; +} diff --git a/source/graphics/cgl/cocoapixelformat.h b/source/graphics/cgl/cocoapixelformat.h new file mode 100644 index 0000000..9748bcd --- /dev/null +++ b/source/graphics/cgl/cocoapixelformat.h @@ -0,0 +1,28 @@ +#ifndef MSP_GRAPHICS_COCOAPIXELFORMAT_H_ +#define MSP_GRAPHICS_COCOAPIXELFORMAT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +enum +{ + CPF_DOUBLEBUFFER = 5, + CPF_ALPHA_SIZE = 11, + CPF_DEPTH_SIZE = 12, + CPF_STENCIL_SIZE = 13, + CPF_SAMPLE_BUFFERS = 55, + CPF_SAMPLES = 56 +}; + +struct _CocoaPixelFormat; +typedef struct _CocoaPixelFormat CocoaPixelFormat; + +CocoaPixelFormat *choose_pixel_format(unsigned *); +void destroy_pixel_format(CocoaPixelFormat *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/graphics/cgl/cocoapixelformat.m b/source/graphics/cgl/cocoapixelformat.m new file mode 100644 index 0000000..1f06f04 --- /dev/null +++ b/source/graphics/cgl/cocoapixelformat.m @@ -0,0 +1,31 @@ +#import +#include +#include "cocoapixelformat.h" + +struct _CocoaPixelFormat +{ + NSOpenGLPixelFormat *format; +}; + +CocoaPixelFormat *choose_pixel_format(unsigned *attribs) +{ + NSOpenGLPixelFormat *format = [NSOpenGLPixelFormat alloc]; + format = [format initWithAttributes:attribs]; + if(!format) + return NULL; + + CocoaPixelFormat *wrapper = (CocoaPixelFormat *)malloc(sizeof(CocoaPixelFormat)); + wrapper->format = format; + return wrapper; +} + +void destroy_pixel_format(CocoaPixelFormat *format) +{ + [format->format release]; + free(format); +} + +NSOpenGLPixelFormat *get_native_pixel_format(CocoaPixelFormat *format) +{ + return format->format; +} diff --git a/source/graphics/cgl/glcontext.cpp b/source/graphics/cgl/glcontext.cpp new file mode 100644 index 0000000..94b9b2f --- /dev/null +++ b/source/graphics/cgl/glcontext.cpp @@ -0,0 +1,83 @@ +#include +#include +#include "cocoaglcontext.h" +#include "cocoapixelformat.h" +#include "glcontext.h" +#include "window_private.h" + +using namespace std; + +namespace Msp { +namespace Graphics { + +typedef CocoaGLContext *ContextHandle; + +struct GLContext::Private +{ + ContextHandle context; +}; + +void GLContext::platform_init(const GLOptions &opts) +{ + priv = new Private; + + vector attribs; + + attribs.push_back(CPF_DEPTH_SIZE); + attribs.push_back(1); + + if(opts.alpha) + { + attribs.push_back(CPF_ALPHA_SIZE); + attribs.push_back(1); + } + + if(opts.stencil) + { + attribs.push_back(CPF_STENCIL_SIZE); + attribs.push_back(1); + } + + if(opts.doublebuffer) + attribs.push_back(CPF_DOUBLEBUFFER); + + if(opts.multisample>0) + { + attribs.push_back(CPF_SAMPLE_BUFFERS); + attribs.push_back(1); + attribs.push_back(CPF_SAMPLES); + attribs.push_back(opts.multisample); + } + + attribs.push_back(0); + + CocoaPixelFormat *pixfmt = choose_pixel_format(&attribs.front()); + if(!pixfmt) + throw unsupported_gl_mode(opts); + + priv->context = create_gl_context(pixfmt); + destroy_pixel_format(pixfmt); + + attach_gl_context_to_window(priv->context, window.get_private().window); + make_gl_context_current(priv->context); +} + +GLContext::~GLContext() +{ + destroy_gl_context(priv->context); + delete priv; +} + +void GLContext::swap_buffers() +{ + flush_gl_buffer(priv->context); +} + +void GLContext::window_resized(unsigned w, unsigned h) +{ + // XXX Call [context update] here? + glViewport(0, 0, w, h); +} + +} // namespace Graphics +} // namespace Msp -- 2.45.2