2 #include <msp/gl/extensions/arb_buffer_storage.h>
3 #include <msp/gl/extensions/arb_direct_state_access.h>
4 #include <msp/gl/extensions/arb_map_buffer_range.h>
5 #include <msp/gl/extensions/arb_vertex_buffer_object.h>
6 #include <msp/gl/extensions/khr_debug.h>
7 #include <msp/gl/extensions/oes_mapbuffer.h>
8 #include <msp/strings/format.h>
17 Buffer *Buffer::scratch_binding = 0;
23 static Require _req(ARB_vertex_buffer_object);
25 if(ARB_direct_state_access)
26 glCreateBuffers(1, &id);
33 if(this==scratch_binding)
35 glDeleteBuffers(1, &id);
38 void Buffer::storage(unsigned sz)
43 throw incompatible_data("Buffer::storage");
47 throw invalid_argument("Buffer::storage");
52 void Buffer::allocate()
55 throw invalid_operation("Buffer::allocate");
59 if(ARB_buffer_storage)
61 static const int flags = GL_MAP_READ_BIT|GL_MAP_WRITE_BIT|GL_DYNAMIC_STORAGE_BIT;
62 if(ARB_direct_state_access)
63 glNamedBufferStorage(id, size, 0, flags);
67 glBufferStorage(GL_ARRAY_BUFFER, size, 0, flags);
76 void Buffer::data(const void *d)
79 throw invalid_operation("Buffer::data");
81 if(ARB_buffer_storage)
82 return sub_data(0, size, d);
84 if(ARB_direct_state_access)
85 glNamedBufferData(id, size, d, GL_STATIC_DRAW);
89 glBufferData(GL_ARRAY_BUFFER, size, d, GL_STATIC_DRAW);
95 void Buffer::sub_data(unsigned off, unsigned sz, const void *d)
98 throw invalid_operation("Buffer::sub_data");
102 if(ARB_direct_state_access)
103 glNamedBufferSubData(id, off, sz, d);
107 glBufferSubData(GL_ARRAY_BUFFER, off, sz, d);
111 void Buffer::require_size(unsigned req_sz) const
114 throw buffer_too_small(format("buffer has %d bytes; %d required", size, req_sz));
119 static Require _req(ARB_map_buffer_range);
122 if(ARB_direct_state_access)
123 return glMapNamedBufferRange(id, 0, size, GL_MAP_READ_BIT|GL_MAP_WRITE_BIT);
127 void *result = glMapBufferRange(GL_ARRAY_BUFFER, 0, size, GL_MAP_READ_BIT|GL_MAP_WRITE_BIT);
134 // TODO check if it's mapped
135 if(ARB_direct_state_access)
136 return glUnmapNamedBuffer(id);
137 else if(OES_mapbuffer)
140 bool result = glUnmapBuffer(GL_ARRAY_BUFFER);
147 void Buffer::set_debug_name(const string &name)
151 glObjectLabel(GL_BUFFER, id, name.size(), name.c_str());
157 void Buffer::bind_scratch()
159 if(scratch_binding!=this)
161 glBindBuffer(GL_ARRAY_BUFFER, id);
162 scratch_binding = this;
166 void Buffer::unbind_scratch()
170 glBindBuffer(GL_ARRAY_BUFFER, 0);