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/khr_debug.h>
6 #include <msp/strings/format.h>
8 #include "deviceinfo.h"
11 #include "vertexsetup.h"
18 Buffer *Buffer::scratch_binding = 0;
24 static Require _req(ARB_vertex_buffer_object);
26 if(ARB_direct_state_access)
27 glCreateBuffers(1, &id);
34 if(this==scratch_binding)
36 glDeleteBuffers(1, &id);
39 void Buffer::storage(unsigned sz)
44 throw incompatible_data("Buffer::storage");
48 throw invalid_argument("Buffer::storage");
53 void Buffer::allocate()
56 throw invalid_operation("Buffer::allocate");
60 if(ARB_buffer_storage)
62 static const int flags = GL_MAP_READ_BIT|GL_MAP_WRITE_BIT|GL_DYNAMIC_STORAGE_BIT;
63 if(ARB_direct_state_access)
64 glNamedBufferStorage(id, size, 0, flags);
68 glBufferStorage(GL_ARRAY_BUFFER, size, 0, flags);
77 void Buffer::set_usage(BufferUsage)
81 void Buffer::data(const void *d)
84 throw invalid_operation("Buffer::data");
86 if(ARB_buffer_storage)
87 return sub_data(0, size, d);
89 if(ARB_direct_state_access)
90 glNamedBufferData(id, size, d, STATIC_DRAW);
94 glBufferData(GL_ARRAY_BUFFER, size, d, STATIC_DRAW);
100 void Buffer::data(unsigned sz, const void *d)
105 throw incompatible_data("Buffer::data");
110 void Buffer::sub_data(unsigned off, unsigned sz, const void *d)
113 throw invalid_operation("Buffer::sub_data");
117 if(ARB_direct_state_access)
118 glNamedBufferSubData(id, off, sz, d);
122 glBufferSubData(GL_ARRAY_BUFFER, off, sz, d);
126 void Buffer::require_size(unsigned req_sz) const
129 throw buffer_too_small(format("buffer has %d bytes; %d required", size, req_sz));
134 static Require _req(ARB_map_buffer_range);
137 if(ARB_direct_state_access)
138 return glMapNamedBufferRange(id, 0, size, GL_MAP_READ_BIT|GL_MAP_WRITE_BIT);
142 void *result = glMapBufferRange(GL_ARRAY_BUFFER, 0, size, GL_MAP_READ_BIT|GL_MAP_WRITE_BIT);
149 // TODO check if it's mapped
150 if(ARB_direct_state_access)
151 return glUnmapNamedBuffer(id);
152 else if(OES_mapbuffer)
155 bool result = glUnmapBuffer(GL_ARRAY_BUFFER);
162 void Buffer::set_debug_name(const string &name)
166 glObjectLabel(GL_BUFFER, id, name.size(), name.c_str());
172 void Buffer::bind_scratch()
174 if(scratch_binding!=this)
176 glBindBuffer(GL_ARRAY_BUFFER, id);
177 scratch_binding = this;
181 void Buffer::unbind_scratch()
185 glBindBuffer(GL_ARRAY_BUFFER, 0);