1//======================================================================== 2// GLFW 3.2 OS X - www.glfw.org 3//------------------------------------------------------------------------ 4// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org> 5// 6// This software is provided 'as-is', without any express or implied 7// warranty. In no event will the authors be held liable for any damages 8// arising from the use of this software. 9// 10// Permission is granted to anyone to use this software for any purpose, 11// including commercial applications, and to alter it and redistribute it 12// freely, subject to the following restrictions: 13// 14// 1. The origin of this software must not be misrepresented; you must not 15// claim that you wrote the original software. If you use this software 16// in a product, an acknowledgment in the product documentation would 17// be appreciated but is not required. 18// 19// 2. Altered source versions must be plainly marked as such, and must not 20// be misrepresented as being the original software. 21// 22// 3. This notice may not be removed or altered from any source 23// distribution. 24// 25//======================================================================== 26 27#include "internal.h" 28 29 30static void makeContextCurrentNSGL(_GLFWwindow* window) 31{ 32 if (window) 33 [window->context.nsgl.object makeCurrentContext]; 34 else 35 [NSOpenGLContext clearCurrentContext]; 36 37 _glfwPlatformSetCurrentContext(window); 38} 39 40static void swapBuffersNSGL(_GLFWwindow* window) 41{ 42 // ARP appears to be unnecessary, but this is future-proof 43 [window->context.nsgl.object flushBuffer]; 44} 45 46static void swapIntervalNSGL(int interval) 47{ 48 _GLFWwindow* window = _glfwPlatformGetCurrentContext(); 49 50 GLint sync = interval; 51 [window->context.nsgl.object setValues:&sync 52 forParameter:NSOpenGLCPSwapInterval]; 53} 54 55static int extensionSupportedNSGL(const char* extension) 56{ 57 // There are no NSGL extensions 58 return GLFW_FALSE; 59} 60 61static GLFWglproc getProcAddressNSGL(const char* procname) 62{ 63 CFStringRef symbolName = CFStringCreateWithCString(kCFAllocatorDefault, 64 procname, 65 kCFStringEncodingASCII); 66 67 GLFWglproc symbol = CFBundleGetFunctionPointerForName(_glfw.nsgl.framework, 68 symbolName); 69 70 CFRelease(symbolName); 71 72 return symbol; 73} 74 75// Destroy the OpenGL context 76// 77static void destroyContextNSGL(_GLFWwindow* window) 78{ 79 [window->context.nsgl.pixelFormat release]; 80 window->context.nsgl.pixelFormat = nil; 81 82 [window->context.nsgl.object release]; 83 window->context.nsgl.object = nil; 84} 85 86 87////////////////////////////////////////////////////////////////////////// 88////// GLFW internal API ////// 89////////////////////////////////////////////////////////////////////////// 90 91// Initialize OpenGL support 92// 93GLFWbool _glfwInitNSGL(void) 94{ 95 if (_glfw.nsgl.framework) 96 return GLFW_TRUE; 97 98 _glfw.nsgl.framework = 99 CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl")); 100 if (_glfw.nsgl.framework == NULL) 101 { 102 _glfwInputError(GLFW_API_UNAVAILABLE, 103 "NSGL: Failed to locate OpenGL framework"); 104 return GLFW_FALSE; 105 } 106 107 return GLFW_TRUE; 108} 109 110// Terminate OpenGL support 111// 112void _glfwTerminateNSGL(void) 113{ 114} 115 116// Create the OpenGL context 117// 118GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window, 119 const _GLFWctxconfig* ctxconfig, 120 const _GLFWfbconfig* fbconfig) 121{ 122 unsigned int attributeCount = 0; 123 124 if (ctxconfig->client == GLFW_OPENGL_ES_API) 125 { 126 _glfwInputError(GLFW_API_UNAVAILABLE, 127 "NSGL: OpenGL ES is not available on OS X"); 128 return GLFW_FALSE; 129 } 130 131 if (ctxconfig->major == 3 && ctxconfig->minor < 2) 132 { 133 _glfwInputError(GLFW_VERSION_UNAVAILABLE, 134 "NSGL: The targeted version of OS X does not support OpenGL 3.0 or 3.1"); 135 fprintf(stderr, "[Engine Log] NSGL: The targeted version of OS X does not support OpenGL 3.0 or 3.1\n"); 136 return GLFW_FALSE; 137 } 138 139 if (ctxconfig->major > 2) 140 { 141 if (!ctxconfig->forward) 142 { 143 _glfwInputError(GLFW_VERSION_UNAVAILABLE, 144 "NSGL: The targeted version of OS X only supports forward-compatible contexts for OpenGL 3.2 and above"); 145 return GLFW_FALSE; 146 } 147 148 if (ctxconfig->profile != GLFW_OPENGL_CORE_PROFILE) 149 { 150 _glfwInputError(GLFW_VERSION_UNAVAILABLE, 151 "NSGL: The targeted version of OS X only supports core profile contexts for OpenGL 3.2 and above"); 152 return GLFW_FALSE; 153 } 154 } 155 156 // Context robustness modes (GL_KHR_robustness) are not yet supported on 157 // OS X but are not a hard constraint, so ignore and continue 158 159 // Context release behaviors (GL_KHR_context_flush_control) are not yet 160 // supported on OS X but are not a hard constraint, so ignore and continue 161 162#define ADD_ATTR(x) { attributes[attributeCount++] = x; } 163#define ADD_ATTR2(x, y) { ADD_ATTR(x); ADD_ATTR(y); } 164 165 // Arbitrary array size here 166 NSOpenGLPixelFormatAttribute attributes[40]; 167 168 ADD_ATTR(NSOpenGLPFAAccelerated); 169 ADD_ATTR(NSOpenGLPFAClosestPolicy); 170 171#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000 172 if (ctxconfig->major >= 4) 173 { 174 ADD_ATTR2(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core); 175 } 176 else 177#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/ 178 if (ctxconfig->major >= 3) 179 { 180 ADD_ATTR2(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core); 181 } 182 183 if (ctxconfig->major <= 2) 184 { 185 if (fbconfig->auxBuffers != GLFW_DONT_CARE) 186 ADD_ATTR2(NSOpenGLPFAAuxBuffers, fbconfig->auxBuffers); 187 188 if (fbconfig->accumRedBits != GLFW_DONT_CARE && 189 fbconfig->accumGreenBits != GLFW_DONT_CARE && 190 fbconfig->accumBlueBits != GLFW_DONT_CARE && 191 fbconfig->accumAlphaBits != GLFW_DONT_CARE) 192 { 193 const int accumBits = fbconfig->accumRedBits + 194 fbconfig->accumGreenBits + 195 fbconfig->accumBlueBits + 196 fbconfig->accumAlphaBits; 197 198 ADD_ATTR2(NSOpenGLPFAAccumSize, accumBits); 199 } 200 } 201 202 if (fbconfig->redBits != GLFW_DONT_CARE && 203 fbconfig->greenBits != GLFW_DONT_CARE && 204 fbconfig->blueBits != GLFW_DONT_CARE) 205 { 206 int colorBits = fbconfig->redBits + 207 fbconfig->greenBits + 208 fbconfig->blueBits; 209 210 // OS X needs non-zero color size, so set reasonable values 211 if (colorBits == 0) 212 colorBits = 24; 213 else if (colorBits < 15) 214 colorBits = 15; 215 216 ADD_ATTR2(NSOpenGLPFAColorSize, colorBits); 217 } 218 219 if (fbconfig->alphaBits != GLFW_DONT_CARE) 220 ADD_ATTR2(NSOpenGLPFAAlphaSize, fbconfig->alphaBits); 221 222 if (fbconfig->depthBits != GLFW_DONT_CARE) 223 ADD_ATTR2(NSOpenGLPFADepthSize, fbconfig->depthBits); 224 225 if (fbconfig->stencilBits != GLFW_DONT_CARE) 226 ADD_ATTR2(NSOpenGLPFAStencilSize, fbconfig->stencilBits); 227 228 if (fbconfig->stereo) 229 ADD_ATTR(NSOpenGLPFAStereo); 230 231 if (fbconfig->doublebuffer) 232 ADD_ATTR(NSOpenGLPFADoubleBuffer); 233 234 if (fbconfig->samples != GLFW_DONT_CARE) 235 { 236 if (fbconfig->samples == 0) 237 { 238 ADD_ATTR2(NSOpenGLPFASampleBuffers, 0); 239 } 240 else 241 { 242 ADD_ATTR2(NSOpenGLPFASampleBuffers, 1); 243 ADD_ATTR2(NSOpenGLPFASamples, fbconfig->samples); 244 } 245 } 246 247 // NOTE: All NSOpenGLPixelFormats on the relevant cards support sRGB 248 // framebuffer, so there's no need (and no way) to request it 249 250 ADD_ATTR(0); 251 252#undef ADD_ATTR 253#undef ADD_ATTR2 254 255 window->context.nsgl.pixelFormat = 256 [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]; 257 if (window->context.nsgl.pixelFormat == nil) 258 { 259 _glfwInputError(GLFW_FORMAT_UNAVAILABLE, 260 "NSGL: Failed to find a suitable pixel format"); 261 return GLFW_FALSE; 262 } 263 264 NSOpenGLContext* share = NULL; 265 266 if (ctxconfig->share) 267 share = ctxconfig->share->context.nsgl.object; 268 269 window->context.nsgl.object = 270 [[NSOpenGLContext alloc] initWithFormat:window->context.nsgl.pixelFormat 271 shareContext:share]; 272 if (window->context.nsgl.object == nil) 273 { 274 _glfwInputError(GLFW_VERSION_UNAVAILABLE, 275 "NSGL: Failed to create OpenGL context"); 276 return GLFW_FALSE; 277 } 278 279 [window->context.nsgl.object setView:window->ns.view]; 280 281 window->context.makeCurrent = makeContextCurrentNSGL; 282 window->context.swapBuffers = swapBuffersNSGL; 283 window->context.swapInterval = swapIntervalNSGL; 284 window->context.extensionSupported = extensionSupportedNSGL; 285 window->context.getProcAddress = getProcAddressNSGL; 286 window->context.destroy = destroyContextNSGL; 287 288 return GLFW_TRUE; 289} 290 291 292////////////////////////////////////////////////////////////////////////// 293////// GLFW native API ////// 294////////////////////////////////////////////////////////////////////////// 295 296GLFWAPI id glfwGetNSGLContext(GLFWwindow* handle) 297{ 298 _GLFWwindow* window = (_GLFWwindow*) handle; 299 _GLFW_REQUIRE_INIT_OR_RETURN(nil); 300 301 if (window->context.client == GLFW_NO_API) 302 { 303 _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); 304 return NULL; 305 } 306 307 return window->context.nsgl.object; 308} 309 310