X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Ftexturing.cpp;h=ab5d39b4c42e2b38d51c9ba1dfea5258e851a23a;hp=69c2b3ca55cdae1ff6df19a9227b7d4ddbfa24bf;hb=bec07999d95b76f4b47cffcc564d0cd0afc0435e;hpb=abc16c5ab0fff0945d724febe9d5d3889fb8a6ce diff --git a/source/texturing.cpp b/source/texturing.cpp index 69c2b3ca..ab5d39b4 100644 --- a/source/texturing.cpp +++ b/source/texturing.cpp @@ -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 #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::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::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::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::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; iattachments.size(); ++i) - unbind_attachment(i); + vector::const_iterator i = attachments.begin(); + vector::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::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::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