]> git.tdb.fi Git - libs/gl.git/blobdiff - source/texturing.cpp
Remove the deprecated ProgramBuilder class
[libs/gl.git] / source / texturing.cpp
index 093c602e917c2ec7bf3ee67a626eedb4f4e43ab4..ab5d39b4c42e2b38d51c9ba1dfea5258e851a23a 100644 (file)
@@ -1,3 +1,4 @@
+#include <msp/core/hash.h>
 #include "texture.h"
 #include "texturing.h"
 #include "texunit.h"
@@ -13,41 +14,87 @@ Texturing::~Texturing()
                unbind();
 }
 
-void Texturing::attach(unsigned attch, const Texture &tex)
+int Texturing::find_free_unit(const string &name_hint) const
 {
-       set_attachment(attch, &tex);
+       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, samp);
+}
+
+void Texturing::attach(unsigned attch, const Sampler &samp)
+{
+       set_attachment(attch, 0, &samp);
 }
 
 void Texturing::detach(unsigned attch)
 {
-       set_attachment(attch, 0);
+       set_attachment(attch, 0, 0);
 }
 
-void Texturing::set_attachment(unsigned attch, const Texture *tex)
+void Texturing::set_attachment(unsigned unit, const Texture *tex, const Sampler *samp)
 {
-       if(attch>=TexUnit::get_n_units())
+       if(unit>=TexUnit::get_n_units())
                throw out_of_range("Texturing::set_attachment");
 
-       if(attachments.size()<=attch)
-               attachments.resize(attch+1);
-
-       attachments[attch] = tex;
+       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;
+                       }
 
-       if(current()==this)
-               bind_attachment(attch);
+               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
 {
-       if(const Texture *tex = attachments[i])
-               tex->bind_to(i);
-       else
-               Texture::unbind_from(i);
+       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
 {
-       Texture::unbind_from(i);
+       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
@@ -55,25 +102,65 @@ 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(unsigned u, const Texture *t, const Sampler *s):
+       unit(u),
+       texture(t),
+       sampler(s)
+{ }
+
 } // namespace GL
 } // namespace Msp;