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 46 /// Returns: Size of buffer in bytes. 47 @property size_t size() pure const nothrow 48 { 49 return _size; 50 } 51 52 /// Returns: Copy bytes to the buffer. 53 /// Throws: $(D OpenGLException) on error. 54 void setData(T)(T[] buffer) 55 { 56 setData(buffer.length * T.sizeof, buffer.ptr); 57 } 58 59 /// Returns: Copy bytes to the buffer. 60 /// Throws: $(D OpenGLException) on error. 61 void setData(size_t size, void * data) 62 { 63 bind(); 64 _size = size; 65 66 // discard previous data 67 if (!_firstLoad) 68 { 69 glBufferData(_target, size, null, _usage); 70 glBufferSubData(_target, 0, size, data); 71 } 72 else 73 glBufferData(_target, size, data, _usage); 74 75 _gl.runtimeCheck(); 76 77 _firstLoad = false; 78 } 79 80 /// Copies bytes to a sub-part of the buffer. You can't adress data beyond the buffer's size. 81 /// Throws: $(D OpenGLException) on error. 82 void setSubData(size_t offset, size_t size, void* data) 83 { 84 bind(); 85 glBufferSubData(_target, offset, size, data); 86 _gl.runtimeCheck(); 87 } 88 89 /// Gets a sub-part of a buffer. 90 /// Throws: $(D OpenGLException) on error. 91 void getSubData(size_t offset, size_t size, void* data) 92 { 93 bind(); 94 glGetBufferSubData(_target, offset, size, data); 95 _gl.runtimeCheck(); 96 } 97 98 /// Gets the whole buffer content in a newly allocated array. 99 /// <b>This is intended for debugging purposes.</b> 100 /// Throws: $(D OpenGLException) on error. 101 ubyte[] getBytes() 102 { 103 auto buffer = new ubyte[_size]; 104 getSubData(0, _size, buffer.ptr); 105 return buffer; 106 } 107 108 /// Binds this buffer. 109 /// Throws: $(D OpenGLException) on error. 110 void bind() 111 { 112 glBindBuffer(_target, _buffer); 113 _gl.runtimeCheck(); 114 } 115 116 /// Unbinds this buffer. 117 /// Throws: $(D OpenGLException) on error. 118 void unbind() 119 { 120 glBindBuffer(_target, 0); 121 } 122 123 /// Returns: Wrapped OpenGL resource handle. 124 GLuint handle() pure const nothrow 125 { 126 return _buffer; 127 } 128 } 129 130 private 131 { 132 OpenGL _gl; 133 GLuint _buffer; 134 size_t _size; 135 GLuint _target; 136 GLuint _usage; 137 bool _firstLoad; 138 bool _initialized; 139 } 140 }