+#include "buffer.h"
#include "color.h"
#include "error.h"
#include "extension.h"
namespace GL {
ProgramData::ProgramData():
+ last_block(0),
+ buffer(0),
modified(false)
{
static RequireExtension _ext("GL_ARB_shader_objects");
// Blocks are intentionally left uncopied
ProgramData::ProgramData(const ProgramData &other):
uniforms(other.uniforms),
+ last_block(0),
+ buffer(0),
modified(false)
{
for(UniformMap::iterator i=uniforms.begin(); i!=uniforms.end(); ++i)
uniform(name, new UniformArray<UniformMatrix4x4f>(n, v));
}
-const UniformBlock &ProgramData::get_block(const Program &prog) const
+const UniformBlock &ProgramData::get_block(const Program &prog, const Program::UniformBlockInfo *info) const
{
if(modified)
{
modified = false;
}
- unsigned layout_hash = prog.get_uniform_layout_hash();
+ unsigned layout_hash = (info ? info->layout_hash : prog.get_uniform_layout_hash());
+
map<unsigned, Block>::iterator i = blocks.find(layout_hash);
if(i==blocks.end())
{
i = blocks.insert(BlockMap::value_type(layout_hash, Block())).first;
i->second.dirty = true;
- i->second.block = new UniformBlock;
+ if(info)
+ {
+ i->second.block = new UniformBlock(info->data_size);
+ if(!buffer)
+ buffer = new Buffer(UNIFORM_BUFFER);
+ i->second.block->use_buffer(buffer, last_block);
+ last_block = i->second.block;
+ }
+ else
+ i->second.block = new UniformBlock;
}
UniformBlock &block = *i->second.block;
if(i->second.dirty)
{
- for(UniformMap::const_iterator j=uniforms.begin(); j!=uniforms.end(); ++j)
+ if(info)
+ {
+ for(vector<const Program::UniformInfo *>::const_iterator j=info->uniforms.begin(); j!=info->uniforms.end(); ++j)
+ {
+ // XXX individual array elements
+ UniformMap::const_iterator k = uniforms.find((*j)->name);
+ if(k!=uniforms.end())
+ block.attach(**j, *k->second);
+ }
+ }
+ else
{
- int loc = prog.get_uniform_location(j->first);
- if(loc>=0)
- block.uniform(loc, *j->second);
+ for(UniformMap::const_iterator j=uniforms.begin(); j!=uniforms.end(); ++j)
+ {
+ int loc = prog.get_uniform_location(j->first);
+ if(loc>=0)
+ block.attach(loc, *j->second);
+ }
}
i->second.dirty = false;
}
return block;
}
+const UniformBlock &ProgramData::get_block(const Program &prog, const string &name) const
+{
+ if(name.empty())
+ return get_block(prog, 0);
+ else
+ return get_block(prog, &prog.get_uniform_block_info(name));
+}
+
void ProgramData::apply() const
{
const Program *prog = Program::current();
if(!prog)
throw invalid_operation("ProgramData::apply");
- const UniformBlock &block = get_block(*prog);
+ const Program::UniformBlockMap &prog_blocks = prog->get_uniform_blocks();
+ if(!prog_blocks.empty())
+ {
+ typedef pair<const UniformBlock *, unsigned> ApplyBlock;
+ list<ApplyBlock> apply_blocks;
+ for(Program::UniformBlockMap::const_iterator i=prog_blocks.begin(); i!=prog_blocks.end(); ++i)
+ {
+ const UniformBlock &block = get_block(*prog, &i->second);
+ apply_blocks.push_back(make_pair(&block, i->second.bind_point));
+ }
+
+ if(buffer)
+ buffer->bind();
+
+ for(list<ApplyBlock>::const_iterator i=apply_blocks.begin(); i!=apply_blocks.end(); ++i)
+ i->first->apply(i->second);
+ }
+
+ const UniformBlock &block = get_block(*prog, 0);
block.apply(-1);
}