1 /**
2  * Copyright:   Copyright (C) 2018 Gabriel Gheorghe, All Rights Reserved
3  * Authors:     $(Gabriel Gheorghe)
4  * License:     $(LINK2 https://www.gnu.org/licenses/gpl-3.0.txt, GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007)
5  * Source:      $(LINK2 https://github.com/GabyForceQ/LibertyEngine/blob/master/source/liberty/graphics/util.d, _util.d)
6  * Documentation:
7  * Coverage:
8  */
9 module liberty.graphics.util;
10 import liberty.graphics.renderer : DataUsage, DrawMode, VectorType;
11 import liberty.graphics.video.backend : VideoBackend;
12 import liberty.graphics.video.buffer : VideoBuffer, BufferTarget;
13 import liberty.graphics.video.vao : VertexArray;
14 import liberty.graphics.video.shader : ShaderProgram;
15 import liberty.graphics.video.vertex : VertexSpec;
16 import liberty.core.utils : Singleton, IService;
17 import derelict.opengl;
18 version (__OpenGL__) {
19 	import liberty.graphics.opengl.backend : GLBackend;
20 	import liberty.graphics.opengl.buffer : GLBuffer;
21 	import liberty.graphics.opengl.vao : GLVertexArray;
22 	import liberty.graphics.opengl.shader : GLShaderProgram;
23 	import liberty.graphics.opengl.vertex : GLVertexSpec;
24 } else version (__Vulkan__) {
25 	import liberty.graphics.vulkan.backend : VKBackend;
26 	import liberty.graphics.vulkan.buffer : VKBuffer;
27 } else version (__WASM__) {
28 	import liberty.graphics.wasm.backend : WASMBackend;
29 }
30 ///
31 class RenderUtil : Singleton!RenderUtil {
32 	///
33     VideoBuffer createBuffer(T)(BufferTarget target, DataUsage usage, T[] data = null) {
34         uint _target, _usage;
35         VideoBuffer buff = null;
36         version (__OpenGL__) {
37             final switch(target) with (BufferTarget) {
38                 case Array: _target = GL_ARRAY_BUFFER; break;
39                 case AtomicCounter: _target = GL_ATOMIC_COUNTER_BUFFER; break;
40                 case CopyRead: _target = GL_COPY_READ_BUFFER; break;
41                 case CopyWrite: _target = GL_COPY_WRITE_BUFFER; break;
42                 case DispatchIndirect: _target = GL_DISPATCH_INDIRECT_BUFFER; break;
43                 case DrawIndirect: _target = GL_DRAW_INDIRECT_BUFFER; break;
44                 case ElementArray: _target = GL_ELEMENT_ARRAY_BUFFER; break;
45                 case PixelPack: _target = GL_PIXEL_PACK_BUFFER; break;
46                 case PixelUnpack: _target = GL_PIXEL_UNPACK_BUFFER; break;
47                 case Query: _target = GL_QUERY_BUFFER; break;
48                 case ShaderStorage: _target = GL_SHADER_STORAGE_BUFFER; break;
49                 case Texture: _target = GL_TEXTURE_BUFFER; break;
50                 case TransformFeedback: _target = GL_TRANSFORM_FEEDBACK_BUFFER; break;
51                 case Uniform: _target = GL_UNIFORM_BUFFER; break;
52             }
53             final switch(usage) with (DataUsage) {
54                 case StreamDraw: _usage = GL_STREAM_DRAW; break;
55                 case StreamRead: _usage = GL_STREAM_READ; break;
56                 case StreamCopy: _usage = GL_STREAM_COPY; break;
57                 case StaticDraw: _usage = GL_STATIC_DRAW; break;
58                 case StaticRead: _usage = GL_STATIC_READ; break;
59                 case StaticCopy: _usage = GL_STATIC_COPY; break;
60                 case DynamicDraw: _usage = GL_DYNAMIC_DRAW; break;
61                 case DynamicRead: _usage = GL_DYNAMIC_READ; break;
62                 case DynamicCopy: _usage = GL_DYNAMIC_COPY; break;
63             }
64             if (data is null) {
65                 buff = new GLBuffer(_target, _usage);
66             } else {
67                 buff = new GLBuffer(_target, _usage, data);
68             }
69         } else version (__Vulkan__) {
70             if (data is null) {
71                 buff = new VKBuffer(_target, _usage);
72             } else {
73 	            buff = new VKBuffer(_target, _usage, data);
74 	        }
75         } else {
76             throw new UnsupportedVideoFeatureException("createBuffer() -> VideoBuffer");
77         }
78         return buff;
79     }
80     ///
81     VertexArray createVertexArray() {
82         VertexArray vao = null;
83         version (__OpenGL__) {
84             vao = new GLVertexArray();
85         } else version (__Vulkan__) {
86             vao = new VKVertexArray();
87         } else {
88             throw new UnsupportedVideoFeatureException("createVertexArray() -> VertexArray");
89         }
90         return vao;
91     }
92     ///
93     ShaderProgram createShaderProgram(string vertex_code, string fragment_code) {
94         ShaderProgram shader = null;
95         version (__OpenGL__) {
96             shader = new GLShaderProgram(vertex_code, fragment_code);
97         } else version (__Vulkan__) {
98             shader = new VKShaderProgram(vertex_code, fragment_code);
99         } else {
100             throw new UnsupportedVideoFeatureException("createShader() -> ShaderProgram");
101         }
102         return shader;
103     }
104     ///
105     VertexSpec!VERTEX createVertexSpec(VERTEX)(ShaderProgram shader_program) {
106         VertexSpec!VERTEX vertex_spec = null;
107         version (__OpenGL__) {
108             vertex_spec = new GLVertexSpec!VERTEX(cast(GLShaderProgram)shader_program);
109         } else version (__Vulkan__) {
110             vertex_spec = new VKVertexSpec!VERTEX(cast(VKShaderProgram)shader_program);
111         } else {
112             throw new UnsupportedVideoFeatureException("createVertexSpec() -> VertexSpec");
113         }
114         return vertex_spec;
115     }
116     ///
117     void drawElements(DrawMode drawMode, int count, VectorType type) @trusted {
118         version (__OpenGL__) {
119             GLenum _drawMode, _type;
120             final switch (drawMode) with (DrawMode) {
121                 case Triangles: _drawMode = GL_TRIANGLES;
122             }
123             final switch (type) with (VectorType) {
124                 case UnsignedInt: _type = GL_UNSIGNED_INT;
125             }
126             glDrawElements(_drawMode, count, _type, cast(void*)0);
127         } else version (__Vulkan__) {
128             // TODO.
129         } else {
130             throw new UnsupportedVideoFeatureException("drawElements()");
131         }
132     }
133 }