github.com/Konstantin8105/c4go@v0.0.0-20240505174241-768bb1c65a51/tests/raylib/external/glfw/src/nsgl_context.m (about)

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