static const T *cur_obj;
Bindable() { }
+ ~Bindable() { if(cur_obj==this) T::unbind(); }
static bool set_current(const T *obj)
{
template<typename T>
class BindableWithDefault: protected Bindable<T>
{
+ friend class Bindable<T>;
+
protected:
BindableWithDefault() { }
+ ~BindableWithDefault() { if(this==&default_object()) Bindable<T>::set_current(0); }
public:
static const T *current()
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()
{
+ for(unsigned i=0; i<5; ++i)
+ if(bound[i]==this)
+ unbind_from(buffer_types[i]);
glDeleteBuffers(1, &id);
}
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);
public:
BufferRange(Buffer &, unsigned, unsigned);
+ ~BufferRange();
void data(const void *);
attenuation[2] = 0;
}
+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)
public:
Light();
+ ~Light();
private:
void update_parameter(int, int = -1) const;
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;
public:
TexEnv();
+ ~TexEnv();
static const TexEnv &default_object();
mode(EYE_LINEAR)
{ }
+TexGen::~TexGen()
+{
+ // TODO unbind
+}
+
void TexGen::set_mode(TexGenMode m)
{
mode = m;
public:
TexGen();
+ ~TexGen();
void set_mode(TexGenMode);
void set_plane(const Vector4 &);
Texture::~Texture()
{
+ while(TexUnit *unit = TexUnit::find_unit(this))
+ unbind_from(unit->get_index());
+
if(id)
glDeleteTextures(1, &id);
}
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)
return data.size()*sizeof(float);
}
-void VertexArray::apply() const
+void VertexArray::bind() const
{
if(format.empty())
throw invalid_operation("VertexArray::apply");
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),
const std::vector<float> &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<Array> *, const std::vector<Array> *, const float *, unsigned);
+public:
+ static void unbind();
};
} // namespace GL