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