#include <msp/gl/extensions/arb_buffer_storage.h>
#include <msp/gl/extensions/arb_direct_state_access.h>
#include <msp/gl/extensions/arb_map_buffer_range.h>
+#include <msp/gl/extensions/arb_vertex_buffer_object.h>
#include <msp/gl/extensions/khr_debug.h>
+#include <msp/gl/extensions/oes_mapbuffer.h>
#include <msp/strings/format.h>
#include "buffer.h"
-#include "deviceinfo.h"
#include "error.h"
-#include "misc.h"
-#include "vertexsetup.h"
using namespace std;
namespace Msp {
namespace GL {
+Buffer *Buffer::scratch_binding = 0;
+
Buffer::Buffer():
- size(0),
- allocated(false)
+ size(0)
{
static Require _req(ARB_vertex_buffer_object);
Buffer::~Buffer()
{
+ if(this==scratch_binding)
+ unbind_scratch();
glDeleteBuffers(1, &id);
}
throw invalid_argument("Buffer::storage");
size = sz;
-}
-
-void Buffer::allocate()
-{
- if(size==0)
- throw invalid_operation("Buffer::allocate");
- if(allocated)
- return;
if(ARB_buffer_storage)
{
glNamedBufferStorage(id, size, 0, flags);
else
{
- glBindBuffer(GL_ARRAY_BUFFER, id);
+ bind_scratch();
glBufferStorage(GL_ARRAY_BUFFER, size, 0, flags);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
}
-
- allocated = true;
}
- else
- data(0);
-}
-
-void Buffer::set_usage(BufferUsage)
-{
-}
-
-void Buffer::data(const void *d)
-{
- if(size==0)
- throw invalid_operation("Buffer::data");
-
- if(ARB_buffer_storage)
- return sub_data(0, size, d);
-
- if(ARB_direct_state_access)
- glNamedBufferData(id, size, d, STATIC_DRAW);
+ else if(ARB_direct_state_access)
+ glNamedBufferData(id, size, 0, GL_STATIC_DRAW);
else
{
- glBindBuffer(GL_ARRAY_BUFFER, id);
- glBufferData(GL_ARRAY_BUFFER, size, d, STATIC_DRAW);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
+ bind_scratch();
+ glBufferData(GL_ARRAY_BUFFER, size, 0, GL_STATIC_DRAW);
}
-
- allocated = true;
}
-void Buffer::data(unsigned sz, const void *d)
+void Buffer::data(const void *d)
{
- if(size==0)
- storage(sz);
- else if(sz!=size)
- throw incompatible_data("Buffer::data");
-
- data(d);
+ return sub_data(0, size, d);
}
void Buffer::sub_data(unsigned off, unsigned sz, const void *d)
if(size==0)
throw invalid_operation("Buffer::sub_data");
- allocate();
-
if(ARB_direct_state_access)
glNamedBufferSubData(id, off, sz, d);
else
{
- glBindBuffer(GL_ARRAY_BUFFER, id);
+ bind_scratch();
glBufferSubData(GL_ARRAY_BUFFER, off, sz, d);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
}
}
{
static Require _req(ARB_map_buffer_range);
- allocate();
if(ARB_direct_state_access)
return glMapNamedBufferRange(id, 0, size, GL_MAP_READ_BIT|GL_MAP_WRITE_BIT);
else
{
- glBindBuffer(GL_ARRAY_BUFFER, id);
+ bind_scratch();
void *result = glMapBufferRange(GL_ARRAY_BUFFER, 0, size, GL_MAP_READ_BIT|GL_MAP_WRITE_BIT);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
return result;
}
}
return glUnmapNamedBuffer(id);
else if(OES_mapbuffer)
{
- glBindBuffer(GL_ARRAY_BUFFER, id);
+ bind_scratch();
bool result = glUnmapBuffer(GL_ARRAY_BUFFER);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
return result;
}
else
#endif
}
+void Buffer::bind_scratch()
+{
+ if(scratch_binding!=this)
+ {
+ glBindBuffer(GL_ARRAY_BUFFER, id);
+ scratch_binding = this;
+ }
+}
+
+void Buffer::unbind_scratch()
+{
+ if(scratch_binding)
+ {
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ scratch_binding = 0;
+ }
+}
+
} // namespace GL
} // namespace Msp