]> git.tdb.fi Git - libs/gl.git/blobdiff - source/programdata.cpp
Get all blocks for the program before applying them
[libs/gl.git] / source / programdata.cpp
index 43767bf9526a4449cde0a6d5d3f076bba0460b4b..e1b4212e9d89588f78a42baf2d3e45d5a5a321db 100644 (file)
@@ -1,3 +1,4 @@
+#include "buffer.h"
 #include "color.h"
 #include "error.h"
 #include "extension.h"
@@ -14,6 +15,8 @@ namespace Msp {
 namespace GL {
 
 ProgramData::ProgramData():
+       last_block(0),
+       buffer(0),
        modified(false)
 {
        static RequireExtension _ext("GL_ARB_shader_objects");
@@ -22,6 +25,8 @@ ProgramData::ProgramData():
 // 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)
@@ -120,7 +125,32 @@ void ProgramData::uniform_matrix4(const string &name, const Matrix &m)
        uniform_matrix4(name, v);
 }
 
-const UniformBlock &ProgramData::get_block(const Program &prog) const
+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));
+}
+
+const UniformBlock &ProgramData::get_block(const Program &prog, const Program::UniformBlockInfo *info) const
 {
        if(modified)
        {
@@ -129,23 +159,46 @@ const UniformBlock &ProgramData::get_block(const Program &prog) const
                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;
        }
@@ -153,13 +206,39 @@ const UniformBlock &ProgramData::get_block(const Program &prog) const
        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);
 }