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.
12 files changed:
static const T *cur_obj;
Bindable() { }
static const T *cur_obj;
Bindable() { }
+ ~Bindable() { if(cur_obj==this) T::unbind(); }
static bool set_current(const T *obj)
{
static bool set_current(const T *obj)
{
template<typename T>
class BindableWithDefault: protected Bindable<T>
{
template<typename T>
class BindableWithDefault: protected Bindable<T>
{
+ friend class Bindable<T>;
+
protected:
BindableWithDefault() { }
protected:
BindableWithDefault() { }
+ ~BindableWithDefault() { if(this==&default_object()) Bindable<T>::set_current(0); }
public:
static const T *current()
public:
static const T *current()
namespace GL {
const Buffer *Buffer::bound[5] = { 0, 0, 0, 0, 0 };
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),
Buffer::Buffer(BufferType t):
type(t),
+ for(unsigned i=0; i<5; ++i)
+ if(bound[i]==this)
+ unbind_from(buffer_types[i]);
glDeleteBuffers(1, &id);
}
glDeleteBuffers(1, &id);
}
throw out_of_range("BufferRange::BufferRange");
}
throw out_of_range("BufferRange::BufferRange");
}
+BufferRange::~BufferRange()
+{
+ for(unsigned i=0; i<bound_uniform.size(); ++i)
+ if(bound_uniform[i]==this)
+ unbind_from(UNIFORM_BUFFER, i);
+}
+
void BufferRange::data(const void *d)
{
buffer.sub_data(offset, size, d);
void BufferRange::data(const void *d)
{
buffer.sub_data(offset, size, d);
public:
BufferRange(Buffer &, unsigned, unsigned);
public:
BufferRange(Buffer &, unsigned, unsigned);
+Light::~Light()
+{
+ while(LightUnit *unit = LightUnit::find_unit(this))
+ unbind_from(unit->get_index());
+}
+
void Light::update_parameter(int mask, int index) const
{
if(index<0)
void Light::update_parameter(int mask, int index) const
{
if(index<0)
private:
void update_parameter(int, int = -1) const;
private:
void update_parameter(int, int = -1) const;
+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;
const TexEnv &TexEnv::default_object()
{
static TexEnv obj;
static const TexEnv &default_object();
static const TexEnv &default_object();
+TexGen::~TexGen()
+{
+ // TODO unbind
+}
+
void TexGen::set_mode(TexGenMode m)
{
mode = m;
void TexGen::set_mode(TexGenMode m)
{
mode = m;
void set_mode(TexGenMode);
void set_plane(const Vector4 &);
void set_mode(TexGenMode);
void set_plane(const Vector4 &);
+ while(TexUnit *unit = TexUnit::find_unit(this))
+ unbind_from(unit->get_index());
+
if(id)
glDeleteTextures(1, &id);
}
if(id)
glDeleteTextures(1, &id);
}
VertexArray::~VertexArray()
{
VertexArray::~VertexArray()
{
+ /* Unbind accesses the current VertexArray, so a call from ~Bindable would
+ try to access destroyed data. */
- {
- /* 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);
- }
}
void VertexArray::reset(const VertexFormat &f)
}
void VertexArray::reset(const VertexFormat &f)
return data.size()*sizeof(float);
}
return data.size()*sizeof(float);
}
-void VertexArray::apply() const
+void VertexArray::bind() const
{
if(format.empty())
throw invalid_operation("VertexArray::apply");
{
if(format.empty())
throw invalid_operation("VertexArray::apply");
glClientActiveTexture(GL_TEXTURE0);
}
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),
VertexArray::Array::Array():
component(0),
const std::vector<float> &get_data() const { return data; }
const float *operator[](unsigned i) const { return &data[0]+i*stride; }
const std::vector<float> &get_data() const { return data; }
const float *operator[](unsigned i) const { return &data[0]+i*stride; }
+ void bind() const;
+ void apply() const { bind(); }
private:
static void apply_arrays(const std::vector<Array> *, const std::vector<Array> *, const float *, unsigned);
private:
static void apply_arrays(const std::vector<Array> *, const std::vector<Array> *, const float *, unsigned);
+public:
+ static void unbind();