]> git.tdb.fi Git - libs/gl.git/commitdiff
Generalize VertexBuffer into Buffer with support for other types as well
authorMikko Rasa <tdb@tdb.fi>
Sun, 24 May 2009 10:56:35 +0000 (10:56 +0000)
committerMikko Rasa <tdb@tdb.fi>
Sun, 24 May 2009 10:56:35 +0000 (10:56 +0000)
Support using index buffer for Mesh
Don't autoreset Immediate on end() to make it compatible with MeshBuilder
Add a RAII class for bindings
Make Program::bind const

15 files changed:
source/batch.cpp
source/batch.h
source/buffer.cpp [new file with mode: 0644]
source/buffer.h [new file with mode: 0644]
source/immediate.cpp
source/immediate.h
source/mesh.cpp
source/mesh.h
source/misc.h
source/program.cpp
source/program.h
source/vertexarray.cpp
source/vertexarray.h
source/vertexbuffer.cpp [deleted file]
source/vertexbuffer.h

index f2a57bcf2fa2ad4f1ea1f4f6c90a17ab85d8cf3f..e522491144f1a7f6a06a0329e5c8e1721b241e69 100644 (file)
@@ -46,6 +46,11 @@ void Batch::draw() const
        draw_range_elements(type, min_index, max_index, indices.size(), &indices[0]);
 }
 
+void Batch::draw_with_buffer(unsigned offset) const
+{
+       draw_range_elements(type, min_index, max_index, indices.size(), (unsigned *)0+offset);
+}
+
 
 Batch::Loader::Loader(Batch &b):
        batch(b)
index 4a2e4b340501a57c222eff7c44b8fb95750fe7dc..9b2072de1f13d6f56e819a759fa3a1f6b3623491 100644 (file)
@@ -29,15 +29,20 @@ public:
                void indices(const std::vector<uint> &);
        };
 
-       Batch(PrimitiveType t);
-       Batch &append(uint);
-       void append(const std::vector<uint> &);
-       void draw() const;
 private:
        PrimitiveType type;
        std::vector<uint> indices;
        uint min_index;
        uint max_index;
+
+public:
+       Batch(PrimitiveType t);
+       Batch &append(uint);
+       void append(const std::vector<uint> &);
+       unsigned size() const { return indices.size(); }
+       const std::vector<uint> &get_indices() const { return indices; }
+       void draw() const;
+       void draw_with_buffer(unsigned) const;
 };
 
 } // namespace GL
diff --git a/source/buffer.cpp b/source/buffer.cpp
new file mode 100644 (file)
index 0000000..b4b71c3
--- /dev/null
@@ -0,0 +1,85 @@
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2007  Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include "arb_vertex_buffer_object.h"
+#include "extension.h"
+#include "buffer.h"
+
+namespace Msp {
+namespace GL {
+
+Buffer::Buffer(BufferType t):
+       type(t),
+       usage(STATIC_DRAW)
+{
+       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");
+
+       glGenBuffersARB(1, &id);
+}
+
+Buffer::~Buffer()
+{
+       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();
+       glBufferDataARB(type, size, d, usage);
+}
+
+void Buffer::sub_data(unsigned offset, unsigned size, const void *d)
+{
+       maybe_bind();
+       glBufferSubDataARB(type, offset, size, d);
+}
+
+void Buffer::unbind(BufferType type)
+{
+       const Buffer *&ptr=binding(type);
+       if(ptr)
+       {
+               glBindBufferARB(type, 0);
+               ptr=0;
+       }
+}
+
+const Buffer *&Buffer::binding(BufferType type)
+{
+       switch(type)
+       {
+       case ARRAY_BUFFER:         return bound[0];
+       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");
+       }
+}
+
+const Buffer *Buffer::bound[4]={ 0, 0, 0, 0 };
+
+} // namespace GL
+} // namespace Msp
diff --git a/source/buffer.h b/source/buffer.h
new file mode 100644 (file)
index 0000000..e915248
--- /dev/null
@@ -0,0 +1,88 @@
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2007  Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef MSP_GL_BUFFER_H_
+#define MSP_GL_BUFFER_H_
+
+#include "types.h"
+
+namespace Msp {
+namespace GL {
+
+enum BufferType
+{
+       ARRAY_BUFFER         = GL_ARRAY_BUFFER_ARB,
+       ELEMENT_ARRAY_BUFFER = GL_ELEMENT_ARRAY_BUFFER_ARB,
+       PIXEL_PACK_BUFFER    = GL_PIXEL_PACK_BUFFER_ARB,
+       PIXEL_UNPACK_BUFFER  = GL_PIXEL_UNPACK_BUFFER_ARB
+};
+
+enum BufferUsage
+{
+       STREAM_DRAW  = GL_STREAM_DRAW_ARB,
+       STREAM_READ  = GL_STREAM_READ_ARB,
+       STREAM_COPY  = GL_STREAM_COPY_ARB,
+       STATIC_DRAW  = GL_STATIC_DRAW_ARB,
+       STATIC_READ  = GL_STATIC_READ_ARB,
+       STATIC_COPY  = GL_STATIC_COPY_ARB,
+       DYNAMIC_DRAW = GL_DYNAMIC_DRAW_ARB,
+       DYNAMIC_READ = GL_DYNAMIC_READ_ARB,
+       DYNAMIC_COPY = GL_DYNAMIC_COPY_ARB
+};
+
+/**
+A buffer for storing data in GL memory.  Putting vertex and index data in
+buffers can improve rendering performance.  The VertexArray and Mesh classes
+contain built-in support for buffers.
+*/
+class Buffer
+{
+private:
+       BufferType type;
+       BufferUsage usage;
+       unsigned id;
+
+       static const Buffer *bound[4];
+
+public:
+       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;
+
+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);
+
+       /** Uploads data into the buffer, completely replacing any previous
+       contents. */
+       void data(unsigned, const void *);
+
+       /** Overwrites part of the buffer data with new data.  The buffer size can
+       not be changed with this call. */
+       void sub_data(unsigned, unsigned, const void *);
+
+       static void unbind(BufferType);
+private:
+       static const Buffer *&binding(BufferType);
+};
+
+} // namespace GL
+} // namespace Msp
+
+#endif
index e12ac9b53ca01ec2b3d9b73a86898605d60c724d..a387d71b4b283eac45dcd47148dad9e6581fb321 100644 (file)
@@ -15,12 +15,20 @@ Immediate::Immediate(VertexFormat f):
        array(f)
 { }
 
+void Immediate::reset()
+{
+       if(in_batch)
+               throw InvalidState("Can't reset Immediate between begin() and end()");
+
+       array.clear();
+       indices.clear();
+}
+
 void Immediate::end_()
 {
        array.apply();
        draw_elements(type, indices.size(), &indices[0]);
 
-       array.clear();
        indices.clear();
 }
 
index c4d8aca5abb0bf83bc97f216c60a59e2d6af6798..89380c41310c3717a20db88b35d9b8ad95b22cc2 100644 (file)
@@ -28,6 +28,7 @@ private:
 
 public:
        Immediate(VertexFormat);
+       void reset();
 private:
        virtual void begin_() { }
        virtual void end_();
index 7f50beb7b61bc055bb1e905529e6f91c9535c1fe..d43e0d0efdd421b43b209c0e8f4f280d2529c895 100644 (file)
@@ -5,6 +5,7 @@ Copyright © 2007  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
+#include "buffer.h"
 #include "mesh.h"
 
 using namespace std;
@@ -13,24 +14,41 @@ namespace Msp {
 namespace GL {
 
 Mesh::Mesh():
-       vertices(VERTEX3)
+       vertices(VERTEX3),
+       ibuf(0)
 { }
 
-Mesh::Mesh(VertexFormat f):
-       vertices(f)
+Mesh::Mesh(const VertexFormat &f):
+       vertices(f),
+       ibuf(0)
 { }
 
 void Mesh::use_vertex_buffer(bool b)
 {
        if(b)
+       {
                vertices.use_vertex_buffer();
+               if(!ibuf)
+                       ibuf=new Buffer(ELEMENT_ARRAY_BUFFER);
+               update_index_buffer();
+       }
        else
+       {
                vertices.use_vertex_buffer(0);
+               delete ibuf;
+               ibuf=0;
+       }
+}
+
+float *Mesh::get_vertex(unsigned i)
+{
+       return vertices[i];
 }
 
 void Mesh::add_batch(const Batch &b)
 {
        batches.push_back(b);
+       update_index_buffer();
 }
 
 void Mesh::clear()
@@ -42,8 +60,41 @@ void Mesh::clear()
 void Mesh::draw() const
 {
        vertices.apply();
+       if(ibuf)
+       {
+               ibuf->bind();
+               unsigned offset=0;
+               for(list<Batch>::const_iterator i=batches.begin(); i!=batches.end(); ++i)
+               {
+                       i->draw_with_buffer(offset);
+                       offset+=i->size();
+               }
+               ibuf->unbind();
+       }
+       else
+       {
+               for(list<Batch>::const_iterator i=batches.begin(); i!=batches.end(); ++i)
+                       i->draw();
+       }
+}
+
+void Mesh::update_index_buffer()
+{
+       if(!ibuf)
+               return;
+
+       unsigned total=0;
+       for(list<Batch>::const_iterator i=batches.begin(); i!=batches.end(); ++i)
+               total+=i->size();
+
+       ibuf->data(total*sizeof(unsigned), 0);
+       unsigned offset=0;
        for(list<Batch>::const_iterator i=batches.begin(); i!=batches.end(); ++i)
-               i->draw();
+       {
+               ibuf->sub_data(offset*sizeof(unsigned), i->size()*sizeof(unsigned), &i->get_indices()[0]);
+               offset+=i->size();
+       }
+       ibuf->unbind();
 }
 
 
index 633cf3ab377651a95bd8835cd6922c2b2a759656..0a4142fea1eebf02f326b9615a4fc5c904ad142b 100644 (file)
@@ -15,6 +15,8 @@ Distributed under the LGPL
 namespace Msp {
 namespace GL {
 
+class Buffer;
+
 class Mesh
 {
        friend class MeshBuilder;
@@ -34,17 +36,21 @@ public:
 private:
        VertexArray vertices;
        std::list<Batch> batches;
+       Buffer *ibuf;
 
 public:
        Mesh();
-       Mesh(VertexFormat f);
+       Mesh(const VertexFormat &f);
 
        void use_vertex_buffer(bool);
        const VertexArray &get_vertices() const { return vertices; }
+       float *get_vertex(unsigned);
        void add_batch(const Batch &b);
        const std::list<Batch> &get_batches() { return batches; }
        void clear();
        void draw() const;
+private:
+       void update_index_buffer();
 };
 
 } // namespace GL
index e9ed91bfa672b300214a69afe06c680b12993bae..7aa8aaf9e7fb6d41c3d4acc893b464d581675b51 100644 (file)
@@ -20,6 +20,31 @@ void set(GLenum, bool);
 void get(GLenum, int &);
 int get_i(GLenum);
 
+class Bind
+{
+private:
+       struct Base
+       {
+               virtual ~Base() { }
+       };
+
+       template<typename T>
+       struct Binder: Base
+       {
+               const T &obj;
+
+               Binder(const T &o): obj(o) { obj.bind(); }
+               ~Binder() { obj.unbind(); }
+       };
+
+       Base *binder;
+
+public:
+       template<typename T>
+       Bind(const T &o): binder(new Binder<T>(o)) { }
+       ~Bind() { delete binder; }
+};
+
 } // namespace GL
 } // namespace Msp
 
index 1b8ffe4dfe3b4fff4e20be818014fb91d083f6c4..75f982d7f5dc8fa4c2235af999249cd23cae4146 100644 (file)
@@ -108,7 +108,7 @@ string Program::get_info_log() const
        return string(log, len);
 }
 
-void Program::bind()
+void Program::bind() const
 {
        if(!linked)
                throw InvalidState("Program is not linked");
@@ -137,7 +137,7 @@ void Program::maybe_bind()
                bind();
 }
 
-Program *Program::cur_prog=0;
+const Program *Program::cur_prog=0;
 
 
 Program::Loader::Loader(Program &p):
index fde4d85439a2cfe9e7cb82a62aebd965f111d082..ad37fb65bfca60d51094e741732faf274da7e1ef 100644 (file)
@@ -27,7 +27,7 @@ private:
        bool del_shaders;
        bool linked;
 
-       static Program *cur_prog;
+       static const Program *cur_prog;
 
 public:
        class Loader: public DataFile::Loader
@@ -61,7 +61,7 @@ public:
        int get_param(GLenum param) const;
        bool get_linked() const { return linked; }
        std::string get_info_log() const;
-       void bind();
+       void bind() const;
        int get_uniform_location(const std::string &) const;
 
        static void unbind();
index 6740818e794228e78ebedbbc880855aa3abcb33c..a2b65daa6d15dd91635c092a73e2434e76a9b51f 100644 (file)
@@ -35,13 +35,13 @@ void VertexArray::use_vertex_buffer()
        if(vbuf && own_vbuf)
                return;
 
-       vbuf=new VertexBuffer();
+       vbuf=new Buffer(ARRAY_BUFFER);
        own_vbuf=true;
 
        update_data();
 }
 
-void VertexArray::use_vertex_buffer(VertexBuffer *b)
+void VertexArray::use_vertex_buffer(Buffer *b)
 {
        if(own_vbuf)
                delete vbuf;
@@ -123,7 +123,7 @@ void VertexArray::apply() const
                set_array(i-4, (found>>i)&1, 1<<i);
 
        if(vbuf)
-               VertexBuffer::unbind();
+               vbuf->unbind();
 }
 
 /**
@@ -134,7 +134,7 @@ void VertexArray::update_data()
        if(vbuf)
        {
                vbuf->data(data.size()*sizeof(float), &data[0]);
-               VertexBuffer::unbind();
+               vbuf->unbind();
        }
 }
 
index ef7f6a24c23482292d38db863c56353159afed9e..281996d457da92894c6a4eb58111564c81c0ef43 100644 (file)
@@ -19,7 +19,7 @@ Distributed under the LGPL
 namespace Msp {
 namespace GL {
 
-class VertexBuffer;
+class Buffer;
 
 class VertexArray
 {
@@ -34,7 +34,7 @@ private:
        VertexFormat format;
        std::vector<float> data;
        uint         stride;
-       VertexBuffer *vbuf;
+       Buffer       *vbuf;
        bool         own_vbuf;
 
        VertexArray(const VertexArray &);
@@ -46,7 +46,7 @@ public:
        const VertexFormat &get_format() const { return format; }
        const std::vector<float> &get_data() const { return data; }
        void         use_vertex_buffer();
-       void         use_vertex_buffer(VertexBuffer *);
+       void         use_vertex_buffer(Buffer *);
        void         reserve(unsigned);
        unsigned     size() const { return data.size()/stride; }
        void         clear();
diff --git a/source/vertexbuffer.cpp b/source/vertexbuffer.cpp
deleted file mode 100644 (file)
index 395334b..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/* $Id$
-
-This file is part of libmspgl
-Copyright © 2007  Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
-#include "arb_vertex_buffer_object.h"
-#include "extension.h"
-#include "vertexbuffer.h"
-
-namespace Msp {
-namespace GL {
-
-VertexBuffer::VertexBuffer()
-{
-       static RequireExtension _ext("GL_ARB_vertex_buffer_object");
-
-       glGenBuffersARB(1, &id);
-}
-
-void VertexBuffer::bind() const
-{
-       glBindBufferARB(GL_ARRAY_BUFFER, id);
-       bound=this;
-}
-
-void VertexBuffer::data(sizei size, void *d)
-{
-       if(bound!=this) bind();
-
-       glBufferDataARB(GL_ARRAY_BUFFER, size, d, GL_STATIC_DRAW);
-}
-
-VertexBuffer::~VertexBuffer()
-{
-       glDeleteBuffersARB(1, &id);
-}
-
-void VertexBuffer::unbind()
-{
-       if(bound)
-       {
-               glBindBufferARB(GL_ARRAY_BUFFER, 0);
-               bound=0;
-       }
-}
-
-const VertexBuffer *VertexBuffer::bound=0;
-
-} // namespace GL
-} // namespace Msp
index 815e268288f985f63bdcba1528d9d87843bb6915..b0963fb358e70e083d2424868a5306e3eea7b2ad 100644 (file)
@@ -8,24 +8,21 @@ Distributed under the LGPL
 #ifndef MSP_GL_VERTEXBUFFER_H_
 #define MSP_GL_VERTEXBUFFER_H_
 
-#include "types.h"
+#include "buffer.h"
 
 namespace Msp {
 namespace GL {
 
-class VertexBuffer
+/**
+Deprecated.  Equivalent to Buffer of type ARRAY_BUFFER.  Retained for backwards
+compatibility only.
+*/
+class VertexBuffer: public Buffer
 {
 public:
-       VertexBuffer();
-       void bind() const;
-       void data(sizei, void *);
-       ~VertexBuffer();
-
-       static void unbind();
-private:
-       uint id;
+       VertexBuffer(): Buffer(ARRAY_BUFFER) { }
 
-       static const VertexBuffer *bound;
+       static void unbind() { Buffer::unbind(ARRAY_BUFFER); }
 };
 
 } // namespace GL