]> git.tdb.fi Git - libs/gl.git/blobdiff - source/renderpass.cpp
Add some missing virtual destructors and a base class copy-c'tor call
[libs/gl.git] / source / renderpass.cpp
index d2fe668839816688fbab3d60414d2d092d15a7a8..93e2bc479b2d7197c3f9f8fe3bc59703c04d3579 100644 (file)
@@ -13,156 +13,152 @@ Distributed under the LGPL
 #include "program.h"
 #include "programdata.h"
 #include "texture.h"
+#include "texture2d.h"
 
 using namespace std;
 
 namespace Msp {
 namespace GL {
 
-const RenderPass *RenderPass::current=0;
-
 RenderPass::RenderPass():
        shprog(0),
        shdata(0),
-       own_material(false),
        material(0)
 { }
 
 RenderPass::RenderPass(const RenderPass &other):
+       Bindable<RenderPass>(other),
        shprog(other.shprog),
        shdata(other.shdata ? new ProgramData(*other.shdata) : 0),
-       own_material(other.own_material),
-       material(own_material ? new Material(*other.material) : other.material),
+       material(other.material),
        textures(other.textures)
 { }
 
-/*RenderPass &RenderPass::operator=(const RenderPass &other)
-{
-       shprog=other.shprog;
-       delete shdata;
-       shdata=(other.shdata ? new ProgramData(*other.shdata) : 0);
-       material=other.material;
-       use_material=other.use_material;
-       textures=other.textures;
-       use_textures=other.use_textures;
-
-       return *this;
-}*/
-
 RenderPass::~RenderPass()
 {
        delete shdata;
-       if(own_material)
-               delete material;
 }
 
 void RenderPass::set_material(const Material *mat)
 {
-       material=mat;
+       material = mat;
 }
 
-unsigned RenderPass::get_texture_index(const string &slot) const
+void RenderPass::set_texture(unsigned index, const Texture *tex)
 {
-       for(unsigned i=0; i<textures.size(); ++i)
-               if(textures[i].name==slot)
-                       return i;
-
-       throw KeyError("Unknown texture slot", slot);
-}
+       for(vector<TextureSlot>::iterator i=textures.begin(); i!=textures.end(); ++i)
+               if(i->index==index)
+               {
+                       i->texture = tex;
+                       i->texture.keep();
+                       return;
+               }
 
-void RenderPass::set_texture(const string &slot, const Texture *tex)
-{
-       textures[get_texture_index(slot)]=tex;
+       throw KeyError("No texture slot for that unit", lexical_cast(index));
 }
 
 void RenderPass::bind() const
 {
-       if(this==current)
+       const RenderPass *old = current();
+       if(!set_current(this))
                return;
 
-       const RenderPass *old=current;
-       current=this;
-
        if(shprog)
        {
                shprog->bind();
                shdata->apply();
        }
-       else if(old && !old->shprog)
+       else if(old && old->shprog)
                GL::Program::unbind();
 
        if(material)
                material->bind();
-       else if(old && !old->material)
+       else if(old && old->material)
                GL::Material::unbind();
 
-       for(unsigned i=0; i<textures.size(); ++i)
-               if(textures[i].texture)
-                       textures[i].texture->bind_to(i);
+       unsigned used_tex_units = 0;
+       for(vector<TextureSlot>::const_iterator i=textures.begin(); i!=textures.end(); ++i)
+       {
+               i->texture->bind_to(i->index);
+               used_tex_units |= 1<<i->index;
+       }
        if(old)
        {
-               for(unsigned i=textures.size(); i<old->textures.size(); ++i)
-                       GL::Texture::unbind_from(i);
+               for(vector<TextureSlot>::const_iterator i=old->textures.begin(); i!=old->textures.end(); ++i)
+                       if(!used_tex_units&(1<<i->index))
+                               Texture::unbind_from(i->index);
        }
 }
 
 void RenderPass::unbind()
 {
-       if(current)
-       {
-               if(current->shprog)
-                       GL::Program::unbind();
+       const RenderPass *old = current();
+       if(!set_current(0))
+               return;
 
-               if(current->material)
-                       GL::Material::unbind();
+       if(old->shprog)
+               GL::Program::unbind();
 
-               for(unsigned i=current->textures.size(); i--; )
-                       GL::Texture::unbind_from(i);
+       if(old->material)
+               GL::Material::unbind();
 
-               current=0;
-       }
+       for(unsigned i=old->textures.size(); i--; )
+               GL::Texture::unbind_from(i);
 }
 
 
+RenderPass::TextureSlot::TextureSlot(unsigned i):
+       index(i),
+       texture(0)
+{ }
+
+
+RenderPass::Loader::Loader(RenderPass &p):
+       DataFile::CollectionObjectLoader<RenderPass>(p, 0)
+{
+       init();
+}
+
 RenderPass::Loader::Loader(RenderPass &p, Collection &c):
        DataFile::CollectionObjectLoader<RenderPass>(p, &c)
 {
+       init();
+}
+
+void RenderPass::Loader::init()
+{
+       allow_pointer_reload = false;
+
        add("shader",   &RenderPass::shprog);
-       add("material", &Loader::material);
-       add("material", &RenderPass::material);
-       add("texture",  &Loader::texture);
+       add("material", static_cast<void (Loader::*)()>(&Loader::material));
+       add("material", static_cast<void (Loader::*)(const string &)>(&Loader::material));
+       add("texunit",  &Loader::texunit);
        add("uniforms", &Loader::uniforms);
 }
 
 void RenderPass::Loader::finish()
 {
-       if(obj.shprog)
-       {
-               if(!obj.shdata)
-                       obj.shdata=new ProgramData;
-
-               for(unsigned i=0; i<obj.textures.size(); ++i)
-               {
-                       unsigned loc=obj.shprog->get_uniform_location(obj.textures[i].name);
-                       obj.shdata->uniform(loc, static_cast<int>(i));
-               }
-       }
+       // XXX Make shdata optional
+       if(obj.shprog && !obj.shdata)
+               obj.shdata = new ProgramData;
 }
 
 void RenderPass::Loader::material()
 {
-       // XXX Potential memory management trouble with multiple material statements
-       RefPtr<Material> mat=new Material;
+       RefPtr<Material> mat = new Material;
        load_sub(*mat);
-       obj.material=mat.release();
-       obj.own_material=true;
+       obj.material = mat;
+}
+
+void RenderPass::Loader::material(const string &name)
+{
+       obj.material = get_collection().get<Material>(name);
+       obj.material.keep();
 }
 
-void RenderPass::Loader::texture(const string &n)
+void RenderPass::Loader::texunit(unsigned i)
 {
-       const Texture *tex=(n.empty() ? 0 : get_collection().get<Texture>(n));
-       TextureSlot slot(tex);
-       slot.name=(obj.textures.empty() ? "texture" : format("texture%d", obj.textures.size()));
+       TextureSlot slot(i);
        load_sub(slot);
        obj.textures.push_back(slot);
 }
@@ -172,20 +168,40 @@ void RenderPass::Loader::uniforms()
        if(!obj.shprog)
                throw InvalidState("Can't load uniforms without a shader program");
        if(!obj.shdata)
-               obj.shdata=new ProgramData;
+               obj.shdata = new ProgramData;
        load_sub(*obj.shdata, *obj.shprog);
 }
 
 
-RenderPass::TextureSlot::TextureSlot(const Texture *t):
-       texture(t)
-{ }
+RenderPass::TextureSlot::Loader::Loader(TextureSlot &s):
+       DataFile::CollectionObjectLoader<TextureSlot>(s, 0)
+{
+       init();
+}
 
+RenderPass::TextureSlot::Loader::Loader(TextureSlot &s, Collection &c):
+       DataFile::CollectionObjectLoader<TextureSlot>(s, &c)
+{
+       init();
+}
 
-RenderPass::TextureSlot::Loader::Loader(TextureSlot &s):
-       DataFile::ObjectLoader<TextureSlot>(s)
+void RenderPass::TextureSlot::Loader::init()
+{
+       add("texture",   &Loader::texture);
+       add("texture2d", &Loader::texture2d);
+}
+
+void RenderPass::TextureSlot::Loader::texture(const string &name)
+{
+       obj.texture = get_collection().get<Texture>(name);
+       obj.texture.keep();
+}
+
+void RenderPass::TextureSlot::Loader::texture2d()
 {
-       add("name", &TextureSlot::name);
+       RefPtr<Texture2D> tex = new Texture2D;
+       load_sub(*tex);
+       obj.texture = tex;
 }
 
 } // namespace GL