+ 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 float *v)
+{
+ uniform(name, new UniformArray<Uniform1f>(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 float *v)
+{
+ uniform(name, new UniformArray<Uniform3f>(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));
+}
+
+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);
+ if(j!=uniform_slots.end() && j->second<MASK_BITS)
+ mask |= 1<<j->second;
+ }
+
+ return mask;
+}
+
+void ProgramData::update_block(UniformBlock &block, const Program::UniformBlockInfo &info) const
+{
+ for(vector<const Program::UniformInfo *>::const_iterator i=info.uniforms.begin(); i!=info.uniforms.end(); ++i)
+ {
+ SlotMap::const_iterator j = uniform_slots.find((*i)->name);
+ if(j!=uniform_slots.end())
+ block.attach(**i, *uniforms[j->second]);
+ }
+}
+
+ProgramData::SharedBlock *ProgramData::get_shared_block(const Program::UniformBlockInfo &info) const
+{
+ BlockMap::iterator i = blocks.find(info.layout_hash);
+ if(i==blocks.end())
+ {
+ unsigned used = compute_slot_mask(info);
+ if(!used)
+ return 0;
+
+ UniformBlock *block;
+ if(info.bind_point>=0)
+ {
+ if(!buffer)
+ {
+ buffer = new Buffer(UNIFORM_BUFFER);
+ buffer->set_usage(STREAM_DRAW);
+ }
+
+ block = new UniformBlock(info.data_size);
+ block->use_buffer(buffer, last_block);
+ last_block = block;
+ }
+ else
+ block = new UniformBlock;
+
+ i = blocks.insert(BlockMap::value_type(info.layout_hash, SharedBlock(used, block))).first;
+ }
+
+ return &i->second;