zorldo

Goofing around with Ebiten
git clone git://bsandro.tech/zorldo
Log | Files | Refs | README

init.c (9267B)


      1 //========================================================================
      2 // GLFW 3.3 - 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 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 = 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
    193             strcpy(description, "ERROR: UNKNOWN GLFW ERROR");
    194     }
    195 
    196     if (_glfw.initialized)
    197     {
    198         error = _glfwPlatformGetTls(&_glfw.errorSlot);
    199         if (!error)
    200         {
    201             error = calloc(1, sizeof(_GLFWerror));
    202             _glfwPlatformSetTls(&_glfw.errorSlot, error);
    203             _glfwPlatformLockMutex(&_glfw.errorLock);
    204             error->next = _glfw.errorListHead;
    205             _glfw.errorListHead = error;
    206             _glfwPlatformUnlockMutex(&_glfw.errorLock);
    207         }
    208     }
    209     else
    210         error = &_glfwMainThreadError;
    211 
    212     error->code = code;
    213     strcpy(error->description, description);
    214 
    215     if (_glfwErrorCallback)
    216         _glfwErrorCallback(code, description);
    217 }
    218 
    219 
    220 //////////////////////////////////////////////////////////////////////////
    221 //////                        GLFW public API                       //////
    222 //////////////////////////////////////////////////////////////////////////
    223 
    224 GLFWAPI int glfwInit(void)
    225 {
    226     if (_glfw.initialized)
    227         return GLFW_TRUE;
    228 
    229     memset(&_glfw, 0, sizeof(_glfw));
    230     _glfw.hints.init = _glfwInitHints;
    231 
    232     if (!_glfwPlatformInit())
    233     {
    234         terminate();
    235         return GLFW_FALSE;
    236     }
    237 
    238     if (!_glfwPlatformCreateMutex(&_glfw.errorLock) ||
    239         !_glfwPlatformCreateTls(&_glfw.errorSlot) ||
    240         !_glfwPlatformCreateTls(&_glfw.contextSlot))
    241     {
    242         terminate();
    243         return GLFW_FALSE;
    244     }
    245 
    246     _glfwPlatformSetTls(&_glfw.errorSlot, &_glfwMainThreadError);
    247 
    248     _glfw.initialized = GLFW_TRUE;
    249     _glfw.timer.offset = _glfwPlatformGetTimerValue();
    250 
    251     glfwDefaultWindowHints();
    252 
    253     {
    254         int i;
    255 
    256         for (i = 0;  _glfwDefaultMappings[i];  i++)
    257         {
    258             if (!glfwUpdateGamepadMappings(_glfwDefaultMappings[i]))
    259             {
    260                 terminate();
    261                 return GLFW_FALSE;
    262             }
    263         }
    264     }
    265 
    266     return GLFW_TRUE;
    267 }
    268 
    269 GLFWAPI void glfwTerminate(void)
    270 {
    271     if (!_glfw.initialized)
    272         return;
    273 
    274     terminate();
    275 }
    276 
    277 GLFWAPI void glfwInitHint(int hint, int value)
    278 {
    279     switch (hint)
    280     {
    281         case GLFW_JOYSTICK_HAT_BUTTONS:
    282             _glfwInitHints.hatButtons = value;
    283             return;
    284         case GLFW_COCOA_CHDIR_RESOURCES:
    285             _glfwInitHints.ns.chdir = value;
    286             return;
    287         case GLFW_COCOA_MENUBAR:
    288             _glfwInitHints.ns.menubar = value;
    289             return;
    290     }
    291 
    292     _glfwInputError(GLFW_INVALID_ENUM,
    293                     "Invalid init hint 0x%08X", hint);
    294 }
    295 
    296 GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev)
    297 {
    298     if (major != NULL)
    299         *major = GLFW_VERSION_MAJOR;
    300     if (minor != NULL)
    301         *minor = GLFW_VERSION_MINOR;
    302     if (rev != NULL)
    303         *rev = GLFW_VERSION_REVISION;
    304 }
    305 
    306 GLFWAPI const char* glfwGetVersionString(void)
    307 {
    308     return _glfwPlatformGetVersionString();
    309 }
    310 
    311 GLFWAPI int glfwGetError(const char** description)
    312 {
    313     _GLFWerror* error;
    314     int code = GLFW_NO_ERROR;
    315 
    316     if (description)
    317         *description = NULL;
    318 
    319     if (_glfw.initialized)
    320         error = _glfwPlatformGetTls(&_glfw.errorSlot);
    321     else
    322         error = &_glfwMainThreadError;
    323 
    324     if (error)
    325     {
    326         code = error->code;
    327         error->code = GLFW_NO_ERROR;
    328         if (description && code)
    329             *description = error->description;
    330     }
    331 
    332     return code;
    333 }
    334 
    335 GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun)
    336 {
    337     _GLFW_SWAP_POINTERS(_glfwErrorCallback, cbfun);
    338     return cbfun;
    339 }
    340