X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fbuffer.cpp;h=f09268741fc7705e69432c6ee18e5f03edb069ec;hb=ab83db6f1e31d44ced585119a57fd10896e469cb;hp=395057cd90ff4bf61e95a7be7c833fefaa20515f;hpb=f14435e58bfa0fa697a06ba9a454bb30cd37d9d8;p=libs%2Fgl.git diff --git a/source/buffer.cpp b/source/buffer.cpp index 395057cd..f0926874 100644 --- a/source/buffer.cpp +++ b/source/buffer.cpp @@ -1,17 +1,23 @@ +#include +#include "arb_uniform_buffer_object.h" #include "arb_vertex_buffer_object.h" -#include "extension.h" #include "buffer.h" +#include "extension.h" +#include "misc.h" + +using namespace std; namespace Msp { namespace GL { +const Buffer *Buffer::bound[5] = { 0, 0, 0, 0, 0 }; + Buffer::Buffer(BufferType t): type(t), - usage(STATIC_DRAW) + 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); } @@ -21,45 +27,54 @@ Buffer::~Buffer() glDeleteBuffersARB(1, &id); } +void Buffer::require_buffer_type(BufferType type) +{ + 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"); + else if(type==UNIFORM_BUFFER) + static RequireExtension _req_ubo("GL_ARB_uniform_buffer_object"); +} + void Buffer::set_usage(BufferUsage u) { usage = u; } -void Buffer::data(unsigned size, const void *d) +void Buffer::data(unsigned sz, const void *d) { const Buffer *old = current(type); bind(); - glBufferDataARB(type, size, d, usage); + glBufferDataARB(type, sz, d, usage); + size = sz; restore(old, type); } -void Buffer::sub_data(unsigned offset, unsigned size, const void *d) +void Buffer::sub_data(unsigned off, unsigned sz, const void *d) { const Buffer *old = current(type); bind(); - glBufferSubDataARB(type, offset, size, d); + glBufferSubDataARB(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) - { + if(t!=type) + require_buffer_type(t); + if(set_current(t, this)) glBindBufferARB(t, id); - ptr = this; - } } void Buffer::unbind_from(BufferType type) { - const Buffer *&ptr = binding(type); - if(ptr) - { + if(set_current(type, 0)) glBindBufferARB(type, 0); - ptr = 0; - } } const Buffer *&Buffer::binding(BufferType type) @@ -70,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]; - default: throw InvalidParameterValue("Invalid buffer type"); + 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)) @@ -85,7 +111,70 @@ void Buffer::restore(const Buffer *buf, BufferType type) } } -const Buffer *Buffer::bound[4] = { 0, 0, 0, 0 }; + +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; +} } // namespace GL } // namespace Msp