#include <stdexcept>
+#include <msp/core/raii.h>
+#include <msp/gl/extensions/arb_direct_state_access.h>
#include "bindable.h"
#include "buffer.h"
#include "bufferable.h"
offset(0),
next_in_buffer(0),
prev_in_buffer(0),
+ location_dirty(false),
dirty(false)
{ }
}
}
+ location_dirty = true;
dirty = true;
update_offset();
}
if(new_offset!=offset)
{
offset = new_offset;
+ location_dirty = true;
dirty = true;
- offset_changed();
}
if(next_in_buffer)
next_in_buffer->update_offset();
-
- /* Do not resize the buffer here, as more bufferables may be added before
- the buffer is actually used. */
+ else if(buffer && offset+get_data_size()>buffer->get_size())
+ {
+ location_dirty = true;
+ dirty = true;
+ }
}
bool Bufferable::resize_buffer() const
return false;
}
-void Bufferable::update_buffer() const
+void Bufferable::update_buffer_size() const
{
- BindRestore bind(buffer, buffer->get_type());
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);
}
-
- upload_data(0);
- dirty = false;
}
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+get_data_size(), target);
+ copy(source, source+data_size, target);
}
else
- buffer->sub_data(offset, get_data_size(), get_data_pointer());
+ buffer->sub_data(offset, data_size, get_data_pointer());
+ dirty = false;
}
// Update all bufferables in the same buffer at once
for(const Bufferable *b=bufferable.prev_in_buffer; b; b=b->prev_in_buffer)
if(b->dirty || buffer_resized)
- {
b->upload_data(mapped_address+b->offset);
- b->dirty = false;
- }
for(const Bufferable *b=bufferable.next_in_buffer; b; b=b->next_in_buffer)
if(b->dirty || buffer_resized)
- {
b->upload_data(mapped_address+b->offset);
- b->dirty = false;
- }
}
} // namespace GL