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>
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.
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:
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.
20 // 2. Altered source versions must be plainly marked as such, and must not
21 // be misrepresented as being the original software.
23 // 3. This notice may not be removed or altered from any source
26 //========================================================================
27 // Please use C89 style variable declarations in this file because VS 2010
28 //========================================================================
40 // The global variables below comprise all mutable global data in GLFW
42 // Any other global variable is a bug
44 // Global state shared between compilation units of GLFW
46 _GLFWlibrary _glfw = { GLFW_FALSE };
48 // These are outside of _glfw so they can be used before initialization and
51 static _GLFWerror _glfwMainThreadError;
52 static GLFWerrorfun _glfwErrorCallback;
53 static _GLFWinitconfig _glfwInitHints =
55 GLFW_TRUE, // hat buttons
56 GLFW_ANGLE_PLATFORM_TYPE_NONE, // ANGLE backend
58 GLFW_TRUE, // macOS menu bar
59 GLFW_TRUE // macOS bundle chdir
63 // Terminate the library
65 static void terminate(void)
69 memset(&_glfw.callbacks, 0, sizeof(_glfw.callbacks));
71 while (_glfw.windowListHead)
72 glfwDestroyWindow((GLFWwindow*) _glfw.windowListHead);
74 while (_glfw.cursorListHead)
75 glfwDestroyCursor((GLFWcursor*) _glfw.cursorListHead);
77 for (i = 0; i < _glfw.monitorCount; i++)
79 _GLFWmonitor* monitor = _glfw.monitors[i];
80 if (monitor->originalRamp.size)
81 _glfwPlatformSetGammaRamp(monitor, &monitor->originalRamp);
82 _glfwFreeMonitor(monitor);
86 _glfw.monitors = NULL;
87 _glfw.monitorCount = 0;
90 _glfw.mappings = NULL;
91 _glfw.mappingCount = 0;
93 _glfwTerminateVulkan();
94 _glfwPlatformTerminateJoysticks();
95 _glfwPlatformTerminate();
97 _glfw.initialized = GLFW_FALSE;
99 while (_glfw.errorListHead)
101 _GLFWerror* error = _glfw.errorListHead;
102 _glfw.errorListHead = error->next;
106 _glfwPlatformDestroyTls(&_glfw.contextSlot);
107 _glfwPlatformDestroyTls(&_glfw.errorSlot);
108 _glfwPlatformDestroyMutex(&_glfw.errorLock);
110 memset(&_glfw, 0, sizeof(_glfw));
114 //////////////////////////////////////////////////////////////////////////
115 ////// GLFW internal API //////
116 //////////////////////////////////////////////////////////////////////////
118 char* _glfw_strdup(const char* source)
120 const size_t length = strlen(source);
121 char* result = calloc(length + 1, 1);
122 strcpy(result, source);
126 float _glfw_fminf(float a, float b)
138 float _glfw_fmaxf(float a, float b)
151 //////////////////////////////////////////////////////////////////////////
152 ////// GLFW event API //////
153 //////////////////////////////////////////////////////////////////////////
155 // Notifies shared code of an error
157 void _glfwInputError(int code, const char* format, ...)
160 char description[_GLFW_MESSAGE_SIZE];
166 va_start(vl, format);
167 vsnprintf(description, sizeof(description), format, vl);
170 description[sizeof(description) - 1] = '\0';
174 if (code == GLFW_NOT_INITIALIZED)
175 strcpy(description, "The GLFW library is not initialized");
176 else if (code == GLFW_NO_CURRENT_CONTEXT)
177 strcpy(description, "There is no current context");
178 else if (code == GLFW_INVALID_ENUM)
179 strcpy(description, "Invalid argument for enum parameter");
180 else if (code == GLFW_INVALID_VALUE)
181 strcpy(description, "Invalid value for parameter");
182 else if (code == GLFW_OUT_OF_MEMORY)
183 strcpy(description, "Out of memory");
184 else if (code == GLFW_API_UNAVAILABLE)
185 strcpy(description, "The requested API is unavailable");
186 else if (code == GLFW_VERSION_UNAVAILABLE)
187 strcpy(description, "The requested API version is unavailable");
188 else if (code == GLFW_PLATFORM_ERROR)
189 strcpy(description, "A platform-specific error occurred");
190 else if (code == GLFW_FORMAT_UNAVAILABLE)
191 strcpy(description, "The requested format is unavailable");
192 else if (code == GLFW_NO_WINDOW_CONTEXT)
193 strcpy(description, "The specified window has no context");
194 else if (code == GLFW_CURSOR_UNAVAILABLE)
195 strcpy(description, "The specified cursor shape is unavailable");
196 else if (code == GLFW_FEATURE_UNAVAILABLE)
197 strcpy(description, "The requested feature cannot be implemented for this platform");
198 else if (code == GLFW_FEATURE_UNIMPLEMENTED)
199 strcpy(description, "The requested feature has not yet been implemented for this platform");
201 strcpy(description, "ERROR: UNKNOWN GLFW ERROR");
204 if (_glfw.initialized)
206 error = _glfwPlatformGetTls(&_glfw.errorSlot);
209 error = calloc(1, sizeof(_GLFWerror));
210 _glfwPlatformSetTls(&_glfw.errorSlot, error);
211 _glfwPlatformLockMutex(&_glfw.errorLock);
212 error->next = _glfw.errorListHead;
213 _glfw.errorListHead = error;
214 _glfwPlatformUnlockMutex(&_glfw.errorLock);
218 error = &_glfwMainThreadError;
221 strcpy(error->description, description);
223 if (_glfwErrorCallback)
224 _glfwErrorCallback(code, description);
228 //////////////////////////////////////////////////////////////////////////
229 ////// GLFW public API //////
230 //////////////////////////////////////////////////////////////////////////
232 GLFWAPI int glfwInit(void)
234 if (_glfw.initialized)
237 memset(&_glfw, 0, sizeof(_glfw));
238 _glfw.hints.init = _glfwInitHints;
240 if (!_glfwPlatformInit())
246 if (!_glfwPlatformCreateMutex(&_glfw.errorLock) ||
247 !_glfwPlatformCreateTls(&_glfw.errorSlot) ||
248 !_glfwPlatformCreateTls(&_glfw.contextSlot))
254 _glfwPlatformSetTls(&_glfw.errorSlot, &_glfwMainThreadError);
256 _glfw.initialized = GLFW_TRUE;
257 _glfw.timer.offset = _glfwPlatformGetTimerValue();
259 glfwDefaultWindowHints();
264 for (i = 0; _glfwDefaultMappings[i]; i++)
266 if (!glfwUpdateGamepadMappings(_glfwDefaultMappings[i]))
277 GLFWAPI void glfwTerminate(void)
279 if (!_glfw.initialized)
285 GLFWAPI void glfwInitHint(int hint, int value)
289 case GLFW_JOYSTICK_HAT_BUTTONS:
290 _glfwInitHints.hatButtons = value;
292 case GLFW_ANGLE_PLATFORM_TYPE:
293 _glfwInitHints.angleType = value;
295 case GLFW_COCOA_CHDIR_RESOURCES:
296 _glfwInitHints.ns.chdir = value;
298 case GLFW_COCOA_MENUBAR:
299 _glfwInitHints.ns.menubar = value;
303 _glfwInputError(GLFW_INVALID_ENUM,
304 "Invalid init hint 0x%08X", hint);
307 GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev)
310 *major = GLFW_VERSION_MAJOR;
312 *minor = GLFW_VERSION_MINOR;
314 *rev = GLFW_VERSION_REVISION;
317 GLFWAPI const char* glfwGetVersionString(void)
319 return _glfwPlatformGetVersionString();
322 GLFWAPI int glfwGetError(const char** description)
325 int code = GLFW_NO_ERROR;
330 if (_glfw.initialized)
331 error = _glfwPlatformGetTls(&_glfw.errorSlot);
333 error = &_glfwMainThreadError;
338 error->code = GLFW_NO_ERROR;
339 if (description && code)
340 *description = error->description;
346 GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun)
348 _GLFW_SWAP_POINTERS(_glfwErrorCallback, cbfun);