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

     1  //========================================================================
     2  // GLFW 3.4 OSMesa - www.glfw.org
     3  //------------------------------------------------------------------------
     4  // Copyright (c) 2016 Google Inc.
     5  // Copyright (c) 2016-2017 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 <stdlib.h>
    31  #include <string.h>
    32  #include <assert.h>
    33  
    34  #include "internal.h"
    35  
    36  
    37  static void makeContextCurrentOSMesa(_GLFWwindow* window)
    38  {
    39      if (window)
    40      {
    41          int width, height;
    42          _glfw.platform.getFramebufferSize(window, &width, &height);
    43  
    44          // Check to see if we need to allocate a new buffer
    45          if ((window->context.osmesa.buffer == NULL) ||
    46              (width != window->context.osmesa.width) ||
    47              (height != window->context.osmesa.height))
    48          {
    49              _glfw_free(window->context.osmesa.buffer);
    50  
    51              // Allocate the new buffer (width * height * 8-bit RGBA)
    52              window->context.osmesa.buffer = _glfw_calloc(4, (size_t) width * height);
    53              window->context.osmesa.width  = width;
    54              window->context.osmesa.height = height;
    55          }
    56  
    57          if (!OSMesaMakeCurrent(window->context.osmesa.handle,
    58                                 window->context.osmesa.buffer,
    59                                 GL_UNSIGNED_BYTE,
    60                                 width, height))
    61          {
    62              _glfwInputError(GLFW_PLATFORM_ERROR,
    63                              "OSMesa: Failed to make context current");
    64              return;
    65          }
    66      }
    67  
    68      _glfwPlatformSetTls(&_glfw.contextSlot, window);
    69  }
    70  
    71  static GLFWglproc getProcAddressOSMesa(const char* procname)
    72  {
    73      return (GLFWglproc) OSMesaGetProcAddress(procname);
    74  }
    75  
    76  static void destroyContextOSMesa(_GLFWwindow* window)
    77  {
    78      if (window->context.osmesa.handle)
    79      {
    80          OSMesaDestroyContext(window->context.osmesa.handle);
    81          window->context.osmesa.handle = NULL;
    82      }
    83  
    84      if (window->context.osmesa.buffer)
    85      {
    86          _glfw_free(window->context.osmesa.buffer);
    87          window->context.osmesa.width = 0;
    88          window->context.osmesa.height = 0;
    89      }
    90  }
    91  
    92  static void swapBuffersOSMesa(_GLFWwindow* window)
    93  {
    94      // No double buffering on OSMesa
    95  }
    96  
    97  static void swapIntervalOSMesa(int interval)
    98  {
    99      // No swap interval on OSMesa
   100  }
   101  
   102  static int extensionSupportedOSMesa(const char* extension)
   103  {
   104      // OSMesa does not have extensions
   105      return GLFW_FALSE;
   106  }
   107  
   108  
   109  //////////////////////////////////////////////////////////////////////////
   110  //////                       GLFW internal API                      //////
   111  //////////////////////////////////////////////////////////////////////////
   112  
   113  GLFWbool _glfwInitOSMesa(void)
   114  {
   115      int i;
   116      const char* sonames[] =
   117      {
   118  #if defined(_GLFW_OSMESA_LIBRARY)
   119          _GLFW_OSMESA_LIBRARY,
   120  #elif defined(_WIN32)
   121          "libOSMesa.dll",
   122          "OSMesa.dll",
   123  #elif defined(__APPLE__)
   124          "libOSMesa.8.dylib",
   125  #elif defined(__CYGWIN__)
   126          "libOSMesa-8.so",
   127  #elif defined(__OpenBSD__) || defined(__NetBSD__)
   128          "libOSMesa.so",
   129  #else
   130          "libOSMesa.so.8",
   131          "libOSMesa.so.6",
   132  #endif
   133          NULL
   134      };
   135  
   136      if (_glfw.osmesa.handle)
   137          return GLFW_TRUE;
   138  
   139      for (i = 0;  sonames[i];  i++)
   140      {
   141          _glfw.osmesa.handle = _glfwPlatformLoadModule(sonames[i]);
   142          if (_glfw.osmesa.handle)
   143              break;
   144      }
   145  
   146      if (!_glfw.osmesa.handle)
   147      {
   148          _glfwInputError(GLFW_API_UNAVAILABLE, "OSMesa: Library not found");
   149          return GLFW_FALSE;
   150      }
   151  
   152      _glfw.osmesa.CreateContextExt = (PFN_OSMesaCreateContextExt)
   153          _glfwPlatformGetModuleSymbol(_glfw.osmesa.handle, "OSMesaCreateContextExt");
   154      _glfw.osmesa.CreateContextAttribs = (PFN_OSMesaCreateContextAttribs)
   155          _glfwPlatformGetModuleSymbol(_glfw.osmesa.handle, "OSMesaCreateContextAttribs");
   156      _glfw.osmesa.DestroyContext = (PFN_OSMesaDestroyContext)
   157          _glfwPlatformGetModuleSymbol(_glfw.osmesa.handle, "OSMesaDestroyContext");
   158      _glfw.osmesa.MakeCurrent = (PFN_OSMesaMakeCurrent)
   159          _glfwPlatformGetModuleSymbol(_glfw.osmesa.handle, "OSMesaMakeCurrent");
   160      _glfw.osmesa.GetColorBuffer = (PFN_OSMesaGetColorBuffer)
   161          _glfwPlatformGetModuleSymbol(_glfw.osmesa.handle, "OSMesaGetColorBuffer");
   162      _glfw.osmesa.GetDepthBuffer = (PFN_OSMesaGetDepthBuffer)
   163          _glfwPlatformGetModuleSymbol(_glfw.osmesa.handle, "OSMesaGetDepthBuffer");
   164      _glfw.osmesa.GetProcAddress = (PFN_OSMesaGetProcAddress)
   165          _glfwPlatformGetModuleSymbol(_glfw.osmesa.handle, "OSMesaGetProcAddress");
   166  
   167      if (!_glfw.osmesa.CreateContextExt ||
   168          !_glfw.osmesa.DestroyContext ||
   169          !_glfw.osmesa.MakeCurrent ||
   170          !_glfw.osmesa.GetColorBuffer ||
   171          !_glfw.osmesa.GetDepthBuffer ||
   172          !_glfw.osmesa.GetProcAddress)
   173      {
   174          _glfwInputError(GLFW_PLATFORM_ERROR,
   175                          "OSMesa: Failed to load required entry points");
   176  
   177          _glfwTerminateOSMesa();
   178          return GLFW_FALSE;
   179      }
   180  
   181      return GLFW_TRUE;
   182  }
   183  
   184  void _glfwTerminateOSMesa(void)
   185  {
   186      if (_glfw.osmesa.handle)
   187      {
   188          _glfwPlatformFreeModule(_glfw.osmesa.handle);
   189          _glfw.osmesa.handle = NULL;
   190      }
   191  }
   192  
   193  #define SET_ATTRIB(a, v) \
   194  { \
   195      assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
   196      attribs[index++] = a; \
   197      attribs[index++] = v; \
   198  }
   199  
   200  GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
   201                                    const _GLFWctxconfig* ctxconfig,
   202                                    const _GLFWfbconfig* fbconfig)
   203  {
   204      OSMesaContext share = NULL;
   205      const int accumBits = fbconfig->accumRedBits +
   206                            fbconfig->accumGreenBits +
   207                            fbconfig->accumBlueBits +
   208                            fbconfig->accumAlphaBits;
   209  
   210      if (ctxconfig->client == GLFW_OPENGL_ES_API)
   211      {
   212          _glfwInputError(GLFW_API_UNAVAILABLE,
   213                          "OSMesa: OpenGL ES is not available on OSMesa");
   214          return GLFW_FALSE;
   215      }
   216  
   217      if (ctxconfig->share)
   218          share = ctxconfig->share->context.osmesa.handle;
   219  
   220      if (OSMesaCreateContextAttribs)
   221      {
   222          int index = 0, attribs[40];
   223  
   224          SET_ATTRIB(OSMESA_FORMAT, OSMESA_RGBA);
   225          SET_ATTRIB(OSMESA_DEPTH_BITS, fbconfig->depthBits);
   226          SET_ATTRIB(OSMESA_STENCIL_BITS, fbconfig->stencilBits);
   227          SET_ATTRIB(OSMESA_ACCUM_BITS, accumBits);
   228  
   229          if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
   230          {
   231              SET_ATTRIB(OSMESA_PROFILE, OSMESA_CORE_PROFILE);
   232          }
   233          else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
   234          {
   235              SET_ATTRIB(OSMESA_PROFILE, OSMESA_COMPAT_PROFILE);
   236          }
   237  
   238          if (ctxconfig->major != 1 || ctxconfig->minor != 0)
   239          {
   240              SET_ATTRIB(OSMESA_CONTEXT_MAJOR_VERSION, ctxconfig->major);
   241              SET_ATTRIB(OSMESA_CONTEXT_MINOR_VERSION, ctxconfig->minor);
   242          }
   243  
   244          if (ctxconfig->forward)
   245          {
   246              _glfwInputError(GLFW_VERSION_UNAVAILABLE,
   247                              "OSMesa: Forward-compatible contexts not supported");
   248              return GLFW_FALSE;
   249          }
   250  
   251          SET_ATTRIB(0, 0);
   252  
   253          window->context.osmesa.handle =
   254              OSMesaCreateContextAttribs(attribs, share);
   255      }
   256      else
   257      {
   258          if (ctxconfig->profile)
   259          {
   260              _glfwInputError(GLFW_VERSION_UNAVAILABLE,
   261                              "OSMesa: OpenGL profiles unavailable");
   262              return GLFW_FALSE;
   263          }
   264  
   265          window->context.osmesa.handle =
   266              OSMesaCreateContextExt(OSMESA_RGBA,
   267                                     fbconfig->depthBits,
   268                                     fbconfig->stencilBits,
   269                                     accumBits,
   270                                     share);
   271      }
   272  
   273      if (window->context.osmesa.handle == NULL)
   274      {
   275          _glfwInputError(GLFW_VERSION_UNAVAILABLE,
   276                          "OSMesa: Failed to create context");
   277          return GLFW_FALSE;
   278      }
   279  
   280      window->context.makeCurrent = makeContextCurrentOSMesa;
   281      window->context.swapBuffers = swapBuffersOSMesa;
   282      window->context.swapInterval = swapIntervalOSMesa;
   283      window->context.extensionSupported = extensionSupportedOSMesa;
   284      window->context.getProcAddress = getProcAddressOSMesa;
   285      window->context.destroy = destroyContextOSMesa;
   286  
   287      return GLFW_TRUE;
   288  }
   289  
   290  #undef SET_ATTRIB
   291  
   292  
   293  //////////////////////////////////////////////////////////////////////////
   294  //////                        GLFW native API                       //////
   295  //////////////////////////////////////////////////////////////////////////
   296  
   297  GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* handle, int* width,
   298                                       int* height, int* format, void** buffer)
   299  {
   300      void* mesaBuffer;
   301      GLint mesaWidth, mesaHeight, mesaFormat;
   302      _GLFWwindow* window = (_GLFWwindow*) handle;
   303      assert(window != NULL);
   304  
   305      _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
   306  
   307      if (window->context.source != GLFW_OSMESA_CONTEXT_API)
   308      {
   309          _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
   310          return GLFW_FALSE;
   311      }
   312  
   313      if (!OSMesaGetColorBuffer(window->context.osmesa.handle,
   314                                &mesaWidth, &mesaHeight,
   315                                &mesaFormat, &mesaBuffer))
   316      {
   317          _glfwInputError(GLFW_PLATFORM_ERROR,
   318                          "OSMesa: Failed to retrieve color buffer");
   319          return GLFW_FALSE;
   320      }
   321  
   322      if (width)
   323          *width = mesaWidth;
   324      if (height)
   325          *height = mesaHeight;
   326      if (format)
   327          *format = mesaFormat;
   328      if (buffer)
   329          *buffer = mesaBuffer;
   330  
   331      return GLFW_TRUE;
   332  }
   333  
   334  GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* handle,
   335                                       int* width, int* height,
   336                                       int* bytesPerValue,
   337                                       void** buffer)
   338  {
   339      void* mesaBuffer;
   340      GLint mesaWidth, mesaHeight, mesaBytes;
   341      _GLFWwindow* window = (_GLFWwindow*) handle;
   342      assert(window != NULL);
   343  
   344      _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
   345  
   346      if (window->context.source != GLFW_OSMESA_CONTEXT_API)
   347      {
   348          _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
   349          return GLFW_FALSE;
   350      }
   351  
   352      if (!OSMesaGetDepthBuffer(window->context.osmesa.handle,
   353                                &mesaWidth, &mesaHeight,
   354                                &mesaBytes, &mesaBuffer))
   355      {
   356          _glfwInputError(GLFW_PLATFORM_ERROR,
   357                          "OSMesa: Failed to retrieve depth buffer");
   358          return GLFW_FALSE;
   359      }
   360  
   361      if (width)
   362          *width = mesaWidth;
   363      if (height)
   364          *height = mesaHeight;
   365      if (bytesPerValue)
   366          *bytesPerValue = mesaBytes;
   367      if (buffer)
   368          *buffer = mesaBuffer;
   369  
   370      return GLFW_TRUE;
   371  }
   372  
   373  GLFWAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow* handle)
   374  {
   375      _GLFWwindow* window = (_GLFWwindow*) handle;
   376      _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
   377  
   378      if (window->context.source != GLFW_OSMESA_CONTEXT_API)
   379      {
   380          _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
   381          return NULL;
   382      }
   383  
   384      return window->context.osmesa.handle;
   385  }
   386