+ for(vector<Uniform *>::iterator i=uniforms.begin(); i!=uniforms.end(); ++i)
+ delete *i;
+ for(BlockMap::iterator i=blocks.begin(); i!=blocks.end(); ++i)
+ delete i->second.block;
+ delete buffer;
+}
+
+void ProgramData::uniform(const string &name, Uniform *uni)
+{
+ if(name[name.size()-1]==']')
+ throw invalid_argument("ProgramData::uniform");
+
+ SlotMap::iterator i = uniform_slots.find(name);
+ if(i!=uniform_slots.end())
+ {
+ Uniform *&slot = uniforms[i->second];
+ /* UniformBlock does not copy the uniforms, so existing default blocks
+ will be left with stale pointers. This is not a problem as long as no
+ one stores pointers to the blocks and expects them to stay valid. */
+ delete slot;
+ slot = uni;
+
+ if(i->second<MASK_BITS)
+ dirty |= 1<<i->second;
+ else // Force a full update if the mask isn't wide enough
+ dirty = ALL_ONES;
+ }
+ else
+ {
+ uniform_slots[name] = uniforms.size();
+ uniforms.push_back(uni);
+ dirty = ALL_ONES;
+ }
+}
+
+void ProgramData::uniform(const string &name, int v)
+{
+ uniform(name, new Uniform1i(v));
+}
+
+void ProgramData::uniform(const string &name, float v)
+{
+ uniform(name, new Uniform1f(v));
+}
+
+void ProgramData::uniform(const string &name, int v0, int v1)
+{
+ int va[2] = { v0, v1 };
+ uniform2(name, va);
+}
+
+void ProgramData::uniform(const string &name, float v0, float v1)
+{
+ float va[2] = { v0, v1 };
+ uniform2(name, va);
+}
+
+void ProgramData::uniform2(const string &name, const int *v)
+{
+ uniform(name, new Uniform2i(v));
+}
+
+void ProgramData::uniform2(const string &name, const float *v)
+{
+ uniform(name, new Uniform2f(v));
+}
+
+void ProgramData::uniform(const string &name, int v0, int v1, int v2)
+{
+ int va[3] = { v0, v1, v2 };
+ uniform3(name, va);
+}
+
+void ProgramData::uniform(const string &name, float v0, float v1, float v2)
+{
+ float va[3] = { v0, v1, v2 };
+ uniform3(name, va);
+}
+
+void ProgramData::uniform(const string &name, const Vector3 &v)
+{
+ uniform(name, v.x, v.y, v.z);
+}
+
+void ProgramData::uniform3(const string &name, const int *v)
+{
+ uniform(name, new Uniform3i(v));
+}
+
+void ProgramData::uniform3(const string &name, const float *v)
+{
+ uniform(name, new Uniform3f(v));
+}
+
+void ProgramData::uniform(const string &name, int v0, int v1, int v2, int v3)
+{
+ int va[4] = { v0, v1, v2, v3 };
+ uniform4(name, va);
+}
+
+void ProgramData::uniform(const string &name, float v0, float v1, float v2, float v3)
+{
+ float va[4] = { v0, v1, v2, v3 };
+ uniform4(name, va);
+}
+
+void ProgramData::uniform(const string &name, const Vector4 &v)
+{
+ uniform(name, v.x, v.y, v.z, v.w);
+}
+
+void ProgramData::uniform(const string &name, const Color &c)
+{
+ uniform(name, c.r, c.g, c.b, c.a);
+}
+
+void ProgramData::uniform4(const string &name, const int *v)
+{
+ uniform(name, new Uniform4i(v));
+}
+
+void ProgramData::uniform4(const string &name, const float *v)
+{
+ uniform(name, new Uniform4f(v));
+}
+
+void ProgramData::uniform(const string &name, const LinAl::Matrix<float, 2, 2> &m)
+{
+ uniform_matrix2(name, &m(0, 0));
+}
+
+void ProgramData::uniform_matrix2(const string &name, const float *v)
+{
+ uniform(name, new UniformMatrix2x2f(v));
+}
+
+void ProgramData::uniform(const string &name, const LinAl::Matrix<float, 3, 3> &m)
+{
+ uniform_matrix3(name, &m(0, 0));
+}
+
+void ProgramData::uniform_matrix3(const string &name, const float *v)
+{
+ uniform(name, new UniformMatrix3x3f(v));
+}
+
+void ProgramData::uniform(const string &name, const Matrix &m)
+{
+ uniform_matrix4(name, m.data());
+}
+
+void ProgramData::uniform_matrix4(const string &name, const float *v)
+{
+ uniform(name, new UniformMatrix4x4f(v));
+}
+
+void ProgramData::uniform1_array(const string &name, unsigned n, const int *v)
+{
+ uniform(name, new UniformArray<Uniform1i>(n, v));
+}
+
+void ProgramData::uniform1_array(const string &name, unsigned n, const float *v)
+{
+ uniform(name, new UniformArray<Uniform1f>(n, v));
+}
+
+void ProgramData::uniform2_array(const string &name, unsigned n, const int *v)
+{
+ uniform(name, new UniformArray<Uniform2i>(n, v));
+}
+
+void ProgramData::uniform2_array(const string &name, unsigned n, const float *v)
+{
+ uniform(name, new UniformArray<Uniform2f>(n, v));
+}
+
+void ProgramData::uniform3_array(const string &name, unsigned n, const int *v)
+{
+ uniform(name, new UniformArray<Uniform3i>(n, v));