Atlas - nsgl_context.m

Home / ext / glfw / src Lines: 1 | Size: 11771 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1//======================================================================== 2// GLFW 3.5 macOS - www.glfw.org 3//------------------------------------------------------------------------ 4// Copyright (c) 2009-2019 Camilla Löwy <[email protected]> 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#if defined(_GLFW_COCOA) 30 31#include <unistd.h> 32#include <math.h> 33#include <assert.h> 34 35static void makeContextCurrentNSGL(_GLFWwindow* window) 36{ 37 @autoreleasepool { 38 39 if (window) 40 [window->context.nsgl.object makeCurrentContext]; 41 else 42 [NSOpenGLContext clearCurrentContext]; 43 44 _glfwPlatformSetTls(&_glfw.contextSlot, window); 45 46 } // autoreleasepool 47} 48 49static void swapBuffersNSGL(_GLFWwindow* window) 50{ 51 @autoreleasepool { 52 53 // HACK: Simulate vsync with usleep as NSGL swap interval does not apply to 54 // windows with a non-visible occlusion state 55 if (window->ns.occluded) 56 { 57 int interval = 0; 58 [window->context.nsgl.object getValues:&interval 59 forParameter:NSOpenGLContextParameterSwapInterval]; 60 61 if (interval > 0) 62 { 63 const double framerate = 60.0; 64 const uint64_t frequency = _glfwPlatformGetTimerFrequency(); 65 const uint64_t value = _glfwPlatformGetTimerValue(); 66 67 const double elapsed = value / (double) frequency; 68 const double period = 1.0 / framerate; 69 const double delay = period - fmod(elapsed, period); 70 71 usleep(floorl(delay * 1e6)); 72 } 73 } 74 75 [window->context.nsgl.object flushBuffer]; 76 77 } // autoreleasepool 78} 79 80static void swapIntervalNSGL(int interval) 81{ 82 @autoreleasepool { 83 84 _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot); 85 assert(window != NULL); 86 87 [window->context.nsgl.object setValues:&interval 88 forParameter:NSOpenGLContextParameterSwapInterval]; 89 90 } // autoreleasepool 91} 92 93static int extensionSupportedNSGL(const char* extension) 94{ 95 // There are no NSGL extensions 96 return GLFW_FALSE; 97} 98 99static GLFWglproc getProcAddressNSGL(const char* procname) 100{ 101 CFStringRef symbolName = CFStringCreateWithCString(kCFAllocatorDefault, 102 procname, 103 kCFStringEncodingASCII); 104 105 GLFWglproc symbol = CFBundleGetFunctionPointerForName(_glfw.nsgl.framework, 106 symbolName); 107 108 CFRelease(symbolName); 109 110 return symbol; 111} 112 113static void destroyContextNSGL(_GLFWwindow* window) 114{ 115 @autoreleasepool { 116 117 [window->context.nsgl.pixelFormat release]; 118 window->context.nsgl.pixelFormat = nil; 119 120 [window->context.nsgl.object release]; 121 window->context.nsgl.object = nil; 122 123 } // autoreleasepool 124} 125 126 127////////////////////////////////////////////////////////////////////////// 128////// GLFW internal API ////// 129////////////////////////////////////////////////////////////////////////// 130 131GLFWbool _glfwInitNSGL(void) 132{ 133 if (_glfw.nsgl.framework) 134 return GLFW_TRUE; 135 136 _glfw.nsgl.framework = 137 CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl")); 138 if (_glfw.nsgl.framework == NULL) 139 { 140 _glfwInputError(GLFW_API_UNAVAILABLE, 141 "NSGL: Failed to locate OpenGL framework"); 142 return GLFW_FALSE; 143 } 144 145 return GLFW_TRUE; 146} 147 148void _glfwTerminateNSGL(void) 149{ 150} 151 152GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window, 153 const _GLFWctxconfig* ctxconfig, 154 const _GLFWfbconfig* fbconfig) 155{ 156 if (ctxconfig->client == GLFW_OPENGL_ES_API) 157 { 158 _glfwInputError(GLFW_API_UNAVAILABLE, 159 "NSGL: OpenGL ES is not available via NSGL"); 160 return GLFW_FALSE; 161 } 162 163 if (ctxconfig->major > 2) 164 { 165 if (ctxconfig->major == 3 && ctxconfig->minor < 2) 166 { 167 _glfwInputError(GLFW_VERSION_UNAVAILABLE, 168 "NSGL: The targeted version of macOS does not support OpenGL 3.0 or 3.1 but may support 3.2 and above"); 169 return GLFW_FALSE; 170 } 171 } 172 173 if (ctxconfig->major >= 3 && ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE) 174 { 175 _glfwInputError(GLFW_VERSION_UNAVAILABLE, 176 "NSGL: The compatibility profile is not available on macOS"); 177 return GLFW_FALSE; 178 } 179 180 // Context robustness modes (GL_KHR_robustness) are not supported by 181 // macOS but are not a hard constraint, so ignore and continue 182 183 // Context release behaviors (GL_KHR_context_flush_control) are not 184 // supported by macOS but are not a hard constraint, so ignore and continue 185 186 // Debug contexts (GL_KHR_debug) are not supported by macOS but are not 187 // a hard constraint, so ignore and continue 188 189 // No-error contexts (GL_KHR_no_error) are not supported by macOS but 190 // are not a hard constraint, so ignore and continue 191 192#define ADD_ATTRIB(a) \ 193{ \ 194 assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \ 195 attribs[index++] = a; \ 196} 197#define SET_ATTRIB(a, v) { ADD_ATTRIB(a); ADD_ATTRIB(v); } 198 199 NSOpenGLPixelFormatAttribute attribs[40]; 200 int index = 0; 201 202 ADD_ATTRIB(NSOpenGLPFAAccelerated); 203 ADD_ATTRIB(NSOpenGLPFAClosestPolicy); 204 205 if (ctxconfig->nsgl.offline) 206 { 207 ADD_ATTRIB(NSOpenGLPFAAllowOfflineRenderers); 208 // NOTE: This replaces the NSSupportsAutomaticGraphicsSwitching key in 209 // Info.plist for unbundled applications 210 // HACK: This assumes that NSOpenGLPixelFormat will remain 211 // a straightforward wrapper of its CGL counterpart 212 ADD_ATTRIB(kCGLPFASupportsAutomaticGraphicsSwitching); 213 } 214 215 if (ctxconfig->major >= 4) 216 { 217 SET_ATTRIB(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core); 218 } 219 else if (ctxconfig->major >= 3) 220 { 221 SET_ATTRIB(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core); 222 } 223 224 if (ctxconfig->major <= 2) 225 { 226 if (fbconfig->auxBuffers != GLFW_DONT_CARE) 227 SET_ATTRIB(NSOpenGLPFAAuxBuffers, fbconfig->auxBuffers); 228 229 if (fbconfig->accumRedBits != GLFW_DONT_CARE && 230 fbconfig->accumGreenBits != GLFW_DONT_CARE && 231 fbconfig->accumBlueBits != GLFW_DONT_CARE && 232 fbconfig->accumAlphaBits != GLFW_DONT_CARE) 233 { 234 const int accumBits = fbconfig->accumRedBits + 235 fbconfig->accumGreenBits + 236 fbconfig->accumBlueBits + 237 fbconfig->accumAlphaBits; 238 239 SET_ATTRIB(NSOpenGLPFAAccumSize, accumBits); 240 } 241 } 242 243 if (fbconfig->redBits != GLFW_DONT_CARE && 244 fbconfig->greenBits != GLFW_DONT_CARE && 245 fbconfig->blueBits != GLFW_DONT_CARE) 246 { 247 int colorBits = fbconfig->redBits + 248 fbconfig->greenBits + 249 fbconfig->blueBits; 250 251 // macOS needs non-zero color size, so set reasonable values 252 if (colorBits == 0) 253 colorBits = 24; 254 else if (colorBits < 15) 255 colorBits = 15; 256 257 SET_ATTRIB(NSOpenGLPFAColorSize, colorBits); 258 } 259 260 if (fbconfig->alphaBits != GLFW_DONT_CARE) 261 SET_ATTRIB(NSOpenGLPFAAlphaSize, fbconfig->alphaBits); 262 263 if (fbconfig->depthBits != GLFW_DONT_CARE) 264 SET_ATTRIB(NSOpenGLPFADepthSize, fbconfig->depthBits); 265 266 if (fbconfig->stencilBits != GLFW_DONT_CARE) 267 SET_ATTRIB(NSOpenGLPFAStencilSize, fbconfig->stencilBits); 268 269 if (fbconfig->stereo) 270 { 271#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200 272 _glfwInputError(GLFW_FORMAT_UNAVAILABLE, 273 "NSGL: Stereo rendering is deprecated"); 274 return GLFW_FALSE; 275#else 276 ADD_ATTRIB(NSOpenGLPFAStereo); 277#endif 278 } 279 280 if (fbconfig->doublebuffer) 281 ADD_ATTRIB(NSOpenGLPFADoubleBuffer); 282 283 if (fbconfig->samples != GLFW_DONT_CARE) 284 { 285 if (fbconfig->samples == 0) 286 { 287 SET_ATTRIB(NSOpenGLPFASampleBuffers, 0); 288 } 289 else 290 { 291 SET_ATTRIB(NSOpenGLPFASampleBuffers, 1); 292 SET_ATTRIB(NSOpenGLPFASamples, fbconfig->samples); 293 } 294 } 295 296 // NOTE: All NSOpenGLPixelFormats on the relevant cards support sRGB 297 // framebuffer, so there's no need (and no way) to request it 298 299 ADD_ATTRIB(0); 300 301#undef ADD_ATTRIB 302#undef SET_ATTRIB 303 304 window->context.nsgl.pixelFormat = 305 [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs]; 306 if (window->context.nsgl.pixelFormat == nil) 307 { 308 _glfwInputError(GLFW_FORMAT_UNAVAILABLE, 309 "NSGL: Failed to find a suitable pixel format"); 310 return GLFW_FALSE; 311 } 312 313 NSOpenGLContext* share = nil; 314 315 if (ctxconfig->share) 316 share = ctxconfig->share->context.nsgl.object; 317 318 window->context.nsgl.object = 319 [[NSOpenGLContext alloc] initWithFormat:window->context.nsgl.pixelFormat 320 shareContext:share]; 321 if (window->context.nsgl.object == nil) 322 { 323 _glfwInputError(GLFW_VERSION_UNAVAILABLE, 324 "NSGL: Failed to create OpenGL context"); 325 return GLFW_FALSE; 326 } 327 328 if (fbconfig->transparent) 329 { 330 GLint opaque = 0; 331 [window->context.nsgl.object setValues:&opaque 332 forParameter:NSOpenGLContextParameterSurfaceOpacity]; 333 } 334 335 [window->ns.view setWantsBestResolutionOpenGLSurface:window->ns.scaleFramebuffer]; 336 337 [window->context.nsgl.object setView:window->ns.view]; 338 339 window->context.makeCurrent = makeContextCurrentNSGL; 340 window->context.swapBuffers = swapBuffersNSGL; 341 window->context.swapInterval = swapIntervalNSGL; 342 window->context.extensionSupported = extensionSupportedNSGL; 343 window->context.getProcAddress = getProcAddressNSGL; 344 window->context.destroy = destroyContextNSGL; 345 346 return GLFW_TRUE; 347} 348 349 350////////////////////////////////////////////////////////////////////////// 351////// GLFW native API ////// 352////////////////////////////////////////////////////////////////////////// 353 354GLFWAPI id glfwGetNSGLContext(GLFWwindow* handle) 355{ 356 _GLFW_REQUIRE_INIT_OR_RETURN(nil); 357 358 if (_glfw.platform.platformID != GLFW_PLATFORM_COCOA) 359 { 360 _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, 361 "NSGL: Platform not initialized"); 362 return nil; 363 } 364 365 _GLFWwindow* window = (_GLFWwindow*) handle; 366 assert(window != NULL); 367 368 if (window->context.source != GLFW_NATIVE_CONTEXT_API) 369 { 370 _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); 371 return nil; 372 } 373 374 return window->context.nsgl.object; 375} 376 377#endif // _GLFW_COCOA 378 379
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.