]> git.sesse.net Git - pistorm/blob - raylib/external/glfw/src/init.c
Update raylib files and Makefile for Pi 4 testing
[pistorm] / raylib / external / glfw / src / init.c
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 #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     GLFW_ANGLE_PLATFORM_TYPE_NONE, // ANGLE backend
57     {
58         GLFW_TRUE,  // macOS menu bar
59         GLFW_TRUE   // macOS bundle chdir
60     }
61 };
62
63 // Terminate the library
64 //
65 static void terminate(void)
66 {
67     int i;
68
69     memset(&_glfw.callbacks, 0, sizeof(_glfw.callbacks));
70
71     while (_glfw.windowListHead)
72         glfwDestroyWindow((GLFWwindow*) _glfw.windowListHead);
73
74     while (_glfw.cursorListHead)
75         glfwDestroyCursor((GLFWcursor*) _glfw.cursorListHead);
76
77     for (i = 0;  i < _glfw.monitorCount;  i++)
78     {
79         _GLFWmonitor* monitor = _glfw.monitors[i];
80         if (monitor->originalRamp.size)
81             _glfwPlatformSetGammaRamp(monitor, &monitor->originalRamp);
82         _glfwFreeMonitor(monitor);
83     }
84
85     free(_glfw.monitors);
86     _glfw.monitors = NULL;
87     _glfw.monitorCount = 0;
88
89     free(_glfw.mappings);
90     _glfw.mappings = NULL;
91     _glfw.mappingCount = 0;
92
93     _glfwTerminateVulkan();
94     _glfwPlatformTerminateJoysticks();
95     _glfwPlatformTerminate();
96
97     _glfw.initialized = GLFW_FALSE;
98
99     while (_glfw.errorListHead)
100     {
101         _GLFWerror* error = _glfw.errorListHead;
102         _glfw.errorListHead = error->next;
103         free(error);
104     }
105
106     _glfwPlatformDestroyTls(&_glfw.contextSlot);
107     _glfwPlatformDestroyTls(&_glfw.errorSlot);
108     _glfwPlatformDestroyMutex(&_glfw.errorLock);
109
110     memset(&_glfw, 0, sizeof(_glfw));
111 }
112
113
114 //////////////////////////////////////////////////////////////////////////
115 //////                       GLFW internal API                      //////
116 //////////////////////////////////////////////////////////////////////////
117
118 char* _glfw_strdup(const char* source)
119 {
120     const size_t length = strlen(source);
121     char* result = calloc(length + 1, 1);
122     strcpy(result, source);
123     return result;
124 }
125
126 float _glfw_fminf(float a, float b)
127 {
128     if (a != a)
129         return b;
130     else if (b != b)
131         return a;
132     else if (a < b)
133         return a;
134     else
135         return b;
136 }
137
138 float _glfw_fmaxf(float a, float b)
139 {
140     if (a != a)
141         return b;
142     else if (b != b)
143         return a;
144     else if (a > b)
145         return a;
146     else
147         return b;
148 }
149
150
151 //////////////////////////////////////////////////////////////////////////
152 //////                         GLFW event API                       //////
153 //////////////////////////////////////////////////////////////////////////
154
155 // Notifies shared code of an error
156 //
157 void _glfwInputError(int code, const char* format, ...)
158 {
159     _GLFWerror* error;
160     char description[_GLFW_MESSAGE_SIZE];
161
162     if (format)
163     {
164         va_list vl;
165
166         va_start(vl, format);
167         vsnprintf(description, sizeof(description), format, vl);
168         va_end(vl);
169
170         description[sizeof(description) - 1] = '\0';
171     }
172     else
173     {
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");
200         else
201             strcpy(description, "ERROR: UNKNOWN GLFW ERROR");
202     }
203
204     if (_glfw.initialized)
205     {
206         error = _glfwPlatformGetTls(&_glfw.errorSlot);
207         if (!error)
208         {
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);
215         }
216     }
217     else
218         error = &_glfwMainThreadError;
219
220     error->code = code;
221     strcpy(error->description, description);
222
223     if (_glfwErrorCallback)
224         _glfwErrorCallback(code, description);
225 }
226
227
228 //////////////////////////////////////////////////////////////////////////
229 //////                        GLFW public API                       //////
230 //////////////////////////////////////////////////////////////////////////
231
232 GLFWAPI int glfwInit(void)
233 {
234     if (_glfw.initialized)
235         return GLFW_TRUE;
236
237     memset(&_glfw, 0, sizeof(_glfw));
238     _glfw.hints.init = _glfwInitHints;
239
240     if (!_glfwPlatformInit())
241     {
242         terminate();
243         return GLFW_FALSE;
244     }
245
246     if (!_glfwPlatformCreateMutex(&_glfw.errorLock) ||
247         !_glfwPlatformCreateTls(&_glfw.errorSlot) ||
248         !_glfwPlatformCreateTls(&_glfw.contextSlot))
249     {
250         terminate();
251         return GLFW_FALSE;
252     }
253
254     _glfwPlatformSetTls(&_glfw.errorSlot, &_glfwMainThreadError);
255
256     _glfw.initialized = GLFW_TRUE;
257     _glfw.timer.offset = _glfwPlatformGetTimerValue();
258
259     glfwDefaultWindowHints();
260
261     {
262         int i;
263
264         for (i = 0;  _glfwDefaultMappings[i];  i++)
265         {
266             if (!glfwUpdateGamepadMappings(_glfwDefaultMappings[i]))
267             {
268                 terminate();
269                 return GLFW_FALSE;
270             }
271         }
272     }
273
274     return GLFW_TRUE;
275 }
276
277 GLFWAPI void glfwTerminate(void)
278 {
279     if (!_glfw.initialized)
280         return;
281
282     terminate();
283 }
284
285 GLFWAPI void glfwInitHint(int hint, int value)
286 {
287     switch (hint)
288     {
289         case GLFW_JOYSTICK_HAT_BUTTONS:
290             _glfwInitHints.hatButtons = value;
291             return;
292         case GLFW_ANGLE_PLATFORM_TYPE:
293             _glfwInitHints.angleType = value;
294             return;
295         case GLFW_COCOA_CHDIR_RESOURCES:
296             _glfwInitHints.ns.chdir = value;
297             return;
298         case GLFW_COCOA_MENUBAR:
299             _glfwInitHints.ns.menubar = value;
300             return;
301     }
302
303     _glfwInputError(GLFW_INVALID_ENUM,
304                     "Invalid init hint 0x%08X", hint);
305 }
306
307 GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev)
308 {
309     if (major != NULL)
310         *major = GLFW_VERSION_MAJOR;
311     if (minor != NULL)
312         *minor = GLFW_VERSION_MINOR;
313     if (rev != NULL)
314         *rev = GLFW_VERSION_REVISION;
315 }
316
317 GLFWAPI const char* glfwGetVersionString(void)
318 {
319     return _glfwPlatformGetVersionString();
320 }
321
322 GLFWAPI int glfwGetError(const char** description)
323 {
324     _GLFWerror* error;
325     int code = GLFW_NO_ERROR;
326
327     if (description)
328         *description = NULL;
329
330     if (_glfw.initialized)
331         error = _glfwPlatformGetTls(&_glfw.errorSlot);
332     else
333         error = &_glfwMainThreadError;
334
335     if (error)
336     {
337         code = error->code;
338         error->code = GLFW_NO_ERROR;
339         if (description && code)
340             *description = error->description;
341     }
342
343     return code;
344 }
345
346 GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun)
347 {
348     _GLFW_SWAP_POINTERS(_glfwErrorCallback, cbfun);
349     return cbfun;
350 }
351