]> git.tdb.fi Git - libs/gl.git/blobdiff - source/core/bufferable.h
Use a member function to set the dirty flag in Bufferable
[libs/gl.git] / source / core / bufferable.h
index b1d991fca5218cfd4a0cd1e7ee554d2920a02463..b430b726277c657fac569fb334bf5c69f624409e 100644 (file)
@@ -1,20 +1,27 @@
 #ifndef MSP_GL_BUFFERABLE_H_
 #define MSP_GL_BUFFERABLE_H_
 
+#include <msp/core/noncopyable.h>
+
 namespace Msp {
 namespace GL {
 
 class Buffer;
 
 /**
-Base class for things that can store data in buffers.  Supports buffer sharing.
-A dirty flag is provided for derived classes.  It should be set when the data
-in the buffer is considered out of date, and is cleared by Bufferable after
-uploading fresh data to the buffer.
+Base class for things that can store data in buffers.  Multiple Bufferables
+may be put in the same buffer.
+
+Derived classes should call mark_dirty() when the stored data has changed.
 */
-class Bufferable
+class Bufferable: public NonCopyable
 {
 public:
+       /**
+       Uploads data to the buffer asynchronously, through a memory mapping.  API
+       calls are done in the constructor and desctructor, so upload_data may be
+       called from a different thread.
+       */
        class AsyncUpdater
        {
        private:
@@ -30,34 +37,37 @@ public:
 
 private:
        Buffer *buffer = 0;
-       unsigned offset = 0;
+       std::size_t offset = 0;
        Bufferable *next_in_buffer = 0;
        Bufferable *prev_in_buffer = 0;
        mutable bool location_dirty = false;
-protected:
        mutable bool dirty = false;
 
+protected:
        Bufferable() = default;
+       Bufferable(Bufferable &&);
 public:
        virtual ~Bufferable();
 
        /** Sets the buffer to use.  If prev is not null, it must use the same
-       buffer, and this object is inserted after it. */
-       void use_buffer(Buffer *buf, Bufferable *prev = 0);
+       buffer, and this object is inserted after it.
+
+       Data is not uploaded immediately, but only when refresh() is called. */
+       void use_buffer(Buffer *, Bufferable *prev = 0);
 
        /** Sets the buffer for the entire chain of objects. */
        void change_buffer(Buffer *);
 
        /** Returns the total amount of storage required by this object and others
-       in the same chain, including any alignment between objects. */
-       unsigned get_required_buffer_size() const;
+       in the same chain, including any padding required by object alignment. */
+       std::size_t get_required_buffer_size() const;
 
        /** Uploads new data into the buffer if necessary. */
        void refresh() const { if(dirty) upload_data(0); }
 
        /** Returns an object which can be used to upload data to the buffer using
-       mapped memory. */
-       AsyncUpdater *refresh_async() const;
+       mapped memory.  If data is not dirty, returns null. */
+       AsyncUpdater *refresh_async() const { return dirty ? new AsyncUpdater(*this) : 0; }
 
 private:
        void unlink_from_buffer();
@@ -67,29 +77,30 @@ public:
        const Buffer *get_buffer() const { return buffer; }
 
        /** Returns the size of the data, in bytes. */
-       virtual unsigned get_data_size() const = 0;
+       virtual std::size_t get_data_size() const = 0;
 
 protected:
-       /** Returns a pointer to the start of data in client memory. */
+       /** Returns a pointer to the start of the data in client memory. */
        virtual const void *get_data_pointer() const = 0;
 
-       /** Returns the alignment required for the data, in bytes.  The offset is
-       guaranteed to be a multiple of this. */
-       virtual unsigned get_alignment() const { return 1; }
+       /** Returns the alignment required for the data, in bytes.  The offset
+       within the buffer is guaranteed to be a multiple of the alignment. */
+       virtual std::size_t get_alignment() const { return 1; }
 
        /** Updates the offsets for the chain so that data from different objects
        does not overlap.  Should be called if either data size or alignment
        changes. */
        void update_offset();
 
+       /* Indicates that the data of the bufferable has changed and should be
+       uploaded to the buffer again. */
+       void mark_dirty();
+
 public:
        /** Returns the offset of the data from the beginning of the buffer. */
-       unsigned get_offset() const { return offset; }
+       std::size_t get_offset() const { return offset; }
 
 private:
-       /** Called when the target buffer or offset within it has changed. */
-       virtual void location_changed(Buffer *, unsigned, unsigned) const { }
-
        /** Uploads data to the buffer.  Receives pointer to mapped buffer memory as
        parameter, or null to use the buffer upload interface. */
        void upload_data(char *) const;