X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fbatch.cpp;h=785fca826ae30e5c9c524b0a2f08a242a2aad15f;hb=7d6b7b18221e670810bdd0505995b8f1fa012eb4;hp=b4b88176559a744ffa602fed13951ebd8a65b669;hpb=2e7f19b895424c3a77940e648639f8df2b395d0f;p=libs%2Fgl.git diff --git a/source/batch.cpp b/source/batch.cpp index b4b88176..785fca82 100644 --- a/source/batch.cpp +++ b/source/batch.cpp @@ -2,12 +2,50 @@ #include "bindable.h" #include "buffer.h" #include "error.h" -#include "extension.h" +#include "ext_draw_range_elements.h" #include "nv_primitive_restart.h" #include "vertexarray.h" using namespace std; +namespace { + +template +void append(vector &data, T i) +{ + data.insert(data.end(), sizeof(T), 0); + *(T *)(&data[data.size()-sizeof(T)]) = i; +} + +template +U convert(T n) +{ + if(!static_cast(~n)) + return ~0; + else + return n; +} + +template +void expand(vector &data) +{ + unsigned count = data.size()/sizeof(T); + data.resize(count*sizeof(U)); + for(unsigned i=count; i--;) + *(U *)(&data[i*sizeof(U)]) = convert(*(T *)(&data[i*sizeof(T)])); +} + +template +void shrink(vector &data) +{ + unsigned count = data.size()/sizeof(T); + for(unsigned i=0; i(*(T *)(&data[i*sizeof(T)])); + data.resize(count*sizeof(U)); +} + +} + namespace Msp { namespace GL { @@ -18,17 +56,15 @@ Batch::Batch(PrimitiveType t): data_type(UNSIGNED_BYTE), min_index(0), max_index(0), - restart(false), - ibuf(0), - ibuf_offset(0), - next_in_ibuf(0), - prev_in_ibuf(0), - dirty(false) -{ } + restart(false) +{ + /* XXX Should probably provide a fallback to glDrawElements since this class + is pretty much required to render anything. */ + static Require _req(EXT_draw_range_elements); +} Batch::~Batch() { - unlink_from_ibuf(); } void Batch::set_data_type(DataType t) @@ -41,45 +77,20 @@ void Batch::set_data_type(DataType t) throw invalid_operation("Batch::set_data_type"); if(data_type==UNSIGNED_BYTE && t==UNSIGNED_SHORT) - expand_data(); + expand(data); else if(data_type==UNSIGNED_BYTE && t==UNSIGNED_INT) - expand_data(); + expand(data); else if(data_type==UNSIGNED_SHORT && t==UNSIGNED_INT) - expand_data(); + expand(data); else if(data_type==UNSIGNED_INT && t==UNSIGNED_BYTE) - shrink_data(); + shrink(data); else if(data_type==UNSIGNED_INT && t==UNSIGNED_SHORT) - shrink_data(); + shrink(data); else if(data_type==UNSIGNED_SHORT && t==UNSIGNED_BYTE) - shrink_data(); + shrink(data); data_type = t; - update_ibuf_offsets(); - dirty = true; -} - -void Batch::use_index_buffer(Buffer *buf, Batch *prev) -{ - if(buf && prev && prev->ibuf!=buf) - throw invalid_argument("Batch::use_index_buffer"); - - if(!buf) - { - prev = 0; - unlink_from_ibuf(); - } - - ibuf = buf; - prev_in_ibuf = prev; - next_in_ibuf = 0; - if(prev) - { - prev->next_in_ibuf = this; - ibuf_offset = prev->ibuf_offset+prev->data.size(); - } - else - ibuf_offset = 0; - + update_offset(); dirty = true; } @@ -99,13 +110,13 @@ Batch &Batch::append(unsigned i) set_data_type(UNSIGNED_SHORT); if(data_type==UNSIGNED_SHORT) - append_index(i); + ::append(data, i); else if(data_type==UNSIGNED_INT) - append_index(i); + ::append(data, i); else data.push_back(i); - update_ibuf_offsets(); + update_offset(); dirty = true; return *this; @@ -149,6 +160,7 @@ void Batch::append(const vector &ind) for(unsigned i=0; i(0xFFFF); + ::append(data, 0xFFFF); else if(data_type==UNSIGNED_INT) - append_index(0xFFFFFFFF); + ::append(data, 0xFFFFFFFF); else data.push_back(0xFF); } @@ -195,6 +207,30 @@ void Batch::append(const Batch &other) append(other.get_index(i)); } +void Batch::upload_data() const +{ + get_buffer()->sub_data(get_offset(), data.size(), &data[0]); +} + +unsigned Batch::get_index_size() const +{ + if(data_type==UNSIGNED_SHORT) + return sizeof(unsigned short); + else if(data_type==UNSIGNED_INT) + return sizeof(unsigned); + return sizeof(unsigned char); +} + +unsigned Batch::get_index(unsigned i) const +{ + if(data_type==UNSIGNED_SHORT) + return *(unsigned short *)&data[i*sizeof(unsigned short)]; + else if(data_type==UNSIGNED_INT) + return *(unsigned *)&data[i*sizeof(unsigned )]; + else + return data[i]; +} + void Batch::draw() const { if(restart) @@ -221,110 +257,20 @@ void Batch::draw() const restart_index = 0; } - if(ibuf) + if(get_buffer()) { if(dirty) - { - const Batch *b = this; - for(; b->prev_in_ibuf; b=b->prev_in_ibuf) ; - - unsigned chain_size = 0; - for(const Batch *a=b; a; a=a->next_in_ibuf) - chain_size += a->data.size(); + update_buffer(); - ibuf->data(chain_size, 0); - - for(; b; b=b->next_in_ibuf) - { - ibuf->sub_data(b->ibuf_offset, b->data.size(), &b->data[0]); - b->dirty = false; - } - } - - BufferAlias alias(*ibuf); + BufferAlias alias(*get_buffer()); Bind bind_ibuf(alias, true); - glDrawRangeElements(prim_type, min_index, max_index, size(), data_type, (void *)ibuf_offset); + glDrawRangeElements(prim_type, min_index, max_index, size(), data_type, reinterpret_cast(get_offset())); } else glDrawRangeElements(prim_type, min_index, max_index, size(), data_type, &data[0]); } -unsigned Batch::get_index_size() const -{ - if(data_type==UNSIGNED_SHORT) - return sizeof(unsigned short); - else if(data_type==UNSIGNED_INT) - return sizeof(unsigned); - return sizeof(unsigned char); -} - -template -void Batch::append_index(T i) -{ - data.insert(data.end(), sizeof(T), 0); - *(T *)(&data[data.size()-sizeof(T)]) = i; -} - -unsigned Batch::get_index(unsigned i) const -{ - if(data_type==UNSIGNED_SHORT) - return *(unsigned short *)&data[i*sizeof(unsigned short)]; - else if(data_type==UNSIGNED_INT) - return *(unsigned *)&data[i*sizeof(unsigned )]; - else - return data[i]; -} - -template -void Batch::expand_data() -{ - unsigned count = data.size()/sizeof(T); - data.resize(count*sizeof(U)); - for(unsigned i=count; i--;) - *(U *)(&data[i*sizeof(U)]) = convert(*(T *)(&data[i*sizeof(T)])); -} - -template -void Batch::shrink_data() -{ - unsigned count = data.size()/sizeof(T); - for(unsigned i=0; i(*(T *)(&data[i*sizeof(T)])); - data.resize(count*sizeof(U)); -} - -template -U Batch::convert(T i) const -{ - if(!static_cast(~i)) - return ~0; - else - return i; -} - -void Batch::unlink_from_ibuf() -{ - if(next_in_ibuf) - next_in_ibuf->prev_in_ibuf = prev_in_ibuf; - if(prev_in_ibuf) - { - prev_in_ibuf->next_in_ibuf = next_in_ibuf; - prev_in_ibuf->update_ibuf_offsets(); - } - else if(next_in_ibuf) - { - next_in_ibuf->ibuf_offset = 0; - next_in_ibuf->update_ibuf_offsets(); - } -} - -void Batch::update_ibuf_offsets() -{ - for(Batch *b=this; b->next_in_ibuf; b=b->next_in_ibuf) - b->next_in_ibuf->ibuf_offset = b->ibuf_offset+b->data.size(); -} - Batch::Loader::Loader(Batch &b): DataFile::ObjectLoader(b)