master
ブランチ master
cpputils / deps / glfw / src / init.c
9.4 KB、340行 生 Blame 履歴
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//
51static _GLFWerror _glfwMainThreadError;
52static GLFWerrorfun _glfwErrorCallback;
53static _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//
64static 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
116char* _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
124float _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
136float _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//
155void _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
224GLFWAPI 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
269GLFWAPI void glfwTerminate(void)
270{
271 if (!_glfw.initialized)
272 return;
273
274 terminate();
275}
276
277GLFWAPI 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
296GLFWAPI 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
306GLFWAPI const char* glfwGetVersionString(void)
307{
308 return _glfwPlatformGetVersionString();
309}
310
311GLFWAPI 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
335GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun)
336{
337 _GLFW_SWAP_POINTERS(_glfwErrorCallback, cbfun);
338 return cbfun;
339}
340