void Buffer::sub_data(size_t off, size_t sz, const void *d)
{
- if(size==0)
- throw invalid_operation("Buffer::sub_data");
- if(off>size || off+sz>size)
- throw out_of_range("Buffer::sub_data");
-
+ check_sub_data(off, sz, "Buffer::sub_data");
BufferBackend::sub_data(off, sz, d);
}
+Buffer::AsyncTransfer Buffer::sub_data_async(size_t off, size_t sz)
+{
+ check_sub_data(off, sz, "Buffer::sub_data_async");
+ return AsyncTransfer(*this, off, sz);
+}
+
+void Buffer::check_sub_data(size_t off, size_t sz, const char *func)
+{
+ if(size==0)
+ throw invalid_operation(func);
+ if(off>get_total_size() || off%size+sz>size)
+ throw out_of_range(func);
+}
+
void Buffer::require_size(size_t req_sz) const
{
if(size<req_sz)
throw buffer_too_small(format("buffer has %d bytes; %d required", size, req_sz));
}
+void *Buffer::map()
+{
+ if(size==0 || !can_map() || mapped)
+ throw invalid_operation("Buffer::map");
+ void *result = BufferBackend::map();
+ mapped = true;
+ return result;
+}
+
+bool Buffer::unmap()
+{
+ if(size==0 || !can_map() || !mapped)
+ throw invalid_operation("Buffer::unmap");
+ bool result = BufferBackend::unmap();
+ mapped = false;
+ return result;
+}
+
+
+Buffer::AsyncTransfer::AsyncTransfer(Buffer &b, size_t o, size_t s):
+ buffer(&b),
+ offset(o),
+ size(s),
+ dest_addr(0)
+{
+ allocate();
+}
+
+Buffer::AsyncTransfer::AsyncTransfer(AsyncTransfer &&other):
+ buffer(other.buffer),
+ offset(other.offset),
+ size(other.size),
+ dest_addr(other.dest_addr)
+{
+ other.dest_addr = 0;
+}
+
+Buffer::AsyncTransfer &Buffer::AsyncTransfer::operator=(AsyncTransfer &&other)
+{
+ if(dest_addr)
+ finalize();
+
+ buffer = other.buffer;
+ offset = other.offset;
+ size = other.size;
+ dest_addr = other.dest_addr;
+
+ other.dest_addr = 0;
+
+ return *this;
+}
+
+Buffer::AsyncTransfer::~AsyncTransfer()
+{
+ if(dest_addr)
+ finalize();
+}
+
} // namespace GL
} // namespace Msp