+ 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));
+}
+
+void ProgramData::uniform3_array(const string &name, unsigned n, const float *v)
+{
+ uniform(name, new UniformArray<Uniform3f>(n, v));
+}
+
+void ProgramData::uniform4_array(const string &name, unsigned n, const int *v)
+{
+ uniform(name, new UniformArray<Uniform4i>(n, v));
+}
+
+void ProgramData::uniform4_array(const string &name, unsigned n, const float *v)
+{
+ uniform(name, new UniformArray<Uniform4f>(n, v));
+}
+
+void ProgramData::uniform_matrix4_array(const string &name, unsigned n, const float *v)
+{
+ uniform(name, new UniformArray<UniformMatrix4x4f>(n, v));
+}
+
+void ProgramData::remove_uniform(const string &name)
+{
+ SlotMap::iterator i = uniform_slots.find(name);
+ if(i!=uniform_slots.end())
+ {
+ vector<Uniform *>::iterator j = uniforms.begin()+i->second;
+ delete *j;
+ uniforms.erase(j);
+
+ for(SlotMap::iterator k=uniform_slots.begin(); k!=uniform_slots.end(); ++k)
+ if(k->second>i->second)
+ --k->second;
+
+ uniform_slots.erase(i);
+
+ dirty = ALL_ONES;
+ }
+}
+
+unsigned ProgramData::compute_slot_mask(const Program::UniformBlockInfo &block) const
+{
+ unsigned mask = 0;
+ for(vector<const Program::UniformInfo *>::const_iterator i=block.uniforms.begin(); i!=block.uniforms.end(); ++i)
+ {
+ SlotMap::const_iterator j = uniform_slots.find((*i)->name);
+ /* TODO issue a warning (or even error?) either here or in update_block
+ if all uniforms for a buffer-backed block are not found */
+ if(j!=uniform_slots.end() && j->second<MASK_BITS)
+ mask |= 1<<j->second;
+ }
+
+ return mask;