ScrapExplorer - init.c

Home / ext / glfw / src Lines: 2 | Size: 14504 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1//======================================================================== 2// GLFW 3.5 - www.glfw.org 3//------------------------------------------------------------------------ 4// Copyright (c) 2002-2006 Marcus Geelnard 5// Copyright (c) 2006-2018 Camilla Löwy <[email protected]> 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// 47static _GLFWerror _glfwMainThreadError; 48static GLFWerrorfun _glfwErrorCallback; 49static GLFWallocator _glfwInitAllocator; 50static _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// 73static 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// 80static void defaultDeallocate(void* block, void* user) 81{ 82 free(block); 83} 84 85// The reallocation function used when no custom allocator is set 86// 87static void* defaultReallocate(void* block, size_t size, void* user) 88{ 89 return realloc(block, size); 90} 91 92// Terminate the library 93// 94static 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// 150size_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// 181char** _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 231char* _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 239int _glfw_min(int a, int b) 240{ 241 return a < b ? a : b; 242} 243 244int _glfw_max(int a, int b) 245{ 246 return a > b ? a : b; 247} 248 249void* _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 274void* _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 296void _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// 309void _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 386GLFWAPI 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 432GLFWAPI void glfwTerminate(void) 433{ 434 if (!_glfw.initialized) 435 return; 436 437 terminate(); 438} 439 440GLFWAPI 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 471GLFWAPI 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 484GLFWAPI void glfwInitVulkanLoader(PFN_vkGetInstanceProcAddr loader) 485{ 486 _glfwInitHints.vulkanLoader = loader; 487} 488 489GLFWAPI 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 499GLFWAPI 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 523GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun) 524{ 525 _GLFW_SWAP(GLFWerrorfun, _glfwErrorCallback, cbfun); 526 return cbfun; 527} 528 529
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.