From: Mikko Rasa Date: Fri, 26 Sep 2014 15:00:18 +0000 (+0300) Subject: Unbind things if they are deleted while current X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=commitdiff_plain;h=0ef8e620a008e92069b0dd9ae4e972bc69430fc7 Unbind things if they are deleted while current Failing to do so can lead to all sorts of stale-state issues, especially if a newly created thing happens to get the exact same address as the just deleted one. --- diff --git a/source/bindable.h b/source/bindable.h index 8a5821b9..20b6482a 100644 --- a/source/bindable.h +++ b/source/bindable.h @@ -15,6 +15,7 @@ protected: static const T *cur_obj; Bindable() { } + ~Bindable() { if(cur_obj==this) T::unbind(); } static bool set_current(const T *obj) { @@ -39,8 +40,11 @@ A helper class for Bindables that revert to a default object on unbind. template class BindableWithDefault: protected Bindable { + friend class Bindable; + protected: BindableWithDefault() { } + ~BindableWithDefault() { if(this==&default_object()) Bindable::set_current(0); } public: static const T *current() diff --git a/source/buffer.cpp b/source/buffer.cpp index 9edcf07d..93ef98db 100644 --- a/source/buffer.cpp +++ b/source/buffer.cpp @@ -13,6 +13,7 @@ namespace Msp { namespace GL { const Buffer *Buffer::bound[5] = { 0, 0, 0, 0, 0 }; +BufferType buffer_types[] = { ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER, PIXEL_PACK_BUFFER, PIXEL_UNPACK_BUFFER, UNIFORM_BUFFER }; Buffer::Buffer(BufferType t): type(t), @@ -26,6 +27,9 @@ Buffer::Buffer(BufferType t): Buffer::~Buffer() { + for(unsigned i=0; i<5; ++i) + if(bound[i]==this) + unbind_from(buffer_types[i]); glDeleteBuffers(1, &id); } @@ -140,6 +144,13 @@ BufferRange::BufferRange(Buffer &b, unsigned o, unsigned s): throw out_of_range("BufferRange::BufferRange"); } +BufferRange::~BufferRange() +{ + for(unsigned i=0; iget_index()); +} + void Light::update_parameter(int mask, int index) const { if(index<0) diff --git a/source/light.h b/source/light.h index 77542a54..fa5bf287 100644 --- a/source/light.h +++ b/source/light.h @@ -35,6 +35,7 @@ private: public: Light(); + ~Light(); private: void update_parameter(int, int = -1) const; diff --git a/source/texenv.cpp b/source/texenv.cpp index 51adf9fb..c8af55f8 100644 --- a/source/texenv.cpp +++ b/source/texenv.cpp @@ -9,6 +9,15 @@ TexEnv::TexEnv(): color(0, 0, 0, 0) { } +TexEnv::~TexEnv() +{ + if(this!=&default_object()) + { + while(TexUnit *unit = TexUnit::find_unit(this)) + unbind_from(unit->get_index()); + } +} + const TexEnv &TexEnv::default_object() { static TexEnv obj; diff --git a/source/texenv.h b/source/texenv.h index 61f70085..c422331a 100644 --- a/source/texenv.h +++ b/source/texenv.h @@ -31,6 +31,7 @@ private: public: TexEnv(); + ~TexEnv(); static const TexEnv &default_object(); diff --git a/source/texgen.cpp b/source/texgen.cpp index eb6179d0..0114b2b7 100644 --- a/source/texgen.cpp +++ b/source/texgen.cpp @@ -12,6 +12,11 @@ TexGen::TexGen(): mode(EYE_LINEAR) { } +TexGen::~TexGen() +{ + // TODO unbind +} + void TexGen::set_mode(TexGenMode m) { mode = m; diff --git a/source/texgen.h b/source/texgen.h index c69df638..5858efb4 100644 --- a/source/texgen.h +++ b/source/texgen.h @@ -31,6 +31,7 @@ private: public: TexGen(); + ~TexGen(); void set_mode(TexGenMode); void set_plane(const Vector4 &); diff --git a/source/texture.cpp b/source/texture.cpp index aec1bc92..0fa65ead 100644 --- a/source/texture.cpp +++ b/source/texture.cpp @@ -65,6 +65,9 @@ Texture::Texture(GLenum t, ResourceManager *m): Texture::~Texture() { + while(TexUnit *unit = TexUnit::find_unit(this)) + unbind_from(unit->get_index()); + if(id) glDeleteTextures(1, &id); } diff --git a/source/vertexarray.cpp b/source/vertexarray.cpp index 38481099..042f58c7 100644 --- a/source/vertexarray.cpp +++ b/source/vertexarray.cpp @@ -18,13 +18,10 @@ VertexArray::VertexArray(const VertexFormat &f) VertexArray::~VertexArray() { + /* Unbind accesses the current VertexArray, so a call from ~Bindable would + try to access destroyed data. */ if(current()==this) - { - /* We must deactivate arrays here, or apply() would try to access deleted - data on the next invocation. */ - set_current(0); - apply_arrays(0, &arrays, 0, 0); - } + unbind(); } void VertexArray::reset(const VertexFormat &f) @@ -103,7 +100,7 @@ unsigned VertexArray::get_data_size() const return data.size()*sizeof(float); } -void VertexArray::apply() const +void VertexArray::bind() const { if(format.empty()) throw invalid_operation("VertexArray::apply"); @@ -210,6 +207,13 @@ void VertexArray::apply_arrays(const vector *arrays, const vector glClientActiveTexture(GL_TEXTURE0); } +void VertexArray::unbind() +{ + const VertexArray *old = current(); + if(set_current(0)) + apply_arrays(0, &old->arrays, 0, 0); +} + VertexArray::Array::Array(): component(0), diff --git a/source/vertexarray.h b/source/vertexarray.h index 0223a1f4..9fa55b71 100644 --- a/source/vertexarray.h +++ b/source/vertexarray.h @@ -68,9 +68,12 @@ public: const std::vector &get_data() const { return data; } const float *operator[](unsigned i) const { return &data[0]+i*stride; } - void apply() const; + void bind() const; + void apply() const { bind(); } private: static void apply_arrays(const std::vector *, const std::vector *, const float *, unsigned); +public: + static void unbind(); }; } // namespace GL