1 /// Translated from C to D 2 module glfw3.init; 3 4 extern(C): nothrow: __gshared: 5 // @nogc: varargs 6 7 //======================================================================== 8 // GLFW 3.3 - www.glfw.org 9 //------------------------------------------------------------------------ 10 // Copyright (c) 2002-2006 Marcus Geelnard 11 // Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org> 12 // 13 // This software is provided 'as-is', without any express or implied 14 // warranty. In no event will the authors be held liable for any damages 15 // arising from the use of this software. 16 // 17 // Permission is granted to anyone to use this software for any purpose, 18 // including commercial applications, and to alter it and redistribute it 19 // freely, subject to the following restrictions: 20 // 21 // 1. The origin of this software must not be misrepresented; you must not 22 // claim that you wrote the original software. If you use this software 23 // in a product, an acknowledgment in the product documentation would 24 // be appreciated but is not required. 25 // 26 // 2. Altered source versions must be plainly marked as such, and must not 27 // be misrepresented as being the original software. 28 // 29 // 3. This notice may not be removed or altered from any source 30 // distribution. 31 // 32 //======================================================================== 33 // Please use C89 style variable declarations in this file because VS 2010 34 //======================================================================== 35 36 import glfw3.internal; 37 import glfw3.mappings; 38 39 import core.stdc.string; 40 import core.stdc.stdlib; 41 import core.stdc.stdio; 42 import core.stdc.stdarg; 43 import core.stdc.assert_; 44 45 // The global variables below comprise all mutable global data in GLFW 46 // 47 // Any other global variable is a bug 48 49 // Global state shared between compilation units of GLFW 50 // 51 _GLFWlibrary _glfw = _GLFWlibrary(GLFW_FALSE); 52 53 // These are outside of _glfw so they can be used before initialization and 54 // after termination 55 // 56 static _GLFWerror _glfwMainThreadError; 57 static GLFWerrorfun _glfwErrorCallback; 58 static _GLFWinitconfig _glfwInitHints = _GLFWinitconfig( 59 GLFW_TRUE, // hat buttons 60 _GLFWinitconfig._Ns( 61 GLFW_TRUE, // macOS menu bar 62 GLFW_TRUE // macOS bundle chdir 63 ) 64 ); 65 66 // Terminate the library 67 // 68 private extern(D) void terminate() { 69 int i; 70 71 memset(&_glfw.callbacks, 0, typeof(_glfw.callbacks).sizeof); 72 73 while (_glfw.windowListHead) 74 glfwDestroyWindow(cast(GLFWwindow*) _glfw.windowListHead); 75 76 while (_glfw.cursorListHead) 77 glfwDestroyCursor(cast(GLFWcursor*) _glfw.cursorListHead); 78 79 for (i = 0; i < _glfw.monitorCount; i++) 80 { 81 _GLFWmonitor* monitor = _glfw.monitors[i]; 82 if (monitor.originalRamp.size) 83 _glfwPlatformSetGammaRamp(monitor, &monitor.originalRamp); 84 _glfwFreeMonitor(monitor); 85 } 86 87 free(_glfw.monitors); 88 _glfw.monitors = null; 89 _glfw.monitorCount = 0; 90 91 free(_glfw.mappings); 92 _glfw.mappings = null; 93 _glfw.mappingCount = 0; 94 95 _glfwTerminateVulkan(); 96 _glfwPlatformTerminate(); 97 98 _glfw.initialized = GLFW_FALSE; 99 100 while (_glfw.errorListHead) 101 { 102 _GLFWerror* error = _glfw.errorListHead; 103 _glfw.errorListHead = error.next; 104 free(error); 105 } 106 107 _glfwPlatformDestroyTls(&_glfw.contextSlot); 108 _glfwPlatformDestroyTls(&_glfw.errorSlot); 109 _glfwPlatformDestroyMutex(&_glfw.errorLock); 110 111 memset(&_glfw, 0, typeof(_glfw).sizeof); 112 } 113 114 115 ////////////////////////////////////////////////////////////////////////// 116 ////// GLFW internal API ////// 117 ////////////////////////////////////////////////////////////////////////// 118 119 char* _glfw_strdup(const(char)* source) { 120 const(size_t) length = strlen(source); 121 auto result = cast(char*) calloc(length + 1, 1); 122 strcpy(result, source); 123 return result; 124 } 125 126 float _glfw_fminf(float a, float b) { 127 if (a != a) 128 return b; 129 else if (b != b) 130 return a; 131 else if (a < b) 132 return a; 133 else 134 return b; 135 } 136 137 float _glfw_fmaxf(float a, float b) { 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 // 155 void _glfwInputError(int code, const(char)* format, ...) { 156 _GLFWerror* error; 157 char[_GLFW_MESSAGE_SIZE] description; 158 159 if (format) 160 { 161 va_list vl; 162 va_start(vl, format); 163 vsnprintf(description.ptr, description.length, format, vl); 164 va_end(vl); 165 166 description[$-1] = '\0'; 167 } 168 else 169 { 170 if (code == GLFW_NOT_INITIALIZED) 171 strcpy(description.ptr, "The GLFW library is not initialized"); 172 else if (code == GLFW_NO_CURRENT_CONTEXT) 173 strcpy(description.ptr, "There is no current context"); 174 else if (code == GLFW_INVALID_ENUM) 175 strcpy(description.ptr, "Invalid argument for enum parameter"); 176 else if (code == GLFW_INVALID_VALUE) 177 strcpy(description.ptr, "Invalid value for parameter"); 178 else if (code == GLFW_OUT_OF_MEMORY) 179 strcpy(description.ptr, "Out of memory"); 180 else if (code == GLFW_API_UNAVAILABLE) 181 strcpy(description.ptr, "The requested API is unavailable"); 182 else if (code == GLFW_VERSION_UNAVAILABLE) 183 strcpy(description.ptr, "The requested API version is unavailable"); 184 else if (code == GLFW_PLATFORM_ERROR) 185 strcpy(description.ptr, "A platform-specific error occurred"); 186 else if (code == GLFW_FORMAT_UNAVAILABLE) 187 strcpy(description.ptr, "The requested format is unavailable"); 188 else if (code == GLFW_NO_WINDOW_CONTEXT) 189 strcpy(description.ptr, "The specified window has no context"); 190 else 191 strcpy(description.ptr, "ERROR: UNKNOWN GLFW ERROR"); 192 } 193 194 if (_glfw.initialized) 195 { 196 error = cast(_GLFWerror*) _glfwPlatformGetTls(&_glfw.errorSlot); 197 if (!error) 198 { 199 error = cast(_GLFWerror*) calloc(1, _GLFWerror.sizeof); 200 _glfwPlatformSetTls(&_glfw.errorSlot, error); 201 _glfwPlatformLockMutex(&_glfw.errorLock); 202 error.next = _glfw.errorListHead; 203 _glfw.errorListHead = error; 204 _glfwPlatformUnlockMutex(&_glfw.errorLock); 205 } 206 } 207 else 208 error = &_glfwMainThreadError; 209 210 error.code = code; 211 strcpy(error.description.ptr, description.ptr); 212 213 if (_glfwErrorCallback) 214 _glfwErrorCallback(code, description.ptr); 215 } 216 217 218 ////////////////////////////////////////////////////////////////////////// 219 ////// GLFW public API ////// 220 ////////////////////////////////////////////////////////////////////////// 221 222 int glfwInit() { 223 if (_glfw.initialized) 224 return GLFW_TRUE; 225 226 memset(&_glfw, 0, typeof(_glfw).sizeof); 227 _glfw.hints.init = _glfwInitHints; 228 229 if (!_glfwPlatformInit()) 230 { 231 terminate(); 232 return GLFW_FALSE; 233 } 234 235 if (!_glfwPlatformCreateMutex(&_glfw.errorLock) || 236 !_glfwPlatformCreateTls(&_glfw.errorSlot) || 237 !_glfwPlatformCreateTls(&_glfw.contextSlot)) 238 { 239 terminate(); 240 return GLFW_FALSE; 241 } 242 243 _glfwPlatformSetTls(&_glfw.errorSlot, &_glfwMainThreadError); 244 245 _glfw.initialized = GLFW_TRUE; 246 _glfw.timer.offset = _glfwPlatformGetTimerValue(); 247 248 glfwDefaultWindowHints(); 249 250 { 251 int i; 252 253 for (i = 0; _glfwDefaultMappings[i]; i++) 254 { 255 if (!glfwUpdateGamepadMappings(_glfwDefaultMappings[i])) 256 { 257 terminate(); 258 return GLFW_FALSE; 259 } 260 } 261 } 262 263 return GLFW_TRUE; 264 } 265 266 void glfwTerminate() { 267 if (!_glfw.initialized) 268 return; 269 270 terminate(); 271 } 272 273 void glfwInitHint(int hint, int value) { 274 switch (hint) 275 { 276 case GLFW_JOYSTICK_HAT_BUTTONS: 277 _glfwInitHints.hatButtons = value; 278 return; 279 case GLFW_COCOA_CHDIR_RESOURCES: 280 _glfwInitHints.ns.chdir = value; 281 return; 282 case GLFW_COCOA_MENUBAR: 283 _glfwInitHints.ns.menubar = value; 284 return; 285 default: break; 286 } 287 288 _glfwInputError(GLFW_INVALID_ENUM, 289 "Invalid init hint 0x%08X", hint); 290 } 291 292 void glfwGetVersion(int* major, int* minor, int* rev) { 293 if (major != null) 294 *major = GLFW_VERSION_MAJOR; 295 if (minor != null) 296 *minor = GLFW_VERSION_MINOR; 297 if (rev != null) 298 *rev = GLFW_VERSION_REVISION; 299 } 300 301 const(char)* glfwGetVersionString() { 302 return _glfwPlatformGetVersionString(); 303 } 304 305 int glfwGetError(const(char)** description) { 306 _GLFWerror* error; 307 int code = GLFW_NO_ERROR; 308 309 if (description) 310 *description = null; 311 312 if (_glfw.initialized) 313 error = cast(_GLFWerror*) _glfwPlatformGetTls(&_glfw.errorSlot); 314 else 315 error = &_glfwMainThreadError; 316 317 if (error) 318 { 319 code = error.code; 320 error.code = GLFW_NO_ERROR; 321 if (description && code) 322 *description = error.description.ptr; 323 } 324 325 return code; 326 } 327 328 GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun) { 329 const old = _glfwErrorCallback; 330 _glfwErrorCallback = cbfun; 331 return old; 332 }