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