1 /++ 2 Module for loading the library of open graphics, as well as some of its 3 extensions. 4 5 Also, the module provides information about which version of the library 6 is used, provides a list of available extensions, and more. 7 8 To load the library, you need the created graphics context. Therefore, 9 you need to create a window and embed a graphical context, 10 which is described $(HREF window.html, here). After that, 11 using the $(LREF loadGraphicsLibrary) function, the functions of 12 the open graphics library will be available. 13 14 Example: 15 --- 16 import tida.runtime; 17 import tida.window; 18 import tida.gl; 19 20 int main(string[] args) 21 { 22 ITidaRuntime.initialize(args, AllLibrary); 23 Window window = new Window(640, 480, "Example window"); 24 window.windowInitialize!(WithContext)(); 25 26 loadGraphicsLibrary(); 27 28 return 0; 29 } 30 --- 31 32 Macros: 33 LREF = <a href="#$1">$1</a> 34 HREF = <a href="$1">$2</a> 35 36 Authors: $(HREF https://github.com/TodNaz,TodNaz) 37 Copyright: Copyright (c) 2020 - 2021, TodNaz. 38 License: $(HREF https://github.com/TodNaz/Tida/blob/master/LICENSE,MIT) 39 +/ 40 module tida.gl; 41 42 public import bindbc.opengl; 43 44 __gshared int[2] _glVersionSpecifed; 45 __gshared string _glslVersion; 46 47 /++ 48 A function that returns the version of the library in the form of two numbers: 49 a major version and a minor version. 50 +/ 51 @property int[2] glVersionSpecifed() @trusted 52 { 53 return _glVersionSpecifed; 54 } 55 56 /++ 57 Indicates whether the use of geometry shaders is supported on this device. 58 +/ 59 @property bool glGeometrySupport() @trusted 60 { 61 ExtList extensions = glExtensionsList(); 62 63 return hasExtensions(extensions, Extensions.geometryShaderARB) || 64 hasExtensions(extensions, Extensions.geometryShaderEXT) || 65 hasExtensions(extensions, Extensions.geometryShaderNV); 66 } 67 68 /++ 69 Returns the maximum version of the shaders in the open graphics. 70 +/ 71 @property string glslVersion() @trusted 72 { 73 return _glslVersion; 74 } 75 76 @property uint glError() @trusted 77 { 78 return glGetError(); 79 } 80 81 @property string glErrorMessage(immutable uint err) @trusted 82 { 83 string error; 84 85 switch (err) 86 { 87 case GL_INVALID_ENUM: 88 error = "Invalid enum!"; 89 break; 90 91 case GL_INVALID_VALUE: 92 error = "Invalid input value!"; 93 break; 94 95 case GL_INVALID_OPERATION: 96 error = "Invalid operation!"; 97 break; 98 99 case GL_STACK_OVERFLOW: 100 error = "Stack overflow!"; 101 break; 102 103 case GL_STACK_UNDERFLOW: 104 error = "Stack underflow!"; 105 break; 106 107 case GL_OUT_OF_MEMORY: 108 error = "Out of memory!"; 109 break; 110 111 case GL_INVALID_FRAMEBUFFER_OPERATION: 112 error = "Invalid framebuffer operation!"; 113 break; 114 115 default: 116 error = "Unkown error!"; 117 } 118 119 return error; 120 } 121 122 void checkGLError( 123 string file = __FILE__, 124 size_t line = __LINE__, 125 string func = __FUNCTION__ 126 ) @safe 127 { 128 immutable err = glError(); 129 if (err != GL_NO_ERROR) 130 { 131 throw new Exception( 132 "In function `" ~ func ~ "` discovered error: `" ~ glErrorMessage(err) ~ "`.", 133 file, 134 line 135 ); 136 } 137 } 138 139 void assertGLError( 140 lazy uint checked, 141 string file = __FILE__, 142 size_t line = __LINE__, 143 string func = __FUNCTION__ 144 ) @safe 145 { 146 immutable err = checked(); 147 if (err != GL_NO_ERROR) 148 { 149 throw new Exception( 150 "In function `" ~ func ~ "` discovered error: `" ~ glErrorMessage(err) ~ "`.", 151 file, 152 line 153 ); 154 } 155 } 156 157 /++ 158 Returns the company responsible for this GL implementation. 159 This name does not change from release to release. 160 161 See_Also: 162 $(HREF https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetString.xhtml, OpenGL Reference - glGetString) 163 +/ 164 @property string glVendor() @trusted 165 { 166 import std.conv : to; 167 168 return glGetString(GL_VENDOR).to!string; 169 } 170 171 /++ 172 Returns the name of the renderer. 173 This name is typically specific to a particular configuration of a hardware platform. 174 It does not change from release to release. 175 176 See_Also: 177 $(HREF https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetString.xhtml, OpenGL Reference - glGetString) 178 +/ 179 @property string glRenderer() @trusted 180 { 181 import std.conv : to; 182 183 return glGetString(GL_RENDERER).to!string; 184 } 185 186 /++ 187 The function loads the `OpenGL` libraries for hardware graphics acceleration. 188 189 Throws: 190 $(HREF https://dlang.org/library/object.html#Exception, Exception) 191 if the library was not found or the context was not created to implement 192 hardware acceleration. 193 +/ 194 void loadGraphicsLibrary() @trusted 195 { 196 import std.exception : enforce; 197 import std.conv : to; 198 199 bool valid(GLSupport value) 200 { 201 return value != GLSupport.noContext && 202 value != GLSupport.badLibrary && 203 value != GLSupport.noLibrary; 204 } 205 206 GLSupport retValue = loadOpenGL(); 207 enforce!Exception(valid(retValue), 208 "The library was not loaded or the context was not created!"); 209 210 glGetIntegerv(GL_MAJOR_VERSION, &_glVersionSpecifed[0]); 211 glGetIntegerv(GL_MINOR_VERSION, &_glVersionSpecifed[1]); 212 _glslVersion = glGetString(GL_SHADING_LANGUAGE_VERSION).to!string[0 .. 4]; 213 } 214 215 alias ExtList = string[]; 216 217 /++ 218 Available extensions that the framework can load with one function. 219 +/ 220 enum Extensions : string 221 { 222 /++ 223 Compressing texture images can reduce texture memory utilization and 224 improve performance when rendering textured primitives. 225 226 See_Also: 227 $(HREF https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_texture_compression.txt, OpenGL reference "GL_ARB_texture_compression") 228 +/ 229 textureCompression = "GL_ARB_texture_compression", 230 231 /++ 232 This extension introduces the notion of one- and two-dimensional array 233 textures. An array texture is a collection of one- and two-dimensional 234 images of identical size and format, arranged in layers. 235 236 See_Also: 237 $(HREF https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_texture_array.txt, OpenGL reference "GL_EXT_texture_array") 238 +/ 239 textureArray = "GL_EXT_texture_array", 240 241 /++ 242 Texture objects are fundamental to the operation of OpenGL. They are 243 used as a source for texture sampling and destination for rendering 244 as well as being accessed in shaders for image load/store operations 245 It is also possible to invalidate the contents of a texture. It is 246 currently only possible to set texture image data to known values by 247 uploading some or all of a image array from application memory or by 248 attaching it to a framebuffer object and using the Clear or ClearBuffer 249 commands. 250 251 See_Also: 252 $(HREF https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_clear_texture.txt, OpenGL reference "GL_ARB_clear_texture") 253 +/ 254 textureClear = "GL_ARB_clear_texture", 255 256 /++ 257 ARB_geometry_shader4 defines a new shader type available to be run on the 258 GPU, called a geometry shader. Geometry shaders are run after vertices are 259 transformed, but prior to color clamping, flat shading and clipping. 260 261 See_Also: 262 $(HREF https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_geometry_shader4.txt, OpenGL reference "GL_ARB_geometry_shader4") 263 +/ 264 geometryShaderARB = "GL_ARB_geometry_shader4", 265 266 /// ditto 267 geometryShaderEXT = "GL_EXT_geometry_shader4", 268 269 /// ditto 270 geometryShaderNV = "GL_NV_geometry_shader4" 271 } 272 273 /++ 274 Checks if the extension specified in the argument is in the open graphics library. 275 276 Params: 277 list = List of extensions. Leave it blank (using the following: '[]') 278 for the function to calculate all the extensions by itself. 279 name = The name of the extension you need. 280 281 Returns: 282 Extension search result. `False` if not found. 283 +/ 284 bool hasExtensions(ExtList list, string name) @trusted 285 { 286 import std.algorithm : canFind; 287 288 if (list.length == 0) 289 list = glExtensionsList(); 290 291 return list.canFind(name); 292 } 293 294 /++ 295 A function that provides a list of available extensions to use. 296 +/ 297 ExtList glExtensionsList() @trusted 298 { 299 import std.conv : to; 300 import std.string : split; 301 302 int numExtensions = 0; 303 glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions); 304 305 string[] extensions; 306 307 foreach (i; 0 .. numExtensions) 308 { 309 extensions ~= glGetStringi(GL_EXTENSIONS, i).to!string; 310 } 311 312 return extensions; 313 } 314 315 // Texture compressed 316 alias FCompressedTexImage2DARB = extern(C) void function(GLenum target, 317 int level, 318 GLenum internalformat, 319 GLsizei width, 320 GLsizei height, 321 int border, 322 GLsizei imagesize, 323 void* data); 324 325 __gshared 326 { 327 FCompressedTexImage2DARB glCompressedTexImage2DARB; 328 } 329 330 alias glCompressedTexImage2D = glCompressedTexImage2DARB; 331 332 enum 333 { 334 GL_COMPRESSED_RGBA_ARB = 0x84EE, 335 GL_COMPRESSED_RGB_ARB = 0x84ED, 336 GL_COMPRESSED_ALPHA_ARB = 0x84E9, 337 338 GL_TEXTURE_COMPRESSION_HINT_ARB = 0x84EF, 339 GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB = 0x86A0, 340 GL_TEXTURE_COMPRESSED_ARB = 0x86A1, 341 GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB = 0x86A2, 342 GL_COMPRESSED_TEXTURE_FORMATS_ARB = 0x86A3 343 } 344 345 /++ 346 Loads the extension `GL_ARB_texture_compression`, that is, 347 extensions for loading compressed textures. 348 349 Returns: 350 Returns the result of loading. False if the download is not successful. 351 +/ 352 bool extTextureCompressionLoad() @trusted 353 { 354 import bindbc.opengl.util; 355 356 if (!hasExtensions(null, "GL_ARB_texture_compression")) 357 return false; 358 359 if (!loadExtendedGLSymbol( cast(void**) &glCompressedTexImage2DARB, 360 "glCompressedTexImage2DARB")) 361 return false; 362 363 return true; 364 } 365 366 // Texture array ext 367 alias FFramebufferTextureLayerEXT = extern(C) void function(); 368 369 __gshared 370 { 371 FFramebufferTextureLayerEXT glFramebufferTextureLayerEXT; 372 } 373 374 enum 375 { 376 GL_TEXTURE_1D_ARRAY_EXT = 0x8C18, 377 GL_TEXTURE_2D_ARRAY_EXT = 0x8C1A, 378 379 GL_TEXTURE_BINDING_1D_ARRAY_EXT = 0x8C1C, 380 GL_TEXTURE_BINDING_2D_ARRAY_EXT = 0x8C1D, 381 GL_MAX_ARRAY_TEXTURE_LAYERS_EXT = 0x88FF, 382 GL_COMPARE_REF_DEPTH_TO_TEXTURE_EXT = 0x884E 383 } 384 385 /++ 386 Loads the extension `GL_EXT_texture_array`, that is, extensions for 387 loading an array of textures. 388 389 Returns: 390 Returns the result of loading. False if the download is not successful. 391 +/ 392 bool extTextureArrayLoad() @trusted 393 { 394 import bindbc.opengl.util; 395 396 if (!hasExtensions(null, Extensions.textureArray)) 397 return false; 398 399 // glFramebufferTextureLayerEXT 400 if (!loadExtendedGLSymbol(cast(void**) &glFramebufferTextureLayerEXT, 401 "glFramebufferTextureLayerEXT")) 402 return false; 403 404 return true; 405 }