1 /* 2 * BSD 3-Clause License 3 * 4 * Copyright (c) 2016, Mango-Engine Team 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are met: 9 * 10 * * Redistributions of source code must retain the above copyright notice, this 11 * list of conditions and the following disclaimer. 12 * 13 * * Redistributions in binary form must reproduce the above copyright notice, 14 * this list of conditions and the following disclaimer in the documentation 15 * and/or other materials provided with the distribution. 16 * 17 * * Neither the name of the copyright holder nor the names of its 18 * contributors may be used to endorse or promote products derived from 19 * this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 module mango_engine.graphics.opengl.gl_backend; 33 34 import mango_engine.mango; 35 import mango_engine.logging; 36 import mango_engine.graphics.backend; 37 38 import derelict.opengl3.gl3; 39 import derelict.glfw3.glfw3; 40 import derelict.freeimage.freeimage; 41 import derelict.util.exception; 42 43 import std.conv : to; 44 45 /// The Major OpenGL version used by mango-engine. 46 immutable uint MANGO_GL_VERSION_MAJOR = 3; 47 /// The Minor OpenGL version used by mango-engine. 48 immutable uint MANGO_GL_VERSION_MINOR = 3; 49 /// The Whole OpenGL version used by mango-engine. 50 immutable GLVersion MANGO_GL_VERSION = GLVersion.GL33; 51 /// The OpenGL version used by mango-engine (string) 52 immutable string MANGO_GL_VERSION_STRING = "GL 3.3"; 53 54 private alias checkSupport = gl_check; 55 56 package shared bool failedContext = false; 57 58 package shared Logger backendLogger; 59 60 void gl_check() @safe { // Check if we were compiled with OpenGL support. 61 if(!mango_hasGLSupport()) { 62 throw new Exception("Mango-Engine was not compiled with OpenGL backend support!"); 63 } 64 } 65 66 extern(C) private void glfwErrorCallback(int error, const char* description) @system { 67 import std.stdio : writeln; 68 import blocksound.util : toDString; 69 70 if(error == 65543) { 71 failedContext = true; 72 } 73 74 (cast(Logger) backendLogger).logError("GLFW ERROR " ~ to!string(error) ~ ", " ~ toDString(description)); 75 } 76 77 /++ 78 The OpenGL Backend implementation for mango_engine. 79 80 Loads the following libraries: 81 OpenGL 82 GLFW 3 83 FreeImage 84 On Windows libraries will be loaded 85 from the "lib" directory (should be placed in current directory), 86 with the exception of OpenGL (see below). 87 88 loadLibraries() accepts the following keys, values: 89 "gl_useProvided" = ONLY ON WINDOWS: 90 Attempts to load opengl32.dll from the 91 DLL library folder "lib" (by default it is loaded from the system). 92 Set to "true" if you want to load the OpenGL DLL from here. 93 Useful for using a software renderer such as LLVMpipe. 94 +/ 95 class GLBackend : Backend { 96 97 this(Logger logger) @trusted { 98 super(logger); 99 // TODO: init logger based on logger class provided 100 backendLogger = cast(shared) new ConsoleLogger("GLBackend"); 101 } 102 103 /// Loads the core methods of OpenGL (1.1+) 104 static void loadCoreMethods() @system { 105 DerelictGL3.reload(); 106 } 107 108 override { 109 void loadLibraries(in string[string] args = null) @system { 110 checkSupport(); 111 112 if("gl_useProvided" in args && to!bool(args["gl_useProvided"]) == true) { 113 loadGL(true); 114 } else loadGL(false); 115 116 loadGLFW(); 117 loadFI(); 118 } 119 120 void doInit() @system { 121 glfwSetErrorCallback(cast(GLFWerrorfun) &glfwErrorCallback); 122 123 if(!glfwInit()) { 124 // GLFW failed to initalize 125 throw new LibraryLoadException("GLFW", "glfwInit() Failed!"); 126 } 127 } 128 129 void doDestroy() @system { 130 glfwTerminate(); 131 } 132 } 133 134 ShouldThrow derelictShouldThrow(string symbolName) { 135 // For now we will ignore missing symbols, TODO: FIX! 136 logger.logWarn("Missing symbol: " ~ symbolName ~ " !"); 137 return ShouldThrow.No; 138 } 139 140 private void loadGL(bool useProvided) @system { // Load code for OpenGL 141 logger.logDebug("Loading OpenGL..."); 142 version(mango_GLBackend) { 143 version(Windows) { 144 //------------------------------- Windows Load Code 145 try { 146 if(useProvided) { 147 DerelictGL3.load("lib\\opengl32.dll"); // Use provided DLL 148 logger.logDebug("Loaded Provided opengl32.dll"); 149 } else { 150 DerelictGL3.load(); 151 } 152 153 } catch(Exception e) { 154 throw new LibraryLoadException("OpenGL", e.toString()); 155 } 156 //------------------------------- End Windows Load Code 157 } else { // All other OS 158 try { 159 DerelictGL3.load(); 160 } catch(Exception e) { 161 throw new LibraryLoadException("OpenGL", e.toString()); 162 } 163 } 164 } 165 } 166 167 private void loadGLFW() @system { // Load code for GLFW 168 logger.logDebug("Loadng GLFW..."); 169 version(Windows) { 170 //------------------------------- Windows Load Code 171 try { 172 DerelictGLFW3.load("lib\\glfw3.dll"); 173 } catch(Exception e) { 174 throw new LibraryLoadException("GLFW", e.toString()); 175 } 176 //------------------------------- End Windows Load Code 177 } else { // All other OS 178 DerelictGLFW3.missingSymbolCallback = &this.derelictShouldThrow; 179 try { 180 DerelictGLFW3.load(); 181 } catch(Exception e) { 182 throw new LibraryLoadException("GLFW", e.toString()); 183 } 184 } 185 } 186 187 private void loadFI() @system { // Load code for FreeImage 188 logger.logDebug("Loading FreeImage..."); 189 version(Windows) { 190 //------------------------------- Windows Load Code 191 try { 192 DerelictFI.load("lib\\FreeImage.dll"); 193 } catch(Exception e) { 194 throw new LibraryLoadException("FreeImage", e.toString()); 195 } 196 //------------------------------- End Windows Load Code 197 } else { // All other OS 198 DerelictFI.missingSymbolCallback = &derelictShouldThrow; 199 try { 200 DerelictFI.load(); 201 } catch(Exception e) { 202 throw new LibraryLoadException("FreeImage", e.toString()); 203 } 204 } 205 } 206 }