diff --git a/src/glcontext_nsgl.mm b/src/glcontext_nsgl.mm index bc31860a7..ea3912582 100644 --- a/src/glcontext_nsgl.mm +++ b/src/glcontext_nsgl.mm @@ -21,22 +21,119 @@ namespace bgfx { namespace gl struct SwapChainGL { - SwapChainGL(void* _nwh) + SwapChainGL(void* _nwh,NSOpenGLContext *_context) { - BX_UNUSED(_nwh); + NSObject* nwh=(NSObject*)_nwh; + + NSWindow* nsWindow = nil; + NSView* contentView = nil; + if ([nwh isKindOfClass:[NSView class]]) + { + contentView = (NSView*)nwh; + } + else if ([nwh isKindOfClass:[NSWindow class]]) + { + nsWindow = (NSWindow*)nwh; + contentView = [nsWindow contentView]; + } + +#if defined(MAC_OS_X_VERSION_MAX_ALLOWED) && (MAC_OS_X_VERSION_MAX_ALLOWED >= 1070) + NSOpenGLPixelFormatAttribute profile = +#if BGFX_CONFIG_RENDERER_OPENGL >= 31 + NSOpenGLProfileVersion3_2Core +#else + NSOpenGLProfileVersionLegacy +#endif // BGFX_CONFIG_RENDERER_OPENGL >= 31 + ; +#endif // defined(MAC_OS_X_VERSION_MAX_ALLOWED) && (MAC_OS_X_VERSION_MAX_ALLOWED >= 1070) + + NSOpenGLPixelFormatAttribute pixelFormatAttributes[] = { +#if defined(MAC_OS_X_VERSION_MAX_ALLOWED) && (MAC_OS_X_VERSION_MAX_ALLOWED >= 1070) + NSOpenGLPFAOpenGLProfile, profile, +#endif // defined(MAC_OS_X_VERSION_MAX_ALLOWED) && (MAC_OS_X_VERSION_MAX_ALLOWED >= 1070) + NSOpenGLPFAColorSize, 24, + NSOpenGLPFAAlphaSize, 8, + NSOpenGLPFADepthSize, 24, + NSOpenGLPFAStencilSize, 8, + NSOpenGLPFADoubleBuffer, true, + NSOpenGLPFAAccelerated, true, + NSOpenGLPFANoRecovery, true, + 0, 0, + }; + + NSOpenGLPixelFormat* pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttributes]; + BGFX_FATAL(NULL != pixelFormat, Fatal::UnableToInitialize, "Failed to initialize pixel format."); + + NSRect glViewRect = [contentView bounds]; + NSOpenGLView* glView = [[NSOpenGLView alloc] initWithFrame:glViewRect pixelFormat:pixelFormat]; + + + // GLFW creates a helper contentView that handles things like keyboard and drag and + // drop events. We don't want to clobber that view if it exists. Instead we just + // add ourselves as a subview and make the view resize automatically. + if (nil != contentView) + { + [glView setAutoresizingMask:( NSViewHeightSizable | + NSViewWidthSizable | + NSViewMinXMargin | + NSViewMaxXMargin | + NSViewMinYMargin | + NSViewMaxYMargin )]; + [contentView addSubview:glView]; + } + else + { + if (nil != nsWindow) + [nsWindow setContentView:glView]; + } + + NSOpenGLContext* glContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:_context]; + BGFX_FATAL(NULL != glContext, Fatal::UnableToInitialize, "Failed to initialize GL context."); + + void (^attachBlock)(void) = ^(void) { + [glView setOpenGLContext: glContext]; + [glContext setView:glView]; + }; + + if([NSThread isMainThread]) + { + attachBlock(); + } + else + { + dispatch_sync(dispatch_get_main_queue(),attachBlock); + } + + [pixelFormat release]; + + [glContext makeCurrentContext]; + GLint interval = 0; + [glContext setValues:&interval forParameter:NSOpenGLCPSwapInterval]; + + + m_view = glView; + m_context = glContext; } ~SwapChainGL() { + if(m_context!=nil) [m_context release]; + if(m_view!=nil) [m_view release]; } void makeCurrent() { + [m_context makeCurrentContext]; } void swapBuffers() { + [m_context makeCurrentContext]; + [m_context flushBuffer]; } + + NSOpenGLView *m_view; + NSOpenGLContext *m_context; }; class AutoreleasePoolHolder @@ -202,12 +299,13 @@ namespace bgfx { namespace gl if ([nwh respondsToSelector:@selector(backingScaleFactor)] && (1.0f < [(id)nwh backingScaleFactor])) caps |= BGFX_CAPS_HIDPI; #endif // defined(MAC_OS_X_VERSION_MAX_ALLOWED) && (MAC_OS_X_VERSION_MAX_ALLOWED >= 1070) + caps |= BGFX_CAPS_SWAP_CHAIN; return caps; } SwapChainGL* GlContext::createSwapChain(void* _nwh) { - return BX_NEW(g_allocator, SwapChainGL)(_nwh); + return BX_NEW(g_allocator, SwapChainGL)(_nwh,(NSOpenGLContext*)m_context); } void GlContext::destroySwapChain(SwapChainGL* _swapChain)