glDeleteBuffersARB(1, &id);
}
-void Buffer::bind(BufferType t) const
-{
- glBindBufferARB(t, id);
- binding(t) = this;
-}
-
-void Buffer::maybe_bind() const
-{
- if(binding(type)!=this)
- bind();
-}
-
void Buffer::set_usage(BufferUsage u)
{
usage = u;
void Buffer::data(unsigned size, const void *d)
{
- maybe_bind();
+ const Buffer *old = current(type);
+ bind();
glBufferDataARB(type, size, d, usage);
+ restore(old, type);
}
void Buffer::sub_data(unsigned offset, unsigned size, const void *d)
{
- maybe_bind();
+ const Buffer *old = current(type);
+ bind();
glBufferSubDataARB(type, offset, size, d);
+ restore(old, type);
+}
+
+void Buffer::bind_to(BufferType t) const
+{
+ const Buffer *&ptr = binding(t);
+ if(ptr!=this)
+ {
+ glBindBufferARB(t, id);
+ ptr = this;
+ }
}
-void Buffer::unbind(BufferType type)
+void Buffer::unbind_from(BufferType type)
{
const Buffer *&ptr = binding(type);
if(ptr)
}
}
+void Buffer::restore(const Buffer *buf, BufferType type)
+{
+ if(buf!=current(type))
+ {
+ if(buf)
+ buf->bind_to(type);
+ else
+ unbind_from(type);
+ }
+}
+
const Buffer *Buffer::bound[4] = { 0, 0, 0, 0 };
} // namespace GL
Buffer(BufferType);
~Buffer();
- /** Binds the buffer in its default slot. */
- void bind() const { bind(type); }
-
- /** Binds the buffer in an alternate slot. */
- void bind(BufferType) const;
-
private:
- void maybe_bind() const;
+ const Buffer *maybe_bind() const;
public:
- /** Unbinds the buffer from its default slot. */
- void unbind() const { unbind(type); }
-
/** Sets the usage hint of the buffer. It will take effect the next time
the buffer's contents are defined. */
void set_usage(BufferUsage);
not be changed with this call. */
void sub_data(unsigned, unsigned, const void *);
- static void unbind(BufferType);
+ /** Binds the buffer in its default slot. */
+ void bind() const { bind_to(type); }
+
+ /** Binds the buffer in an alternate slot. */
+ void bind_to(BufferType) const;
+
+ /** Unbinds the buffer from its default slot. */
+ void unbind() const { unbind_from(type); }
+
+ static const Buffer *current(BufferType t) { return binding(t); }
+ static void unbind_from(BufferType);
private:
static const Buffer *&binding(BufferType);
+ static void restore(const Buffer *, BufferType);
};
} // namespace GL
Immediate::Immediate(VertexFormat f):
PrimitiveBuilder(array),
array(f)
-{ }
+{
+ array.use_vertex_buffer(0);
+}
void Immediate::reset()
{
*/
#include "arb_vertex_program.h"
+#include "buffer.h"
#include "extension.h"
#include "gl.h"
#include "version_1_2.h"
#include "version_1_3.h"
#include "vertexarray.h"
-#include "vertexbuffer.h"
using namespace std;
namespace Msp {
namespace GL {
+VertexArray::ArrayMask VertexArray::enabled_arrays;
+
VertexArray::VertexArray(const VertexFormat &f):
- vbuf(0),
- own_vbuf(false)
+ defer_vbuf(true),
+ dirty(false)
{
reset(f);
}
VertexArray::~VertexArray()
-{
- if(own_vbuf)
- delete vbuf;
-}
+{ }
void VertexArray::use_vertex_buffer()
{
- if(vbuf && own_vbuf)
+ if(vbuf)
return;
vbuf = new Buffer(ARRAY_BUFFER);
- own_vbuf = true;
-
- update_data();
+ defer_vbuf = false;
+ dirty = true;
}
void VertexArray::use_vertex_buffer(Buffer *b)
{
- if(own_vbuf)
- delete vbuf;
vbuf = b;
- own_vbuf = false;
-
- update_data();
+ vbuf.keep();
+ defer_vbuf = false;
+ dirty = true;
}
void VertexArray::reserve(unsigned n)
throw InvalidState("Trying to apply a vertex array with no data");
if(vbuf)
- vbuf->bind();
+ {
+ vbuf->bind_to(ARRAY_BUFFER);
+ if(dirty)
+ {
+ vbuf->data(data.size()*sizeof(float), &data[0]);
+ dirty = false;
+ }
+ }
- const float *base = vbuf?0:&data[0];
+ const float *base = (vbuf ? 0 : &data[0]);
unsigned offset = 0;
ArrayMask found;
unsigned bpv = stride*sizeof(float);
glClientActiveTexture(GL_TEXTURE0);
if(vbuf)
- vbuf->unbind();
+ Buffer::unbind_from(ARRAY_BUFFER);
}
-/**
-Updates the VertexArray data to the VertexBuffer tied to the array, if any.
-*/
-void VertexArray::update_data()
+float *VertexArray::append()
{
- if(vbuf)
- {
- vbuf->data(data.size()*sizeof(float), &data[0]);
- vbuf->unbind();
- }
+ data.insert(data.end(), stride, 0.0f);
+ set_dirty();
+ return &*(data.end()-stride);
}
-float *VertexArray::append()
+float *VertexArray::modify(unsigned i)
{
- data.insert(data.end(), stride, 0.0f);
- return &*data.end()-stride;
+ set_dirty();
+ return &data[0]+i*stride;
}
-VertexArray::ArrayMask VertexArray::enabled_arrays;
+void VertexArray::set_dirty()
+{
+ dirty = true;
+ if(defer_vbuf)
+ {
+ vbuf = new Buffer(ARRAY_BUFFER);
+ defer_vbuf = false;
+ }
+}
VertexArray::ArrayMask::ArrayMask()
VertexFormat format;
std::vector<float> data;
unsigned stride;
- Buffer *vbuf;
- bool own_vbuf;
+ RefPtr<Buffer> vbuf;
+ bool defer_vbuf;
+ mutable bool dirty;
+
+ static ArrayMask enabled_arrays;
VertexArray(const VertexArray &);
VertexArray &operator=(const VertexArray &);
void clear();
void reset(const VertexFormat &);
void apply() const;
- void update_data();
float *append();
- float *operator[](unsigned i) { return &data[0]+i*stride; }
+ float *modify(unsigned);
+ float *operator[](unsigned i) { return modify(i); }
const float *operator[](unsigned i) const { return &data[0]+i*stride; }
private:
- static ArrayMask enabled_arrays;
+ void set_dirty();
};
void array_element(int);
array(a)
{ }
-VertexArrayBuilder::~VertexArrayBuilder()
-{
- array.update_data();
-}
-
void VertexArrayBuilder::vertex_(const Vector4 &v)
{
float *ptr = array.append();
VertexArrayBuilder(const VertexArrayBuilder &);
public:
VertexArrayBuilder(VertexArray &);
- ~VertexArrayBuilder();
private:
virtual void vertex_(const Vector4 &);
+++ /dev/null
-/* $Id$
-
-This file is part of libmspgl
-Copyright © 2007 Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
-#ifndef MSP_GL_VERTEXBUFFER_H_
-#define MSP_GL_VERTEXBUFFER_H_
-
-#include "buffer.h"
-
-namespace Msp {
-namespace GL {
-
-/**
-Deprecated. Equivalent to Buffer of type ARRAY_BUFFER. Retained for backwards
-compatibility only.
-*/
-class VertexBuffer: public Buffer
-{
-public:
- VertexBuffer(): Buffer(ARRAY_BUFFER) { }
-
- static void unbind() { Buffer::unbind(ARRAY_BUFFER); }
-};
-
-} // namespace GL
-} // namespace Msp
-
-#endif