]> git.tdb.fi Git - libs/gl.git/commitdiff
Better state tracking for bound objects
authorMikko Rasa <tdb@tdb.fi>
Thu, 28 Nov 2013 12:14:56 +0000 (14:14 +0200)
committerMikko Rasa <tdb@tdb.fi>
Thu, 28 Nov 2013 12:14:56 +0000 (14:14 +0200)
14 files changed:
source/light.cpp
source/light.h
source/lighting.cpp
source/lightunit.cpp
source/lightunit.h
source/material.cpp
source/material.h
source/pixelstore.cpp
source/pixelstore.h
source/texenv.cpp
source/texenv.h
source/texture.cpp
source/texunit.cpp
source/texunit.h

index f9b45c87bfeac3bf5712dec6001fe29f7419d1f6..d4b45aaf82cc66371c4a73f11174eaf7356af611 100644 (file)
@@ -21,34 +21,72 @@ Light::Light():
        attenuation[2] = 0;
 }
 
+void Light::update_parameter(int mask, int index) const
+{
+       if(index<0)
+       {
+               LightUnit *unit = LightUnit::find_unit(this);
+               if(!unit)
+                       return;
+
+               index = unit->get_index();
+       }
+
+       GLenum l = GL_LIGHT0+index;
+       if(mask&DIFFUSE)
+               glLightfv(l, GL_DIFFUSE, &diffuse.r);
+       if(mask&SPECULAR)
+               glLightfv(l, GL_SPECULAR, &specular.r);
+       if(mask&POSITION)
+               glLightfv(l, GL_POSITION, &position.x);
+       if(mask&SPOT_DIR)
+               glLightfv(l, GL_SPOT_DIRECTION, &spot_dir.x);
+       if(mask&SPOT_EXP)
+               glLightf(l, GL_SPOT_EXPONENT, spot_exp);
+       if(mask&SPOT_CUTOFF)
+               glLightf(l, GL_SPOT_CUTOFF, spot_cutoff);
+       if(mask&ATTENUATION)
+       {
+               glLightf(l, GL_CONSTANT_ATTENUATION, attenuation[0]);
+               glLightf(l, GL_LINEAR_ATTENUATION, attenuation[1]);
+               glLightf(l, GL_QUADRATIC_ATTENUATION, attenuation[2]);
+       }
+}
+
 void Light::set_diffuse(const Color &c)
 {
        diffuse = c;
+       update_parameter(DIFFUSE);
 }
 
 void Light::set_specular(const Color &c)
 {
        specular = c;
+       update_parameter(SPECULAR);
 }
 
 void Light::set_position(const Vector4 &p)
 {
        position = p;
+       update_parameter(POSITION);
 }
 
 void Light::set_spot_direction(const Vector3 &d)
 {
        spot_dir = d;
+       update_parameter(SPOT_DIR);
 }
 
 void Light::set_spot_exponent(float e)
 {
        spot_exp = e;
+       update_parameter(SPOT_EXP);
 }
 
 void Light::set_spot_cutoff(float c)
 {
        spot_cutoff = c;
+       update_parameter(SPOT_CUTOFF);
 }
 
 void Light::set_attenuation(float c, float l, float q)
@@ -56,6 +94,7 @@ void Light::set_attenuation(float c, float l, float q)
        attenuation[0] = c;
        attenuation[1] = l;
        attenuation[2] = q;
+       update_parameter(ATTENUATION);
 }
 
 void Light::bind_to(unsigned i) const
@@ -63,17 +102,8 @@ void Light::bind_to(unsigned i) const
        LightUnit &unit = LightUnit::get_unit(i);
        if(unit.set_light(this))
        {
-               GLenum l = GL_LIGHT0+unit.get_index();
-               enable(l);
-               glLightfv(l, GL_DIFFUSE, &diffuse.r);
-               glLightfv(l, GL_SPECULAR, &specular.r);
-               glLightfv(l, GL_POSITION, &position.x);
-               glLightfv(l, GL_SPOT_DIRECTION, &spot_dir.x);
-               glLightf(l, GL_SPOT_EXPONENT, spot_exp);
-               glLightf(l, GL_SPOT_CUTOFF, spot_cutoff);
-               glLightf(l, GL_CONSTANT_ATTENUATION, attenuation[0]);
-               glLightf(l, GL_LINEAR_ATTENUATION, attenuation[1]);
-               glLightf(l, GL_QUADRATIC_ATTENUATION, attenuation[2]);
+               enable(GL_LIGHT0+unit.get_index());
+               update_parameter(-1, unit.get_index());
        }
 }
 
index cf9ab8a1acb69cdbec2cdfead4ad2580e66f40e7..1c6a52272f56db8597103093c99a3050602fa7b3 100644 (file)
@@ -11,6 +11,17 @@ namespace GL {
 class Light
 {
 private:
+       enum ParameterMask
+       {
+               DIFFUSE = 1,
+               SPECULAR = 2,
+               POSITION = 4,
+               SPOT_DIR = 8,
+               SPOT_EXP = 16,
+               SPOT_CUTOFF = 32,
+               ATTENUATION = 64
+       };
+
        Color diffuse;
        Color specular;
        Vector4 position;
@@ -22,6 +33,10 @@ private:
 public:
        Light();
 
+private:
+       void update_parameter(int, int = -1) const;
+
+public:
        void set_diffuse(const Color &c);
        void set_specular(const Color &c);
        const Color &get_diffuse() const { return diffuse; }
index 0af2416c14729788d411e747b91e8bcedfa0303c..aae5d331384919e0af9f8523523eda56a5273bab 100644 (file)
@@ -20,6 +20,8 @@ void Lighting::attach(unsigned i, const Light &l)
                lights.resize(i+1);
 
        lights[i] = &l;
+       if(current()==this)
+               l.bind_to(i);
 }
 
 void Lighting::detach(unsigned i)
@@ -28,6 +30,8 @@ void Lighting::detach(unsigned i)
                return;
 
        lights[i] = 0;
+       if(current()==this)
+               Light::unbind_from(i);
 }
 
 void Lighting::bind() const
index 58d42e6d730f893d3370532e2b84e993dc89221e..d33c9b25a12ef5cc50e8c53b0e2875981d3568ff 100644 (file)
@@ -44,5 +44,13 @@ LightUnit &LightUnit::get_unit(unsigned n)
        return units[n];
 }
 
+LightUnit *LightUnit::find_unit(const Light *l)
+{
+       for(vector<LightUnit>::iterator i=units.begin(); i!=units.end(); ++i)
+               if(i->light==l)
+                       return &*i;
+       return 0;
+}
+
 } // namespace GL
 } // namespace Msp
index 3f65d770704944134af68f5d9ee178ba0a35b947..658712df1bd092b62c3ab2498cdfc6f2c71c2882 100644 (file)
@@ -26,6 +26,7 @@ public:
 
        static unsigned get_n_units();
        static LightUnit &get_unit(unsigned i);
+       static LightUnit *find_unit(const Light *);
 };
 
 } // namespace GL
index 12d15010e579a39af819fdb557f8669d2eadd1dc..d6e21683d2a7f3b8fb08498b269419d386d7d9d7 100644 (file)
@@ -12,41 +12,57 @@ Material::Material():
        shininess(0)
 { }
 
+void Material::update_parameter(int mask) const
+{
+       if(cur_obj!=this)
+               return;
+
+       if(mask&AMBIENT)
+               glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, &ambient.r);
+       if(mask&DIFFUSE)
+               glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, &diffuse.r);
+       if(mask&SPECULAR)
+               glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &specular.r);
+       if(mask&EMISSION)
+               glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, &emission.r);
+       if(mask&SHININESS)
+               glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess);
+}
+
 void Material::set_ambient(const Color &a)
 {
        ambient = a;
+       update_parameter(AMBIENT);
 }
 
 void Material::set_diffuse(const Color &d)
 {
        diffuse = d;
+       update_parameter(DIFFUSE);
 }
 
 void Material::set_specular(const Color &s)
 {
        specular = s;
+       update_parameter(SPECULAR);
 }
 
 void Material::set_emission(const Color &e)
 {
        emission = e;
+       update_parameter(EMISSION);
 }
 
 void Material::set_shininess(float s)
 {
        shininess = s;
+       update_parameter(SHININESS);
 }
 
 void Material::bind() const
 {
        if(set_current(this))
-       {
-               glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, &ambient.r);
-               glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, &diffuse.r);
-               glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &specular.r);
-               glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, &emission.r);
-               glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess);
-       }
+               update_parameter(-1);
 }
 
 
index 3a65f339344787512f59597c1483a3596ec4376c..a787a6d3b7078ee60f706debaf2d62b903c4989f 100644 (file)
@@ -28,6 +28,15 @@ public:
        };
 
 private:
+       enum ParameterMask
+       {
+               AMBIENT = 1,
+               DIFFUSE = 2,
+               SPECULAR = 4,
+               EMISSION = 8,
+               SHININESS = 16
+       };
+
        Color ambient;
        Color diffuse;
        Color specular;
@@ -36,6 +45,11 @@ private:
 
 public:
        Material();
+
+private:
+       void update_parameter(int) const;
+
+public:
        void set_ambient(const Color &a);
        void set_diffuse(const Color &d);
        void set_specular(const Color &s);
index c32cf60964a30b43cf7946782fa2c5943231e710..011866e3e72410a44031a0b154367c621bebb44f 100644 (file)
@@ -27,10 +27,31 @@ PixelStore PixelStore::from_image(const Graphics::Image &img)
        return pstore;
 }
 
+void PixelStore::update_parameter(int mask) const
+{
+       if(cur_obj!=this)
+               return;
+
+       if(mask&SIZE)
+       {
+               glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length);
+               glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, image_height);
+       }
+       if(mask&ORIGIN)
+       {
+               glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels);
+               glPixelStorei(GL_UNPACK_SKIP_ROWS, skip_rows);
+               glPixelStorei(GL_UNPACK_SKIP_IMAGES, skip_images);
+       }
+       if(mask&ALIGNMENT)
+               glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
+}
+
 void PixelStore::set_canvas_size(unsigned w, unsigned h)
 {
        row_length = w;
        image_height = h;
+       update_parameter(SIZE);
 }
 
 void PixelStore::set_origin(unsigned x, unsigned y, unsigned z)
@@ -38,24 +59,19 @@ void PixelStore::set_origin(unsigned x, unsigned y, unsigned z)
        skip_pixels = x;
        skip_rows = y;
        skip_images = z;
+       update_parameter(ORIGIN);
 }
 
 void PixelStore::set_alignment(unsigned a)
 {
        alignment = a;
+       update_parameter(ALIGNMENT);
 }
 
 void PixelStore::bind() const
 {
        if(set_current(this))
-       {
-               glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length);
-               glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, image_height);
-               glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels);
-               glPixelStorei(GL_UNPACK_SKIP_ROWS, skip_rows);
-               glPixelStorei(GL_UNPACK_SKIP_IMAGES, skip_images);
-               glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
-       }
+               update_parameter(-1);
 }
 
 } // namespace GL
index 0c430300d9be0b5bb9c89c6bdb65c2629b741fce..5229556709b5119bb5157bc70ff3646d80309df3 100644 (file)
@@ -10,6 +10,13 @@ namespace GL {
 class PixelStore: public BindableWithDefault<PixelStore>
 {
 private:
+       enum ParameterMask
+       {
+               SIZE,
+               ORIGIN,
+               ALIGNMENT
+       };
+
        unsigned row_length;
        unsigned image_height;
        unsigned skip_pixels;
@@ -22,6 +29,10 @@ public:
 
        static PixelStore from_image(const Graphics::Image &);
 
+private:
+       void update_parameter(int) const;
+
+public:
        void set_canvas_size(unsigned, unsigned);
        void set_origin(unsigned, unsigned, unsigned);
        void set_alignment(unsigned);
index ff9ea197b982cdb6a092137f14c5c8f8709e2d68..51adf9fb4aee45f1aa40e93effbad084e3c3b4d4 100644 (file)
@@ -15,18 +15,33 @@ const TexEnv &TexEnv::default_object()
        return obj;
 }
 
+void TexEnv::update_parameter(int mask) const
+{
+       if(TexUnit::current().get_texenv()!=this)
+       {
+               TexUnit *unit = TexUnit::find_unit(this);
+               if(!unit)
+                       return;
+
+               unit->bind();
+       }
+
+       if(mask&MODE)
+               glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, mode);
+       if(mask&COLOR)
+               glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &color.r);
+}
+
 void TexEnv::set_mode(TexEnvMode m)
 {
        mode = m;
-       if(TexUnit::current().get_texenv()==this)
-               glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, mode);
+       update_parameter(MODE);
 }
 
 void TexEnv::set_color(const Color &c)
 {
        color = c;
-       if(TexUnit::current().get_texenv()==this)
-               glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &color.r);
+       update_parameter(COLOR);
 }
 
 void TexEnv::bind_to(unsigned i) const
@@ -35,8 +50,7 @@ void TexEnv::bind_to(unsigned i) const
        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);
+               update_parameter(-1);
        }
 }
 
index 55a12f306ed2e33850b9b73788c1a122d69052a7..61f700854b50030e43297b96310aa106622a36fb 100644 (file)
@@ -20,6 +20,12 @@ enum TexEnvMode
 class TexEnv
 {
 private:
+       enum ParameterMask
+       {
+               MODE = 1,
+               COLOR = 2
+       };
+
        TexEnvMode mode;
        Color color;
 
@@ -28,6 +34,10 @@ public:
 
        static const TexEnv &default_object();
 
+private:
+       void update_parameter(int) const;
+
+public:
        void set_mode(TexEnvMode);
        void set_color(const Color &);
        TexEnvMode get_mode() const { return mode; }
index f6b5f8e4be06f6e0706de648d9a8f30da78bff56..fe8b7be9a3e4fbb56dda02464bfb0541d8e131ce 100644 (file)
@@ -64,29 +64,36 @@ Texture::~Texture()
 
 void Texture::update_parameter(int mask) const
 {
-       if(TexUnit::current().get_texture()==this)
+       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&MAX_ANISOTROPY)
-                       glTexParameteri(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_anisotropy);
-               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&COMPARE_FUNC)
-                       glTexParameteri(target, GL_TEXTURE_COMPARE_FUNC, cmp_func);
+               TexUnit *unit = TexUnit::find_unit(this);
+               if(!unit)
+               {
+                       dirty_params |= mask;
+                       return;
+               }
+
+               unit->bind();
        }
-       else
-               dirty_params |= mask;
+
+       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&MAX_ANISOTROPY)
+               glTexParameteri(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_anisotropy);
+       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&COMPARE_FUNC)
+               glTexParameteri(target, GL_TEXTURE_COMPARE_FUNC, cmp_func);
 }
 
 void Texture::set_min_filter(TextureFilter f)
index 982e524e0189fa74a10181c9a2ff7f7014e8746e..1129a0365617816a58ee1f0ff884cbd2f1e0ef59 100644 (file)
@@ -96,5 +96,21 @@ TexUnit &TexUnit::current()
        return *cur_unit;
 }
 
+TexUnit *TexUnit::find_unit(const Texture *tex)
+{
+       for(vector<TexUnit>::iterator i=units.begin(); i!=units.end(); ++i)
+               if(i->texture==tex)
+                       return &*i;
+       return 0;
+}
+
+TexUnit *TexUnit::find_unit(const TexEnv *env)
+{
+       for(vector<TexUnit>::iterator i=units.begin(); i!=units.end(); ++i)
+               if(i->texenv==env)
+                       return &*i;
+       return 0;
+}
+
 } // namespace GL
 } // namespace Msp
index 8bcb5f023059cf9ef3ea76e61e3a2a976da5fc8d..05952a2207b57ae015be531b4995dcfd12ee1345 100644 (file)
@@ -36,6 +36,8 @@ public:
        static unsigned get_n_units();
        static TexUnit &get_unit(unsigned);
        static TexUnit &current();
+       static TexUnit *find_unit(const Texture *);
+       static TexUnit *find_unit(const TexEnv *);
 };
 
 } // namespace GL