volviewer

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

init.c (14504B)


      1 //========================================================================
      2 // GLFW 3.4 - www.glfw.org
      3 //------------------------------------------------------------------------
      4 // Copyright (c) 2002-2006 Marcus Geelnard
      5 // Copyright (c) 2006-2018 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 <string.h>
     31 #include <stdlib.h>
     32 #include <stdio.h>
     33 #include <stdarg.h>
     34 #include <assert.h>
     35 
     36 
     37 // NOTE: The global variables below comprise all mutable global data in GLFW
     38 //       Any other mutable global variable is a bug
     39 
     40 // This contains all mutable state shared between compilation units of GLFW
     41 //
     42 _GLFWlibrary _glfw = { GLFW_FALSE };
     43 
     44 // These are outside of _glfw so they can be used before initialization and
     45 // after termination without special handling when _glfw is cleared to zero
     46 //
     47 static _GLFWerror _glfwMainThreadError;
     48 static GLFWerrorfun _glfwErrorCallback;
     49 static GLFWallocator _glfwInitAllocator;
     50 static _GLFWinitconfig _glfwInitHints =
     51 {
     52     .hatButtons = GLFW_TRUE,
     53     .angleType = GLFW_ANGLE_PLATFORM_TYPE_NONE,
     54     .platformID = GLFW_ANY_PLATFORM,
     55     .vulkanLoader = NULL,
     56     .ns =
     57     {
     58         .menubar = GLFW_TRUE,
     59         .chdir = GLFW_TRUE
     60     },
     61     .x11 =
     62     {
     63         .xcbVulkanSurface = GLFW_TRUE,
     64     },
     65     .wl =
     66     {
     67         .libdecorMode = GLFW_WAYLAND_PREFER_LIBDECOR
     68     },
     69 };
     70 
     71 // The allocation function used when no custom allocator is set
     72 //
     73 static void* defaultAllocate(size_t size, void* user)
     74 {
     75     return malloc(size);
     76 }
     77 
     78 // The deallocation function used when no custom allocator is set
     79 //
     80 static void defaultDeallocate(void* block, void* user)
     81 {
     82     free(block);
     83 }
     84 
     85 // The reallocation function used when no custom allocator is set
     86 //
     87 static void* defaultReallocate(void* block, size_t size, void* user)
     88 {
     89     return realloc(block, size);
     90 }
     91 
     92 // Terminate the library
     93 //
     94 static void terminate(void)
     95 {
     96     int i;
     97 
     98     memset(&_glfw.callbacks, 0, sizeof(_glfw.callbacks));
     99 
    100     while (_glfw.windowListHead)
    101         glfwDestroyWindow((GLFWwindow*) _glfw.windowListHead);
    102 
    103     while (_glfw.cursorListHead)
    104         glfwDestroyCursor((GLFWcursor*) _glfw.cursorListHead);
    105 
    106     for (i = 0;  i < _glfw.monitorCount;  i++)
    107     {
    108         _GLFWmonitor* monitor = _glfw.monitors[i];
    109         if (monitor->originalRamp.size)
    110             _glfw.platform.setGammaRamp(monitor, &monitor->originalRamp);
    111         _glfwFreeMonitor(monitor);
    112     }
    113 
    114     _glfw_free(_glfw.monitors);
    115     _glfw.monitors = NULL;
    116     _glfw.monitorCount = 0;
    117 
    118     _glfw_free(_glfw.mappings);
    119     _glfw.mappings = NULL;
    120     _glfw.mappingCount = 0;
    121 
    122     _glfwTerminateVulkan();
    123     _glfw.platform.terminateJoysticks();
    124     _glfw.platform.terminate();
    125 
    126     _glfw.initialized = GLFW_FALSE;
    127 
    128     while (_glfw.errorListHead)
    129     {
    130         _GLFWerror* error = _glfw.errorListHead;
    131         _glfw.errorListHead = error->next;
    132         _glfw_free(error);
    133     }
    134 
    135     _glfwPlatformDestroyTls(&_glfw.contextSlot);
    136     _glfwPlatformDestroyTls(&_glfw.errorSlot);
    137     _glfwPlatformDestroyMutex(&_glfw.errorLock);
    138 
    139     memset(&_glfw, 0, sizeof(_glfw));
    140 }
    141 
    142 
    143 //////////////////////////////////////////////////////////////////////////
    144 //////                       GLFW internal API                      //////
    145 //////////////////////////////////////////////////////////////////////////
    146 
    147 // Encode a Unicode code point to a UTF-8 stream
    148 // Based on cutef8 by Jeff Bezanson (Public Domain)
    149 //
    150 size_t _glfwEncodeUTF8(char* s, uint32_t codepoint)
    151 {
    152     size_t count = 0;
    153 
    154     if (codepoint < 0x80)
    155         s[count++] = (char) codepoint;
    156     else if (codepoint < 0x800)
    157     {
    158         s[count++] = (codepoint >> 6) | 0xc0;
    159         s[count++] = (codepoint & 0x3f) | 0x80;
    160     }
    161     else if (codepoint < 0x10000)
    162     {
    163         s[count++] = (codepoint >> 12) | 0xe0;
    164         s[count++] = ((codepoint >> 6) & 0x3f) | 0x80;
    165         s[count++] = (codepoint & 0x3f) | 0x80;
    166     }
    167     else if (codepoint < 0x110000)
    168     {
    169         s[count++] = (codepoint >> 18) | 0xf0;
    170         s[count++] = ((codepoint >> 12) & 0x3f) | 0x80;
    171         s[count++] = ((codepoint >> 6) & 0x3f) | 0x80;
    172         s[count++] = (codepoint & 0x3f) | 0x80;
    173     }
    174 
    175     return count;
    176 }
    177 
    178 // Splits and translates a text/uri-list into separate file paths
    179 // NOTE: This function destroys the provided string
    180 //
    181 char** _glfwParseUriList(char* text, int* count)
    182 {
    183     const char* prefix = "file://";
    184     char** paths = NULL;
    185     char* line;
    186 
    187     *count = 0;
    188 
    189     while ((line = strtok(text, "\r\n")))
    190     {
    191         char* path;
    192 
    193         text = NULL;
    194 
    195         if (line[0] == '#')
    196             continue;
    197 
    198         if (strncmp(line, prefix, strlen(prefix)) == 0)
    199         {
    200             line += strlen(prefix);
    201             // TODO: Validate hostname
    202             while (*line != '/')
    203                 line++;
    204         }
    205 
    206         (*count)++;
    207 
    208         path = _glfw_calloc(strlen(line) + 1, 1);
    209         paths = _glfw_realloc(paths, *count * sizeof(char*));
    210         paths[*count - 1] = path;
    211 
    212         while (*line)
    213         {
    214             if (line[0] == '%' && line[1] && line[2])
    215             {
    216                 const char digits[3] = { line[1], line[2], '\0' };
    217                 *path = (char) strtol(digits, NULL, 16);
    218                 line += 2;
    219             }
    220             else
    221                 *path = *line;
    222 
    223             path++;
    224             line++;
    225         }
    226     }
    227 
    228     return paths;
    229 }
    230 
    231 char* _glfw_strdup(const char* source)
    232 {
    233     const size_t length = strlen(source);
    234     char* result = _glfw_calloc(length + 1, 1);
    235     strcpy(result, source);
    236     return result;
    237 }
    238 
    239 int _glfw_min(int a, int b)
    240 {
    241     return a < b ? a : b;
    242 }
    243 
    244 int _glfw_max(int a, int b)
    245 {
    246     return a > b ? a : b;
    247 }
    248 
    249 void* _glfw_calloc(size_t count, size_t size)
    250 {
    251     if (count && size)
    252     {
    253         void* block;
    254 
    255         if (count > SIZE_MAX / size)
    256         {
    257             _glfwInputError(GLFW_INVALID_VALUE, "Allocation size overflow");
    258             return NULL;
    259         }
    260 
    261         block = _glfw.allocator.allocate(count * size, _glfw.allocator.user);
    262         if (block)
    263             return memset(block, 0, count * size);
    264         else
    265         {
    266             _glfwInputError(GLFW_OUT_OF_MEMORY, NULL);
    267             return NULL;
    268         }
    269     }
    270     else
    271         return NULL;
    272 }
    273 
    274 void* _glfw_realloc(void* block, size_t size)
    275 {
    276     if (block && size)
    277     {
    278         void* resized = _glfw.allocator.reallocate(block, size, _glfw.allocator.user);
    279         if (resized)
    280             return resized;
    281         else
    282         {
    283             _glfwInputError(GLFW_OUT_OF_MEMORY, NULL);
    284             return NULL;
    285         }
    286     }
    287     else if (block)
    288     {
    289         _glfw_free(block);
    290         return NULL;
    291     }
    292     else
    293         return _glfw_calloc(1, size);
    294 }
    295 
    296 void _glfw_free(void* block)
    297 {
    298     if (block)
    299         _glfw.allocator.deallocate(block, _glfw.allocator.user);
    300 }
    301 
    302 
    303 //////////////////////////////////////////////////////////////////////////
    304 //////                         GLFW event API                       //////
    305 //////////////////////////////////////////////////////////////////////////
    306 
    307 // Notifies shared code of an error
    308 //
    309 void _glfwInputError(int code, const char* format, ...)
    310 {
    311     _GLFWerror* error;
    312     char description[_GLFW_MESSAGE_SIZE];
    313 
    314     if (format)
    315     {
    316         va_list vl;
    317 
    318         va_start(vl, format);
    319         vsnprintf(description, sizeof(description), format, vl);
    320         va_end(vl);
    321 
    322         description[sizeof(description) - 1] = '\0';
    323     }
    324     else
    325     {
    326         if (code == GLFW_NOT_INITIALIZED)
    327             strcpy(description, "The GLFW library is not initialized");
    328         else if (code == GLFW_NO_CURRENT_CONTEXT)
    329             strcpy(description, "There is no current context");
    330         else if (code == GLFW_INVALID_ENUM)
    331             strcpy(description, "Invalid argument for enum parameter");
    332         else if (code == GLFW_INVALID_VALUE)
    333             strcpy(description, "Invalid value for parameter");
    334         else if (code == GLFW_OUT_OF_MEMORY)
    335             strcpy(description, "Out of memory");
    336         else if (code == GLFW_API_UNAVAILABLE)
    337             strcpy(description, "The requested API is unavailable");
    338         else if (code == GLFW_VERSION_UNAVAILABLE)
    339             strcpy(description, "The requested API version is unavailable");
    340         else if (code == GLFW_PLATFORM_ERROR)
    341             strcpy(description, "A platform-specific error occurred");
    342         else if (code == GLFW_FORMAT_UNAVAILABLE)
    343             strcpy(description, "The requested format is unavailable");
    344         else if (code == GLFW_NO_WINDOW_CONTEXT)
    345             strcpy(description, "The specified window has no context");
    346         else if (code == GLFW_CURSOR_UNAVAILABLE)
    347             strcpy(description, "The specified cursor shape is unavailable");
    348         else if (code == GLFW_FEATURE_UNAVAILABLE)
    349             strcpy(description, "The requested feature cannot be implemented for this platform");
    350         else if (code == GLFW_FEATURE_UNIMPLEMENTED)
    351             strcpy(description, "The requested feature has not yet been implemented for this platform");
    352         else if (code == GLFW_PLATFORM_UNAVAILABLE)
    353             strcpy(description, "The requested platform is unavailable");
    354         else
    355             strcpy(description, "ERROR: UNKNOWN GLFW ERROR");
    356     }
    357 
    358     if (_glfw.initialized)
    359     {
    360         error = _glfwPlatformGetTls(&_glfw.errorSlot);
    361         if (!error)
    362         {
    363             error = _glfw_calloc(1, sizeof(_GLFWerror));
    364             _glfwPlatformSetTls(&_glfw.errorSlot, error);
    365             _glfwPlatformLockMutex(&_glfw.errorLock);
    366             error->next = _glfw.errorListHead;
    367             _glfw.errorListHead = error;
    368             _glfwPlatformUnlockMutex(&_glfw.errorLock);
    369         }
    370     }
    371     else
    372         error = &_glfwMainThreadError;
    373 
    374     error->code = code;
    375     strcpy(error->description, description);
    376 
    377     if (_glfwErrorCallback)
    378         _glfwErrorCallback(code, description);
    379 }
    380 
    381 
    382 //////////////////////////////////////////////////////////////////////////
    383 //////                        GLFW public API                       //////
    384 //////////////////////////////////////////////////////////////////////////
    385 
    386 GLFWAPI int glfwInit(void)
    387 {
    388     if (_glfw.initialized)
    389         return GLFW_TRUE;
    390 
    391     memset(&_glfw, 0, sizeof(_glfw));
    392     _glfw.hints.init = _glfwInitHints;
    393 
    394     _glfw.allocator = _glfwInitAllocator;
    395     if (!_glfw.allocator.allocate)
    396     {
    397         _glfw.allocator.allocate   = defaultAllocate;
    398         _glfw.allocator.reallocate = defaultReallocate;
    399         _glfw.allocator.deallocate = defaultDeallocate;
    400     }
    401 
    402     if (!_glfwSelectPlatform(_glfw.hints.init.platformID, &_glfw.platform))
    403         return GLFW_FALSE;
    404 
    405     if (!_glfw.platform.init())
    406     {
    407         terminate();
    408         return GLFW_FALSE;
    409     }
    410 
    411     if (!_glfwPlatformCreateMutex(&_glfw.errorLock) ||
    412         !_glfwPlatformCreateTls(&_glfw.errorSlot) ||
    413         !_glfwPlatformCreateTls(&_glfw.contextSlot))
    414     {
    415         terminate();
    416         return GLFW_FALSE;
    417     }
    418 
    419     _glfwPlatformSetTls(&_glfw.errorSlot, &_glfwMainThreadError);
    420 
    421     _glfwInitGamepadMappings();
    422 
    423     _glfwPlatformInitTimer();
    424     _glfw.timer.offset = _glfwPlatformGetTimerValue();
    425 
    426     _glfw.initialized = GLFW_TRUE;
    427 
    428     glfwDefaultWindowHints();
    429     return GLFW_TRUE;
    430 }
    431 
    432 GLFWAPI void glfwTerminate(void)
    433 {
    434     if (!_glfw.initialized)
    435         return;
    436 
    437     terminate();
    438 }
    439 
    440 GLFWAPI void glfwInitHint(int hint, int value)
    441 {
    442     switch (hint)
    443     {
    444         case GLFW_JOYSTICK_HAT_BUTTONS:
    445             _glfwInitHints.hatButtons = value;
    446             return;
    447         case GLFW_ANGLE_PLATFORM_TYPE:
    448             _glfwInitHints.angleType = value;
    449             return;
    450         case GLFW_PLATFORM:
    451             _glfwInitHints.platformID = value;
    452             return;
    453         case GLFW_COCOA_CHDIR_RESOURCES:
    454             _glfwInitHints.ns.chdir = value;
    455             return;
    456         case GLFW_COCOA_MENUBAR:
    457             _glfwInitHints.ns.menubar = value;
    458             return;
    459         case GLFW_X11_XCB_VULKAN_SURFACE:
    460             _glfwInitHints.x11.xcbVulkanSurface = value;
    461             return;
    462         case GLFW_WAYLAND_LIBDECOR:
    463             _glfwInitHints.wl.libdecorMode = value;
    464             return;
    465     }
    466 
    467     _glfwInputError(GLFW_INVALID_ENUM,
    468                     "Invalid init hint 0x%08X", hint);
    469 }
    470 
    471 GLFWAPI void glfwInitAllocator(const GLFWallocator* allocator)
    472 {
    473     if (allocator)
    474     {
    475         if (allocator->allocate && allocator->reallocate && allocator->deallocate)
    476             _glfwInitAllocator = *allocator;
    477         else
    478             _glfwInputError(GLFW_INVALID_VALUE, "Missing function in allocator");
    479     }
    480     else
    481         memset(&_glfwInitAllocator, 0, sizeof(GLFWallocator));
    482 }
    483 
    484 GLFWAPI void glfwInitVulkanLoader(PFN_vkGetInstanceProcAddr loader)
    485 {
    486     _glfwInitHints.vulkanLoader = loader;
    487 }
    488 
    489 GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev)
    490 {
    491     if (major != NULL)
    492         *major = GLFW_VERSION_MAJOR;
    493     if (minor != NULL)
    494         *minor = GLFW_VERSION_MINOR;
    495     if (rev != NULL)
    496         *rev = GLFW_VERSION_REVISION;
    497 }
    498 
    499 GLFWAPI int glfwGetError(const char** description)
    500 {
    501     _GLFWerror* error;
    502     int code = GLFW_NO_ERROR;
    503 
    504     if (description)
    505         *description = NULL;
    506 
    507     if (_glfw.initialized)
    508         error = _glfwPlatformGetTls(&_glfw.errorSlot);
    509     else
    510         error = &_glfwMainThreadError;
    511 
    512     if (error)
    513     {
    514         code = error->code;
    515         error->code = GLFW_NO_ERROR;
    516         if (description && code)
    517             *description = error->description;
    518     }
    519 
    520     return code;
    521 }
    522 
    523 GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun)
    524 {
    525     _GLFW_SWAP(GLFWerrorfun, _glfwErrorCallback, cbfun);
    526     return cbfun;
    527 }
    528