]> git.tdb.fi Git - gldbg.git/commitdiff
More complete support for textures
authorMikko Rasa <tdb@tdb.fi>
Sat, 25 Aug 2012 16:47:11 +0000 (19:47 +0300)
committerMikko Rasa <tdb@tdb.fi>
Sat, 25 Aug 2012 17:32:04 +0000 (20:32 +0300)
Trace 1D, 3D and cube map texture images, as well as texture enable state.

flavors/gl/source/glstate.cpp
flavors/gl/source/glstate.h
flavors/gl/source/inspector.cpp
flavors/gl/source/texturestate.cpp
flavors/gl/source/texturestate.h

index 750d70315835a45395512512ce04ff2a2963cf3d..fc355c7972aceb2a9b2f7e174eefe070b7766219 100644 (file)
@@ -80,6 +80,8 @@ GlState::GlState():
 
        decoder->glGetIntegerv = glGetIntegerv;
 
+       decoder->glEnable = glEnable;
+       decoder->glDisable = glDisable;
        decoder->glEnableClientState = glEnableClientState;
        decoder->glDisableClientState = glDisableClientState;
 
@@ -197,6 +199,21 @@ void GlState::glGetIntegerv(void *user_data, GLenum pname, int *param)
 // Boolean state
 
 bool &GlState::get_boolean_state(GLenum state)
+{
+       if(state==GL_TEXTURE_1D)
+               return texunits[active_tex].binding_1d.enabled;
+       else if(state==GL_TEXTURE_2D)
+               return texunits[active_tex].binding_2d.enabled;
+       else if(state==GL_TEXTURE_3D)
+               return texunits[active_tex].binding_3d.enabled;
+       else if(state==GL_TEXTURE_CUBE_MAP)
+               return texunits[active_tex].binding_cube.enabled;
+
+       static bool dummy;
+       return dummy;
+}
+
+bool &GlState::get_boolean_client_state(GLenum state)
 {
        if(state==GL_VERTEX_ARRAY)
                return vertex_array.enabled;
@@ -211,16 +228,26 @@ bool &GlState::get_boolean_state(GLenum state)
        return dummy;
 }
 
-void GlState::glEnableClientState(void *user_data, GLenum state)
+void GlState::glEnable(void *user_data, GLenum state)
 {
        reinterpret_cast<GlState *>(user_data)->get_boolean_state(state) = true;
 }
 
-void GlState::glDisableClientState(void *user_data, GLenum state)
+void GlState::glDisable(void *user_data, GLenum state)
 {
        reinterpret_cast<GlState *>(user_data)->get_boolean_state(state) = false;
 }
 
+void GlState::glEnableClientState(void *user_data, GLenum state)
+{
+       reinterpret_cast<GlState *>(user_data)->get_boolean_client_state(state) = true;
+}
+
+void GlState::glDisableClientState(void *user_data, GLenum state)
+{
+       reinterpret_cast<GlState *>(user_data)->get_boolean_client_state(state) = false;
+}
+
 // Vertex attributes
 
 void GlState::glColor3f(void *user_data, float r, float g, float b)
@@ -499,10 +526,36 @@ void GlState::glBindTexture(void *user_data, GLenum target, unsigned id)
        reinterpret_cast<GlState *>(user_data)->set_current_texture(target, id);
 }
 
+void GlState::glTexImage1D(void *user_data, GLenum target, int level, int ifmt, int width, int, GLenum, GLenum, const void *)
+{
+       if(TextureState *tex = reinterpret_cast<GlState *>(user_data)->get_current_texture(target))
+               tex->set_image_1d(level, ifmt, width);
+}
+
 void GlState::glTexImage2D(void *user_data, GLenum target, int level, int ifmt, int width, int height, int, GLenum, GLenum, const void *)
+{
+       GLenum face = 0;
+       for(unsigned i=0; i<6; ++i)
+               if(texture_cube_faces[i]==target)
+               {
+                       face = target;
+                       target = GL_TEXTURE_CUBE_MAP;
+                       break;
+               }
+
+       if(TextureState *tex = reinterpret_cast<GlState *>(user_data)->get_current_texture(target))
+       {
+               if(face)
+                       tex->set_face_image_2d(face, level, ifmt, width, height);
+               else
+                       tex->set_image_2d(level, ifmt, width, height);
+       }
+}
+
+void GlState::glTexImage3D(void *user_data, GLenum target, int level, int ifmt, int width, int height, int depth, int, GLenum, GLenum, const void *)
 {
        if(TextureState *tex = reinterpret_cast<GlState *>(user_data)->get_current_texture(target))
-               tex->set_image_2d(level, ifmt, width, height);
+               tex->set_image_3d(level, ifmt, width, height, depth);
 }
 
 void GlState::glTexParameteri(void *user_data, GLenum target, GLenum param, int value)
index 11191955e93383839fc837cc7ac7597f06b64128..ae16deb0399cd85fbd69ca79471b15a36f14d168 100644 (file)
@@ -76,6 +76,10 @@ public:
 
 private:
        bool &get_boolean_state(GLenum);
+       bool &get_boolean_client_state(GLenum);
+
+       static void glEnable(void *, GLenum);
+       static void glDisable(void *, GLenum);
        static void glEnableClientState(void *, GLenum);
        static void glDisableClientState(void *, GLenum);
 
@@ -136,7 +140,9 @@ private:
 
        static void glActiveTexture(void *, unsigned);
        static void glBindTexture(void *, GLenum, unsigned);
+       static void glTexImage1D(void *, GLenum, int, int, int, int, GLenum, GLenum, const void *);
        static void glTexImage2D(void *, GLenum, int, int, int, int, int, GLenum, GLenum, const void *);
+       static void glTexImage3D(void *, GLenum, int, int, int, int, int, int, GLenum, GLenum, const void *);
        static void glTexParameteri(void *, GLenum, GLenum, int);
        static void glTexParameteriv(void *, GLenum, GLenum, const int *);
        static void glDeleteTextures(void *, int, const unsigned *);
index de8031b2f22931d429c27ac1dbd45fd922050352..b6456ce7ec1afcfabf52e8b995bb2840cde1e38d 100644 (file)
@@ -150,10 +150,14 @@ void Inspector::cmd_state(const string &args)
                {
                        printf("  Texture unit %d:\n", i);
                        const TexUnitState &unit = glstate.get_texture_unit(i);
-                       string descr = unit.describe_binding(GL_TEXTURE_2D);
-                       printf("    GL_TEXTURE_2D: %s\n", descr.c_str());
+                       string descr = unit.describe_binding(GL_TEXTURE_1D);
+                       printf("    GL_TEXTURE_1D:       %s\n", descr.c_str());
+                       descr = unit.describe_binding(GL_TEXTURE_2D);
+                       printf("    GL_TEXTURE_2D:       %s\n", descr.c_str());
                        descr = unit.describe_binding(GL_TEXTURE_3D);
-                       printf("    GL_TEXTURE_3D: %s\n", descr.c_str());
+                       printf("    GL_TEXTURE_3D:       %s\n", descr.c_str());
+                       descr = unit.describe_binding(GL_TEXTURE_CUBE_MAP);
+                       printf("    GL_TEXTURE_CUBE_MAP: %s\n", descr.c_str());
                }
                printf("  Buffers:\n");
                const BufferState *buf = glstate.get_current_buffer(GL_ARRAY_BUFFER);
@@ -198,15 +202,33 @@ void Inspector::cmd_texture(const string &args)
                printf("Texture object %d\n", id);
                printf("  Target:          %s\n", describe_enum(tex.target, "TextureTarget"));
                printf("  Images:\n");
-               for(unsigned i=0; i<tex.images.size(); ++i)
+               if(tex.target==GL_TEXTURE_CUBE_MAP)
                {
-                       string descr = tex.images[i].describe();
-                       printf("    Level %2d:      %s\n", i, descr.c_str());
+                       static const char *face_labels[6] = { "+X", "-X", "+Y", "-Y", "+Z", "-Z" };
+                       for(unsigned i=0; i<6; ++i)
+                       {
+                               printf("    Face %s:\n", face_labels[i]);
+                               for(unsigned j=i; j<tex.images.size(); j+=6)
+                               {
+                                       string descr = tex.images[j].describe();
+                                       printf("      Level %2d:    %s\n", j/6, descr.c_str());
+                               }
+                       }
+               }
+               else
+               {
+                       for(unsigned i=0; i<tex.images.size(); ++i)
+                       {
+                               string descr = tex.images[i].describe();
+                               printf("    Level %2d:      %s\n", i, descr.c_str());
+                       }
                }
                printf("  Min. filter:     %s\n", describe_enum(tex.min_filter, "TextureMinFilter"));
                printf("  Mag. filter:     %s\n", describe_enum(tex.mag_filter, "TextureMagFilter"));
-               printf("  Wrap modes:      S=%s / T=%s / R=%s\n", describe_enum(tex.wrap_s, "TextureWrapMode"),
-                       describe_enum(tex.wrap_t, "TextureWrapMode"), describe_enum(tex.wrap_r, "TextureWrapMode"));
+               printf("  Wrap modes:\n");
+               printf("    S:             %s\n", describe_enum(tex.wrap_s, "TextureWrapMode"));
+               printf("    T:             %s\n", describe_enum(tex.wrap_t, "TextureWrapMode"));
+               printf("    R:             %s\n", describe_enum(tex.wrap_r, "TextureWrapMode"));
                printf("  Compare mode:    %s\n", describe_enum(tex.compare_mode, ""));
                printf("  Compare func:    %s\n", describe_enum(tex.compare_func, "DepthFunction"));
                printf("  Generate mipmap: %s\n", (tex.generate_mipmap ? "true" : "false"));
index 314ff760d3b3c8f4487ffbb37ae4f1e5259e7104..04c36a98e9cc041e843c1e3fa8f447571cf01bff 100644 (file)
@@ -11,11 +11,21 @@ TexImageState::TexImageState():
        internal_format(0)
 { }
 
+void TexImageState::set_1d(GLenum ifmt, unsigned wd)
+{
+       set_3d(ifmt, wd, 0, 0);
+}
+
 void TexImageState::set_2d(GLenum ifmt, unsigned wd, unsigned ht)
+{
+       set_3d(ifmt, wd, ht, 0);
+}
+
+void TexImageState::set_3d(GLenum ifmt, unsigned wd, unsigned ht, unsigned dp)
 {
        width = wd;
        height = ht;
-       depth = 0;
+       depth = dp;
        internal_format = ifmt;
 }
 
@@ -33,6 +43,16 @@ string TexImageState::describe() const
 }
 
 
+GLenum texture_cube_faces[6] = 
+{
+       GL_TEXTURE_CUBE_MAP_POSITIVE_X,
+       GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
+       GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
+       GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
+       GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
+       GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
+};
+
 TextureState::TextureState():
        id(0),
        target(0),
@@ -46,26 +66,66 @@ TextureState::TextureState():
        generate_mipmap(false)
 { }
 
+TexImageState &TextureState::get_image(unsigned level)
+{
+       if(images.size()<=level)
+               images.resize(level+1);
+       return images[level];
+}
+
+void TextureState::set_image_1d(unsigned level, GLenum ifmt, unsigned wd)
+{
+       get_image(level).set_1d(ifmt, wd);
+       if(level==0 && generate_mipmap)
+               create_mipmaps();
+}
+
 void TextureState::set_image_2d(unsigned level, GLenum ifmt, unsigned wd, unsigned ht)
 {
-       while(1)
+       get_image(level).set_2d(ifmt, wd, ht);
+       if(level==0 && generate_mipmap)
+               create_mipmaps();
+}
+
+void TextureState::set_face_image_2d(GLenum face, unsigned level, GLenum ifmt, unsigned wd, unsigned ht)
+{
+       unsigned index = 0;
+       for(; (index<6 && texture_cube_faces[index]!=face); ++index) ;
+       if(index>=6)
+               return;
+
+       set_image_2d(level*6+index, ifmt, wd, ht);
+}
+
+void TextureState::set_image_3d(unsigned level, GLenum ifmt, unsigned wd, unsigned ht, unsigned dp)
+{
+       get_image(level).set_3d(ifmt, wd, ht, dp);
+       if(level==0 && generate_mipmap)
+               create_mipmaps();
+}
+
+void TextureState::create_mipmaps(unsigned face)
+{
+       unsigned stride = (target==GL_TEXTURE_CUBE_MAP ? 6 : 1);
+       if(face>=stride)
+               face = 0;
+
+       unsigned wd = images[face].width;
+       unsigned ht = images[face].height;
+       unsigned dp = images[face].depth;
+       for(unsigned i=1;; ++i)
        {
-               if(images.size()<=level)
-                       images.resize(level+1);
-               images[level].set_2d(ifmt, wd, ht);
-
-               if(generate_mipmap)
-               {
-                       if(wd==1 && ht==1)
-                               break;
-                       ++level;
-                       if(wd>1)
-                               wd /= 2;
-                       if(ht>1)
-                               ht /= 2;
-               }
-               else
+               if(wd<=1 && ht<=1 && dp<=1)
                        break;
+
+               if(wd>1)
+                       wd /= 2;
+               if(ht>1)
+                       ht /= 2;
+               if(dp>1)
+                       dp /= 2;
+
+               get_image(i*stride+face).set_3d(images[0].internal_format, wd, ht, dp);
        }
 }
 
@@ -94,31 +154,52 @@ string TextureState::describe() const
        string descr = describe_enum(target, "TextureTarget");
        if(images.empty())
                descr += ", undefined";
+       else if(target==GL_TEXTURE_CUBE_MAP)
+       {
+               bool homogeneous = true;
+               for(unsigned i=1; (homogeneous && i<6); ++i)
+                       homogeneous = (images[i].width==images[0].width && images[i].height==images[0].height &&
+                               images[i].internal_format==images[0].internal_format);
+               if(homogeneous)
+                       descr += ", "+images.front().describe();
+               else
+                       descr += ", heterogeneous faces";
+       }
        else
                descr += ", "+images.front().describe();
        return descr;
 }
 
 
-TexUnitState::TexUnitState():
-       current_2d(0),
-       current_3d(0)
-{ }
+TexUnitState::Binding *TexUnitState::get_binding(GLenum target)
+{
+       if(target==GL_TEXTURE_1D)
+               return &binding_1d;
+       else if(target==GL_TEXTURE_2D)
+               return &binding_2d;
+       else if(target==GL_TEXTURE_3D)
+               return &binding_3d;
+       else if(target==GL_TEXTURE_CUBE_MAP)
+               return &binding_cube;
+       else
+               return 0;
+}
+
+const TexUnitState::Binding *TexUnitState::get_binding(GLenum target) const
+{
+       return const_cast<TexUnitState *>(this)->get_binding(target);
+}
 
 void TexUnitState::set_current_texture(GLenum target, TextureState *tex)
 {
-       if(target==GL_TEXTURE_2D)
-               current_2d = tex;
-       else if(target==GL_TEXTURE_3D)
-               current_3d = tex;
+       if(Binding *binding = get_binding(target))
+               binding->current = tex;
 }
 
 TextureState *TexUnitState::get_current_texture(GLenum target)
 {
-       if(target==GL_TEXTURE_2D)
-               return current_2d;
-       else if(target==GL_TEXTURE_3D)
-               return current_3d;
+       if(Binding *binding = get_binding(target))
+               return binding->current;
        else
                return 0;
 }
@@ -128,17 +209,43 @@ const TextureState *TexUnitState::get_current_texture(GLenum target) const
        return const_cast<TexUnitState *>(this)->get_current_texture(target);
 }
 
+bool TexUnitState::is_enabled(GLenum target) const
+{
+       if(const Binding *binding = get_binding(target))
+               return binding->enabled;
+       else
+               return false;
+}
+
 string TexUnitState::describe_binding(GLenum target) const
 {
-       if(const TextureState *tex = get_current_texture(target))
+       if(const Binding *binding = get_binding(target))
+               return binding->describe();
+       else
+               return "None";
+}
+
+
+TexUnitState::Binding::Binding():
+       enabled(false),
+       current(0)
+{ }
+
+string TexUnitState::Binding::describe() const
+{
+       if(current)
        {
-               string descr = strformat("%d ", tex->id);
-               if(tex->images.empty())
+               string descr = strformat("%d ", current->id);
+               if(current->images.empty())
                        descr += "(undefined)";
                else
-                       descr += "("+tex->images.front().describe()+")";
+                       descr += "("+current->images.front().describe()+")";
+               if(enabled)
+                       descr += ", enabled";
                return descr;
        }
+       else if(enabled)
+               return "None, enabled";
        else
                return "None";
 }
index 9bc739bbed6abee16b613770002093a4d5ab3c6f..c340f4b0392f64ceb8f3e80cf882b6d43d33b14d 100644 (file)
@@ -14,10 +14,15 @@ struct TexImageState
        GLenum internal_format;
 
        TexImageState();
+
+       void set_1d(GLenum, unsigned);
        void set_2d(GLenum, unsigned, unsigned);
+       void set_3d(GLenum, unsigned, unsigned, unsigned);
        std::string describe() const;
 };
 
+extern GLenum texture_cube_faces[6];
+
 struct TextureState
 {
        unsigned id;
@@ -33,21 +38,39 @@ struct TextureState
        bool generate_mipmap;
 
        TextureState();
+
+       TexImageState &get_image(unsigned);
+       void set_image_1d(unsigned, GLenum, unsigned);
        void set_image_2d(unsigned, GLenum, unsigned, unsigned);
+       void set_face_image_2d(GLenum, unsigned, GLenum, unsigned, unsigned);
+       void set_image_3d(unsigned, GLenum, unsigned, unsigned, unsigned);
+       void create_mipmaps(unsigned = 0);
        void set_parameter(GLenum, const int *);
        std::string describe() const;
 };
 
 struct TexUnitState
 {
-       AutoConstPtr<TextureState> current_2d;
-       AutoConstPtr<TextureState> current_3d;
+       struct Binding
+       {
+               bool enabled;
+               AutoConstPtr<TextureState> current;
+
+               Binding();
+               std::string describe() const;
+       };
 
-       TexUnitState();
+       Binding binding_1d;
+       Binding binding_2d;
+       Binding binding_3d;
+       Binding binding_cube;
 
+       Binding *get_binding(GLenum);
+       const Binding *get_binding(GLenum) const;
        void set_current_texture(GLenum, TextureState *);
        TextureState *get_current_texture(GLenum);
        const TextureState *get_current_texture(GLenum) const;
+       bool is_enabled(GLenum) const;
        std::string describe_binding(GLenum) const;
 };