1 module gfm.opengl.buffer;
2
3 import derelict.opengl3.gl3;
4
5 import gfm.opengl.opengl;
6
7 /// OpenGL Buffer wrapper.
8 final class GLBuffer
9 {
10 public
11 {
12 /// Creates an empty buffer.
13 /// Throws: $(D OpenGLException) on error.
14 this(OpenGL gl, GLuint target, GLuint usage)
15 {
16 _gl = gl;
17 _usage = usage;
18 _target = target;
19 _firstLoad = true;
20
21 glGenBuffers(1, &_buffer);
22 gl.runtimeCheck();
23 _initialized = true;
24 _size = 0;
25 }
26
27 /// Creates a buffer already filled with data.
28 /// Throws: $(D OpenGLException) on error.
29 this(T)(OpenGL gl, GLuint target, GLuint usage, T[] buffer)
30 {
31 this(gl, target, usage);
32 setData(buffer);
33 }
34
35 /// Releases the OpenGL buffer resource.
36 ~this()
37 {
38 if (_initialized)
39 {
40 debug ensureNotInGC("GLBuffer");
41 glDeleteBuffers(1, &_buffer);
42 _initialized = false;
43 }
44 }
45 deprecated("Use .destroy instead") void close(){}
46
47 /// Returns: Size of buffer in bytes.
48 @property size_t size() pure const nothrow
49 {
50 return _size;
51 }
52
53 /// Returns: Copy bytes to the buffer.
54 /// Throws: $(D OpenGLException) on error.
55 void setData(T)(T[] buffer)
56 {
57 setData(buffer.length * T.sizeof, buffer.ptr);
58 }
59
60 /// Returns: Copy bytes to the buffer.
61 /// Throws: $(D OpenGLException) on error.
62 void setData(size_t size, void * data)
63 {
64 bind();
65 _size = size;
66
67 // discard previous data
68 if (!_firstLoad)
69 {
70 glBufferData(_target, size, null, _usage);
71 glBufferSubData(_target, 0, size, data);
72 }
73 else
74 glBufferData(_target, size, data, _usage);
75
76 _gl.runtimeCheck();
77
78 _firstLoad = false;
79 }
80
81 /// Copies bytes to a sub-part of the buffer. You can't adress data beyond the buffer's size.
82 /// Throws: $(D OpenGLException) on error.
83 void setSubData(size_t offset, size_t size, void* data)
84 {
85 bind();
86 glBufferSubData(_target, offset, size, data);
87 _gl.runtimeCheck();
88 }
89
90 /// Gets a sub-part of a buffer.
91 /// Throws: $(D OpenGLException) on error.
92 void getSubData(size_t offset, size_t size, void* data)
93 {
94 bind();
95 glGetBufferSubData(_target, offset, size, data);
96 _gl.runtimeCheck();
97 }
98
99 /// Gets the whole buffer content in a newly allocated array.
100 /// <b>This is intended for debugging purposes.</b>
101 /// Throws: $(D OpenGLException) on error.
102 ubyte[] getBytes()
103 {
104 auto buffer = new ubyte[_size];
105 getSubData(0, _size, buffer.ptr);
106 return buffer;
107 }
108
109 /// Binds this buffer.
110 /// Throws: $(D OpenGLException) on error.
111 void bind()
112 {
113 glBindBuffer(_target, _buffer);
114 _gl.runtimeCheck();
115 }
116
117 /// Unbinds this buffer.
118 /// Throws: $(D OpenGLException) on error.
119 void unbind()
120 {
121 glBindBuffer(_target, 0);
122 }
123
124 /// Returns: Wrapped OpenGL resource handle.
125 GLuint handle() pure const nothrow
126 {
127 return _buffer;
128 }
129 }
130
131 private
132 {
133 OpenGL _gl;
134 GLuint _buffer;
135 size_t _size;
136 GLuint _target;
137 GLuint _usage;
138 bool _firstLoad;
139 bool _initialized;
140 }
141 }