1 /++ Gives you access to all glFunctions, GL_CONSTANTS and GLtypes. 2 3 In debug mode, glGetError() is automatically checked before and after all 4 calls to all glFunctions (except glGetError). Any errors are then thrown 5 as an moggle.core.gl.GLError. 6 7 When not in debug mode, moggle.core.gl simply publicly imports the Derelict OpenGL modules. 8 9 Don't forget to call loadOpenGL() after you created your OpenGL context, 10 or some glFunctions will still be null. 11 12 The Derelict library is used for OpenGL bindings. 13 +/ 14 module moggle.core.gl; 15 16 import std.traits; 17 18 import derelict.opengl3.gl3; 19 public import derelict.opengl3.types; 20 public import derelict.opengl3.constants; 21 22 pragma(lib, "dl"); 23 pragma(lib, "DerelictGL3"); 24 pragma(lib, "DerelictUtil"); 25 26 static this() { 27 DerelictGL3.load(); 28 } 29 30 /// Call this after creating your OpenGL context. 31 GLVersion loadOpenGL() { 32 return DerelictGL3.reload(); 33 } 34 35 /// The error that is thrown when glGetError() indicates an error. 36 class GLError : Exception { 37 this(string func, string what, string file = __FILE__, size_t line = __LINE__) { 38 super(func ~ ": " ~ what, file, line); 39 } 40 } 41 42 debug { 43 immutable string[uint] constant_names; 44 45 static this() { 46 foreach (x; __traits(allMembers, derelict.opengl3.constants)) { 47 static if (x[0..3] == "GL_") { 48 if (mixin(x) !in constant_names) constant_names[mixin(x)] = x; 49 } 50 } 51 } 52 53 void check_error(string file, size_t line, string func) { 54 auto e = glGetError(); 55 if (e != GL_NO_ERROR) throw new GLError(func, constant_names[e], file, line); 56 } 57 58 auto wrap(alias glSomething)(ParameterTypeTuple!glSomething parameters, string file = __FILE__, size_t line = __LINE__) 59 in { check_error(file, line, "Before " ~ __traits(identifier, glSomething)); } 60 out { check_error(file, line, __traits(identifier, glSomething)); } 61 body { return glSomething(parameters); } 62 63 mixin((){ 64 string code; 65 foreach (part, members; [ 66 "functions": [__traits(allMembers, derelict.opengl3.functions)], 67 "arb": [__traits(allMembers, derelict.opengl3.arb)], 68 "ext": [__traits(allMembers, derelict.opengl3.ext)] 69 ]) { 70 foreach (x; members) { 71 if (x[0..2] == "gl" && x != "glGetError") { 72 code ~= "alias wrap!(derelict.opengl3." ~ part ~ "." ~ x ~ ") " ~ x ~ ";\n"; 73 } else if (x[0..2] == "GL" || x == "glGetError") { 74 code ~= "alias derelict.opengl3." ~ part ~ "." ~ x ~ " " ~ x ~ ";\n"; 75 } 76 } 77 } 78 return code; 79 }()); 80 81 } else { 82 83 public import derelict.opengl3.functions; 84 public import derelict.opengl3.arb; 85 public import derelict.opengl3.ext; 86 87 } 88 89 /++ Get the GL_CONSTANT representing the type T. 90 91 This is an alias of one of GL_FLOAT, GL_DOUBLE, GL_UNSIGNED_INT, GL_INT, 92 GL_UNSIGNED_SHORT, GL_SHORT, GL_UNSIGNED_BYTE, and GL_BYTE. 93 94 Examples: 95 --- 96 assert(GL_type!float == GL_FLOAT); 97 --- 98 +/ 99 template GL_type(T) { 100 static if (is(T == GLfloat )) alias GL_FLOAT GL_type; 101 else static if (is(T == GLdouble)) alias GL_DOUBLE GL_type; 102 else static if (is(T == GLubyte )) alias GL_UNSIGNED_BYTE GL_type; 103 else static if (is(T == GLbyte )) alias GL_BYTE GL_type; 104 else static if (is(T == GLushort)) alias GL_UNSIGNED_SHORT GL_type; 105 else static if (is(T == GLshort )) alias GL_SHORT GL_type; 106 else static if (is(T == GLuint )) alias GL_UNSIGNED_INT GL_type; 107 else static if (is(T == GLint )) alias GL_INT GL_type; 108 }