From 6fd9b09f47ff6a07bd5ca7f9e8887db3486bfcb1 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Wed, 27 Nov 2013 23:23:33 +0200 Subject: [PATCH] Always bind textures in a specific texture unit This eliminates one level of global state, simplifying the API and offering new optimization possibilities. Since single-texturing is a common use case, the parameterless bind/unbind functions have been left in but changed to operate on unit 0. --- source/environmentmap.cpp | 2 -- source/shadowmap.cpp | 14 ++++++------- source/texenv.cpp | 20 ++++++++++-------- source/texenv.h | 8 +++++--- source/texgen.cpp | 15 ++++++++------ source/texgen.h | 9 +++++--- source/texture.cpp | 43 +++++++++++++++------------------------ source/texture.h | 6 +++--- source/texturing.cpp | 14 ++++++------- source/texunit.cpp | 17 +++++++++------- source/texunit.h | 3 ++- 11 files changed, 75 insertions(+), 76 deletions(-) diff --git a/source/environmentmap.cpp b/source/environmentmap.cpp index 8a1dfe39..be0bf410 100644 --- a/source/environmentmap.cpp +++ b/source/environmentmap.cpp @@ -87,14 +87,12 @@ void EnvironmentMap::render(Renderer &renderer, const Tag &tag) const shdata.uniform_matrix3("env_eye_matrix", env_mdata); env_tex.bind_to(4); - TexUnit::activate(0); Renderer::Push _push_rend(renderer); renderer.add_shader_data(shdata); renderer.render(renderable, tag); env_tex.unbind_from(4); - TexUnit::activate(0); } } // namespace GL diff --git a/source/shadowmap.cpp b/source/shadowmap.cpp index 91c056fe..86715fca 100644 --- a/source/shadowmap.cpp +++ b/source/shadowmap.cpp @@ -153,20 +153,18 @@ void ShadowMap::render(Renderer &renderer, const Tag &tag) const tg_s.set_plane(Vector4(matrix[0]/diam, matrix[4]/diam, matrix[8]/diam, matrix[12]/diam+0.5f)); tg_t.set_plane(Vector4(matrix[1]/diam, matrix[5]/diam, matrix[9]/diam, matrix[13]/diam+0.5f)); tg_r.set_plane(Vector4(-matrix[2]/diam, -matrix[6]/diam, -matrix[10]/diam, 0.5f-matrix[14]/diam-depth_bias/size)); - tg_s.bind_to(SCOORD); - tg_t.bind_to(TCOORD); - tg_r.bind_to(RCOORD); - TexUnit::activate(0); + tg_s.bind_to(unit, SCOORD); + tg_t.bind_to(unit, TCOORD); + tg_r.bind_to(unit, RCOORD); Renderer::Push _push_rend(renderer); renderer.add_shader_data(shdata); renderer.render(renderable, tag); Texture::unbind_from(unit); - TexGen::unbind_from(SCOORD); - TexGen::unbind_from(TCOORD); - TexGen::unbind_from(RCOORD); - TexUnit::activate(0); + TexGen::unbind_from(unit, SCOORD); + TexGen::unbind_from(unit, TCOORD); + TexGen::unbind_from(unit, RCOORD); } } // namespace GL diff --git a/source/texenv.cpp b/source/texenv.cpp index c1585391..ff77e8ce 100644 --- a/source/texenv.cpp +++ b/source/texenv.cpp @@ -11,35 +11,39 @@ TexEnv::TexEnv(): void TexEnv::set_mode(TexEnvMode m) { mode = m; - if(current()==this) + if(TexUnit::current().get_texenv()==this) glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, mode); } void TexEnv::set_color(const Color &c) { color = c; - if(current()==this) + if(TexUnit::current().get_texenv()==this) glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &color.r); } -void TexEnv::bind() const +void TexEnv::bind_to(unsigned i) const { - if(TexUnit::current().set_texenv(this)) + TexUnit &unit = TexUnit::get_unit(i); + if(unit.set_texenv(this)) { + unit.bind(); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, mode); glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &color.r); } } -const TexEnv *TexEnv::current() +const TexEnv *TexEnv::current(unsigned i) { - return TexUnit::current().get_texenv(); + return TexUnit::get_unit(i).get_texenv(); } -void TexEnv::unbind() +void TexEnv::unbind_from(unsigned i) { - if(TexUnit::current().set_texenv(0)) + TexUnit &unit = TexUnit::get_unit(i); + if(unit.set_texenv(0)) { + unit.bind(); 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); diff --git a/source/texenv.h b/source/texenv.h index 5ed05d6c..1327bb85 100644 --- a/source/texenv.h +++ b/source/texenv.h @@ -29,10 +29,12 @@ public: void set_color(const Color &); TexEnvMode get_mode() const { return mode; } const Color &get_color() const { return color; } - void bind() const; + void bind() const { bind_to(0); } + void bind_to(unsigned) const; - static const TexEnv *current(); - static void unbind(); + static const TexEnv *current(unsigned = 0); + static void unbind() { unbind_from(0); } + static void unbind_from(unsigned); }; } // namespace GL diff --git a/source/texgen.cpp b/source/texgen.cpp index e9a75d7a..eb6179d0 100644 --- a/source/texgen.cpp +++ b/source/texgen.cpp @@ -22,10 +22,12 @@ void TexGen::set_plane(const Vector4 &p) plane = p; } -void TexGen::bind_to(TexCoordComponent c) const +void TexGen::bind_to(unsigned i, TexCoordComponent c) const { - if(TexUnit::current().set_texgen(coord_index(c), this)) + TexUnit &unit = TexUnit::get_unit(i); + if(unit.set_texgen(coord_index(c), this)) { + unit.bind(); glTexGeni(c, GL_TEXTURE_GEN_MODE, mode); if(mode==EYE_LINEAR) glTexGenfv(c, GL_EYE_PLANE, &plane.x); @@ -35,14 +37,15 @@ void TexGen::bind_to(TexCoordComponent c) const } } -const TexGen *TexGen::current(TexCoordComponent c) +const TexGen *TexGen::current(unsigned i, TexCoordComponent c) { - return TexUnit::current().get_texgen(coord_index(c)); + return TexUnit::get_unit(i).get_texgen(coord_index(c)); } -void TexGen::unbind_from(TexCoordComponent c) +void TexGen::unbind_from(unsigned i, TexCoordComponent c) { - if(TexUnit::current().set_texgen(coord_index(c), 0)) + TexUnit &unit = TexUnit::get_unit(i); + if(unit.set_texgen(coord_index(c), 0)) disable(GL_TEXTURE_GEN_S+coord_index(c)); } diff --git a/source/texgen.h b/source/texgen.h index bb076c62..c69df638 100644 --- a/source/texgen.h +++ b/source/texgen.h @@ -35,10 +35,13 @@ public: void set_mode(TexGenMode); void set_plane(const Vector4 &); - void bind_to(TexCoordComponent) const; + void bind_to(TexCoordComponent c) const { bind_to(0, c); } + void bind_to(unsigned, TexCoordComponent) const; - static const TexGen *current(TexCoordComponent); - static void unbind_from(TexCoordComponent); + static const TexGen *current(TexCoordComponent c) { return current(0, c); } + static const TexGen *current(unsigned, TexCoordComponent); + static void unbind_from(TexCoordComponent c) { unbind_from(0, c); } + static void unbind_from(unsigned, TexCoordComponent); private: static unsigned coord_index(TexCoordComponent); }; diff --git a/source/texture.cpp b/source/texture.cpp index aeea2818..f6b5f8e4 100644 --- a/source/texture.cpp +++ b/source/texture.cpp @@ -64,7 +64,7 @@ Texture::~Texture() void Texture::update_parameter(int mask) const { - if(current()==this) + if(TexUnit::current().get_texture()==this) { if(mask&MIN_FILTER) glTexParameteri(target, GL_TEXTURE_MIN_FILTER, min_filter); @@ -162,18 +162,18 @@ void Texture::set_compare_func(Predicate f) update_parameter(COMPARE_FUNC); } -void Texture::bind() const +void Texture::bind_to(unsigned i) const { - const Texture *cur = TexUnit::current().get_texture(); - if(cur!=this) + TexUnit &unit = TexUnit::get_unit(i); + const Texture *cur = unit.get_texture(); + if(unit.set_texture(this)) { + unit.bind(); if(cur && cur->target!=target) glDisable(cur->target); if(!cur || cur->target!=target) glEnable(target); - glBindTexture(target, id); - TexUnit::current().set_texture(this); if(dirty_params) { @@ -183,32 +183,21 @@ void Texture::bind() const } } -void Texture::bind_to(unsigned i) const -{ - TexUnit::activate(i); - bind(); -} - -const Texture *Texture::current() +const Texture *Texture::current(unsigned i) { - return TexUnit::current().get_texture(); -} - -void Texture::unbind() -{ - const Texture *cur = TexUnit::current().get_texture(); - if(!cur) - return; - - glBindTexture(cur->target, 0); - glDisable(cur->target); - TexUnit::current().set_texture(0); + return TexUnit::get_unit(i).get_texture(); } void Texture::unbind_from(unsigned i) { - TexUnit::activate(i); - unbind(); + TexUnit &unit = TexUnit::get_unit(i); + const Texture *cur = unit.get_texture(); + if(unit.set_texture(0)) + { + unit.bind(); + glBindTexture(cur->target, 0); + glDisable(cur->target); + } } diff --git a/source/texture.h b/source/texture.h index 6b8117fe..c091c884 100644 --- a/source/texture.h +++ b/source/texture.h @@ -149,11 +149,11 @@ public: GLenum get_target() const { return target; } unsigned get_id() const { return id; } - void bind() const; + void bind() const { bind_to(0); } void bind_to(unsigned) const; - static const Texture *current(); - static void unbind(); + static const Texture *current(unsigned = 0); + static void unbind() { unbind_from(0); } static void unbind_from(unsigned); }; diff --git a/source/texturing.cpp b/source/texturing.cpp index 880f3f07..1c8410c5 100644 --- a/source/texturing.cpp +++ b/source/texturing.cpp @@ -47,22 +47,20 @@ void Texturing::set_attachment(unsigned attch, const Texture *tex, const TexEnv void Texturing::bind_attachment(unsigned i) const { const Attachment &attch = attachments[i]; - TexUnit::activate(i); if(attch.tex) - attch.tex->bind(); + attch.tex->bind_to(i); else - Texture::unbind(); + Texture::unbind_from(i); if(attch.env) - attch.env->bind(); + attch.env->bind_to(i); else - TexEnv::unbind(); + TexEnv::unbind_from(i); } void Texturing::unbind_attachment(unsigned i) { - TexUnit::activate(i); - Texture::unbind(); - TexEnv::unbind(); + Texture::unbind_from(i); + TexEnv::unbind_from(i); } void Texturing::bind() const diff --git a/source/texunit.cpp b/source/texunit.cpp index 2b3418fe..982e524e 100644 --- a/source/texunit.cpp +++ b/source/texunit.cpp @@ -49,6 +49,13 @@ const TexGen *TexUnit::get_texgen(unsigned i) return texgen[i]; } +void TexUnit::bind() +{ + if(cur_unit!=this && (cur_unit || index)) + glActiveTexture(GL_TEXTURE0+index); + cur_unit = this; +} + unsigned TexUnit::get_n_units() { static int count = -1; @@ -64,12 +71,12 @@ unsigned TexUnit::get_n_units() return count; } -TexUnit &TexUnit::activate(unsigned n) +TexUnit &TexUnit::get_unit(unsigned n) { if(n>0) static Require _req(ARB_multitexture); if(n>=get_n_units()) - throw out_of_range("TexUnit::activate"); + throw out_of_range("TexUnit::get_unit"); if(units.size()<=n) { @@ -79,17 +86,13 @@ TexUnit &TexUnit::activate(unsigned n) units[i].index = i; } - if(cur_unit!=&units[n] && (cur_unit || n)) - glActiveTexture(GL_TEXTURE0+n); - cur_unit = &units[n]; - return units[n]; } TexUnit &TexUnit::current() { if(!cur_unit) - return activate(0); + get_unit(0).bind(); return *cur_unit; } diff --git a/source/texunit.h b/source/texunit.h index 93f6dd08..8bcb5f02 100644 --- a/source/texunit.h +++ b/source/texunit.h @@ -31,9 +31,10 @@ public: const TexEnv *get_texenv() const { return texenv; } bool set_texgen(unsigned, const TexGen *); const TexGen *get_texgen(unsigned); + void bind(); static unsigned get_n_units(); - static TexUnit &activate(unsigned); + static TexUnit &get_unit(unsigned); static TexUnit ¤t(); }; -- 2.45.2