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

     1  //========================================================================
     2  // GLFW 3.4 - www.glfw.org
     3  //------------------------------------------------------------------------
     4  // Copyright (c) 2002-2006 Marcus Geelnard
     5  // Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
     6  //
     7  // This software is provided 'as-is', without any express or implied
     8  // warranty. In no event will the authors be held liable for any damages
     9  // arising from the use of this software.
    10  //
    11  // Permission is granted to anyone to use this software for any purpose,
    12  // including commercial applications, and to alter it and redistribute it
    13  // freely, subject to the following restrictions:
    14  //
    15  // 1. The origin of this software must not be misrepresented; you must not
    16  //    claim that you wrote the original software. If you use this software
    17  //    in a product, an acknowledgment in the product documentation would
    18  //    be appreciated but is not required.
    19  //
    20  // 2. Altered source versions must be plainly marked as such, and must not
    21  //    be misrepresented as being the original software.
    22  //
    23  // 3. This notice may not be removed or altered from any source
    24  //    distribution.
    25  //
    26  //========================================================================
    27  // Please use C89 style variable declarations in this file because VS 2010
    28  //========================================================================
    29  
    30  #include "internal.h"
    31  
    32  #include <assert.h>
    33  #include <stdio.h>
    34  #include <string.h>
    35  #include <limits.h>
    36  #include <stdio.h>
    37  
    38  
    39  //////////////////////////////////////////////////////////////////////////
    40  //////                       GLFW internal API                      //////
    41  //////////////////////////////////////////////////////////////////////////
    42  
    43  // Checks whether the desired context attributes are valid
    44  //
    45  // This function checks things like whether the specified client API version
    46  // exists and whether all relevant options have supported and non-conflicting
    47  // values
    48  //
    49  GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
    50  {
    51      if (ctxconfig->source != GLFW_NATIVE_CONTEXT_API &&
    52          ctxconfig->source != GLFW_EGL_CONTEXT_API &&
    53          ctxconfig->source != GLFW_OSMESA_CONTEXT_API)
    54      {
    55          _glfwInputError(GLFW_INVALID_ENUM,
    56                          "Invalid context creation API 0x%08X",
    57                          ctxconfig->source);
    58          return GLFW_FALSE;
    59      }
    60  
    61      if (ctxconfig->client != GLFW_NO_API &&
    62          ctxconfig->client != GLFW_OPENGL_API &&
    63          ctxconfig->client != GLFW_OPENGL_ES_API)
    64      {
    65          _glfwInputError(GLFW_INVALID_ENUM,
    66                          "Invalid client API 0x%08X",
    67                          ctxconfig->client);
    68          return GLFW_FALSE;
    69      }
    70  
    71      if (ctxconfig->share)
    72      {
    73          if (ctxconfig->client == GLFW_NO_API ||
    74              ctxconfig->share->context.client == GLFW_NO_API)
    75          {
    76              _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
    77              return GLFW_FALSE;
    78          }
    79  
    80          if (ctxconfig->source != ctxconfig->share->context.source)
    81          {
    82              _glfwInputError(GLFW_INVALID_ENUM,
    83                              "Context creation APIs do not match between contexts");
    84              return GLFW_FALSE;
    85          }
    86      }
    87  
    88      if (ctxconfig->client == GLFW_OPENGL_API)
    89      {
    90          if ((ctxconfig->major < 1 || ctxconfig->minor < 0) ||
    91              (ctxconfig->major == 1 && ctxconfig->minor > 5) ||
    92              (ctxconfig->major == 2 && ctxconfig->minor > 1) ||
    93              (ctxconfig->major == 3 && ctxconfig->minor > 3))
    94          {
    95              // OpenGL 1.0 is the smallest valid version
    96              // OpenGL 1.x series ended with version 1.5
    97              // OpenGL 2.x series ended with version 2.1
    98              // OpenGL 3.x series ended with version 3.3
    99              // For now, let everything else through
   100  
   101              _glfwInputError(GLFW_INVALID_VALUE,
   102                              "Invalid OpenGL version %i.%i",
   103                              ctxconfig->major, ctxconfig->minor);
   104              return GLFW_FALSE;
   105          }
   106  
   107          if (ctxconfig->profile)
   108          {
   109              if (ctxconfig->profile != GLFW_OPENGL_CORE_PROFILE &&
   110                  ctxconfig->profile != GLFW_OPENGL_COMPAT_PROFILE)
   111              {
   112                  _glfwInputError(GLFW_INVALID_ENUM,
   113                                  "Invalid OpenGL profile 0x%08X",
   114                                  ctxconfig->profile);
   115                  return GLFW_FALSE;
   116              }
   117  
   118              if (ctxconfig->major <= 2 ||
   119                  (ctxconfig->major == 3 && ctxconfig->minor < 2))
   120              {
   121                  // Desktop OpenGL context profiles are only defined for version 3.2
   122                  // and above
   123  
   124                  _glfwInputError(GLFW_INVALID_VALUE,
   125                                  "Context profiles are only defined for OpenGL version 3.2 and above");
   126                  return GLFW_FALSE;
   127              }
   128          }
   129  
   130          if (ctxconfig->forward && ctxconfig->major <= 2)
   131          {
   132              // Forward-compatible contexts are only defined for OpenGL version 3.0 and above
   133              _glfwInputError(GLFW_INVALID_VALUE,
   134                              "Forward-compatibility is only defined for OpenGL version 3.0 and above");
   135              return GLFW_FALSE;
   136          }
   137      }
   138      else if (ctxconfig->client == GLFW_OPENGL_ES_API)
   139      {
   140          if (ctxconfig->major < 1 || ctxconfig->minor < 0 ||
   141              (ctxconfig->major == 1 && ctxconfig->minor > 1) ||
   142              (ctxconfig->major == 2 && ctxconfig->minor > 0))
   143          {
   144              // OpenGL ES 1.0 is the smallest valid version
   145              // OpenGL ES 1.x series ended with version 1.1
   146              // OpenGL ES 2.x series ended with version 2.0
   147              // For now, let everything else through
   148  
   149              _glfwInputError(GLFW_INVALID_VALUE,
   150                              "Invalid OpenGL ES version %i.%i",
   151                              ctxconfig->major, ctxconfig->minor);
   152              return GLFW_FALSE;
   153          }
   154      }
   155  
   156      if (ctxconfig->robustness)
   157      {
   158          if (ctxconfig->robustness != GLFW_NO_RESET_NOTIFICATION &&
   159              ctxconfig->robustness != GLFW_LOSE_CONTEXT_ON_RESET)
   160          {
   161              _glfwInputError(GLFW_INVALID_ENUM,
   162                              "Invalid context robustness mode 0x%08X",
   163                              ctxconfig->robustness);
   164              return GLFW_FALSE;
   165          }
   166      }
   167  
   168      if (ctxconfig->release)
   169      {
   170          if (ctxconfig->release != GLFW_RELEASE_BEHAVIOR_NONE &&
   171              ctxconfig->release != GLFW_RELEASE_BEHAVIOR_FLUSH)
   172          {
   173              _glfwInputError(GLFW_INVALID_ENUM,
   174                              "Invalid context release behavior 0x%08X",
   175                              ctxconfig->release);
   176              return GLFW_FALSE;
   177          }
   178      }
   179  
   180      return GLFW_TRUE;
   181  }
   182  
   183  // Chooses the framebuffer config that best matches the desired one
   184  //
   185  const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
   186                                           const _GLFWfbconfig* alternatives,
   187                                           unsigned int count)
   188  {
   189      unsigned int i;
   190      unsigned int missing, leastMissing = UINT_MAX;
   191      unsigned int colorDiff, leastColorDiff = UINT_MAX;
   192      unsigned int extraDiff, leastExtraDiff = UINT_MAX;
   193      const _GLFWfbconfig* current;
   194      const _GLFWfbconfig* closest = NULL;
   195  
   196      for (i = 0;  i < count;  i++)
   197      {
   198          current = alternatives + i;
   199  
   200          if (desired->stereo > 0 && current->stereo == 0)
   201          {
   202              // Stereo is a hard constraint
   203              continue;
   204          }
   205  
   206          // Count number of missing buffers
   207          {
   208              missing = 0;
   209  
   210              if (desired->alphaBits > 0 && current->alphaBits == 0)
   211                  missing++;
   212  
   213              if (desired->depthBits > 0 && current->depthBits == 0)
   214                  missing++;
   215  
   216              if (desired->stencilBits > 0 && current->stencilBits == 0)
   217                  missing++;
   218  
   219              if (desired->auxBuffers > 0 &&
   220                  current->auxBuffers < desired->auxBuffers)
   221              {
   222                  missing += desired->auxBuffers - current->auxBuffers;
   223              }
   224  
   225              if (desired->samples > 0 && current->samples == 0)
   226              {
   227                  // Technically, several multisampling buffers could be
   228                  // involved, but that's a lower level implementation detail and
   229                  // not important to us here, so we count them as one
   230                  missing++;
   231              }
   232  
   233              if (desired->transparent != current->transparent)
   234                  missing++;
   235          }
   236  
   237          // These polynomials make many small channel size differences matter
   238          // less than one large channel size difference
   239  
   240          // Calculate color channel size difference value
   241          {
   242              colorDiff = 0;
   243  
   244              if (desired->redBits != GLFW_DONT_CARE)
   245              {
   246                  colorDiff += (desired->redBits - current->redBits) *
   247                               (desired->redBits - current->redBits);
   248              }
   249  
   250              if (desired->greenBits != GLFW_DONT_CARE)
   251              {
   252                  colorDiff += (desired->greenBits - current->greenBits) *
   253                               (desired->greenBits - current->greenBits);
   254              }
   255  
   256              if (desired->blueBits != GLFW_DONT_CARE)
   257              {
   258                  colorDiff += (desired->blueBits - current->blueBits) *
   259                               (desired->blueBits - current->blueBits);
   260              }
   261          }
   262  
   263          // Calculate non-color channel size difference value
   264          {
   265              extraDiff = 0;
   266  
   267              if (desired->alphaBits != GLFW_DONT_CARE)
   268              {
   269                  extraDiff += (desired->alphaBits - current->alphaBits) *
   270                               (desired->alphaBits - current->alphaBits);
   271              }
   272  
   273              if (desired->depthBits != GLFW_DONT_CARE)
   274              {
   275                  extraDiff += (desired->depthBits - current->depthBits) *
   276                               (desired->depthBits - current->depthBits);
   277              }
   278  
   279              if (desired->stencilBits != GLFW_DONT_CARE)
   280              {
   281                  extraDiff += (desired->stencilBits - current->stencilBits) *
   282                               (desired->stencilBits - current->stencilBits);
   283              }
   284  
   285              if (desired->accumRedBits != GLFW_DONT_CARE)
   286              {
   287                  extraDiff += (desired->accumRedBits - current->accumRedBits) *
   288                               (desired->accumRedBits - current->accumRedBits);
   289              }
   290  
   291              if (desired->accumGreenBits != GLFW_DONT_CARE)
   292              {
   293                  extraDiff += (desired->accumGreenBits - current->accumGreenBits) *
   294                               (desired->accumGreenBits - current->accumGreenBits);
   295              }
   296  
   297              if (desired->accumBlueBits != GLFW_DONT_CARE)
   298              {
   299                  extraDiff += (desired->accumBlueBits - current->accumBlueBits) *
   300                               (desired->accumBlueBits - current->accumBlueBits);
   301              }
   302  
   303              if (desired->accumAlphaBits != GLFW_DONT_CARE)
   304              {
   305                  extraDiff += (desired->accumAlphaBits - current->accumAlphaBits) *
   306                               (desired->accumAlphaBits - current->accumAlphaBits);
   307              }
   308  
   309              if (desired->samples != GLFW_DONT_CARE)
   310              {
   311                  extraDiff += (desired->samples - current->samples) *
   312                               (desired->samples - current->samples);
   313              }
   314  
   315              if (desired->sRGB && !current->sRGB)
   316                  extraDiff++;
   317          }
   318  
   319          // Figure out if the current one is better than the best one found so far
   320          // Least number of missing buffers is the most important heuristic,
   321          // then color buffer size match and lastly size match for other buffers
   322  
   323          if (missing < leastMissing)
   324              closest = current;
   325          else if (missing == leastMissing)
   326          {
   327              if ((colorDiff < leastColorDiff) ||
   328                  (colorDiff == leastColorDiff && extraDiff < leastExtraDiff))
   329              {
   330                  closest = current;
   331              }
   332          }
   333  
   334          if (current == closest)
   335          {
   336              leastMissing = missing;
   337              leastColorDiff = colorDiff;
   338              leastExtraDiff = extraDiff;
   339          }
   340      }
   341  
   342      return closest;
   343  }
   344  
   345  // Retrieves the attributes of the current context
   346  //
   347  GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
   348                                      const _GLFWctxconfig* ctxconfig)
   349  {
   350      int i;
   351      _GLFWwindow* previous;
   352      const char* version;
   353      const char* prefixes[] =
   354      {
   355          "OpenGL ES-CM ",
   356          "OpenGL ES-CL ",
   357          "OpenGL ES ",
   358          NULL
   359      };
   360  
   361      window->context.source = ctxconfig->source;
   362      window->context.client = GLFW_OPENGL_API;
   363  
   364      previous = _glfwPlatformGetTls(&_glfw.contextSlot);
   365      glfwMakeContextCurrent((GLFWwindow*) window);
   366  
   367      window->context.GetIntegerv = (PFNGLGETINTEGERVPROC)
   368          window->context.getProcAddress("glGetIntegerv");
   369      window->context.GetString = (PFNGLGETSTRINGPROC)
   370          window->context.getProcAddress("glGetString");
   371      if (!window->context.GetIntegerv || !window->context.GetString)
   372      {
   373          _glfwInputError(GLFW_PLATFORM_ERROR, "Entry point retrieval is broken");
   374          glfwMakeContextCurrent((GLFWwindow*) previous);
   375          return GLFW_FALSE;
   376      }
   377  
   378      version = (const char*) window->context.GetString(GL_VERSION);
   379      if (!version)
   380      {
   381          if (ctxconfig->client == GLFW_OPENGL_API)
   382          {
   383              _glfwInputError(GLFW_PLATFORM_ERROR,
   384                              "OpenGL version string retrieval is broken");
   385          }
   386          else
   387          {
   388              _glfwInputError(GLFW_PLATFORM_ERROR,
   389                              "OpenGL ES version string retrieval is broken");
   390          }
   391  
   392          glfwMakeContextCurrent((GLFWwindow*) previous);
   393          return GLFW_FALSE;
   394      }
   395  
   396      for (i = 0;  prefixes[i];  i++)
   397      {
   398          const size_t length = strlen(prefixes[i]);
   399  
   400          if (strncmp(version, prefixes[i], length) == 0)
   401          {
   402              version += length;
   403              window->context.client = GLFW_OPENGL_ES_API;
   404              break;
   405          }
   406      }
   407  
   408      if (!sscanf(version, "%d.%d.%d",
   409                  &window->context.major,
   410                  &window->context.minor,
   411                  &window->context.revision))
   412      {
   413          if (window->context.client == GLFW_OPENGL_API)
   414          {
   415              _glfwInputError(GLFW_PLATFORM_ERROR,
   416                              "No version found in OpenGL version string");
   417          }
   418          else
   419          {
   420              _glfwInputError(GLFW_PLATFORM_ERROR,
   421                              "No version found in OpenGL ES version string");
   422          }
   423  
   424          glfwMakeContextCurrent((GLFWwindow*) previous);
   425          return GLFW_FALSE;
   426      }
   427  
   428      if (window->context.major < ctxconfig->major ||
   429          (window->context.major == ctxconfig->major &&
   430           window->context.minor < ctxconfig->minor))
   431      {
   432          // The desired OpenGL version is greater than the actual version
   433          // This only happens if the machine lacks {GLX|WGL}_ARB_create_context
   434          // /and/ the user has requested an OpenGL version greater than 1.0
   435  
   436          // For API consistency, we emulate the behavior of the
   437          // {GLX|WGL}_ARB_create_context extension and fail here
   438  
   439          if (window->context.client == GLFW_OPENGL_API)
   440          {
   441              _glfwInputError(GLFW_VERSION_UNAVAILABLE,
   442                              "Requested OpenGL version %i.%i, got version %i.%i",
   443                              ctxconfig->major, ctxconfig->minor,
   444                              window->context.major, window->context.minor);
   445          }
   446          else
   447          {
   448              _glfwInputError(GLFW_VERSION_UNAVAILABLE,
   449                              "Requested OpenGL ES version %i.%i, got version %i.%i",
   450                              ctxconfig->major, ctxconfig->minor,
   451                              window->context.major, window->context.minor);
   452          }
   453  
   454          glfwMakeContextCurrent((GLFWwindow*) previous);
   455          return GLFW_FALSE;
   456      }
   457  
   458      if (window->context.major >= 3)
   459      {
   460          // OpenGL 3.0+ uses a different function for extension string retrieval
   461          // We cache it here instead of in glfwExtensionSupported mostly to alert
   462          // users as early as possible that their build may be broken
   463  
   464          window->context.GetStringi = (PFNGLGETSTRINGIPROC)
   465              window->context.getProcAddress("glGetStringi");
   466          if (!window->context.GetStringi)
   467          {
   468              _glfwInputError(GLFW_PLATFORM_ERROR,
   469                              "Entry point retrieval is broken");
   470              glfwMakeContextCurrent((GLFWwindow*) previous);
   471              return GLFW_FALSE;
   472          }
   473      }
   474  
   475      if (window->context.client == GLFW_OPENGL_API)
   476      {
   477          // Read back context flags (OpenGL 3.0 and above)
   478          if (window->context.major >= 3)
   479          {
   480              GLint flags;
   481              window->context.GetIntegerv(GL_CONTEXT_FLAGS, &flags);
   482  
   483              if (flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)
   484                  window->context.forward = GLFW_TRUE;
   485  
   486              if (flags & GL_CONTEXT_FLAG_DEBUG_BIT)
   487                  window->context.debug = GLFW_TRUE;
   488              else if (glfwExtensionSupported("GL_ARB_debug_output") &&
   489                       ctxconfig->debug)
   490              {
   491                  // HACK: This is a workaround for older drivers (pre KHR_debug)
   492                  //       not setting the debug bit in the context flags for
   493                  //       debug contexts
   494                  window->context.debug = GLFW_TRUE;
   495              }
   496  
   497              if (flags & GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR)
   498                  window->context.noerror = GLFW_TRUE;
   499          }
   500  
   501          // Read back OpenGL context profile (OpenGL 3.2 and above)
   502          if (window->context.major >= 4 ||
   503              (window->context.major == 3 && window->context.minor >= 2))
   504          {
   505              GLint mask;
   506              window->context.GetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask);
   507  
   508              if (mask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT)
   509                  window->context.profile = GLFW_OPENGL_COMPAT_PROFILE;
   510              else if (mask & GL_CONTEXT_CORE_PROFILE_BIT)
   511                  window->context.profile = GLFW_OPENGL_CORE_PROFILE;
   512              else if (glfwExtensionSupported("GL_ARB_compatibility"))
   513              {
   514                  // HACK: This is a workaround for the compatibility profile bit
   515                  //       not being set in the context flags if an OpenGL 3.2+
   516                  //       context was created without having requested a specific
   517                  //       version
   518                  window->context.profile = GLFW_OPENGL_COMPAT_PROFILE;
   519              }
   520          }
   521  
   522          // Read back robustness strategy
   523          if (glfwExtensionSupported("GL_ARB_robustness"))
   524          {
   525              // NOTE: We avoid using the context flags for detection, as they are
   526              //       only present from 3.0 while the extension applies from 1.1
   527  
   528              GLint strategy;
   529              window->context.GetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB,
   530                                          &strategy);
   531  
   532              if (strategy == GL_LOSE_CONTEXT_ON_RESET_ARB)
   533                  window->context.robustness = GLFW_LOSE_CONTEXT_ON_RESET;
   534              else if (strategy == GL_NO_RESET_NOTIFICATION_ARB)
   535                  window->context.robustness = GLFW_NO_RESET_NOTIFICATION;
   536          }
   537      }
   538      else
   539      {
   540          // Read back robustness strategy
   541          if (glfwExtensionSupported("GL_EXT_robustness"))
   542          {
   543              // NOTE: The values of these constants match those of the OpenGL ARB
   544              //       one, so we can reuse them here
   545  
   546              GLint strategy;
   547              window->context.GetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB,
   548                                          &strategy);
   549  
   550              if (strategy == GL_LOSE_CONTEXT_ON_RESET_ARB)
   551                  window->context.robustness = GLFW_LOSE_CONTEXT_ON_RESET;
   552              else if (strategy == GL_NO_RESET_NOTIFICATION_ARB)
   553                  window->context.robustness = GLFW_NO_RESET_NOTIFICATION;
   554          }
   555      }
   556  
   557      if (glfwExtensionSupported("GL_KHR_context_flush_control"))
   558      {
   559          GLint behavior;
   560          window->context.GetIntegerv(GL_CONTEXT_RELEASE_BEHAVIOR, &behavior);
   561  
   562          if (behavior == GL_NONE)
   563              window->context.release = GLFW_RELEASE_BEHAVIOR_NONE;
   564          else if (behavior == GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH)
   565              window->context.release = GLFW_RELEASE_BEHAVIOR_FLUSH;
   566      }
   567  
   568      // Clearing the front buffer to black to avoid garbage pixels left over from
   569      // previous uses of our bit of VRAM
   570      {
   571          PFNGLCLEARPROC glClear = (PFNGLCLEARPROC)
   572              window->context.getProcAddress("glClear");
   573          glClear(GL_COLOR_BUFFER_BIT);
   574  
   575          if (window->doublebuffer)
   576              window->context.swapBuffers(window);
   577      }
   578  
   579      glfwMakeContextCurrent((GLFWwindow*) previous);
   580      return GLFW_TRUE;
   581  }
   582  
   583  // Searches an extension string for the specified extension
   584  //
   585  GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions)
   586  {
   587      const char* start = extensions;
   588  
   589      for (;;)
   590      {
   591          const char* where;
   592          const char* terminator;
   593  
   594          where = strstr(start, string);
   595          if (!where)
   596              return GLFW_FALSE;
   597  
   598          terminator = where + strlen(string);
   599          if (where == start || *(where - 1) == ' ')
   600          {
   601              if (*terminator == ' ' || *terminator == '\0')
   602                  break;
   603          }
   604  
   605          start = terminator;
   606      }
   607  
   608      return GLFW_TRUE;
   609  }
   610  
   611  
   612  //////////////////////////////////////////////////////////////////////////
   613  //////                        GLFW public API                       //////
   614  //////////////////////////////////////////////////////////////////////////
   615  
   616  GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle)
   617  {
   618      _GLFWwindow* window = (_GLFWwindow*) handle;
   619      _GLFWwindow* previous;
   620  
   621      _GLFW_REQUIRE_INIT();
   622  
   623      previous = _glfwPlatformGetTls(&_glfw.contextSlot);
   624  
   625      if (window && window->context.client == GLFW_NO_API)
   626      {
   627          _glfwInputError(GLFW_NO_WINDOW_CONTEXT,
   628                          "Cannot make current with a window that has no OpenGL or OpenGL ES context");
   629          return;
   630      }
   631  
   632      if (previous)
   633      {
   634          if (!window || window->context.source != previous->context.source)
   635              previous->context.makeCurrent(NULL);
   636      }
   637  
   638      if (window)
   639          window->context.makeCurrent(window);
   640  }
   641  
   642  GLFWAPI GLFWwindow* glfwGetCurrentContext(void)
   643  {
   644      _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
   645      return _glfwPlatformGetTls(&_glfw.contextSlot);
   646  }
   647  
   648  GLFWAPI void glfwSwapBuffers(GLFWwindow* handle)
   649  {
   650      _GLFWwindow* window = (_GLFWwindow*) handle;
   651      assert(window != NULL);
   652  
   653      _GLFW_REQUIRE_INIT();
   654  
   655      if (window->context.client == GLFW_NO_API)
   656      {
   657          _glfwInputError(GLFW_NO_WINDOW_CONTEXT,
   658                          "Cannot swap buffers of a window that has no OpenGL or OpenGL ES context");
   659          return;
   660      }
   661  
   662      window->context.swapBuffers(window);
   663  }
   664  
   665  GLFWAPI void glfwSwapInterval(int interval)
   666  {
   667      _GLFWwindow* window;
   668  
   669      _GLFW_REQUIRE_INIT();
   670  
   671      window = _glfwPlatformGetTls(&_glfw.contextSlot);
   672      if (!window)
   673      {
   674          _glfwInputError(GLFW_NO_CURRENT_CONTEXT,
   675                          "Cannot set swap interval without a current OpenGL or OpenGL ES context");
   676          return;
   677      }
   678  
   679      window->context.swapInterval(interval);
   680  }
   681  
   682  GLFWAPI int glfwExtensionSupported(const char* extension)
   683  {
   684      _GLFWwindow* window;
   685      assert(extension != NULL);
   686  
   687      _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
   688  
   689      window = _glfwPlatformGetTls(&_glfw.contextSlot);
   690      if (!window)
   691      {
   692          _glfwInputError(GLFW_NO_CURRENT_CONTEXT,
   693                          "Cannot query extension without a current OpenGL or OpenGL ES context");
   694          return GLFW_FALSE;
   695      }
   696  
   697      if (*extension == '\0')
   698      {
   699          _glfwInputError(GLFW_INVALID_VALUE, "Extension name cannot be an empty string");
   700          return GLFW_FALSE;
   701      }
   702  
   703      if (window->context.major >= 3)
   704      {
   705          int i;
   706          GLint count;
   707  
   708          // Check if extension is in the modern OpenGL extensions string list
   709  
   710          window->context.GetIntegerv(GL_NUM_EXTENSIONS, &count);
   711  
   712          for (i = 0;  i < count;  i++)
   713          {
   714              const char* en = (const char*)
   715                  window->context.GetStringi(GL_EXTENSIONS, i);
   716              if (!en)
   717              {
   718                  _glfwInputError(GLFW_PLATFORM_ERROR,
   719                                  "Extension string retrieval is broken");
   720                  return GLFW_FALSE;
   721              }
   722  
   723              if (strcmp(en, extension) == 0)
   724                  return GLFW_TRUE;
   725          }
   726      }
   727      else
   728      {
   729          // Check if extension is in the old style OpenGL extensions string
   730  
   731          const char* extensions = (const char*)
   732              window->context.GetString(GL_EXTENSIONS);
   733          if (!extensions)
   734          {
   735              _glfwInputError(GLFW_PLATFORM_ERROR,
   736                              "Extension string retrieval is broken");
   737              return GLFW_FALSE;
   738          }
   739  
   740          if (_glfwStringInExtensionString(extension, extensions))
   741              return GLFW_TRUE;
   742      }
   743  
   744      // Check if extension is in the platform-specific string
   745      return window->context.extensionSupported(extension);
   746  }
   747  
   748  GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname)
   749  {
   750      _GLFWwindow* window;
   751      assert(procname != NULL);
   752  
   753      _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
   754  
   755      window = _glfwPlatformGetTls(&_glfw.contextSlot);
   756      if (!window)
   757      {
   758          _glfwInputError(GLFW_NO_CURRENT_CONTEXT,
   759                          "Cannot query entry point without a current OpenGL or OpenGL ES context");
   760          return NULL;
   761      }
   762  
   763      return window->context.getProcAddress(procname);
   764  }
   765