X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fbuffer.cpp;h=84c72716d0e5da16cebb42fcd8e191c093ae1bd3;hb=6afbace895a7bbcf216ab8e48280ea0303ab5892;hp=c19f3727f8f5c685a2ab5abc761a0293c3aa7c85;hpb=196093790e242dec24bfbbf7ad8c28dcc442824c;p=libs%2Fgl.git diff --git a/source/buffer.cpp b/source/buffer.cpp index c19f3727..84c72716 100644 --- a/source/buffer.cpp +++ b/source/buffer.cpp @@ -1,30 +1,39 @@ #include +#include "arb_pixel_buffer_object.h" +#include "arb_uniform_buffer_object.h" #include "arb_vertex_buffer_object.h" -#include "extension.h" #include "buffer.h" +#include "misc.h" using namespace std; namespace Msp { namespace GL { -const Buffer *Buffer::bound[4] = { 0, 0, 0, 0 }; +const Buffer *Buffer::bound[5] = { 0, 0, 0, 0, 0 }; Buffer::Buffer(BufferType t): type(t), usage(STATIC_DRAW), size(0) { - static RequireExtension _req_vbo("GL_ARB_vertex_buffer_object"); - if(type==PIXEL_PACK_BUFFER || type==PIXEL_UNPACK_BUFFER) - static RequireExtension _req_pbo("GL_ARB_pixel_buffer_object"); + require_buffer_type(type); - glGenBuffersARB(1, &id); + glGenBuffers(1, &id); } Buffer::~Buffer() { - glDeleteBuffersARB(1, &id); + glDeleteBuffers(1, &id); +} + +void Buffer::require_buffer_type(BufferType type) +{ + static Require _req_vbo(ARB_vertex_buffer_object); + if(type==PIXEL_PACK_BUFFER || type==PIXEL_UNPACK_BUFFER) + static Require _req_pbo(ARB_pixel_buffer_object); + else if(type==UNIFORM_BUFFER) + static Require _req_ubo(ARB_uniform_buffer_object); } void Buffer::set_usage(BufferUsage u) @@ -36,7 +45,7 @@ void Buffer::data(unsigned sz, const void *d) { const Buffer *old = current(type); bind(); - glBufferDataARB(type, sz, d, usage); + glBufferData(type, sz, d, usage); size = sz; restore(old, type); } @@ -45,28 +54,27 @@ void Buffer::sub_data(unsigned off, unsigned sz, const void *d) { const Buffer *old = current(type); bind(); - glBufferSubDataARB(type, off, sz, d); + glBufferSubData(type, off, sz, d); restore(old, type); } +BufferRange *Buffer::create_range(unsigned s, unsigned o) +{ + return new BufferRange(*this, s, o); +} + void Buffer::bind_to(BufferType t) const { - const Buffer *&ptr = binding(t); - if(ptr!=this) - { - glBindBufferARB(t, id); - ptr = this; - } + if(t!=type) + require_buffer_type(t); + if(set_current(t, this)) + glBindBuffer(t, id); } void Buffer::unbind_from(BufferType type) { - const Buffer *&ptr = binding(type); - if(ptr) - { - glBindBufferARB(type, 0); - ptr = 0; - } + if(set_current(type, 0)) + glBindBuffer(type, 0); } const Buffer *&Buffer::binding(BufferType type) @@ -77,10 +85,21 @@ const Buffer *&Buffer::binding(BufferType type) case ELEMENT_ARRAY_BUFFER: return bound[1]; case PIXEL_PACK_BUFFER: return bound[2]; case PIXEL_UNPACK_BUFFER: return bound[3]; + case UNIFORM_BUFFER: return bound[4]; default: throw invalid_argument("Buffer::binding"); } } +bool Buffer::set_current(BufferType type, const Buffer *buf) +{ + const Buffer *&ptr = binding(type); + if(ptr==buf) + return false; + + ptr = buf; + return true; +} + void Buffer::restore(const Buffer *buf, BufferType type) { if(buf!=current(type)) @@ -92,5 +111,76 @@ void Buffer::restore(const Buffer *buf, BufferType type) } } + +vector BufferRange::bound_uniform; + +BufferRange::BufferRange(Buffer &b, unsigned o, unsigned s): + buffer(b), + offset(o), + size(s) +{ + if(o>buffer.get_size() || o+s>buffer.get_size()) + throw out_of_range("BufferRange::BufferRange"); +} + +void BufferRange::data(const void *d) +{ + buffer.sub_data(offset, size, d); +} + +void BufferRange::bind_to(BufferType t, unsigned i) +{ + if(t!=buffer.type) + Buffer::require_buffer_type(t); + // Intentionally using bitwise | to avoid short-circuiting + if(Buffer::set_current(t, &buffer) | set_current(t, i, this)) + glBindBufferRange(t, i, buffer.id, offset, size); +} + +void BufferRange::unbind_from(BufferType t, unsigned i) +{ + if(set_current(t, i, 0)) + { + Buffer::set_current(t, 0); + glBindBufferBase(t, i, 0); + } +} + +const BufferRange *&BufferRange::binding(BufferType type, unsigned index) +{ + if(type==UNIFORM_BUFFER) + { + if(index>=get_n_uniform_buffer_bindings()) + throw out_of_range("Buffer::binding"); + if(bound_uniform.size()<=index) + bound_uniform.resize(index+1); + return bound_uniform[index]; + } + else + throw invalid_argument("Buffer::binding"); +} + +bool BufferRange::set_current(BufferType type, unsigned index, const BufferRange *buf) +{ + const BufferRange *&ptr = binding(type, index); + if(ptr==buf) + return false; + + ptr = buf; + return true; +} + +unsigned BufferRange::get_n_uniform_buffer_bindings() +{ + static unsigned count = get_i(GL_MAX_UNIFORM_BUFFER_BINDINGS); + return count; +} + +unsigned BufferRange::get_uniform_buffer_alignment() +{ + static unsigned align = get_i(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT); + return align; +} + } // namespace GL } // namespace Msp