volviewer

Volumetric Data Toy Viewer
git clone anongit@rnpnr.xyz:volviewer.git
Log | Files | Refs | Feed | LICENSE

osmesa_context.c (11935B)


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