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