From: Mikko Rasa Date: Fri, 6 Nov 2009 13:09:29 +0000 (+0000) Subject: Add classes to track OpenGL state and commands to inspect it X-Git-Url: http://git.tdb.fi/?p=gldbg.git;a=commitdiff_plain;h=ee7f1e3a5912789664648ac5be85127e62c1cda5 Add classes to track OpenGL state and commands to inspect it Fix some leftover warnings --- diff --git a/Makefile b/Makefile index 226ff88..60da9b2 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ glwrap.so: source/glwrap.o source/arraysize.o gldump: source/gldecoder.o source/gldump.o source/glprint.o source/enums.o source/arraysize.o source/tmpalloc.o $(CC) -o $@ $^ $(LIBS) $(LDFLAGS) -gldbg: source/gldbg.o source/gldecoder.o source/glprint.o source/commandinterpreter.o source/tracer.o source/process.o source/enums.o source/arraysize.o source/tmpalloc.o +gldbg: source/gldbg.o source/gldecoder.o source/glprint.o source/commandinterpreter.o source/tracer.o source/process.o source/enums.o source/arraysize.o source/tmpalloc.o source/glstate.o source/texturestate.o source/bufferstate.o $(CXX) -o $@ $^ $(LIBS_gldbg) $(LIBS) $(LDFLAGS) source/glwrap.o: source/functions.h gensrc/functions.enum gensrc/glwrap.funcs @@ -23,17 +23,14 @@ source/gldecoder.o: source/functions.h gensrc/gldecoder.struct gensrc/gldecoder. source/gldump.o: source/gldecoder.h gensrc/gldecoder.struct source/glprint.h source/glprint.o: source/arraysize.h gensrc/glprint.funcs gensrc/gldecoder.struct source/enums.o: gensrc/enums.table - -source/gldbg.o: source/gldbg.cpp source/gldbg.h source/gldecoder.h source/tracer.h - $(CXX) -c $(CXXFLAGS) $(CXXFLAGS_gldbg) -o $@ $< - -source/tracer.o: source/tracer.cpp source/gldecoder.h source/glprint.h - $(CXX) -c $(CXXFLAGS) $(CXXFLAGS_gldbg) -o $@ $< - -source/commandinterpreter.o: source/commandinterpreter.cpp source/gldbg.h - $(CXX) -c $(CXXFLAGS) $(CXXFLAGS_gldbg) -o $@ $< - -source/process.o: source/process.cpp source/process.h +source/gldbg.o: source/gldbg.h source/gldecoder.h source/tracer.h source/commandinterpreter.h source/glstate.h +source/tracer.o: source/gldecoder.h source/glprint.h +source/commandinterpreter.o: source/gldbg.h source/glstate.h +source/process.o: source/process.h +source/glstate.o: source/glstate.h source/gldecoder.h source/texturestate.h source/bufferstate.h +source/texturestate.o: source/texturestate.h + +%.o: %.cpp $(CXX) -c $(CXXFLAGS) $(CXXFLAGS_gldbg) -o $@ $< gensrc/%: source/%.t gensrc/.created genwrap.py gl.files gl.tm gl.io gl.spec glx.files glx.tm glx.io glx.spec glxext.spec diff --git a/source/arraysize.c b/source/arraysize.c index 2e88139..b81ea4b 100644 --- a/source/arraysize.c +++ b/source/arraysize.c @@ -89,7 +89,7 @@ int paramsize(GLenum pname) } } -int mapsize(GLenum target) +int mapsize(GLenum target __attribute__((unused))) { // XXX Implement this return 1; diff --git a/source/autoconstptr.h b/source/autoconstptr.h new file mode 100644 index 0000000..04e1fba --- /dev/null +++ b/source/autoconstptr.h @@ -0,0 +1,30 @@ +/* $Id$ + +This file is part of gldbg +Copyright © 2009 Mikko Rasa, Mikkosoft Productions +Distributed under the GPL +*/ + +#ifndef AUTOCONSTPTR_H_ +#define AUTOCONSTPTR_H_ + +/** +A smart pointer that only provides non-const access to the contents if the +pointer itself is non-const. +*/ +template +class AutoConstPtr +{ +private: + T *ptr; + +public: + AutoConstPtr(T *p): ptr(p) { } + AutoConstPtr &operator=(T *p) { ptr = p; return *this; } + T *operator->() { return ptr; } + const T *operator->() const { return ptr; } + operator T *() { return ptr; } + operator const T *() const { return ptr; } +}; + +#endif diff --git a/source/bufferstate.cpp b/source/bufferstate.cpp new file mode 100644 index 0000000..9b1c38f --- /dev/null +++ b/source/bufferstate.cpp @@ -0,0 +1,43 @@ +/* $Id$ + +This file is part of gldbg +Copyright © 2009 Mikko Rasa, Mikkosoft Productions +Distributed under the GPL +*/ + +#include +#include "bufferstate.h" +#include "enums.h" + +using namespace std; +using namespace Msp; + +BufferState::BufferState(): + usage(GL_STATIC_DRAW), + size(0), + data(0) +{ } + +void BufferState::set_data(unsigned sz, const void *ptr, GLenum use) +{ + usage = use; + size = sz; + delete[] data; + data = new char[size]; + if(ptr) + set_sub_data(0, size, ptr); +} + +void BufferState::set_sub_data(unsigned off, unsigned sz, const void *ptr) +{ + if(data && off+sz(ptr); + copy(cptr, cptr+sz, data+off); + } +} + +string BufferState::describe() const +{ + return format("%d bytes, %s", size, describe_enum(usage, "")); +} diff --git a/source/bufferstate.h b/source/bufferstate.h new file mode 100644 index 0000000..17462c6 --- /dev/null +++ b/source/bufferstate.h @@ -0,0 +1,27 @@ +/* $Id$ + +This file is part of gldbg +Copyright © 2009 Mikko Rasa, Mikkosoft Productions +Distributed under the GPL +*/ + +#ifndef BUFFERSTATE_H_ +#define BUFFERSTATE_H_ + +#include +#include + +struct BufferState +{ + unsigned id; + GLenum usage; + unsigned size; + char *data; + + BufferState(); + void set_data(unsigned, const void *, GLenum); + void set_sub_data(unsigned, unsigned, const void *); + std::string describe() const; +}; + +#endif diff --git a/source/commandinterpreter.cpp b/source/commandinterpreter.cpp index c51d0a2..36c3b3c 100644 --- a/source/commandinterpreter.cpp +++ b/source/commandinterpreter.cpp @@ -12,6 +12,7 @@ Distributed under the GPL #include #include #include "commandinterpreter.h" +#include "enums.h" #include "gldbg.h" #include "tracer.h" @@ -52,6 +53,27 @@ CommandInterpreter::CommandInterpreter(GlDbg &d): " Temporarily suspend or resume trace without closing the file.\n\n" "trace end\n" " Terminate trace, closing the file.\n"); + + commands["state"] = Command(&CommandInterpreter::cmd_state, + "Inspects general GL state", + "state vertex\n" + " Print current vertex attributes\n\n" + "state bind\n" + " Show current bindings\n"); + + commands["texture"] = Command(&CommandInterpreter::cmd_texture, + "Inspect texture state", + "texture\n" + " Lists texture objects\n\n" + "texture ID\n" + " Print information about a texture object\n"); + + commands["buffer"] = Command(&CommandInterpreter::cmd_buffer, + "Inspect buffer object state", + "buffer\n" + " Lists buffer objects\n\n" + "buffer ID\n" + " Print information about a buffer object\n"); } void CommandInterpreter::execute(const string &cmd) @@ -100,6 +122,7 @@ void CommandInterpreter::cmd_run(const string &) void CommandInterpreter::cmd_continue(const string &) { + IO::print("Continuing.\n"); gldbg.get_process().resume(); } @@ -170,6 +193,95 @@ void CommandInterpreter::cmd_trace(const string &args) } } +void CommandInterpreter::cmd_state(const string &args) +{ + const GlState &glstate = gldbg.get_glstate(); + if(args=="vertex") + { + IO::print("Current vertex attributes:\n"); + const Vector4 &color = glstate.get_color(); + IO::print(" Color: [%05.3f, %05.3f, %05.3f, %05.3f]\n", color.r, color.g, color.b, color.a); + for(unsigned i=0; i<8; ++i) + { + const Vector4 &texcoord = glstate.get_texcoord(i); + IO::print(" TexCoord%d: [%05.3f, %05.3f, %05.3f, %05.3f]\n", i, texcoord.s, texcoord.t, texcoord.p, texcoord.q); + } + const Vector3 &normal = glstate.get_normal(); + IO::print(" Normal: [%05.3f, %05.3f, %05.3f]\n", normal.x, normal.y, normal.z); + } + else if(args=="bind") + { + IO::print("Current bindings:\n"); + for(unsigned i=0; i<8; ++i) + { + IO::print(" Texture unit %d:\n", i); + const TexUnitState &unit = glstate.get_texture_unit(i); + IO::print(" GL_TEXTURE_2D: %s\n", unit.describe_binding(GL_TEXTURE_2D)); + IO::print(" GL_TEXTURE_3D: %s\n", unit.describe_binding(GL_TEXTURE_3D)); + } + IO::print(" Buffers:\n"); + const BufferState *buf = glstate.get_current_buffer(GL_ARRAY_BUFFER); + IO::print(" GL_ARRAY_BUFFER: %d\n", (buf ? buf->id : 0)); + buf = glstate.get_current_buffer(GL_ELEMENT_ARRAY_BUFFER); + IO::print(" GL_ELEMENT_ARRAY_BUFFER: %d\n", (buf ? buf->id : 0)); + } + else + throw InvalidParameterValue("Invalid or missing argument"); +} + +void CommandInterpreter::cmd_texture(const string &args) +{ + if(args.empty()) + { + const map &textures = gldbg.get_glstate().get_textures(); + IO::print("%d texture objects:\n", textures.size()); + for(map::const_iterator i = textures.begin(); i!=textures.end(); ++i) + { + const TextureState &tex = i->second; + IO::print(" %d: %s, %d images\n", i->first, tex.describe(), tex.images.size()); + } + } + else + { + unsigned id = lexical_cast(args); + const TextureState &tex = gldbg.get_glstate().get_texture(id); + IO::print("Texture object %d\n", id); + IO::print(" Target: %s\n", describe_enum(tex.target, "TextureTarget")); + IO::print(" Images:\n"); + for(unsigned i=0; ifirst, i->second.describe()); + } + else + { + unsigned id = lexical_cast(args); + const BufferState &buf = gldbg.get_glstate().get_buffer(id); + IO::print("Buffer %d:\n", id); + IO::print(" Size: %d bytes\n", buf.size); + IO::print(" Usage: %s\n", describe_enum(buf.usage, "")); + } +} + CommandInterpreter::Command::Command(): func(0) diff --git a/source/commandinterpreter.h b/source/commandinterpreter.h index bdd3c17..14d8eb9 100644 --- a/source/commandinterpreter.h +++ b/source/commandinterpreter.h @@ -46,6 +46,9 @@ private: void cmd_kill(const std::string &); void cmd_exit(const std::string &); void cmd_trace(const std::string &); + void cmd_state(const std::string &); + void cmd_texture(const std::string &); + void cmd_buffer(const std::string &); }; #endif diff --git a/source/enums.h b/source/enums.h index ff20eee..a3ae8d8 100644 --- a/source/enums.h +++ b/source/enums.h @@ -10,7 +10,15 @@ Distributed under the GPL #include +#ifdef __cplusplus +extern "C" { +#endif + extern const char *describe_enum(GLenum, const char *); extern const char *describe_bitfield(int, const char *); +#ifdef __cplusplus +} +#endif + #endif diff --git a/source/gldbg.cpp b/source/gldbg.cpp index c91e00a..b95f81d 100644 --- a/source/gldbg.cpp +++ b/source/gldbg.cpp @@ -44,6 +44,8 @@ int GlDbg::main() IO::print("Type \"help\" for a list of commands\n"); Application::main(); + + return 0; } void GlDbg::launch() @@ -131,6 +133,7 @@ void GlDbg::read_stream() if(size<0) break; tracer.decode(data, len); + glstate.decode(data, len); buf_offset += size; } if(buf_offset>8192) diff --git a/source/gldbg.h b/source/gldbg.h index 5f75164..ff84451 100644 --- a/source/gldbg.h +++ b/source/gldbg.h @@ -13,6 +13,7 @@ Distributed under the GPL #include #include #include "commandinterpreter.h" +#include "glstate.h" #include "process.h" #include "tracer.h" @@ -26,6 +27,7 @@ private: unsigned buf_offset; bool flushing; Tracer tracer; + GlState glstate; bool got_sigchld; static RegApp reg; @@ -34,6 +36,7 @@ public: GlDbg(int, char **); int main(); Tracer &get_tracer() { return tracer; } + GlState &get_glstate() { return glstate; } Process &get_process() { return process; } void launch(); void quit(); diff --git a/source/glstate.cpp b/source/glstate.cpp new file mode 100644 index 0000000..ff8f3a2 --- /dev/null +++ b/source/glstate.cpp @@ -0,0 +1,282 @@ +/* $Id$ + +This file is part of gldbg +Copyright © 2009 Mikko Rasa, Mikkosoft Productions +Distributed under the GPL +*/ + +#include +#include "glstate.h" + +using namespace std; +using namespace Msp; + +namespace { + +template +float normalize(T v); + +template<> +float normalize(GLubyte v) +{ return v/255.0f; } + +template<> +float normalize(GLbyte v) +{ return (2*v+1)/255.0f; } + +template +void wrap_normalized(void *user_data, T v0) +{ func(user_data, v0); } + +template +void wrap_normalized(void *user_data, T v0, T v1) +{ func(user_data, v0, v1); } + +template +void wrap_normalized(void *user_data, T v0, T v1, T v2) +{ func(user_data, v0, v1, v2); } + +template +void wrap_normalized(void *user_data, T v0, T v1, T v2, T v3) +{ func(user_data, v0, v1, v2, v3); } + +template +void wrap_array(void *user_data, const T *v) +{ func(user_data, v[0]); } + +template +void wrap_array(void *user_data, const T *v) +{ func(user_data, v[0], v[1]); } + +template +void wrap_array(void *user_data, const T *v) +{ func(user_data, v[0], v[1], v[2]); } + +template +void wrap_array(void *user_data, const T *v) +{ func(user_data, v[0], v[1], v[2], v[3]); } + +} + + +Vector3::Vector3(): + x(0), y(0), z(0) +{ } + + +Vector4::Vector4(): + x(0), y(0), z(0), w(1) +{ } + + +GlState::GlState(): + decoder(gldecoder_new(this, NULL)), + active_tex(0), + array_buffer(0), + element_buffer(0) +{ + decoder->glColor3ub = wrap_normalized; + decoder->glColor3ubv = wrap_array >; + decoder->glColor4ub = wrap_normalized; + decoder->glColor4ubv = wrap_array >; + decoder->glColor3f = glColor3f; + decoder->glColor3fv = wrap_array; + decoder->glColor4f = glColor4f; + decoder->glColor4fv = wrap_array; + decoder->glTexCoord1f = glTexCoord1f; + decoder->glTexCoord1fv = wrap_array; + decoder->glTexCoord2f = glTexCoord2f; + decoder->glTexCoord2fv = wrap_array; + decoder->glTexCoord3f = glTexCoord3f; + decoder->glTexCoord3fv = wrap_array; + decoder->glTexCoord4f = glTexCoord4f; + decoder->glTexCoord4fv = wrap_array; + decoder->glNormal3f = glNormal3f; + decoder->glNormal3fv = wrap_array; + decoder->glActiveTexture = glActiveTexture; + decoder->glActiveTextureARB = glActiveTexture; + decoder->glBindTexture = glBindTexture; + decoder->glTexImage2D = glTexImage2D; + decoder->glTexParameteri = glTexParameteri; + decoder->glTexParameteriv = glTexParameteriv; + decoder->glDeleteTextures = glDeleteTextures; + decoder->glBindBuffer = glBindBuffer; + decoder->glBindBufferARB = glBindBuffer; + decoder->glBufferData = glBufferData; + decoder->glBufferDataARB = glBufferData; + decoder->glBufferSubData = glBufferSubData; + decoder->glBufferSubDataARB = glBufferSubData; +} + +GlState::~GlState() +{ + gldecoder_delete(decoder); +} + +int GlState::decode(const char *data, unsigned len) +{ + return gldecoder_decode(decoder, data, len); +} + +const TextureState &GlState::get_texture(unsigned id) const +{ + TextureMap::const_iterator i = textures.find(id); + if(i==textures.end()) + throw KeyError("Unknown texture"); + return i->second; +} + +const BufferState &GlState::get_buffer(unsigned id) const +{ + BufferMap::const_iterator i = buffers.find(id); + if(i==buffers.end()) + throw KeyError("Unknown buffer"); + return i->second; +} + +const BufferState *GlState::get_current_buffer(GLenum target) const +{ + return const_cast(this)->get_current_buffer(target); +} + +TextureState *GlState::get_current_texture(GLenum target) +{ + return texunits[active_tex].get_current_texture(target); +} + +BufferState *GlState::get_current_buffer(GLenum target) +{ + if(target==GL_ARRAY_BUFFER) + return array_buffer; + else if(target==GL_ELEMENT_ARRAY_BUFFER) + return element_buffer; + return 0; +} + +void GlState::set_current_texture(GLenum target, unsigned id) +{ + TexUnitState &unit = texunits[active_tex]; + TextureState *tex = 0; + if(id) + { + tex = &textures[id]; + if(!tex->id) + { + tex->id = id; + tex->target = target; + } + else if(tex->target!=target) + return; + } + unit.set_current_texture(target, tex); +} + +void GlState::set_current_buffer(GLenum target, unsigned id) +{ + BufferState *buf = 0; + if(id) + { + buf = &buffers[id]; + if(!buf->id) + buf->id = id; + } + + if(target==GL_ARRAY_BUFFER) + array_buffer = buf; + else if(target==GL_ELEMENT_ARRAY_BUFFER) + element_buffer = buf; +} + +// Vertex attributes + +void GlState::glColor3f(void *user_data, float r, float g, float b) +{ glColor4f(user_data, r, g, b, 1.0f); } + +void GlState::glColor4f(void *user_data, float r, float g, float b, float a) +{ + Vector4 &color = reinterpret_cast(user_data)->color; + color.r = r; + color.g = g; + color.b = b; + color.a = a; +} + +void GlState::glNormal3f(void *user_data, float x, float y, float z) +{ + Vector3 &normal = reinterpret_cast(user_data)->normal; + normal.x = x; + normal.y = y; + normal.z = z; +} + +void GlState::glTexCoord1f(void *user_data, float s) +{ glTexCoord4f(user_data, s, 0.0f, 0.0f, 1.0f); } + +void GlState::glTexCoord2f(void *user_data, float s, float t) +{ glTexCoord4f(user_data, s, t, 0.0f, 1.0f); } + +void GlState::glTexCoord3f(void *user_data, float s, float t, float p) +{ glTexCoord4f(user_data, s, t, p, 1.0f); } + +void GlState::glTexCoord4f(void *user_data, float s, float t, float p, float q) +{ + unsigned index = reinterpret_cast(user_data)->active_tex; + glMultiTexCoord4f(user_data, index, s, t, p, q); +} + +void GlState::glMultiTexCoord4f(void *user_data, unsigned index, float s, float t, float p, float q) +{ + Vector4 &texcoord = reinterpret_cast(user_data)->texcoord[index]; + texcoord.s = s; + texcoord.t = t; + texcoord.p = p; + texcoord.q = q; +} + +// Textures + +void GlState::glActiveTexture(void *user_data, unsigned index) +{ + reinterpret_cast(user_data)->active_tex = index; +} + +void GlState::glBindTexture(void *user_data, GLenum target, unsigned id) +{ reinterpret_cast(user_data)->set_current_texture(target, id); } + +void GlState::glTexImage2D(void *user_data, GLenum target, int level, int ifmt, int width, int height, int, GLenum, GLenum, const void *) +{ + if(TextureState *tex = reinterpret_cast(user_data)->get_current_texture(target)) + tex->set_image_2d(level, ifmt, width, height); +} + +void GlState::glTexParameteri(void *user_data, GLenum target, GLenum param, int value) +{ glTexParameteriv(user_data, target, param, &value); } + +void GlState::glTexParameteriv(void *user_data, GLenum target, GLenum param, const int *values) +{ + if(TextureState *tex = reinterpret_cast(user_data)->get_current_texture(target)) + tex->set_parameter(param, values); +} + +void GlState::glDeleteTextures(void *user_data, int count, const unsigned *ids) +{ + for(int i=0; i(user_data)->textures.erase(ids[i]); +} + +// Buffer objects + +void GlState::glBindBuffer(void *user_data, GLenum target, unsigned id) +{ reinterpret_cast(user_data)->set_current_buffer(target, id); } + +void GlState::glBufferData(void *user_data, GLenum target, int size, const void *data, GLenum usage) +{ + if(BufferState *buf = reinterpret_cast(user_data)->get_current_buffer(target)) + buf->set_data(size, data, usage); +} + +void GlState::glBufferSubData(void *user_data, GLenum target, int offset, int size, const void *data) +{ + if(BufferState *buf = reinterpret_cast(user_data)->get_current_buffer(target)) + buf->set_sub_data(offset, size, data); +} diff --git a/source/glstate.h b/source/glstate.h new file mode 100644 index 0000000..b21034d --- /dev/null +++ b/source/glstate.h @@ -0,0 +1,100 @@ +/* $Id$ + +This file is part of gldbg +Copyright © 2009 Mikko Rasa, Mikkosoft Productions +Distributed under the GPL +*/ + +#ifndef GLSTATE_H_ +#define GLSTATE_H_ + +#include +#include +#include "bufferstate.h" +#include "gldecoder.h" +#include "texturestate.h" + +struct Vector3 +{ + float x, y, z; + + Vector3(); +}; + +struct Vector4 +{ + union { float x, r, s; }; + union { float y, g, t; }; + union { float z, b, p; }; + union { float w, a, q; }; + + Vector4(); +}; + +/** +Tracks OpenGL state based on the command stream. This class is essentially a +(partial) OpenGL implementation in itself. + +XXX Should determine the number of texture units the target implementation +actually supports. +*/ +class GlState +{ +public: + typedef std::map TextureMap; + typedef std::map BufferMap; + +private: + GlDecoder *decoder; + Vector4 color; + Vector4 texcoord[8]; + Vector3 normal; + unsigned active_tex; + TextureMap textures; + TexUnitState texunits[8]; + BufferMap buffers; + BufferState *array_buffer; + BufferState *element_buffer; + +public: + GlState(); + ~GlState(); + + int decode(const char *, unsigned); + const Vector4 &get_color() const { return color; } + const Vector4 &get_texcoord(unsigned i) const { return texcoord[i]; } + const Vector3 &get_normal() const { return normal; } + const TextureMap &get_textures() const { return textures; } + const TextureState &get_texture(unsigned) const; + const TexUnitState &get_texture_unit(unsigned i) const { return texunits[i]; } + const BufferMap &get_buffers() const { return buffers; } + const BufferState &get_buffer(unsigned) const; + const BufferState *get_current_buffer(GLenum) const; +private: + TextureState *get_current_texture(GLenum); + BufferState *get_current_buffer(GLenum); + void set_current_texture(GLenum, unsigned); + void set_current_buffer(GLenum, unsigned); + + static void glColor3f(void *, float, float, float); + static void glColor4f(void *, float, float, float, float); + static void glNormal3f(void *, float, float, float); + static void glTexCoord1f(void *, float); + static void glTexCoord2f(void *, float, float); + static void glTexCoord3f(void *, float, float, float); + static void glTexCoord4f(void *, float, float, float, float); + static void glMultiTexCoord4f(void *, unsigned, float, float, float, float); + + static void glActiveTexture(void *, unsigned); + static void glBindTexture(void *, GLenum, unsigned); + static void glTexImage2D(void *, GLenum, 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 *); + + static void glBindBuffer(void *, GLenum, unsigned); + static void glBufferData(void *, GLenum, int, const void *, GLenum); + static void glBufferSubData(void *, GLenum, int, int, const void *); +}; + +#endif diff --git a/source/texturestate.cpp b/source/texturestate.cpp new file mode 100644 index 0000000..187707c --- /dev/null +++ b/source/texturestate.cpp @@ -0,0 +1,152 @@ +/* $Id$ + +This file is part of gldbg +Copyright © 2009 Mikko Rasa, Mikkosoft Productions +Distributed under the GPL +*/ + +#include +#include "enums.h" +#include "texturestate.h" + +using namespace std; +using namespace Msp; + +TexImageState::TexImageState(): + width(0), + height(0), + depth(0), + internal_format(0) +{ } + +void TexImageState::set_2d(GLenum ifmt, unsigned wd, unsigned ht) +{ + width = wd; + height = ht; + depth = 0; + internal_format = ifmt; +} + +string TexImageState::describe() const +{ + string descr = format("%d", width); + if(height) + { + descr += format("x%d", height); + if(depth) + descr += format("x%d", height); + } + descr += format(", %s", describe_enum(internal_format, "PixelFormat")); + return descr; +} + + +TextureState::TextureState(): + id(0), + target(0), + min_filter(GL_LINEAR_MIPMAP_LINEAR), + mag_filter(GL_LINEAR), + wrap_s(GL_REPEAT), + wrap_t(GL_REPEAT), + wrap_r(GL_REPEAT), + compare_mode(GL_NONE), + compare_func(GL_LEQUAL), + generate_mipmap(false) +{ } + +void TextureState::set_image_2d(unsigned level, GLenum ifmt, unsigned wd, unsigned ht) +{ + while(1) + { + 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 + break; + } +} + +void TextureState::set_parameter(GLenum pname, const int *values) +{ + if(pname==GL_TEXTURE_MIN_FILTER) + min_filter = values[0]; + else if(pname==GL_TEXTURE_MAG_FILTER) + mag_filter = values[0]; + else if(pname==GL_TEXTURE_WRAP_S) + wrap_s = values[0]; + else if(pname==GL_TEXTURE_WRAP_T) + wrap_t = values[0]; + else if(pname==GL_TEXTURE_WRAP_R) + wrap_r = values[0]; + else if(pname==GL_TEXTURE_COMPARE_MODE) + compare_mode = values[0]; + else if(pname==GL_TEXTURE_COMPARE_FUNC) + compare_func = values[0]; + else if(pname==GL_GENERATE_MIPMAP) + generate_mipmap = values[0]; +} + +string TextureState::describe() const +{ + string descr = describe_enum(target, "TextureTarget"); + if(images.empty()) + descr += ", undefined"; + else + descr += format(", %s", images.front().describe()); + return descr; +} + + +TexUnitState::TexUnitState(): + current_2d(0), + current_3d(0) +{ } + +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; +} + +TextureState *TexUnitState::get_current_texture(GLenum target) +{ + if(target==GL_TEXTURE_2D) + return current_2d; + else if(target==GL_TEXTURE_3D) + return current_3d; + else + return 0; +} + +const TextureState *TexUnitState::get_current_texture(GLenum target) const +{ + return const_cast(this)->get_current_texture(target); +} + +string TexUnitState::describe_binding(GLenum target) const +{ + if(const TextureState *tex = get_current_texture(target)) + { + string descr = format("%d ", tex->id); + if(tex->images.empty()) + descr += "(undefined)"; + else + descr += format("(%s)", tex->images.front().describe()); + return descr; + } + else + return "None"; +} diff --git a/source/texturestate.h b/source/texturestate.h new file mode 100644 index 0000000..13f5674 --- /dev/null +++ b/source/texturestate.h @@ -0,0 +1,61 @@ +/* $Id$ + +This file is part of gldbg +Copyright © 2009 Mikko Rasa, Mikkosoft Productions +Distributed under the GPL +*/ + +#ifndef TEXTURESTATE_H_ +#define TEXTURESTATE_H_ + +#include +#include +#include +#include "autoconstptr.h" + +struct TexImageState +{ + unsigned width; + unsigned height; + unsigned depth; + GLenum internal_format; + + TexImageState(); + void set_2d(GLenum, unsigned, unsigned); + std::string describe() const; +}; + +struct TextureState +{ + unsigned id; + GLenum target; + std::vector images; + GLenum min_filter; + GLenum mag_filter; + GLenum wrap_s; + GLenum wrap_t; + GLenum wrap_r; + GLenum compare_mode; + GLenum compare_func; + bool generate_mipmap; + + TextureState(); + void set_image_2d(unsigned, GLenum, unsigned, unsigned); + void set_parameter(GLenum, const int *); + std::string describe() const; +}; + +struct TexUnitState +{ + AutoConstPtr current_2d; + AutoConstPtr current_3d; + + TexUnitState(); + + void set_current_texture(GLenum, TextureState *); + TextureState *get_current_texture(GLenum); + const TextureState *get_current_texture(GLenum) const; + std::string describe_binding(GLenum) const; +}; + +#endif