hs

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | Submodules | LICENSE

init.c (9485B)


      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 // Please use C89 style variable declarations in this file because VS 2010
     28 //========================================================================
     29 
     30 #include "internal.h"
     31 #include "mappings.h"
     32 
     33 #include <string.h>
     34 #include <stdlib.h>
     35 #include <stdio.h>
     36 #include <stdarg.h>
     37 #include <assert.h>
     38 
     39 
     40 // The global variables below comprise all mutable global data in GLFW
     41 //
     42 // Any other global variable is a bug
     43 
     44 // Global state shared between compilation units of GLFW
     45 //
     46 _GLFWlibrary _glfw = { GLFW_FALSE };
     47 
     48 // These are outside of _glfw so they can be used before initialization and
     49 // after termination
     50 //
     51 static _GLFWerror _glfwMainThreadError;
     52 static GLFWerrorfun _glfwErrorCallback;
     53 static _GLFWinitconfig _glfwInitHints =
     54 {
     55     GLFW_TRUE,      // hat buttons
     56     {
     57         GLFW_TRUE,  // macOS menu bar
     58         GLFW_TRUE   // macOS bundle chdir
     59     }
     60 };
     61 
     62 // Terminate the library
     63 //
     64 static void _glfw_terminate(void)
     65 {
     66     int i;
     67 
     68     memset(&_glfw.callbacks, 0, sizeof(_glfw.callbacks));
     69 
     70     while (_glfw.windowListHead)
     71         glfwDestroyWindow((GLFWwindow*) _glfw.windowListHead);
     72 
     73     while (_glfw.cursorListHead)
     74         glfwDestroyCursor((GLFWcursor*) _glfw.cursorListHead);
     75 
     76     for (i = 0;  i < _glfw.monitorCount;  i++)
     77     {
     78         _GLFWmonitor* monitor = _glfw.monitors[i];
     79         if (monitor->originalRamp.size)
     80             _glfwPlatformSetGammaRamp(monitor, &monitor->originalRamp);
     81         _glfwFreeMonitor(monitor);
     82     }
     83 
     84     free(_glfw.monitors);
     85     _glfw.monitors = NULL;
     86     _glfw.monitorCount = 0;
     87 
     88     free(_glfw.mappings);
     89     _glfw.mappings = NULL;
     90     _glfw.mappingCount = 0;
     91 
     92     _glfwTerminateVulkan();
     93     _glfwPlatformTerminate();
     94 
     95     _glfw.initialized = GLFW_FALSE;
     96 
     97     while (_glfw.errorListHead)
     98     {
     99         _GLFWerror* error = _glfw.errorListHead;
    100         _glfw.errorListHead = error->next;
    101         free(error);
    102     }
    103 
    104     _glfwPlatformDestroyTls(&_glfw.contextSlot);
    105     _glfwPlatformDestroyTls(&_glfw.errorSlot);
    106     _glfwPlatformDestroyMutex(&_glfw.errorLock);
    107 
    108     memset(&_glfw, 0, sizeof(_glfw));
    109 }
    110 
    111 
    112 //////////////////////////////////////////////////////////////////////////
    113 //////                       GLFW internal API                      //////
    114 //////////////////////////////////////////////////////////////////////////
    115 
    116 char* _glfw_strdup(const char* source)
    117 {
    118     const size_t length = strlen(source);
    119     char* result = (char*)calloc(length + 1, 1);
    120     strcpy(result, source);
    121     return result;
    122 }
    123 
    124 float _glfw_fminf(float a, float b)
    125 {
    126     if (a != a)
    127         return b;
    128     else if (b != b)
    129         return a;
    130     else if (a < b)
    131         return a;
    132     else
    133         return b;
    134 }
    135 
    136 float _glfw_fmaxf(float a, float b)
    137 {
    138     if (a != a)
    139         return b;
    140     else if (b != b)
    141         return a;
    142     else if (a > b)
    143         return a;
    144     else
    145         return b;
    146 }
    147 
    148 
    149 //////////////////////////////////////////////////////////////////////////
    150 //////                         GLFW event API                       //////
    151 //////////////////////////////////////////////////////////////////////////
    152 
    153 // Notifies shared code of an error
    154 //
    155 void _glfwInputError(int code, const char* format, ...)
    156 {
    157     _GLFWerror* error;
    158     char description[_GLFW_MESSAGE_SIZE];
    159 
    160     if (format)
    161     {
    162         va_list vl;
    163 
    164         va_start(vl, format);
    165         vsnprintf(description, sizeof(description), format, vl);
    166         va_end(vl);
    167 
    168         description[sizeof(description) - 1] = '\0';
    169     }
    170     else
    171     {
    172         if (code == GLFW_NOT_INITIALIZED)
    173             strcpy(description, "The GLFW library is not initialized");
    174         else if (code == GLFW_NO_CURRENT_CONTEXT)
    175             strcpy(description, "There is no current context");
    176         else if (code == GLFW_INVALID_ENUM)
    177             strcpy(description, "Invalid argument for enum parameter");
    178         else if (code == GLFW_INVALID_VALUE)
    179             strcpy(description, "Invalid value for parameter");
    180         else if (code == GLFW_OUT_OF_MEMORY)
    181             strcpy(description, "Out of memory");
    182         else if (code == GLFW_API_UNAVAILABLE)
    183             strcpy(description, "The requested API is unavailable");
    184         else if (code == GLFW_VERSION_UNAVAILABLE)
    185             strcpy(description, "The requested API version is unavailable");
    186         else if (code == GLFW_PLATFORM_ERROR)
    187             strcpy(description, "A platform-specific error occurred");
    188         else if (code == GLFW_FORMAT_UNAVAILABLE)
    189             strcpy(description, "The requested format is unavailable");
    190         else if (code == GLFW_NO_WINDOW_CONTEXT)
    191             strcpy(description, "The specified window has no context");
    192         else if (code == GLFW_CURSOR_UNAVAILABLE)
    193             strcpy(description, "The specified cursor shape is unavailable");
    194         else
    195             strcpy(description, "ERROR: UNKNOWN GLFW ERROR");
    196     }
    197 
    198     if (_glfw.initialized)
    199     {
    200         error = (_GLFWerror*)_glfwPlatformGetTls(&_glfw.errorSlot);
    201         if (!error)
    202         {
    203             error = (_GLFWerror*)calloc(1, sizeof(_GLFWerror));
    204             _glfwPlatformSetTls(&_glfw.errorSlot, error);
    205             _glfwPlatformLockMutex(&_glfw.errorLock);
    206             error->next = _glfw.errorListHead;
    207             _glfw.errorListHead = error;
    208             _glfwPlatformUnlockMutex(&_glfw.errorLock);
    209         }
    210     }
    211     else
    212         error = &_glfwMainThreadError;
    213 
    214     error->code = code;
    215     strcpy(error->description, description);
    216 
    217     if (_glfwErrorCallback)
    218         _glfwErrorCallback(code, description);
    219 }
    220 
    221 
    222 //////////////////////////////////////////////////////////////////////////
    223 //////                        GLFW public API                       //////
    224 //////////////////////////////////////////////////////////////////////////
    225 
    226 GLFWAPI int glfwInit(void)
    227 {
    228     if (_glfw.initialized)
    229         return GLFW_TRUE;
    230 
    231     memset(&_glfw, 0, sizeof(_glfw));
    232     _glfw.hints.init = _glfwInitHints;
    233 
    234     if (!_glfwPlatformInit())
    235     {
    236         _glfw_terminate();
    237         return GLFW_FALSE;
    238     }
    239 
    240     if (!_glfwPlatformCreateMutex(&_glfw.errorLock) ||
    241         !_glfwPlatformCreateTls(&_glfw.errorSlot) ||
    242         !_glfwPlatformCreateTls(&_glfw.contextSlot))
    243     {
    244         _glfw_terminate();
    245         return GLFW_FALSE;
    246     }
    247 
    248     _glfwPlatformSetTls(&_glfw.errorSlot, &_glfwMainThreadError);
    249 
    250     _glfw.initialized = GLFW_TRUE;
    251     _glfw.timer.offset = _glfwPlatformGetTimerValue();
    252 
    253     glfwDefaultWindowHints();
    254 
    255     {
    256         int i;
    257 
    258         for (i = 0;  _glfwDefaultMappings[i];  i++)
    259         {
    260             if (!glfwUpdateGamepadMappings(_glfwDefaultMappings[i]))
    261             {
    262                 _glfw_terminate();
    263                 return GLFW_FALSE;
    264             }
    265         }
    266     }
    267 
    268     return GLFW_TRUE;
    269 }
    270 
    271 GLFWAPI void glfwTerminate(void)
    272 {
    273     if (!_glfw.initialized)
    274         return;
    275 
    276     _glfw_terminate();
    277 }
    278 
    279 GLFWAPI void glfwInitHint(int hint, int value)
    280 {
    281     switch (hint)
    282     {
    283         case GLFW_JOYSTICK_HAT_BUTTONS:
    284             _glfwInitHints.hatButtons = value;
    285             return;
    286         case GLFW_COCOA_CHDIR_RESOURCES:
    287             _glfwInitHints.ns.chdir = value;
    288             return;
    289         case GLFW_COCOA_MENUBAR:
    290             _glfwInitHints.ns.menubar = value;
    291             return;
    292     }
    293 
    294     _glfwInputError(GLFW_INVALID_ENUM,
    295                     "Invalid init hint 0x%08X", hint);
    296 }
    297 
    298 GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev)
    299 {
    300     if (major != NULL)
    301         *major = GLFW_VERSION_MAJOR;
    302     if (minor != NULL)
    303         *minor = GLFW_VERSION_MINOR;
    304     if (rev != NULL)
    305         *rev = GLFW_VERSION_REVISION;
    306 }
    307 
    308 GLFWAPI const char* glfwGetVersionString(void)
    309 {
    310     return _glfwPlatformGetVersionString();
    311 }
    312 
    313 GLFWAPI int glfwGetError(const char** description)
    314 {
    315     _GLFWerror* error;
    316     int code = GLFW_NO_ERROR;
    317 
    318     if (description)
    319         *description = NULL;
    320 
    321     if (_glfw.initialized)
    322         error = (_GLFWerror*)_glfwPlatformGetTls(&_glfw.errorSlot);
    323     else
    324         error = &_glfwMainThreadError;
    325 
    326     if (error)
    327     {
    328         code = error->code;
    329         error->code = GLFW_NO_ERROR;
    330         if (description && code)
    331             *description = error->description;
    332     }
    333 
    334     return code;
    335 }
    336 
    337 GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun)
    338 {
    339     _GLFW_SWAP_POINTERS(GLFWerrorfun, _glfwErrorCallback, cbfun);
    340     return cbfun;
    341 }
    342