+ return false;
+}
+
+void Bufferable::update_buffer_size() const
+{
+ if(resize_buffer())
+ {
+ Conditional<BindRestore> _bind(!ARB_direct_state_access, buffer, buffer->get_type());
+
+ /* Resizing the buffer invalidates its contents. Non-dirty data may
+ be in use, so reupload it. */
+ for(const Bufferable *b=prev_in_buffer; b; b=b->prev_in_buffer)
+ if(!b->dirty)
+ b->upload_data(0);
+ for(const Bufferable *b=next_in_buffer; b; b=b->next_in_buffer)
+ if(!b->dirty)
+ b->upload_data(0);
+ }
+}
+
+void Bufferable::upload_data(char *target) const
+{
+ unsigned data_size = get_data_size();
+ if(location_dirty)
+ {
+ update_buffer_size();
+ location_changed(buffer, offset, data_size);
+ location_dirty = false;
+ }
+
+ if(target)
+ {
+ const char *source = reinterpret_cast<const char *>(get_data_pointer());
+ copy(source, source+data_size, target);
+ }
+ else
+ buffer->sub_data(offset, data_size, get_data_pointer());