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/opengl/buffer.d, _buffer.d)
6  * Documentation:
7  * Coverage:
8  */
9 // TODO: optimize imports
10 module liberty.graphics.opengl.buffer;
11 version (__OpenGL__) :
12 import derelict.opengl;
13 import liberty.graphics.renderer;
14 import liberty.graphics.video.buffer : VideoBuffer;
15 /// OpenGL Buffer.
16 final class GLBuffer : VideoBuffer {
17     /// Creates an empty buffer.
18     /// Throws: $(D GLException) on error.
19     this(uint target, uint usage) {
20         _usage = usage;
21         _target = target;
22         _firstLoad = true;
23         glGenBuffers(1, &_buffer);
24         GraphicsEngine.get.backend.runtimeCheck();
25         _initialized = true;
26         _size = 0;
27     }
28     /// Creates a buffer already filled with data.
29     /// Throws: $(D GLException) on error.
30     this(T)(uint target, uint usage, T[] buffer) {
31         this(target, usage);
32         data(buffer);
33     }
34     /// Releases the OpenGL buffer resource.
35     ~this() {
36         if (_initialized) {
37             debug import liberty.core.memory : ensureNotInGC;
38             debug ensureNotInGC("GLBuffer");
39             glDeleteBuffers(1, &_buffer);
40             _initialized = false;
41         }
42     }
43     /// Returns the size of the buffer in bytes.
44     override size_t size() pure const nothrow {
45         return _size;
46     }
47     /// Returns the copy bytes to the buffer.
48     /// Throws: $(D OpenGLException) on error.
49     void data(T)(T[] buffer) {
50         setData(buffer.length * T.sizeof, buffer.ptr);
51     }
52     /// Returns the copy bytes to the buffer.
53     /// Throws: $(D GLException) on error.
54     override void setData(size_t size, void* data) {
55         bind();
56         _size = size;
57         if (!_firstLoad) {
58             glBufferData(_target, size, null, _usage);
59             glBufferSubData(_target, 0, size, data);
60         } else {
61             glBufferData(_target, size, data, _usage);
62 		}
63         GraphicsEngine.get.backend.runtimeCheck();
64         _firstLoad = false;
65     }
66     /// Copies bytes to a sub-part of the buffer. You can't adress data beyond the buffer's size.
67     /// Throws: $(D GLException) on error.
68     override void setSubData(size_t offset, size_t size, void* data) {
69         bind();
70         glBufferSubData(_target, offset, size, data);
71         GraphicsEngine.get.backend.runtimeCheck();
72     }
73 
74     /// Gets a sub-part of a buffer.
75     /// Throws: $(D GLException) on error.
76     override void getSubData(size_t offset, size_t size, void* data) {
77         bind();
78         glGetBufferSubData(_target, offset, size, data);
79         GraphicsEngine.get.backend.runtimeCheck();
80     }
81 
82     /// Gets the whole buffer content in a newly allocated array.
83     /// <b>This is intended for debugging purposes.</b>
84     /// Throws: $(D GLException) on error.
85     override ubyte[] bytes() {
86         auto buffer = new ubyte[_size];
87         getSubData(0, _size, buffer.ptr);
88         return buffer;
89     }
90     /// Binds this buffer.
91     /// Throws: $(D GLException) on error.
92     override void bind() @trusted {
93         glBindBuffer(_target, _buffer);
94         GraphicsEngine.get.backend.runtimeCheck();
95     }
96     /// Unbinds this buffer.
97     /// Throws: $(D GLException) on error.
98     override void unbind() {
99         glBindBuffer(_target, 0);
100     }
101     /// Returns: Wrapped OpenGL resource handle.
102     override uint handle() pure nothrow const {
103         return _buffer;
104     }
105 }