]> git.tdb.fi Git - libs/gl.git/commitdiff
Alter the working logic of Bufferable to avoid some problems
authorMikko Rasa <tdb@tdb.fi>
Sun, 26 Aug 2012 07:53:56 +0000 (10:53 +0300)
committerMikko Rasa <tdb@tdb.fi>
Sun, 26 Aug 2012 07:53:56 +0000 (10:53 +0300)
It was possible for the buffer data to be updated without going through
the dirty check in UniformBlock::apply, leaving the UniformBlock with a
null buf_range and resulting in a segfault.

source/bufferable.cpp
source/bufferable.h
source/uniformblock.cpp
source/uniformblock.h

index 5c7cb9e0891a74a753987dd32735a128228c6def..4660e9c31b32f787bfc553326078da669063b0a5 100644 (file)
@@ -36,7 +36,7 @@ void Bufferable::use_buffer(Buffer *buf, Bufferable *prev)
                        prev_in_buffer->next_in_buffer = this;
        }
 
-       update_buffer_offsets();
+       update_buffer_offset();
 }
 
 void Bufferable::unlink_from_buffer()
@@ -46,13 +46,13 @@ void Bufferable::unlink_from_buffer()
        if(next_in_buffer)
        {
                next_in_buffer->prev_in_buffer = prev_in_buffer;
-               next_in_buffer->update_buffer_offsets();
+               next_in_buffer->update_buffer_offset();
        }
        prev_in_buffer = 0;
        next_in_buffer = 0;
 }
 
-void Bufferable::update_buffer_offsets()
+void Bufferable::update_buffer_offset()
 {
        unsigned offset = 0;
        if(prev_in_buffer)
@@ -62,10 +62,14 @@ void Bufferable::update_buffer_offsets()
        {
                buffer_offset = offset;
                dirty = true;
+               offset_changed();
        }
 
        if(next_in_buffer)
-               next_in_buffer->update_buffer_offsets();
+               next_in_buffer->update_buffer_offset();
+
+       /* Do not resize the buffer here, as the offsets may change multiple times
+       before the buffer is actually used */
 }
 
 void Bufferable::update_buffer_data() const
@@ -77,12 +81,16 @@ void Bufferable::update_buffer_data() const
        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)
+       if(total_size!=buffer->get_size())
        {
-               buffer->sub_data(b->buffer_offset, b->get_data_size(), b->get_data());
-               b->dirty = false;
+               buffer->data(total_size, 0);
+               // Resizing the buffer invalidates its contents.
+               for(const Bufferable *b=first; b; b=b->next_in_buffer)
+                       b->dirty = true;
        }
+
+       upload_data();
+       dirty = false;
 }
 
 } // namespace GL
index dd7cff8e9b0a1c37b8e43416ec89ad607ccfeb45..fa81554dd0090be867ddfc6ca905c6c68ab5d790 100644 (file)
@@ -25,10 +25,12 @@ private:
 
 protected:
        virtual unsigned get_data_size() const = 0;
-       virtual const void *get_data() const = 0;
 
-       void update_buffer_offsets();
+       void update_buffer_offset();
+       virtual void offset_changed() { }
+
        void update_buffer_data() const;
+       virtual void upload_data() const = 0;
 };
 
 } // namespace GL
index 350f57ab6d0f48acaad3bca42f961ac8bf634aee..6ea0d320c5b50d1f9e5cf352a0dd78871465b879 100644 (file)
@@ -22,6 +22,24 @@ UniformBlock::UniformBlock(unsigned s):
        buf_range(0)
 { }
 
+UniformBlock::~UniformBlock()
+{
+       delete buf_range;
+}
+
+void UniformBlock::offset_changed()
+{
+       delete buf_range;
+       buf_range = 0;
+}
+
+void UniformBlock::upload_data() const
+{
+       if(!buf_range)
+               buf_range = new BufferRange(*buffer, buffer_offset, size);
+       buf_range->data(&data[0]);
+}
+
 void UniformBlock::attach(int index, const Uniform &uni)
 {
        uniforms[index] = &uni;
@@ -45,11 +63,7 @@ void UniformBlock::apply(int index) const
        if(buffer)
        {
                if(dirty)
-               {
                        update_buffer_data();
-                       if(!buf_range)
-                               buf_range = new BufferRange(*buffer, buffer_offset, size);
-               }
                buf_range->bind_to(UNIFORM_BUFFER, index);
        }
        else
index fbc9c7047b3fdd57acb162338c9369dbdb442cf0..66b3c7e0c1424b2b4fedc2bb7a15c8232881ed4a 100644 (file)
@@ -29,10 +29,12 @@ private:
 public:
        UniformBlock();
        UniformBlock(unsigned);
+       ~UniformBlock();
 
 private:
-       virtual const void *get_data() const { return &data[0]; }
        virtual unsigned get_data_size() const { return size; }
+       virtual void offset_changed();
+       virtual void upload_data() const;
 
 public:
        void attach(int, const Uniform &);