diff --git a/src/cocoa_platform.h b/src/cocoa_platform.h index 21589a69..3a1c4d26 100644 --- a/src/cocoa_platform.h +++ b/src/cocoa_platform.h @@ -109,5 +109,9 @@ void _glfwRestoreVideoMode(void); // OpenGL support int _glfwInitOpenGL(void); void _glfwTerminateOpenGL(void); +int _glfwCreateContext(_GLFWwindow* window, + const _GLFWwndconfig* wndconfig, + const _GLFWfbconfig* fbconfig); +void _glfwDestroyContext(_GLFWwindow* window); #endif // _cocoa_platform_h_ diff --git a/src/cocoa_window.m b/src/cocoa_window.m index aa28d241..fc090119 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -711,166 +711,6 @@ static GLboolean createWindow(_GLFWwindow* window, } -//======================================================================== -// Create the OpenGL context -//======================================================================== - -static GLboolean createContext(_GLFWwindow* window, - const _GLFWwndconfig* wndconfig, - const _GLFWfbconfig* fbconfig) -{ - unsigned int attributeCount = 0; - - // Mac OS X needs non-zero color size, so set resonable values - int colorBits = fbconfig->redBits + fbconfig->greenBits + fbconfig->blueBits; - if (colorBits == 0) - colorBits = 24; - else if (colorBits < 15) - colorBits = 15; - - if (wndconfig->clientAPI == GLFW_OPENGL_ES_API) - { - _glfwSetError(GLFW_VERSION_UNAVAILABLE, - "NSOpenGL: This API does not support OpenGL ES"); - return GL_FALSE; - } - -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 - // Fail if any OpenGL version above 2.1 other than 3.2 was requested - if (wndconfig->glMajor > 3 || - (wndconfig->glMajor == 3 && wndconfig->glMinor != 2)) - { - _glfwSetError(GLFW_VERSION_UNAVAILABLE, - "NSOpenGL: The targeted version of Mac OS X does not " - "support any OpenGL version above 2.1 except 3.2"); - return GL_FALSE; - } - - if (wndconfig->glMajor > 2) - { - if (!wndconfig->glForward) - { - _glfwSetError(GLFW_VERSION_UNAVAILABLE, - "NSOpenGL: The targeted version of Mac OS X only " - "supports OpenGL 3.2 contexts if they are " - "forward-compatible"); - return GL_FALSE; - } - - if (wndconfig->glProfile != GLFW_OPENGL_CORE_PROFILE) - { - _glfwSetError(GLFW_VERSION_UNAVAILABLE, - "NSOpenGL: The targeted version of Mac OS X only " - "supports OpenGL 3.2 contexts if they use the " - "core profile"); - return GL_FALSE; - } - } -#else - // Fail if OpenGL 3.0 or above was requested - if (wndconfig->glMajor > 2) - { - _glfwSetError(GLFW_VERSION_UNAVAILABLE, - "NSOpenGL: The targeted version of Mac OS X does not " - "support OpenGL version 3.0 or above"); - return GL_FALSE; - } -#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/ - - // Fail if a robustness strategy was requested - if (wndconfig->glRobustness) - { - _glfwSetError(GLFW_VERSION_UNAVAILABLE, - "NSOpenGL: Mac OS X does not support OpenGL robustness " - "strategies"); - return GL_FALSE; - } - -#define ADD_ATTR(x) { attributes[attributeCount++] = x; } -#define ADD_ATTR2(x, y) { ADD_ATTR(x); ADD_ATTR(y); } - - // Arbitrary array size here - NSOpenGLPixelFormatAttribute attributes[40]; - - ADD_ATTR(NSOpenGLPFADoubleBuffer); - - if (wndconfig->mode == GLFW_FULLSCREEN) - { - ADD_ATTR(NSOpenGLPFANoRecovery); - ADD_ATTR2(NSOpenGLPFAScreenMask, - CGDisplayIDToOpenGLDisplayMask(CGMainDisplayID())); - } - -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 - if (wndconfig->glMajor > 2) - ADD_ATTR2(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core); -#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/ - - ADD_ATTR2(NSOpenGLPFAColorSize, colorBits); - - if (fbconfig->alphaBits > 0) - ADD_ATTR2(NSOpenGLPFAAlphaSize, fbconfig->alphaBits); - - if (fbconfig->depthBits > 0) - ADD_ATTR2(NSOpenGLPFADepthSize, fbconfig->depthBits); - - if (fbconfig->stencilBits > 0) - ADD_ATTR2(NSOpenGLPFAStencilSize, fbconfig->stencilBits); - - int accumBits = fbconfig->accumRedBits + fbconfig->accumGreenBits + - fbconfig->accumBlueBits + fbconfig->accumAlphaBits; - - if (accumBits > 0) - ADD_ATTR2(NSOpenGLPFAAccumSize, accumBits); - - if (fbconfig->auxBuffers > 0) - ADD_ATTR2(NSOpenGLPFAAuxBuffers, fbconfig->auxBuffers); - - if (fbconfig->stereo) - ADD_ATTR(NSOpenGLPFAStereo); - - if (fbconfig->samples > 0) - { - ADD_ATTR2(NSOpenGLPFASampleBuffers, 1); - ADD_ATTR2(NSOpenGLPFASamples, fbconfig->samples); - } - - // NOTE: All NSOpenGLPixelFormats on the relevant cards support sRGB - // frambuffer, so there's no need (and no way) to request it - - ADD_ATTR(0); - -#undef ADD_ATTR -#undef ADD_ATTR2 - - window->NSGL.pixelFormat = - [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]; - if (window->NSGL.pixelFormat == nil) - { - _glfwSetError(GLFW_PLATFORM_ERROR, - "NSOpenGL: Failed to create OpenGL pixel format"); - return GL_FALSE; - } - - NSOpenGLContext* share = NULL; - - if (wndconfig->share) - share = wndconfig->share->NSGL.context; - - window->NSGL.context = - [[NSOpenGLContext alloc] initWithFormat:window->NSGL.pixelFormat - shareContext:share]; - if (window->NSGL.context == nil) - { - _glfwSetError(GLFW_PLATFORM_ERROR, - "NSOpenGL: Failed to create OpenGL context"); - return GL_FALSE; - } - - return GL_TRUE; -} - - ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// @@ -923,7 +763,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, if (!createWindow(window, wndconfig)) return GL_FALSE; - if (!createContext(window, wndconfig, fbconfig)) + if (!_glfwCreateContext(window, wndconfig, fbconfig)) return GL_FALSE; [window->NSGL.context setView:[window->NS.object contentView]]; @@ -968,11 +808,7 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window) _glfwRestoreVideoMode(); } - [window->NSGL.pixelFormat release]; - window->NSGL.pixelFormat = nil; - - [window->NSGL.context release]; - window->NSGL.context = nil; + _glfwDestroyContext(window); [window->NS.object setDelegate:nil]; [window->NS.delegate release]; diff --git a/src/nsgl_context.m b/src/nsgl_context.m index caf4353a..315c39d5 100644 --- a/src/nsgl_context.m +++ b/src/nsgl_context.m @@ -69,6 +69,180 @@ void _glfwTerminateOpenGL(void) } +//======================================================================== +// Create the OpenGL context +//======================================================================== + +int _glfwCreateContext(_GLFWwindow* window, + const _GLFWwndconfig* wndconfig, + const _GLFWfbconfig* fbconfig) +{ + unsigned int attributeCount = 0; + + // Mac OS X needs non-zero color size, so set resonable values + int colorBits = fbconfig->redBits + fbconfig->greenBits + fbconfig->blueBits; + if (colorBits == 0) + colorBits = 24; + else if (colorBits < 15) + colorBits = 15; + + if (wndconfig->clientAPI == GLFW_OPENGL_ES_API) + { + _glfwSetError(GLFW_VERSION_UNAVAILABLE, + "NSOpenGL: This API does not support OpenGL ES"); + return GL_FALSE; + } + +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 + // Fail if any OpenGL version above 2.1 other than 3.2 was requested + if (wndconfig->glMajor > 3 || + (wndconfig->glMajor == 3 && wndconfig->glMinor != 2)) + { + _glfwSetError(GLFW_VERSION_UNAVAILABLE, + "NSOpenGL: The targeted version of Mac OS X does not " + "support any OpenGL version above 2.1 except 3.2"); + return GL_FALSE; + } + + if (wndconfig->glMajor > 2) + { + if (!wndconfig->glForward) + { + _glfwSetError(GLFW_VERSION_UNAVAILABLE, + "NSOpenGL: The targeted version of Mac OS X only " + "supports OpenGL 3.2 contexts if they are " + "forward-compatible"); + return GL_FALSE; + } + + if (wndconfig->glProfile != GLFW_OPENGL_CORE_PROFILE) + { + _glfwSetError(GLFW_VERSION_UNAVAILABLE, + "NSOpenGL: The targeted version of Mac OS X only " + "supports OpenGL 3.2 contexts if they use the " + "core profile"); + return GL_FALSE; + } + } +#else + // Fail if OpenGL 3.0 or above was requested + if (wndconfig->glMajor > 2) + { + _glfwSetError(GLFW_VERSION_UNAVAILABLE, + "NSOpenGL: The targeted version of Mac OS X does not " + "support OpenGL version 3.0 or above"); + return GL_FALSE; + } +#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/ + + // Fail if a robustness strategy was requested + if (wndconfig->glRobustness) + { + _glfwSetError(GLFW_VERSION_UNAVAILABLE, + "NSOpenGL: Mac OS X does not support OpenGL robustness " + "strategies"); + return GL_FALSE; + } + +#define ADD_ATTR(x) { attributes[attributeCount++] = x; } +#define ADD_ATTR2(x, y) { ADD_ATTR(x); ADD_ATTR(y); } + + // Arbitrary array size here + NSOpenGLPixelFormatAttribute attributes[40]; + + ADD_ATTR(NSOpenGLPFADoubleBuffer); + + if (wndconfig->mode == GLFW_FULLSCREEN) + { + ADD_ATTR(NSOpenGLPFANoRecovery); + ADD_ATTR2(NSOpenGLPFAScreenMask, + CGDisplayIDToOpenGLDisplayMask(CGMainDisplayID())); + } + +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 + if (wndconfig->glMajor > 2) + ADD_ATTR2(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core); +#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/ + + ADD_ATTR2(NSOpenGLPFAColorSize, colorBits); + + if (fbconfig->alphaBits > 0) + ADD_ATTR2(NSOpenGLPFAAlphaSize, fbconfig->alphaBits); + + if (fbconfig->depthBits > 0) + ADD_ATTR2(NSOpenGLPFADepthSize, fbconfig->depthBits); + + if (fbconfig->stencilBits > 0) + ADD_ATTR2(NSOpenGLPFAStencilSize, fbconfig->stencilBits); + + int accumBits = fbconfig->accumRedBits + fbconfig->accumGreenBits + + fbconfig->accumBlueBits + fbconfig->accumAlphaBits; + + if (accumBits > 0) + ADD_ATTR2(NSOpenGLPFAAccumSize, accumBits); + + if (fbconfig->auxBuffers > 0) + ADD_ATTR2(NSOpenGLPFAAuxBuffers, fbconfig->auxBuffers); + + if (fbconfig->stereo) + ADD_ATTR(NSOpenGLPFAStereo); + + if (fbconfig->samples > 0) + { + ADD_ATTR2(NSOpenGLPFASampleBuffers, 1); + ADD_ATTR2(NSOpenGLPFASamples, fbconfig->samples); + } + + // NOTE: All NSOpenGLPixelFormats on the relevant cards support sRGB + // frambuffer, so there's no need (and no way) to request it + + ADD_ATTR(0); + +#undef ADD_ATTR +#undef ADD_ATTR2 + + window->NSGL.pixelFormat = + [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]; + if (window->NSGL.pixelFormat == nil) + { + _glfwSetError(GLFW_PLATFORM_ERROR, + "NSOpenGL: Failed to create OpenGL pixel format"); + return GL_FALSE; + } + + NSOpenGLContext* share = NULL; + + if (wndconfig->share) + share = wndconfig->share->NSGL.context; + + window->NSGL.context = + [[NSOpenGLContext alloc] initWithFormat:window->NSGL.pixelFormat + shareContext:share]; + if (window->NSGL.context == nil) + { + _glfwSetError(GLFW_PLATFORM_ERROR, + "NSOpenGL: Failed to create OpenGL context"); + return GL_FALSE; + } + + return GL_TRUE; +} + + +//======================================================================== +// Destroy the OpenGL context +//======================================================================== + +void _glfwDestroyContext(_GLFWwindow* window) +{ + [window->NSGL.pixelFormat release]; + window->NSGL.pixelFormat = nil; + + [window->NSGL.context release]; + window->NSGL.context = nil; +} + + ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// //////////////////////////////////////////////////////////////////////////