X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fbatch.cpp;h=1d9b1d4cd4ab7081a3bf95522056f61b91375217;hb=50175b88e2f189e80881d292dcc32523c5b272fc;hp=1260c6abe5e995203af5ff3a70d10ce9fc1d8d63;hpb=f14435e58bfa0fa697a06ba9a454bb30cd37d9d8;p=libs%2Fgl.git diff --git a/source/batch.cpp b/source/batch.cpp index 1260c6ab..1d9b1d4c 100644 --- a/source/batch.cpp +++ b/source/batch.cpp @@ -1,12 +1,51 @@ #include "batch.h" #include "bindable.h" #include "buffer.h" -#include "extension.h" +#include "error.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 { @@ -23,7 +62,11 @@ Batch::Batch(PrimitiveType t): next_in_ibuf(0), prev_in_ibuf(0), dirty(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() { @@ -33,24 +76,24 @@ Batch::~Batch() void Batch::set_data_type(DataType t) { if(t!=UNSIGNED_BYTE && t!=UNSIGNED_SHORT && t!=UNSIGNED_INT) - throw InvalidParameterValue("Batch data type must be an unsigned integer"); + throw invalid_argument("Batch::set_data_type"); if(t==UNSIGNED_BYTE && max_index>0xFE) - throw InvalidState("UNSIGNED_BYTE can't hold all indices in Batch"); + throw invalid_operation("Batch::set_data_type"); else if(t==UNSIGNED_SHORT && max_index>0xFFFE) - throw InvalidState("UNSIGNED_SHORT can't hold all indices in Batch"); + 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(); @@ -60,7 +103,7 @@ void Batch::set_data_type(DataType t) void Batch::use_index_buffer(Buffer *buf, Batch *prev) { if(buf && prev && prev->ibuf!=buf) - throw InvalidParameterValue("Previous batch is not in the same buffer"); + throw invalid_argument("Batch::use_index_buffer"); if(!buf) { @@ -82,6 +125,28 @@ void Batch::use_index_buffer(Buffer *buf, Batch *prev) dirty = true; } +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 &Batch::append(unsigned i) { if(data.empty()) @@ -98,9 +163,9 @@ 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); @@ -153,24 +218,24 @@ void Batch::append(const vector &ind) void Batch::append(const Batch &other) { if(other.prim_type!=prim_type) - throw InvalidParameterValue("Can't concatenate batches with different primitive types"); + throw invalid_argument("Batch::append"); if(prim_type==LINE_STRIP || prim_type==LINE_LOOP) - throw InvalidState("Can't concatenate line strips or loops"); + throw incompatible_data("Batch::append"); else if(prim_type==POLYGON) - throw InvalidState("Can't concatenate polygons"); + throw incompatible_data("Batch::append"); else if(prim_type==TRIANGLE_FAN) - static RequireExtension _ext("GL_NV_primitive_restart"); + static Require _req(NV_primitive_restart); if(other.data.empty()) return; - if(is_supported("GL_NV_primitive_restart")) + if(NV_primitive_restart) { restart = true; if(data_type==UNSIGNED_SHORT) - append_index(0xFFFF); + ::append(data, 0xFFFF); else if(data_type==UNSIGNED_INT) - append_index(0xFFFFFFFF); + ::append(data, 0xFFFFFFFF); else data.push_back(0xFF); } @@ -194,6 +259,25 @@ void Batch::append(const Batch &other) append(other.get_index(i)); } +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) @@ -243,87 +327,12 @@ void Batch::draw() const BufferAlias alias(*ibuf); 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(ibuf_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)