#include <stdexcept>
-#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/khr_debug.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():
- size(0),
- allocated(false)
-{
- static Require _req(ARB_vertex_buffer_object);
-
- if(ARB_direct_state_access)
- glCreateBuffers(1, &id);
- else
- glGenBuffers(1, &id);
-}
-
-Buffer::~Buffer()
-{
- glDeleteBuffers(1, &id);
-}
-
void Buffer::storage(unsigned sz)
{
if(size>0)
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)
- {
- static const int flags = GL_MAP_READ_BIT|GL_MAP_WRITE_BIT|GL_DYNAMIC_STORAGE_BIT;
- if(ARB_direct_state_access)
- glNamedBufferStorage(id, size, 0, flags);
- else
- {
- glBindBuffer(GL_ARRAY_BUFFER, id);
- glBufferStorage(GL_ARRAY_BUFFER, size, 0, flags);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- }
-
- allocated = true;
- }
- else
- data(0);
-}
-
-void Buffer::set_usage(BufferUsage)
-{
+ allocate();
}
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
- {
- glBindBuffer(GL_ARRAY_BUFFER, id);
- glBufferData(GL_ARRAY_BUFFER, size, d, STATIC_DRAW);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- }
-
- allocated = true;
-}
-
-void Buffer::data(unsigned sz, 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);
- glBufferSubData(GL_ARRAY_BUFFER, off, sz, d);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- }
+ BufferBackend::sub_data(off, sz, d);
}
void Buffer::require_size(unsigned req_sz) const
throw buffer_too_small(format("buffer has %d bytes; %d required", size, req_sz));
}
-void *Buffer::map()
-{
- 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);
- void *result = glMapBufferRange(GL_ARRAY_BUFFER, 0, size, GL_MAP_READ_BIT|GL_MAP_WRITE_BIT);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- return result;
- }
-}
-
-bool Buffer::unmap()
-{
- // TODO check if it's mapped
- if(ARB_direct_state_access)
- return glUnmapNamedBuffer(id);
- else if(OES_mapbuffer)
- {
- glBindBuffer(GL_ARRAY_BUFFER, id);
- bool result = glUnmapBuffer(GL_ARRAY_BUFFER);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- return result;
- }
- else
- return true;
-}
-
-void Buffer::set_debug_name(const string &name)
-{
-#ifdef DEBUG
- if(KHR_debug)
- glObjectLabel(GL_BUFFER, id, name.size(), name.c_str());
-#else
- (void)name;
-#endif
-}
-
} // namespace GL
} // namespace Msp