]> git.tdb.fi Git - libs/gl.git/blobdiff - source/texturing.cpp
Remove the deprecated ProgramBuilder class
[libs/gl.git] / source / texturing.cpp
index 69c2b3ca55cdae1ff6df19a9227b7d4ddbfa24bf..ab5d39b4c42e2b38d51c9ba1dfea5258e851a23a 100644 (file)
@@ -1,15 +1,10 @@
-/* $Id$
-
-This file is part of libmspgl
-Copyright © 2010  Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
-#include "texenv.h"
+#include <msp/core/hash.h>
 #include "texture.h"
 #include "texturing.h"
 #include "texunit.h"
 
+using namespace std;
+
 namespace Msp {
 namespace GL {
 
@@ -19,14 +14,31 @@ Texturing::~Texturing()
                unbind();
 }
 
-void Texturing::attach(unsigned attch, const Texture &tex)
+int Texturing::find_free_unit(const string &name_hint) const
+{
+       unsigned max_unit = TexUnit::get_n_units();
+       // Leave some space for effect textures
+       max_unit -= min(max_unit/4, 8U);
+       unsigned initial_unit = (name_hint.empty() ? 0 : hash32(name_hint)%max_unit);
+       unsigned unit = initial_unit;
+       while(get_attached_texture(unit) || get_attached_sampler(unit))
+       {
+               unit = (unit+1)%max_unit;
+               if(unit==initial_unit)
+                       return -1;
+       }
+
+       return unit;
+}
+
+void Texturing::attach(unsigned attch, const Texture &tex, const Sampler *samp)
 {
-       set_attachment(attch, &tex, 0);
+       set_attachment(attch, &tex, samp);
 }
 
-void Texturing::attach(unsigned attch, const Texture &tex, const TexEnv &env)
+void Texturing::attach(unsigned attch, const Sampler &samp)
 {
-       set_attachment(attch, &tex, &env);
+       set_attachment(attch, 0, &samp);
 }
 
 void Texturing::detach(unsigned attch)
@@ -34,40 +46,55 @@ void Texturing::detach(unsigned attch)
        set_attachment(attch, 0, 0);
 }
 
-void Texturing::set_attachment(unsigned attch, const Texture *tex, const TexEnv *env)
+void Texturing::set_attachment(unsigned unit, const Texture *tex, const Sampler *samp)
 {
-       if(attch>=TexUnit::get_n_units())
-               throw InvalidParameterValue("Invalid texture attachment");
-
-       if(attachments.size()<=attch)
-               attachments.resize(attch+1);
-
-       attachments[attch].tex = tex;
-       attachments[attch].env = env;
+       if(unit>=TexUnit::get_n_units())
+               throw out_of_range("Texturing::set_attachment");
 
-       if(current()==this)
-               bind_attachment(attch);
+       if(tex || samp)
+       {
+               vector<Attachment>::iterator i;
+               for(i=attachments.begin(); (i!=attachments.end() && i->unit<=unit); ++i)
+                       if(i->unit==unit)
+                       {
+                               i->texture = tex;
+                               i->sampler = samp;
+                               if(current()==this)
+                                       bind_attachment(*i);
+                               return;
+                       }
+
+               attachments.insert(i, Attachment(unit, tex, samp));
+               if(current()==this)
+                       tex->bind_to(unit);
+       }
+       else
+       {
+               for(vector<Attachment>::iterator i=attachments.begin(); (i!=attachments.end() && i->unit<=unit); ++i)
+                       if(i->unit==unit)
+                       {
+                               attachments.erase(i);
+                               if(current()==this)
+                                       unbind_attachment(unit);
+                               return;
+                       }
+       }
 }
 
-void Texturing::bind_attachment(unsigned i) const
+const Texture *Texturing::get_attached_texture(unsigned unit) const
 {
-       const Attachment &attch = attachments[i];
-       TexUnit::activate(i);
-       if(attch.tex)
-               attch.tex->bind();
-       else
-               Texture::unbind();
-       if(attch.env)
-               attch.env->bind();
-       else
-               TexEnv::unbind();
+       for(vector<Attachment>::const_iterator i=attachments.begin(); (i!=attachments.end() && i->unit<=unit); ++i)
+               if(i->unit==unit)
+                       return i->texture;
+       return 0;
 }
 
-void Texturing::unbind_attachment(unsigned i)
+const Sampler *Texturing::get_attached_sampler(unsigned unit) const
 {
-       TexUnit::activate(i);
-       Texture::unbind();
-       TexEnv::unbind();
+       for(vector<Attachment>::const_iterator i=attachments.begin(); (i!=attachments.end() && i->unit<=unit); ++i)
+               if(i->unit==unit)
+                       return i->sampler;
+       return 0;
 }
 
 void Texturing::bind() const
@@ -75,30 +102,64 @@ void Texturing::bind() const
        const Texturing *old = current();
        if(set_current(this))
        {
-               for(unsigned i=0; i<attachments.size(); ++i)
-                       bind_attachment(i);
                if(old)
                {
-                       for(unsigned i=attachments.size(); i<old->attachments.size(); ++i)
-                               unbind_attachment(i);
+                       vector<Attachment>::const_iterator i = attachments.begin();
+                       vector<Attachment>::const_iterator j = old->attachments.begin();
+                       while(i!=attachments.end() || j!=old->attachments.end())
+                       {
+                               if(i!=attachments.end() && (j==old->attachments.end() || i->unit<=j->unit))
+                               {
+                                       bind_attachment(*i);
+                                       if(j!=old->attachments.end() && j->unit==i->unit)
+                                               ++j;
+                                       ++i;
+                               }
+                               else
+                               {
+                                       unbind_attachment(j->unit);
+                                       ++j;
+                               }
+                       }
+               }
+               else
+               {
+                       for(vector<Attachment>::const_iterator i=attachments.begin(); i!=attachments.end(); ++i)
+                               bind_attachment(*i);
                }
        }
 }
 
+void Texturing::bind_attachment(const Attachment &attch) const
+{
+       if(attch.sampler)
+               attch.sampler->bind_to(attch.unit);
+       else
+               Sampler::unbind_from(attch.unit);
+       attch.texture->bind_to(attch.unit);
+}
+
 void Texturing::unbind()
 {
        const Texturing *old = current();
        if(set_current(0))
        {
-               for(unsigned i=old->attachments.size(); i--;)
-                       unbind_attachment(i);
+               for(vector<Attachment>::const_iterator i=old->attachments.begin(); i!=old->attachments.end(); ++i)
+                       unbind_attachment(i->unit);
        }
 }
 
+void Texturing::unbind_attachment(unsigned unit)
+{
+       Texture::unbind_from(unit);
+       Sampler::unbind_from(unit);
+}
+
 
-Texturing::Attachment::Attachment():
-       tex(0),
-       env(0)
+Texturing::Attachment::Attachment(unsigned u, const Texture *t, const Sampler *s):
+       unit(u),
+       texture(t),
+       sampler(s)
 { }
 
 } // namespace GL