init.c 9.16 KB
Newer Older
Camilla Berglund's avatar
Camilla Berglund committed
1
//========================================================================
Camilla Berglund's avatar
Camilla Berglund committed
2
// GLFW 3.3 - www.glfw.org
Camilla Berglund's avatar
Camilla Berglund committed
3
4
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
Camilla Löwy's avatar
Camilla Löwy committed
5
// Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
Camilla Berglund's avatar
Camilla Berglund committed
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
//    claim that you wrote the original software. If you use this software
//    in a product, an acknowledgment in the product documentation would
//    be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
//    be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
//    distribution.
//
//========================================================================
27
28
// Please use C89 style variable declarations in this file because VS 2010
//========================================================================
Camilla Berglund's avatar
Camilla Berglund committed
29
30

#include "internal.h"
31
#include "mappings.h"
Camilla Berglund's avatar
Camilla Berglund committed
32

33
#include <string.h>
34
#include <stdlib.h>
35
36
#include <stdio.h>
#include <stdarg.h>
Camilla Löwy's avatar
Camilla Löwy committed
37
#include <assert.h>
38
39


40
41
42
// The global variables below comprise all mutable global data in GLFW
//
// Any other global variable is a bug
43

44
// Global state shared between compilation units of GLFW
45
//
46
_GLFWlibrary _glfw = { GLFW_FALSE };
47

Camilla Löwy's avatar
Camilla Löwy committed
48
49
// These are outside of _glfw so they can be used before initialization and
// after termination
50
//
51
static _GLFWerror _glfwMainThreadError;
Camilla Löwy's avatar
Camilla Löwy committed
52
53
54
static GLFWerrorfun _glfwErrorCallback;
static _GLFWinitconfig _glfwInitHints =
{
Camilla Löwy's avatar
Camilla Löwy committed
55
    GLFW_TRUE,      // hat buttons
Camilla Löwy's avatar
Camilla Löwy committed
56
    {
Camilla Löwy's avatar
Camilla Löwy committed
57
58
        GLFW_TRUE,  // macOS menu bar
        GLFW_TRUE   // macOS bundle chdir
Camilla Löwy's avatar
Camilla Löwy committed
59
60
    }
};
61

62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
// Terminate the library
//
static void terminate(void)
{
    int i;

    memset(&_glfw.callbacks, 0, sizeof(_glfw.callbacks));

    while (_glfw.windowListHead)
        glfwDestroyWindow((GLFWwindow*) _glfw.windowListHead);

    while (_glfw.cursorListHead)
        glfwDestroyCursor((GLFWcursor*) _glfw.cursorListHead);

    for (i = 0;  i < _glfw.monitorCount;  i++)
    {
        _GLFWmonitor* monitor = _glfw.monitors[i];
        if (monitor->originalRamp.size)
            _glfwPlatformSetGammaRamp(monitor, &monitor->originalRamp);
        _glfwFreeMonitor(monitor);
    }

    free(_glfw.monitors);
    _glfw.monitors = NULL;
    _glfw.monitorCount = 0;

88
89
90
91
    free(_glfw.mappings);
    _glfw.mappings = NULL;
    _glfw.mappingCount = 0;

92
93
94
    _glfwTerminateVulkan();
    _glfwPlatformTerminate();

95
    _glfw.initialized = GLFW_FALSE;
Camilla Löwy's avatar
Camilla Löwy committed
96

97
98
99
100
101
102
103
    while (_glfw.errorListHead)
    {
        _GLFWerror* error = _glfw.errorListHead;
        _glfw.errorListHead = error->next;
        free(error);
    }

104
    _glfwPlatformDestroyTls(&_glfw.usercontextSlot);
105
106
107
    _glfwPlatformDestroyTls(&_glfw.contextSlot);
    _glfwPlatformDestroyTls(&_glfw.errorSlot);
    _glfwPlatformDestroyMutex(&_glfw.errorLock);
Camilla Löwy's avatar
Camilla Löwy committed
108

109
110
111
    memset(&_glfw, 0, sizeof(_glfw));
}

112

113
114
115
116
117
118
119
120
121
122
123
124
//////////////////////////////////////////////////////////////////////////
//////                       GLFW internal API                      //////
//////////////////////////////////////////////////////////////////////////

char* _glfw_strdup(const char* source)
{
    const size_t length = strlen(source);
    char* result = calloc(length + 1, 1);
    strcpy(result, source);
    return result;
}

125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
float _glfw_fminf(float a, float b)
{
    if (a != a)
        return b;
    else if (b != b)
        return a;
    else if (a < b)
        return a;
    else
        return b;
}

float _glfw_fmaxf(float a, float b)
{
    if (a != a)
        return b;
    else if (b != b)
        return a;
    else if (a > b)
        return a;
    else
        return b;
}

149

Camilla Berglund's avatar
Camilla Berglund committed
150
//////////////////////////////////////////////////////////////////////////
151
//////                         GLFW event API                       //////
Camilla Berglund's avatar
Camilla Berglund committed
152
153
//////////////////////////////////////////////////////////////////////////

154
155
// Notifies shared code of an error
//
156
void _glfwInputError(int code, const char* format, ...)
157
{
158
    _GLFWerror* error;
159
    char description[_GLFW_MESSAGE_SIZE];
Camilla Löwy's avatar
Camilla Löwy committed
160

161
    if (format)
162
    {
163
        va_list vl;
164

165
        va_start(vl, format);
Camilla Löwy's avatar
Cleanup    
Camilla Löwy committed
166
        vsnprintf(description, sizeof(description), format, vl);
167
        va_end(vl);
168

Camilla Löwy's avatar
Cleanup    
Camilla Löwy committed
169
        description[sizeof(description) - 1] = '\0';
170
171
    }
    else
Camilla Löwy's avatar
Cleanup    
Camilla Löwy committed
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
    {
        if (code == GLFW_NOT_INITIALIZED)
            strcpy(description, "The GLFW library is not initialized");
        else if (code == GLFW_NO_CURRENT_CONTEXT)
            strcpy(description, "There is no current context");
        else if (code == GLFW_INVALID_ENUM)
            strcpy(description, "Invalid argument for enum parameter");
        else if (code == GLFW_INVALID_VALUE)
            strcpy(description, "Invalid value for parameter");
        else if (code == GLFW_OUT_OF_MEMORY)
            strcpy(description, "Out of memory");
        else if (code == GLFW_API_UNAVAILABLE)
            strcpy(description, "The requested API is unavailable");
        else if (code == GLFW_VERSION_UNAVAILABLE)
            strcpy(description, "The requested API version is unavailable");
        else if (code == GLFW_PLATFORM_ERROR)
            strcpy(description, "A platform-specific error occurred");
        else if (code == GLFW_FORMAT_UNAVAILABLE)
            strcpy(description, "The requested format is unavailable");
        else if (code == GLFW_NO_WINDOW_CONTEXT)
            strcpy(description, "The specified window has no context");
        else
            strcpy(description, "ERROR: UNKNOWN GLFW ERROR");
    }
196

197
198
199
200
201
202
203
204
205
206
207
    if (_glfw.initialized)
    {
        error = _glfwPlatformGetTls(&_glfw.errorSlot);
        if (!error)
        {
            error = calloc(1, sizeof(_GLFWerror));
            _glfwPlatformSetTls(&_glfw.errorSlot, error);
            _glfwPlatformLockMutex(&_glfw.errorLock);
            error->next = _glfw.errorListHead;
            _glfw.errorListHead = error;
            _glfwPlatformUnlockMutex(&_glfw.errorLock);
208
209
        }
    }
210
211
212
213
214
215
216
217
    else
        error = &_glfwMainThreadError;

    error->code = code;
    strcpy(error->description, description);

    if (_glfwErrorCallback)
        _glfwErrorCallback(code, description);
218
}
219
220


221
222
223
//////////////////////////////////////////////////////////////////////////
//////                        GLFW public API                       //////
//////////////////////////////////////////////////////////////////////////
Camilla Berglund's avatar
Camilla Berglund committed
224

Camilla Berglund's avatar
Camilla Berglund committed
225
GLFWAPI int glfwInit(void)
Camilla Berglund's avatar
Camilla Berglund committed
226
{
227
    if (_glfw.initialized)
228
        return GLFW_TRUE;
Camilla Berglund's avatar
Camilla Berglund committed
229

230
    memset(&_glfw, 0, sizeof(_glfw));
Camilla Löwy's avatar
Camilla Löwy committed
231
    _glfw.hints.init = _glfwInitHints;
Camilla Berglund's avatar
Camilla Berglund committed
232

233
    if (!_glfwPlatformInit())
234
    {
235
        terminate();
236
        return GLFW_FALSE;
237
    }
Camilla Berglund's avatar
Camilla Berglund committed
238

239
240
    if (!_glfwPlatformCreateMutex(&_glfw.errorLock) ||
        !_glfwPlatformCreateTls(&_glfw.errorSlot) ||
241
242
        !_glfwPlatformCreateTls(&_glfw.contextSlot) ||
        !_glfwPlatformCreateTls(&_glfw.usercontextSlot))
243
244
    {
        terminate();
Camilla Löwy's avatar
Camilla Löwy committed
245
        return GLFW_FALSE;
246
    }
Camilla Löwy's avatar
Camilla Löwy committed
247

248
    _glfwPlatformSetTls(&_glfw.errorSlot, &_glfwMainThreadError);
Camilla Löwy's avatar
Camilla Löwy committed
249

250
    _glfw.initialized = GLFW_TRUE;
Camilla Löwy's avatar
Cleanup    
Camilla Löwy committed
251
    _glfw.timer.offset = _glfwPlatformGetTimerValue();
252

253
    glfwDefaultWindowHints();
254
255

    {
256
257
258
259
260
261
262
263
264
265
        int i;

        for (i = 0;  _glfwDefaultMappings[i];  i++)
        {
            if (!glfwUpdateGamepadMappings(_glfwDefaultMappings[i]))
            {
                terminate();
                return GLFW_FALSE;
            }
        }
266
    }
267

268
    return GLFW_TRUE;
Camilla Berglund's avatar
Camilla Berglund committed
269
270
}

271
GLFWAPI void glfwTerminate(void)
Camilla Berglund's avatar
Camilla Berglund committed
272
{
273
    if (!_glfw.initialized)
Camilla Berglund's avatar
Camilla Berglund committed
274
        return;
275

276
    terminate();
Camilla Berglund's avatar
Camilla Berglund committed
277
278
}

Camilla Löwy's avatar
Camilla Löwy committed
279
280
281
282
GLFWAPI void glfwInitHint(int hint, int value)
{
    switch (hint)
    {
Camilla Löwy's avatar
Camilla Löwy committed
283
284
285
        case GLFW_JOYSTICK_HAT_BUTTONS:
            _glfwInitHints.hatButtons = value;
            return;
Camilla Löwy's avatar
Camilla Löwy committed
286
287
288
289
290
291
292
293
        case GLFW_COCOA_CHDIR_RESOURCES:
            _glfwInitHints.ns.chdir = value;
            return;
        case GLFW_COCOA_MENUBAR:
            _glfwInitHints.ns.menubar = value;
            return;
    }

Camilla Löwy's avatar
Camilla Löwy committed
294
    _glfwInputError(GLFW_INVALID_ENUM,
295
                    "Invalid init hint 0x%08X", hint);
Camilla Löwy's avatar
Camilla Löwy committed
296
297
}

298
GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev)
Camilla Berglund's avatar
Camilla Berglund committed
299
{
300
    if (major != NULL)
301
        *major = GLFW_VERSION_MAJOR;
302
    if (minor != NULL)
303
        *minor = GLFW_VERSION_MINOR;
304
    if (rev != NULL)
305
        *rev = GLFW_VERSION_REVISION;
Camilla Berglund's avatar
Camilla Berglund committed
306
307
}

Camilla Berglund's avatar
Camilla Berglund committed
308
309
310
311
312
GLFWAPI const char* glfwGetVersionString(void)
{
    return _glfwPlatformGetVersionString();
}

313
GLFWAPI int glfwGetError(const char** description)
Camilla Löwy's avatar
Camilla Löwy committed
314
{
315
316
317
318
319
    _GLFWerror* error;
    int code = GLFW_NO_ERROR;

    if (description)
        *description = NULL;
Camilla Löwy's avatar
Camilla Löwy committed
320
321

    if (_glfw.initialized)
322
        error = _glfwPlatformGetTls(&_glfw.errorSlot);
Camilla Löwy's avatar
Camilla Löwy committed
323
    else
324
325
326
        error = &_glfwMainThreadError;

    if (error)
Camilla Löwy's avatar
Camilla Löwy committed
327
    {
328
329
330
331
        code = error->code;
        error->code = GLFW_NO_ERROR;
        if (description && code)
            *description = error->description;
Camilla Löwy's avatar
Camilla Löwy committed
332
333
    }

334
    return code;
Camilla Löwy's avatar
Camilla Löwy committed
335
336
}

337
GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun)
338
{
339
340
    _GLFW_SWAP_POINTERS(_glfwErrorCallback, cbfun);
    return cbfun;
341
342
}