medfall

A super great game engine
Log | Files | Refs

osmesa_context.cc (11295B)


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