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 }