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