1//========================================================================
2// GLFW 3.2 - www.glfw.org
3//------------------------------------------------------------------------
4// Copyright (c) 2002-2006 Marcus Geelnard
5// Copyright (c) 2006-2016 Camilla Berglund <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
28#include "internal.h"
29
30#include <string.h>
31#include <stdlib.h>
32#include <stdio.h>
33#include <stdarg.h>
34
35
36// The three global variables below comprise all global data in GLFW.
37// Any other global variable is a bug.
38
39// Global state shared between compilation units of GLFW
40// These are documented in internal.h
41//
42GLFWbool _glfwInitialized = GLFW_FALSE;
43_GLFWlibrary _glfw;
44
45// This is outside of _glfw so it can be initialized and usable before
46// glfwInit is called, which lets that function report errors
47//
48static GLFWerrorfun _glfwErrorCallback = NULL;
49
50
51// Returns a generic string representation of the specified error
52//
53static const char* getErrorString(int error)
54{
55 switch (error)
56 {
57 case GLFW_NOT_INITIALIZED:
58 return "The GLFW library is not initialized";
59 case GLFW_NO_CURRENT_CONTEXT:
60 return "There is no current context";
61 case GLFW_INVALID_ENUM:
62 return "Invalid argument for enum parameter";
63 case GLFW_INVALID_VALUE:
64 return "Invalid value for parameter";
65 case GLFW_OUT_OF_MEMORY:
66 return "Out of memory";
67 case GLFW_API_UNAVAILABLE:
68 return "The requested client API is unavailable";
69 case GLFW_VERSION_UNAVAILABLE:
70 return "The requested client API version is unavailable";
71 case GLFW_PLATFORM_ERROR:
72 return "A platform-specific error occurred";
73 case GLFW_FORMAT_UNAVAILABLE:
74 return "The requested format is unavailable";
75 case GLFW_NO_WINDOW_CONTEXT:
76 return "The specified window has no context";
77 default:
78 return "ERROR: UNKNOWN GLFW ERROR";
79 }
80}
81
82
83//////////////////////////////////////////////////////////////////////////
84////// GLFW event API //////
85//////////////////////////////////////////////////////////////////////////
86
87void _glfwInputError(int error, const char* format, ...)
88{
89 if (_glfwErrorCallback)
90 {
91 char buffer[8192];
92 const char* description;
93
94 if (format)
95 {
96 int count;
97 va_list vl;
98
99 va_start(vl, format);
100 count = vsnprintf(buffer, sizeof(buffer), format, vl);
101 va_end(vl);
102
103 if (count < 0)
104 buffer[sizeof(buffer) - 1] = '\0';
105
106 description = buffer;
107 }
108 else
109 description = getErrorString(error);
110
111 _glfwErrorCallback(error, description);
112 }
113}
114
115
116//////////////////////////////////////////////////////////////////////////
117////// GLFW public API //////
118//////////////////////////////////////////////////////////////////////////
119
120GLFWAPI int glfwInit(void)
121{
122 if (_glfwInitialized)
123 return GLFW_TRUE;
124
125 memset(&_glfw, 0, sizeof(_glfw));
126
127 if (!_glfwPlatformInit())
128 {
129 _glfwPlatformTerminate();
130 return GLFW_FALSE;
131 }
132
133 _glfwInitVulkan();
134
135 _glfw.monitors = _glfwPlatformGetMonitors(&_glfw.monitorCount);
136 _glfwInitialized = GLFW_TRUE;
137
138 _glfw.timerOffset = _glfwPlatformGetTimerValue();
139
140 // Not all window hints have zero as their default value
141 glfwDefaultWindowHints();
142
143 return GLFW_TRUE;
144}
145
146GLFWAPI void glfwTerminate(void)
147{
148 int i;
149
150 if (!_glfwInitialized)
151 return;
152
153 memset(&_glfw.callbacks, 0, sizeof(_glfw.callbacks));
154
155 while (_glfw.windowListHead)
156 glfwDestroyWindow((GLFWwindow*) _glfw.windowListHead);
157
158 while (_glfw.cursorListHead)
159 glfwDestroyCursor((GLFWcursor*) _glfw.cursorListHead);
160
161 for (i = 0; i < _glfw.monitorCount; i++)
162 {
163 _GLFWmonitor* monitor = _glfw.monitors[i];
164 if (monitor->originalRamp.size)
165 _glfwPlatformSetGammaRamp(monitor, &monitor->originalRamp);
166 }
167
168 _glfwTerminateVulkan();
169
170 _glfwFreeMonitors(_glfw.monitors, _glfw.monitorCount);
171 _glfw.monitors = NULL;
172 _glfw.monitorCount = 0;
173
174 _glfwPlatformTerminate();
175
176 memset(&_glfw, 0, sizeof(_glfw));
177 _glfwInitialized = GLFW_FALSE;
178}
179
180GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev)
181{
182 if (major != NULL)
183 *major = GLFW_VERSION_MAJOR;
184
185 if (minor != NULL)
186 *minor = GLFW_VERSION_MINOR;
187
188 if (rev != NULL)
189 *rev = GLFW_VERSION_REVISION;
190}
191
192GLFWAPI const char* glfwGetVersionString(void)
193{
194 return _glfwPlatformGetVersionString();
195}
196
197GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun)
198{
199 _GLFW_SWAP_POINTERS(_glfwErrorCallback, cbfun);
200 return cbfun;
201}
202
203