X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fbuffer.cpp;h=84c72716d0e5da16cebb42fcd8e191c093ae1bd3;hb=6afbace895a7bbcf216ab8e48280ea0303ab5892;hp=b4b71c3a0130efadcaea894f0fd921b9e833629b;hpb=76e338af116120d93d082ad247591ec9adad9233;p=libs%2Fgl.git diff --git a/source/buffer.cpp b/source/buffer.cpp index b4b71c3a..84c72716 100644 --- a/source/buffer.cpp +++ b/source/buffer.cpp @@ -1,70 +1,80 @@ -/* $Id$ - -This file is part of libmspgl -Copyright © 2007 Mikko Rasa, Mikkosoft Productions -Distributed under the LGPL -*/ - +#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[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); + glGenBuffers(1, &id); } Buffer::~Buffer() { - glDeleteBuffersARB(1, &id); + glDeleteBuffers(1, &id); } -void Buffer::bind(BufferType t) const +void Buffer::require_buffer_type(BufferType type) { - glBindBufferARB(t, id); - binding(t)=this; + 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::maybe_bind() const +void Buffer::set_usage(BufferUsage u) { - if(binding(type)!=this) - bind(); + usage = u; } -void Buffer::set_usage(BufferUsage u) +void Buffer::data(unsigned sz, const void *d) { - usage=u; + const Buffer *old = current(type); + bind(); + glBufferData(type, sz, d, usage); + size = sz; + restore(old, type); } -void Buffer::data(unsigned size, const void *d) +void Buffer::sub_data(unsigned off, unsigned sz, const void *d) { - maybe_bind(); - glBufferDataARB(type, size, d, usage); + const Buffer *old = current(type); + bind(); + glBufferSubData(type, off, sz, d); + restore(old, type); } -void Buffer::sub_data(unsigned offset, unsigned size, const void *d) +BufferRange *Buffer::create_range(unsigned s, unsigned o) { - maybe_bind(); - glBufferSubDataARB(type, offset, size, d); + return new BufferRange(*this, s, o); } -void Buffer::unbind(BufferType type) +void Buffer::bind_to(BufferType t) const { - const Buffer *&ptr=binding(type); - if(ptr) - { - glBindBufferARB(type, 0); - ptr=0; - } + if(t!=type) + require_buffer_type(t); + if(set_current(t, this)) + glBindBuffer(t, id); +} + +void Buffer::unbind_from(BufferType type) +{ + if(set_current(type, 0)) + glBindBuffer(type, 0); } const Buffer *&Buffer::binding(BufferType type) @@ -75,11 +85,102 @@ 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)) + { + if(buf) + buf->bind_to(type); + else + unbind_from(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"); } -const Buffer *Buffer::bound[4]={ 0, 0, 0, 0 }; +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