Trace 1D, 3D and cube map texture images, as well as texture enable state.
decoder->glGetIntegerv = glGetIntegerv;
+ decoder->glEnable = glEnable;
+ decoder->glDisable = glDisable;
decoder->glEnableClientState = glEnableClientState;
decoder->glDisableClientState = glDisableClientState;
// 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;
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)
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)
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);
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 *);
{
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);
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"));
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;
}
}
+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),
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);
}
}
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;
}
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";
}
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;
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;
};