From bd3e61a3d71a527b7b87197c2f52c5cf342aba81 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sat, 25 Aug 2012 00:50:00 +0300 Subject: [PATCH] Add a class to negotiate the storage of multiple objects in a buffer --- source/bufferable.cpp | 89 +++++++++++++++++++++++++++++++++++++++++++ source/bufferable.h | 37 ++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 source/bufferable.cpp create mode 100644 source/bufferable.h diff --git a/source/bufferable.cpp b/source/bufferable.cpp new file mode 100644 index 00000000..5c7cb9e0 --- /dev/null +++ b/source/bufferable.cpp @@ -0,0 +1,89 @@ +#include +#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 index 00000000..dd7cff8e --- /dev/null +++ b/source/bufferable.h @@ -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 -- 2.45.2