]> git.tdb.fi Git - libs/gl.git/commitdiff
Add a class to negotiate the storage of multiple objects in a buffer
authorMikko Rasa <tdb@tdb.fi>
Fri, 24 Aug 2012 21:50:00 +0000 (00:50 +0300)
committerMikko Rasa <tdb@tdb.fi>
Fri, 24 Aug 2012 21:50:00 +0000 (00:50 +0300)
source/bufferable.cpp [new file with mode: 0644]
source/bufferable.h [new file with mode: 0644]

diff --git a/source/bufferable.cpp b/source/bufferable.cpp
new file mode 100644 (file)
index 0000000..5c7cb9e
--- /dev/null
@@ -0,0 +1,89 @@
+#include <stdexcept>
+#include "buffer.h"
+#include "bufferable.h"
+
+using namespace std;
+
+namespace Msp {
+namespace GL {
+
+Bufferable::Bufferable():
+       buffer(0),
+       buffer_offset(0),
+       next_in_buffer(0),
+       prev_in_buffer(0),
+       dirty(false)
+{ }
+
+Bufferable::~Bufferable()
+{
+       unlink_from_buffer();
+}
+
+void Bufferable::use_buffer(Buffer *buf, Bufferable *prev)
+{
+       if(prev && buf!=prev->buffer)
+               throw invalid_argument("Bufferable::use_buffer");
+
+       if(buffer)
+               unlink_from_buffer();
+
+       buffer = buf;
+       if(buffer)
+       {
+               prev_in_buffer = prev;
+               if(prev_in_buffer)
+                       prev_in_buffer->next_in_buffer = this;
+       }
+
+       update_buffer_offsets();
+}
+
+void Bufferable::unlink_from_buffer()
+{
+       if(prev_in_buffer)
+               prev_in_buffer->next_in_buffer = next_in_buffer;
+       if(next_in_buffer)
+       {
+               next_in_buffer->prev_in_buffer = prev_in_buffer;
+               next_in_buffer->update_buffer_offsets();
+       }
+       prev_in_buffer = 0;
+       next_in_buffer = 0;
+}
+
+void Bufferable::update_buffer_offsets()
+{
+       unsigned offset = 0;
+       if(prev_in_buffer)
+               offset = prev_in_buffer->buffer_offset+prev_in_buffer->get_data_size();
+
+       if(offset!=buffer_offset)
+       {
+               buffer_offset = offset;
+               dirty = true;
+       }
+
+       if(next_in_buffer)
+               next_in_buffer->update_buffer_offsets();
+}
+
+void Bufferable::update_buffer_data() const
+{
+       const Bufferable *first = this;
+       for(; first->prev_in_buffer; first=first->prev_in_buffer) ;
+
+       unsigned total_size = 0;
+       for(const Bufferable *b=first; b; b=b->next_in_buffer)
+               total_size += b->get_data_size();
+
+       buffer->data(total_size, 0);
+       for(const Bufferable *b=first; b; b=b->next_in_buffer)
+       {
+               buffer->sub_data(b->buffer_offset, b->get_data_size(), b->get_data());
+               b->dirty = false;
+       }
+}
+
+} // namespace GL
+} // namespace Msp
diff --git a/source/bufferable.h b/source/bufferable.h
new file mode 100644 (file)
index 0000000..dd7cff8
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef MSP_GL_BUFFERABLE_H_
+#define MSP_GL_BUFFERABLE_H_
+
+namespace Msp {
+namespace GL {
+
+class Buffer;
+
+class Bufferable
+{
+protected:
+       Buffer *buffer;
+       unsigned buffer_offset;
+       Bufferable *next_in_buffer;
+       Bufferable *prev_in_buffer;
+       mutable bool dirty;
+
+       Bufferable();
+public:
+       virtual ~Bufferable();
+
+       void use_buffer(Buffer *, Bufferable * = 0);
+private:
+       void unlink_from_buffer();
+
+protected:
+       virtual unsigned get_data_size() const = 0;
+       virtual const void *get_data() const = 0;
+
+       void update_buffer_offsets();
+       void update_buffer_data() const;
+};
+
+} // namespace GL
+} // namespace Msp
+
+#endif