From abc16c5ab0fff0945d724febe9d5d3889fb8a6ce Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Thu, 15 Jul 2010 12:11:59 +0000 Subject: [PATCH] Add a Texturing class to encapsulate the state of multiple texturing units Make TexEnv::bind const Propagate changes to GL when changing the currently bound TexEnv Restore default TexEnv state on unbind Take GL version into account in TexUnit::get_n_units --- source/texenv.cpp | 13 +++++- source/texenv.h | 2 +- source/texturing.cpp | 105 +++++++++++++++++++++++++++++++++++++++++++ source/texturing.h | 54 ++++++++++++++++++++++ source/texunit.cpp | 18 ++++---- 5 files changed, 181 insertions(+), 11 deletions(-) create mode 100644 source/texturing.cpp create mode 100644 source/texturing.h diff --git a/source/texenv.cpp b/source/texenv.cpp index e6c06bcb..3730a7e1 100644 --- a/source/texenv.cpp +++ b/source/texenv.cpp @@ -18,14 +18,18 @@ TexEnv::TexEnv(): void TexEnv::set_mode(TexEnvMode m) { mode = m; + if(current()==this) + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, mode); } void TexEnv::set_color(const Color &c) { color = c; + if(current()==this) + glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &color.r); } -void TexEnv::bind() +void TexEnv::bind() const { if(TexUnit::current().set_texenv(this)) { @@ -36,7 +40,12 @@ void TexEnv::bind() void TexEnv::unbind() { - TexUnit::current().set_texenv(0); + if(TexUnit::current().set_texenv(0)) + { + Color black(0, 0, 0, 0); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, MODULATE); + glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &black.r); + } } } // namespace GL diff --git a/source/texenv.h b/source/texenv.h index b5fee448..01e4a556 100644 --- a/source/texenv.h +++ b/source/texenv.h @@ -36,7 +36,7 @@ public: void set_color(const Color &); TexEnvMode get_mode() const { return mode; } const Color &get_color() const { return color; } - void bind(); + void bind() const; static void unbind(); }; diff --git a/source/texturing.cpp b/source/texturing.cpp new file mode 100644 index 00000000..69c2b3ca --- /dev/null +++ b/source/texturing.cpp @@ -0,0 +1,105 @@ +/* $Id$ + +This file is part of libmspgl +Copyright © 2010 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ + +#include "texenv.h" +#include "texture.h" +#include "texturing.h" +#include "texunit.h" + +namespace Msp { +namespace GL { + +Texturing::~Texturing() +{ + if(current()==this) + unbind(); +} + +void Texturing::attach(unsigned attch, const Texture &tex) +{ + set_attachment(attch, &tex, 0); +} + +void Texturing::attach(unsigned attch, const Texture &tex, const TexEnv &env) +{ + set_attachment(attch, &tex, &env); +} + +void Texturing::detach(unsigned attch) +{ + set_attachment(attch, 0, 0); +} + +void Texturing::set_attachment(unsigned attch, const Texture *tex, const TexEnv *env) +{ + 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(current()==this) + bind_attachment(attch); +} + +void Texturing::bind_attachment(unsigned i) 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(); +} + +void Texturing::unbind_attachment(unsigned i) +{ + TexUnit::activate(i); + Texture::unbind(); + TexEnv::unbind(); +} + +void Texturing::bind() const +{ + const Texturing *old = current(); + if(set_current(this)) + { + for(unsigned i=0; iattachments.size(); ++i) + unbind_attachment(i); + } + } +} + +void Texturing::unbind() +{ + const Texturing *old = current(); + if(set_current(0)) + { + for(unsigned i=old->attachments.size(); i--;) + unbind_attachment(i); + } +} + + +Texturing::Attachment::Attachment(): + tex(0), + env(0) +{ } + +} // namespace GL +} // namespace Msp; diff --git a/source/texturing.h b/source/texturing.h new file mode 100644 index 00000000..c51782bb --- /dev/null +++ b/source/texturing.h @@ -0,0 +1,54 @@ +/* $Id$ + +This file is part of libmspgl +Copyright © 2010 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ + +#ifndef MSP_GL_TEXTURING_H_ +#define MSP_GL_TEXTURING_H_ + +#include +#include "bindable.h" + +namespace Msp { +namespace GL { + +class TexEnv; +class Texture; + +class Texturing: public Bindable +{ +private: + struct Attachment + { + const Texture *tex; + const TexEnv *env; + + Attachment(); + }; + + std::vector attachments; + +public: + ~Texturing(); + + void attach(unsigned, const Texture &); + void attach(unsigned, const Texture &, const TexEnv &); + void detach(unsigned); +private: + void set_attachment(unsigned, const Texture *, const TexEnv *); + void bind_attachment(unsigned) const; + + static void unbind_attachment(unsigned); + +public: + void bind() const; + + static void unbind(); +}; + +} // namespace GL +} // namespace Msp; + +#endif diff --git a/source/texunit.cpp b/source/texunit.cpp index a5427965..4d5ff81a 100644 --- a/source/texunit.cpp +++ b/source/texunit.cpp @@ -41,19 +41,21 @@ unsigned TexUnit::get_n_units() { static int count = -1; if(count<0) - // XXX Should use GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS since GL 2.0 - glGetIntegerv(GL_MAX_TEXTURE_UNITS, &count); + { + if(is_version_at_least(2, 0) || is_supported("ARB_vertex_shader")) + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &count); + else if(is_version_at_least(1, 3)) + glGetIntegerv(GL_MAX_TEXTURE_UNITS, &count); + else + count = 1; + } return count; } TexUnit &TexUnit::activate(unsigned n) { - if(n>0) - { - static RequireVersion _ver(1, 3); - if(n>=get_n_units()) - throw InvalidParameterValue("Invalid texture unit number"); - } + if(n>=get_n_units()) + throw InvalidParameterValue("Invalid texture unit number"); if(units.size()<=n) units.resize(n+1); -- 2.43.0