]> git.tdb.fi Git - gldbg.git/blobdiff - flavors/gl/source/texturestate.cpp
More complete support for textures
[gldbg.git] / flavors / gl / source / texturestate.cpp
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";
 }