]> git.tdb.fi Git - libs/gl.git/commitdiff
Get rid of the generic Texture::parameter method
authorMikko Rasa <tdb@tdb.fi>
Sun, 4 Jul 2010 11:28:36 +0000 (11:28 +0000)
committerMikko Rasa <tdb@tdb.fi>
Sun, 4 Jul 2010 11:28:36 +0000 (11:28 +0000)
Add distinct methods for setting texture attributes
Don't bind textures for setting attributes, cache the changes instead
Restore previous binding after uploading texture images
Some improvements for choosing texture unit

source/bloom.cpp
source/shadowmap.cpp
source/texture.cpp
source/texture.h
source/texture2d.cpp
source/texture3d.cpp
source/texunit.cpp
source/texunit.h

index 5f2adc85c2bf592a8379d58ee9d3efc228fe055a..3993c8c901b9a01c66e621af65d6bcefc5ebc1f7 100644 (file)
@@ -75,9 +75,9 @@ Bloom::Bloom(unsigned w, unsigned h):
        for(unsigned i=0; i<2; ++i)
        {
                blur_shdata[i].uniform(loc, 0);
+               tex[i].set_min_filter(NEAREST);
                tex[i].storage(RGB16F, w, h, 0);
                tex[i].image(0, RGB, UNSIGNED_BYTE, 0);
-               tex[i].set_min_filter(NEAREST);
        }
 
        combine_shdata.uniform(combine_shader.get_uniform_location("source"), 1);
@@ -153,9 +153,8 @@ void Bloom::render(const Texture2D &src)
        src.bind_to(1);
        quad.draw();
        Program::unbind();
-       Texture::unbind();
-       TexUnit::activate(0);
-       Texture::unbind();
+       Texture::unbind_from(1);
+       Texture::unbind_from(0);
        // XXX Should check if the modes were enabled in the first place
        enable(DEPTH_TEST);
        enable(BLEND);
index 7a761e7ad2bf15c6e35a5576f645f2980ab441c7..25b0d6d66f4345246f120b2087c9766fd71143d3 100644 (file)
@@ -28,17 +28,14 @@ ShadowMap::ShadowMap(unsigned s, const Scene &c, const Light &l):
        radius(1)
 {
        depth_buf.set_min_filter(LINEAR);
+       depth_buf.set_compare_enabled(true);
+       depth_buf.set_compare_func(LEQUAL);
+       depth_buf.set_wrap(CLAMP_TO_EDGE);
        depth_buf.storage(DEPTH_COMPONENT, size, size, 0);
        depth_buf.image(0, DEPTH_COMPONENT, UNSIGNED_BYTE, 0);
-       depth_buf.parameter(GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE);
-       depth_buf.parameter(GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
-       depth_buf.parameter(GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
-       depth_buf.parameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-       depth_buf.parameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        fbo.attach(DEPTH_ATTACHMENT, depth_buf, 0);
        draw_buffer(NO_BUFFER);
        Framebuffer::unbind();
-       Texture::unbind();
 }
 
 void ShadowMap::set_target(const Vector3 &t, float r)
@@ -146,8 +143,7 @@ void ShadowMap::prepare()
 
 void ShadowMap::cleanup()
 {
-       TexUnit::activate(unit);
-       Texture::unbind();
+       Texture::unbind_from(unit);
        disable(GL_TEXTURE_GEN_S);
        disable(GL_TEXTURE_GEN_T);
        disable(GL_TEXTURE_GEN_R);
index 40f18d45eff1f0c8d10d2363d8ea2a6123bbc650..eca0334795ad838c109bad4ed0aa06cf3e06577e 100644 (file)
@@ -38,10 +38,110 @@ istream &operator>>(istream &in, TextureFilter &tf)
 }
 
 
+Texture::Texture(GLenum t):
+       target(t),
+       min_filter(NEAREST_MIPMAP_LINEAR),
+       mag_filter(LINEAR),
+       wrap_s(REPEAT),
+       wrap_t(REPEAT),
+       wrap_r(REPEAT),
+       gen_mipmap(false),
+       compare(false),
+       cmp_func(LEQUAL),
+       dirty_params(0)
+{
+       glGenTextures(1, &id);
+}
+
+Texture::~Texture()
+{
+       glDeleteTextures(1, &id);
+}
+
+void Texture::update_parameter(int mask) const
+{
+       if(TexUnit::current().get_texture()==this)
+       {
+               if(mask&MIN_FILTER)
+                       glTexParameteri(target, GL_TEXTURE_MIN_FILTER, min_filter);
+               if(mask&MAG_FILTER)
+                       glTexParameteri(target, GL_TEXTURE_MAG_FILTER, mag_filter);
+               if(mask&WRAP_S)
+                       glTexParameteri(target, GL_TEXTURE_WRAP_S, wrap_s);
+               if(mask&WRAP_T)
+                       glTexParameteri(target, GL_TEXTURE_WRAP_T, wrap_t);
+               if(mask&WRAP_R)
+                       glTexParameteri(target, GL_TEXTURE_WRAP_R, wrap_r);
+               if(mask&GENERATE_MIPMAP)
+                       glTexParameteri(target, GL_GENERATE_MIPMAP_SGIS, gen_mipmap);
+               if(mask&COMPARE)
+                       glTexParameteri(target, GL_TEXTURE_COMPARE_MODE, (compare ? GL_COMPARE_R_TO_TEXTURE : GL_NONE));
+               if(mask&cmp_func)
+                       glTexParameteri(target, GL_TEXTURE_COMPARE_FUNC, cmp_func);
+       }
+       else
+               dirty_params |= mask;
+}
+
+void Texture::set_min_filter(TextureFilter f)
+{
+       min_filter = f;
+       update_parameter(MIN_FILTER);
+}
+
+void Texture::set_mag_filter(TextureFilter f)
+{
+       mag_filter = f;
+       update_parameter(MAG_FILTER);
+}
+
+void Texture::set_wrap(TextureWrap w)
+{
+       set_wrap_s(w);
+       set_wrap_t(w);
+       set_wrap_r(w);
+}
+
+void Texture::set_wrap_s(TextureWrap w)
+{
+       wrap_s = w;
+       update_parameter(WRAP_S);
+}
+
+void Texture::set_wrap_t(TextureWrap w)
+{
+       wrap_t = w;
+       update_parameter(WRAP_T);
+}
+
+void Texture::set_wrap_r(TextureWrap w)
+{
+       wrap_r = w;
+       update_parameter(WRAP_R);
+}
+
+void Texture::set_generate_mipmap(bool gm)
+{
+       gen_mipmap = gm;
+       update_parameter(GENERATE_MIPMAP);
+}
+
+void Texture::set_compare_enabled(bool c)
+{
+       compare = c;
+       update_parameter(COMPARE);
+}
+
+void Texture::set_compare_func(Predicate f)
+{
+       cmp_func = f;
+       update_parameter(COMPARE_FUNC);
+}
+
 void Texture::bind() const
 {
        if(!target)
-               throw InvalidState("Attempt to bind a texture without target");
+               throw InvalidState("Attempt to bind a texture without target (should never happen)");
 
        const Texture *cur = TexUnit::current().get_texture();
        if(cur!=this)
@@ -50,8 +150,15 @@ void Texture::bind() const
                        glDisable(cur->target);
                if(!cur || cur->target!=target)
                        glEnable(target);
+
                glBindTexture(target, id);
                TexUnit::current().set_texture(this);
+
+               if(dirty_params)
+               {
+                       update_parameter(dirty_params);
+                       dirty_params = 0;
+               }
        }
 }
 
@@ -61,23 +168,9 @@ void Texture::bind_to(unsigned i) const
        bind();
 }
 
-void Texture::parameter(GLenum param, int value)
-{
-       maybe_bind();
-
-       glTexParameteri(target, param, value);
-}
-
-void Texture::parameter(GLenum param, float value)
-{
-       maybe_bind();
-
-       glTexParameterf(target, param, value);
-}
-
-Texture::~Texture()
+const Texture *Texture::current()
 {
-       glDeleteTextures(1, &id);
+       return TexUnit::current().get_texture();
 }
 
 void Texture::unbind()
@@ -97,18 +190,6 @@ void Texture::unbind_from(unsigned i)
        unbind();
 }
 
-Texture::Texture():
-       target(0)
-{
-       glGenTextures(1, &id);
-}
-
-void Texture::maybe_bind() const
-{
-       if(TexUnit::current().get_texture()!=this)
-               bind();
-}
-
 
 Texture::Loader::Loader(Texture &t):
        DataFile::ObjectLoader<Texture>(t)
@@ -130,7 +211,7 @@ void Texture::Loader::mag_filter(TextureFilter f)
 
 void Texture::Loader::generate_mipmap(bool gm)
 {
-       obj.parameter(GL_GENERATE_MIPMAP_SGIS, gm);
+       obj.set_generate_mipmap(gm);
 }
 
 } // namespace GL
index 848517eb45c99da20a67c8261ed81488b7902ea3..35f70ad693e51f7e567639dd89ae28ce5b4bd160 100644 (file)
@@ -11,6 +11,7 @@ Distributed under the LGPL
 #include <istream>
 #include <msp/datafile/objectloader.h>
 #include "gl.h"
+#include "predicate.h"
 
 namespace Msp {
 namespace GL {
@@ -28,6 +29,15 @@ enum TextureFilter
 std::istream &operator>>(std::istream &, TextureFilter &);
 
 
+enum TextureWrap
+{
+       REPEAT          = GL_REPEAT,
+       CLAMP_TO_EDGE   = GL_CLAMP_TO_EDGE,
+       CLAMP_TO_BORDER = GL_CLAMP_TO_BORDER,
+       MIRRORED_REPEAT = GL_MIRRORED_REPEAT
+};
+
+
 /**
 Base class for textures.  This class only defines operations common for all
 texture types and is not instantiable.  For specifying images for textures, see
@@ -45,28 +55,57 @@ protected:
                void generate_mipmap(bool);
        };
 
+       enum ParameterMask
+       {
+               MIN_FILTER = 1,
+               MAG_FILTER = 2,
+               WRAP_S = 4,
+               WRAP_T = 8,
+               WRAP_R = 16,
+               GENERATE_MIPMAP = 32,
+               COMPARE = 64,
+               COMPARE_FUNC = 128
+       };
+
+       unsigned id;
+       GLenum target;
+       TextureFilter min_filter;
+       TextureFilter mag_filter;
+       TextureWrap wrap_s;
+       TextureWrap wrap_t;
+       TextureWrap wrap_r;
+       bool gen_mipmap;
+       bool compare;
+       Predicate cmp_func;
+       mutable int dirty_params;
+
+       Texture(GLenum);
+       Texture(const Texture &);
+       Texture &operator=(const Texture &);
 public:
        ~Texture();
 
+protected:
+       void update_parameter(int) const;
+public:
+       void set_min_filter(TextureFilter);
+       void set_mag_filter(TextureFilter);
+       void set_wrap(TextureWrap);
+       void set_wrap_s(TextureWrap);
+       void set_wrap_t(TextureWrap);
+       void set_wrap_r(TextureWrap);
+       void set_generate_mipmap(bool);
+       void set_compare_enabled(bool);
+       void set_compare_func(Predicate);
+       GLenum get_target() const { return target; }
+       unsigned get_id() const { return id; }
+
        void bind() const;
        void bind_to(unsigned) const;
-       void parameter(GLenum, int);
-       void parameter(GLenum, float);
-       void set_min_filter(TextureFilter f) { parameter(GL_TEXTURE_MIN_FILTER, f); }
-       void set_mag_filter(TextureFilter f) { parameter(GL_TEXTURE_MAG_FILTER, f); }
-       GLenum get_target() const            { return target; }
-       unsigned  get_id() const                 { return id; }
 
+       static const Texture *current();
        static void unbind();
        static void unbind_from(unsigned);
-protected:
-       unsigned   id;
-       GLenum target;
-
-       Texture();
-       Texture(const Texture &);
-       Texture &operator=(const Texture &);
-       void maybe_bind() const;
 };
 
 } // namespace GL
index 197e04df63830269f92a04ed4279636319ef4344..8935933f995117322069ad1652b6b1d9ffc87d0c 100644 (file)
@@ -5,6 +5,7 @@ Copyright © 2007  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
+#include "bindable.h"
 #include "except.h"
 #include "texture2d.h"
 
@@ -14,12 +15,10 @@ namespace Msp {
 namespace GL {
 
 Texture2D::Texture2D():
+       Texture(GL_TEXTURE_2D),
        width(0),
        height(0)
-{
-       target = GL_TEXTURE_2D;
-       bind();
-}
+{ }
 
 void Texture2D::storage(PixelFormat fmt, unsigned wd, unsigned ht, int brd)
 {
@@ -39,8 +38,7 @@ void Texture2D::image(int level, PixelFormat fmt, DataType type, const void *dat
        if(width==0)
                throw InvalidState("Texture storage has not been specified");
 
-       maybe_bind();
-
+       Bind _bind(this, true);
        glTexImage2D(target, level, ifmt, width, height, border, fmt, type, data);
 }
 
@@ -49,8 +47,7 @@ void Texture2D::sub_image(int level, int x, int y, unsigned wd, unsigned ht, Pix
        if(width==0)
                throw InvalidState("Texture storage has not been specified");
 
-       maybe_bind();
-
+       Bind _bind(this, true);
        glTexSubImage2D(target, level, x, y, wd, ht, fmt, type, data);
 }
 
index 183bede5acf5d32389e8942fb9ceeb0c3c55153e..7edc908098c73ed0866ff6d9733874f4efa7993d 100644 (file)
@@ -7,6 +7,7 @@ Distributed under the LGPL
 
 #include <cmath>
 #include <msp/gbase/image.h>
+#include "bindable.h"
 #include "except.h"
 #include "extension.h"
 #include "texture3d.h"
@@ -18,20 +19,18 @@ namespace Msp {
 namespace GL {
 
 Texture3D::Texture3D():
+       Texture(GL_TEXTURE_3D),
        width(0),
        height(0),
        depth(0)
 {
-       static RequireVersion _ver(1, 3);
-
-       target = GL_TEXTURE_3D;
-       bind();
+       static RequireVersion _ver(1, 2);
 }
 
 void Texture3D::storage(PixelFormat f, unsigned w, unsigned h, unsigned d, int b)
 {
        if(width>0)
-               throw InvalidState("Textures may only be created once");
+               throw InvalidState("Textures storage may only be specified once");
        if(w==0 || h==0 || d==0)
                throw InvalidParameterValue("Invalid texture dimensions");
 
@@ -46,7 +45,10 @@ void Texture3D::storage(PixelFormat f, unsigned w, unsigned h, unsigned d, int b
 
 void Texture3D::image(int level, PixelFormat fmt, DataType type, const void *data)
 {
-       maybe_bind();
+       if(width==0)
+               throw InvalidState("Texture storage has not been specified");
+
+       Bind _bind(this, true);
        glTexImage3D(target, level, ifmt, width, height, depth, border, fmt, type, data);
 }
 
index 1155fa96286be0ab199280e61ea909115545df30..a542796548f0ae120bc9037b81bf0e2e3071c0fd 100644 (file)
@@ -15,10 +15,13 @@ using namespace std;
 namespace Msp {
 namespace GL {
 
+vector<TexUnit> TexUnit::units;
+TexUnit *TexUnit::cur_unit = 0;
+
 TexUnit::TexUnit():
-       texture(0)
-{
-}
+       texture(0),
+       texenv(0)
+}
 
 bool TexUnit::set_texture(const Texture *tex)
 {
@@ -34,16 +37,29 @@ bool TexUnit::set_texenv(const TexEnv *env)
        return result;
 }
 
+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);
+       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(units.size()<=n)
                units.resize(n+1);
 
        if(cur_unit!=&units[n] && (cur_unit || n))
-       {
-               static RequireVersion _ver(1, 3);
                glActiveTexture(GL_TEXTURE0+n);
-       }
        cur_unit = &units[n];
 
        return units[n];
@@ -56,8 +72,5 @@ TexUnit &TexUnit::current()
        return *cur_unit;
 }
 
-vector<TexUnit> TexUnit::units;
-TexUnit *TexUnit::cur_unit = 0;
-
 } // namespace GL
 } // namespace Msp
index 1b616505ac5d2ea3d6f90cfc54ea5ee9cf6c4ded..1a4111e6e52569b53bbb003d452aed90c333a2a9 100644 (file)
@@ -18,21 +18,24 @@ class Texture;
 
 class TexUnit
 {
+private:
+       const Texture *texture;
+       const TexEnv *texenv;
+
+       static std::vector<TexUnit> units;
+       static TexUnit *cur_unit;
+
 public:
        TexUnit();
+
        bool set_texture(const Texture *);
        const Texture *get_texture() const { return texture; }
        bool set_texenv(const TexEnv *);
        const TexEnv *get_texenv() const { return texenv; }
 
+       static unsigned get_n_units();
        static TexUnit &activate(unsigned);
        static TexUnit &current();
-private:
-       const Texture *texture;
-       const TexEnv *texenv;
-
-       static std::vector<TexUnit> units;
-       static TexUnit *cur_unit;
 };
 
 } // namespace GL