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 source/glstate.o source/texturestate.o source/bufferstate.o source/profiler.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 source/profiler.o source/arraystate.o
$(CXX) -o $@ $^ $(LIBS_gldbg) $(LIBS) $(LDFLAGS)
source/glwrap.o: source/functions.h gensrc/functions.enum gensrc/glwrap.funcs
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
+source/bufferstate.o: source/arraystate.h source/bufferstate.h source/enums.h
+source/arraystate.o: source/arraystate.h source/bufferstate.h
%.o: %.cpp
$(CXX) -c $(CXXFLAGS) $(CXXFLAGS_gldbg) -o $@ $<
--- /dev/null
+/* $Id$
+
+This file is part of gldbg
+Copyright © 2010 Mikko Rasa, Mikkosoft Productions
+Distributed under the GPL
+*/
+
+#include "arraystate.h"
+#include "bufferstate.h"
+
+ArrayState::ArrayState():
+ kind(0),
+ index(0),
+ enabled(false),
+ size(4),
+ type(GL_FLOAT),
+ normalized(false),
+ stride(0),
+ buffer(0),
+ pointer(0)
+{ }
+
+void ArrayState::set(unsigned s, GLenum t, bool n, unsigned r, BufferState *b, long p)
+{
+ size = s;
+ type = t;
+ stride = r;
+ normalized = n;
+ buffer = b;
+ pointer = p;
+
+ if(buffer)
+ buffer->content.update(*this);
+}
--- /dev/null
+/* $Id$
+
+This file is part of gldbg
+Copyright © 2010 Mikko Rasa, Mikkosoft Productions
+Distributed under the GPL
+*/
+
+#ifndef ARRAYSTATE_H_
+#define ARRAYSTATE_H_
+
+#include <GL/gl.h>
+
+struct BufferState;
+
+struct ArrayState
+{
+ GLenum kind;
+ unsigned index;
+ bool enabled;
+ unsigned size;
+ GLenum type;
+ bool normalized;
+ unsigned stride;
+ BufferState *buffer;
+ long pointer;
+
+ ArrayState();
+ void set(unsigned, GLenum, bool, unsigned, BufferState *, long);
+};
+
+#endif
/* $Id$
This file is part of gldbg
-Copyright © 2009 Mikko Rasa, Mikkosoft Productions
+Copyright © 2009-2010 Mikko Rasa, Mikkosoft Productions
Distributed under the GPL
*/
#include <msp/strings/formatter.h>
+#include "arraystate.h"
#include "bufferstate.h"
#include "enums.h"
using namespace std;
using namespace Msp;
+BufferContent::BufferContent():
+ consistent(true),
+ stride(0)
+{ }
+
+void BufferContent::update(const ArrayState &array)
+{
+ if(array.stride!=stride)
+ consistent = false;
+
+ stride = array.stride;
+
+ for(vector<Array>::iterator i=arrays.begin(); i!=arrays.end(); ++i)
+ if(i->kind==array.kind && i->index==array.index)
+ {
+ if(array.size!=i->size || array.type!=i->type || array.pointer!=i->offset)
+ {
+ consistent = false;
+ arrays.erase(i);
+ }
+ else
+ return;
+
+
+ break;
+ }
+
+ vector<Array>::iterator place = arrays.end();
+ for(vector<Array>::iterator i=arrays.begin(); i!=arrays.end(); ++i)
+ if(i->offset>array.pointer)
+ {
+ place = i;
+ break;
+ }
+
+ arrays.insert(place, array);
+}
+
+string BufferContent::describe() const
+{
+ if(arrays.empty())
+ return "(unknown)";
+
+ string result;
+ for(vector<Array>::const_iterator i=arrays.begin(); i!=arrays.end(); ++i)
+ {
+ char kind = '?';
+ if(i->kind==GL_VERTEX_ARRAY)
+ kind = 'V';
+ else if(i->kind==GL_NORMAL_ARRAY)
+ kind = 'N';
+ else if(i->kind==GL_COLOR_ARRAY)
+ kind = 'C';
+ else if(i->kind==GL_TEXTURE_COORD_ARRAY && i->index==0)
+ kind = 'T';
+
+ char type[3] = { '?', 0, 0 };
+ if(i->type==GL_FLOAT)
+ type[0] = 'F';
+ else if(i->type==GL_DOUBLE)
+ type[0] = 'D';
+ else if(i->type==GL_INT || i->type==GL_UNSIGNED_INT)
+ type[0] = 'I';
+ else if(i->type==GL_SHORT || i->type==GL_UNSIGNED_SHORT)
+ type[0] = 'S';
+ else if(i->type==GL_BYTE || i->type==GL_UNSIGNED_BYTE)
+ type[0] = 'B';
+
+ if(i->type==GL_UNSIGNED_INT || i->type==GL_UNSIGNED_SHORT || i->type==GL_UNSIGNED_BYTE)
+ {
+ type[1] = type[0];
+ type[0] = 'U';
+ }
+
+ if(!result.empty())
+ result += '_';
+ result += format("%c%d%s", kind, i->size, type);
+ }
+
+ return result;
+}
+
+
+BufferContent::Array::Array(const ArrayState &a):
+ kind(a.kind),
+ index(a.index),
+ size(a.size),
+ type(a.type),
+ offset(a.pointer)
+{ }
+
+
BufferState::BufferState():
usage(GL_STATIC_DRAW),
size(0),
data = new char[size];
if(ptr)
set_sub_data(0, size, ptr);
+ content = BufferContent();
}
void BufferState::set_sub_data(unsigned off, unsigned sz, const void *ptr)
{
- if(data && off+sz<size)
+ if(data && off+sz<=size)
{
const char *cptr = reinterpret_cast<const char *>(ptr);
copy(cptr, cptr+sz, data+off);
string BufferState::describe() const
{
- return format("%d bytes, %s", size, describe_enum(usage, ""));
+ if(content.stride)
+ return format("%s, %d vertices (%d bytes), %s",
+ content.describe(), size/content.stride, size, describe_enum(usage, ""));
+ else
+ return format("%d bytes, %s", size, describe_enum(usage, ""));
}
/* $Id$
This file is part of gldbg
-Copyright © 2009 Mikko Rasa, Mikkosoft Productions
+Copyright © 2009-2010 Mikko Rasa, Mikkosoft Productions
Distributed under the GPL
*/
#define BUFFERSTATE_H_
#include <string>
+#include <vector>
#include <GL/gl.h>
+struct ArrayState;
+
+struct BufferContent
+{
+ struct Array
+ {
+ GLenum kind;
+ unsigned index;
+ unsigned size;
+ GLenum type;
+ int offset;
+
+ Array(const ArrayState &);
+ };
+
+ bool consistent;
+ unsigned stride;
+ std::vector<Array> arrays;
+
+ BufferContent();
+ void update(const ArrayState &);
+ std::string describe() const;
+};
+
struct BufferState
{
unsigned id;
+ GLenum target;
GLenum usage;
unsigned size;
char *data;
+ BufferContent content;
BufferState();
void set_data(unsigned, const void *, GLenum);
/* $Id$
This file is part of gldbg
-Copyright © 2009 Mikko Rasa, Mikkosoft Productions
+Copyright © 2009-2010 Mikko Rasa, Mikkosoft Productions
Distributed under the GPL
*/
IO::print("Buffer %d:\n", id);
IO::print(" Size: %d bytes\n", buf.size);
IO::print(" Usage: %s\n", describe_enum(buf.usage, ""));
+ if(buf.content.stride)
+ {
+ IO::print(" Stride: %d bytes\n", buf.content.stride);
+
+ IO::print(" Arrays:\n");
+ const vector<BufferContent::Array> &arrays = buf.content.arrays;
+ for(vector<BufferContent::Array>::const_iterator i=arrays.begin(); i!=arrays.end(); ++i)
+ {
+ if(i->kind)
+ IO::print(" %2d: %s, %d %s\n", i->offset,
+ describe_enum(i->kind, ""), i->size, describe_enum(i->type, "DataType"));
+ else
+ IO::print(" %2d: Attrib %d, %d %s\n", i->offset,
+ i->index, i->size, describe_enum(i->type, "DataType"));
+ }
+
+ IO::print(" Data:\n");
+ string header;
+ for(vector<BufferContent::Array>::const_iterator i=arrays.begin(); i!=arrays.end(); ++i)
+ {
+ if(!header.empty())
+ header += " | ";
+
+ string label;
+ if(i->kind==GL_VERTEX_ARRAY)
+ label = "Vertex";
+ else if(i->kind==GL_NORMAL_ARRAY)
+ label = "Normal";
+ else if(i->kind==GL_COLOR_ARRAY)
+ label = "Color";
+ else if(i->kind==GL_TEXTURE_COORD_ARRAY)
+ {
+ if(i->size==1)
+ label = "TexC";
+ else
+ label = "TexCoord";
+ }
+ else if(!i->kind)
+ {
+ if(i->size==1)
+ label = format("A %d", i->index);
+ else
+ label = format("Attrib %d", i->index);
+ }
+
+ unsigned width = i->size;
+ if(i->type==GL_FLOAT)
+ width *= 5;
+ else if(i->type==GL_UNSIGNED_BYTE)
+ width *= 3;
+ width += i->size-1;
+
+ header.append((width-label.size())/2, ' ');
+ header += label;
+ header.append((width-label.size()+1)/2, ' ');
+ }
+ IO::print(" %s\n", header);
+
+ unsigned n_verts = buf.size/buf.content.stride;
+ for(unsigned i=0; i<n_verts; ++i)
+ {
+ const char *vertex = buf.data+i*buf.content.stride;
+
+ string line;
+ for(vector<BufferContent::Array>::const_iterator j=arrays.begin(); j!=arrays.end(); ++j)
+ {
+ if(!line.empty())
+ line += " |";
+
+ const char *base = vertex+j->offset;
+ for(unsigned k=0; k<j->size; ++k)
+ {
+ if(j->type==GL_FLOAT)
+ line += format(" %5.2f", *(reinterpret_cast<const float *>(base)+k));
+ else if(j->type==GL_UNSIGNED_BYTE)
+ line += format(" %3u", *(reinterpret_cast<const unsigned char *>(base)+k));
+ }
+ }
+
+ IO::print("%3d:%s\n", i, line);
+ }
+ }
}
}
/* $Id$
This file is part of gldbg
-Copyright © 2009 Mikko Rasa, Mikkosoft Productions
+Copyright © 2009-2010 Mikko Rasa, Mikkosoft Productions
Distributed under the GPL
*/
GlState::GlState():
decoder(gldecoder_new(this, NULL)),
active_tex(0),
+ client_active_tex(0),
array_buffer(0),
element_buffer(0)
{
+ vertex_array.kind = GL_VERTEX_ARRAY;
+ normal_array.kind = GL_NORMAL_ARRAY;
+ color_array.kind = GL_COLOR_ARRAY;
+ for(unsigned i=0; i<8; ++i)
+ {
+ texcoord_arrays[i].kind = GL_TEXTURE_COORD_ARRAY;
+ texcoord_arrays[i].index = i;
+ }
+
decoder->glColor3ub = wrap_normalized<GLubyte, glColor3f>;
decoder->glColor3ubv = wrap_array<GLubyte, wrap_normalized<GLubyte, glColor3f> >;
decoder->glColor4ub = wrap_normalized<GLubyte, glColor4f>;
decoder->glTexCoord4fv = wrap_array<float, glTexCoord4f>;
decoder->glNormal3f = glNormal3f;
decoder->glNormal3fv = wrap_array<float, glNormal3f>;
+
decoder->glActiveTexture = glActiveTexture;
decoder->glActiveTextureARB = glActiveTexture;
decoder->glBindTexture = glBindTexture;
decoder->glTexParameteri = glTexParameteri;
decoder->glTexParameteriv = glTexParameteriv;
decoder->glDeleteTextures = glDeleteTextures;
+
+ decoder->glVertexPointer = glVertexPointer;
+ decoder->glNormalPointer = glNormalPointer;
+ decoder->glColorPointer = glColorPointer;
+ decoder->glClientActiveTexture = glClientActiveTexture;
+ decoder->glClientActiveTextureARB = glClientActiveTexture;
+ decoder->glTexCoordPointer = glTexCoordPointer;
+
decoder->glBindBuffer = glBindBuffer;
decoder->glBindBufferARB = glBindBuffer;
decoder->glBufferData = glBufferData;
decoder->glBufferDataARB = glBufferData;
decoder->glBufferSubData = glBufferSubData;
decoder->glBufferSubDataARB = glBufferSubData;
+ decoder->glDeleteBuffers = glDeleteBuffers;
+ decoder->glDeleteBuffersARB = glDeleteBuffers;
}
GlState::~GlState()
return const_cast<GlState *>(this)->get_current_buffer(target);
}
+bool &GlState::get_boolean_state(GLenum state)
+{
+ if(state==GL_VERTEX_ARRAY)
+ return vertex_array.enabled;
+ else if(state==GL_NORMAL_ARRAY)
+ return normal_array.enabled;
+ else if(state==GL_COLOR_ARRAY)
+ return color_array.enabled;
+ else if(state==GL_TEXTURE_COORD_ARRAY)
+ return texcoord_arrays[client_active_tex].enabled;
+
+ static bool dummy;
+ return dummy;
+}
+
TextureState *GlState::get_current_texture(GLenum target)
{
return texunits[active_tex].get_current_texture(target);
return 0;
}
+const ArrayState &GlState::get_array(GLenum array) const
+{
+ if(array==GL_VERTEX_ARRAY)
+ return vertex_array;
+ else if(array==GL_NORMAL_ARRAY)
+ return normal_array;
+ else if(array==GL_COLOR_ARRAY)
+ return color_array;
+ else if(array==GL_TEXTURE_COORD_ARRAY)
+ return texcoord_arrays[client_active_tex];
+ else
+ throw InvalidParameterValue("Invalid array");
+}
+
+const ArrayState &GlState::get_texture_coord_array(unsigned index) const
+{
+ return texcoord_arrays[index];
+}
+
+const ArrayState &GlState::get_attrib_array(unsigned index) const
+{
+ map<unsigned, ArrayState>::const_iterator i = attrib_arrays.find(index);
+ if(i!=attrib_arrays.end())
+ return i->second;
+
+ // XXX Return a dummy?
+ throw KeyError("Unknown attribute array");
+}
+
void GlState::set_current_texture(GLenum target, unsigned id)
{
TexUnitState &unit = texunits[active_tex];
element_buffer = buf;
}
+// Boolean state
+
+void GlState::glEnableClientState(void *user_data, GLenum state)
+{
+ reinterpret_cast<GlState *>(user_data)->get_boolean_state(state) = true;
+}
+
+void GlState::glDisableClientState(void *user_data, GLenum state)
+{
+ reinterpret_cast<GlState *>(user_data)->get_boolean_state(state) = false;
+}
+
+void GlState::glEnableVertexAttribArray(void *user_data, unsigned index)
+{
+ reinterpret_cast<GlState *>(user_data)->attrib_arrays[index].enabled = true;
+}
+
+void GlState::glDisableVertexAttribArray(void *user_data, unsigned index)
+{
+ reinterpret_cast<GlState *>(user_data)->attrib_arrays[index].enabled = false;
+}
+
// Vertex attributes
void GlState::glColor3f(void *user_data, float r, float g, float b)
}
void GlState::glBindTexture(void *user_data, GLenum target, unsigned id)
-{ reinterpret_cast<GlState *>(user_data)->set_current_texture(target, id); }
+{
+ reinterpret_cast<GlState *>(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 *)
{
reinterpret_cast<GlState *>(user_data)->textures.erase(ids[i]);
}
+// Vertex arrays
+
+void GlState::glVertexPointer(void *user_data, int size, GLenum type, int stride, const void *data)
+{
+ GlState *self = reinterpret_cast<GlState *>(user_data);
+ self->vertex_array.set(size, type, false, stride, self->array_buffer, reinterpret_cast<long>(data));
+}
+
+void GlState::glNormalPointer(void *user_data, GLenum type, int stride, const void *data)
+{
+ GlState *self = reinterpret_cast<GlState *>(user_data);
+ self->normal_array.set(3, type, true, stride, self->array_buffer, reinterpret_cast<long>(data));
+}
+
+void GlState::glColorPointer(void *user_data, int size, GLenum type, int stride, const void *data)
+{
+ GlState *self = reinterpret_cast<GlState *>(user_data);
+ self->color_array.set(size, type, true, stride, self->array_buffer, reinterpret_cast<long>(data));
+}
+
+void GlState::glClientActiveTexture(void *user_data, unsigned index)
+{
+ reinterpret_cast<GlState *>(user_data)->client_active_tex = index-GL_TEXTURE0;
+}
+
+void GlState::glTexCoordPointer(void *user_data, int size, GLenum type, int stride, const void *data)
+{
+ GlState *self = reinterpret_cast<GlState *>(user_data);
+ self->texcoord_arrays[self->client_active_tex].set(size, type, false, stride, self->array_buffer, reinterpret_cast<long>(data));
+}
+
+void GlState::glVertexAttribPointer(void *user_data, unsigned index, int size, GLenum type, int norm, int stride, const void *data)
+{
+ GlState *self = reinterpret_cast<GlState *>(user_data);
+ self->attrib_arrays[index].set(size, type, norm, stride, self->array_buffer, reinterpret_cast<long>(data));
+}
+
// Buffer objects
void GlState::glBindBuffer(void *user_data, GLenum target, unsigned id)
if(BufferState *buf = reinterpret_cast<GlState *>(user_data)->get_current_buffer(target))
buf->set_sub_data(offset, size, data);
}
+
+void GlState::glDeleteBuffers(void *user_data, int count, const unsigned *ids)
+{
+ for(int i=0; i<count; ++i)
+ reinterpret_cast<GlState *>(user_data)->buffers.erase(ids[i]);
+}
/* $Id$
This file is part of gldbg
-Copyright © 2009 Mikko Rasa, Mikkosoft Productions
+Copyright © 2009-2010 Mikko Rasa, Mikkosoft Productions
Distributed under the GPL
*/
#include <map>
#include <vector>
+#include "arraystate.h"
#include "bufferstate.h"
#include "gldecoder.h"
#include "texturestate.h"
Vector4 texcoord[8];
Vector3 normal;
unsigned active_tex;
+ unsigned client_active_tex;
TextureMap textures;
TexUnitState texunits[8];
BufferMap buffers;
BufferState *array_buffer;
BufferState *element_buffer;
+ ArrayState vertex_array;
+ ArrayState normal_array;
+ ArrayState color_array;
+ ArrayState texcoord_arrays[8];
+ std::map<unsigned, ArrayState> attrib_arrays;
public:
GlState();
const BufferMap &get_buffers() const { return buffers; }
const BufferState &get_buffer(unsigned) const;
const BufferState *get_current_buffer(GLenum) const;
+ const ArrayState &get_array(GLenum) const;
+ const ArrayState &get_texture_coord_array(unsigned) const;
+ const ArrayState &get_attrib_array(unsigned) const;
private:
+ bool &get_boolean_state(GLenum);
TextureState *get_current_texture(GLenum);
BufferState *get_current_buffer(GLenum);
void set_current_texture(GLenum, unsigned);
void set_current_buffer(GLenum, unsigned);
+ static void glEnableClientState(void *, GLenum);
+ static void glDisableClientState(void *, GLenum);
+ static void glEnableVertexAttribArray(void *, unsigned);
+ static void glDisableVertexAttribArray(void *, 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 glTexParameteriv(void *, GLenum, GLenum, const int *);
static void glDeleteTextures(void *, int, const unsigned *);
+ static void glVertexPointer(void *, int, GLenum, int, const void *);
+ static void glNormalPointer(void *, GLenum, int, const void *);
+ static void glColorPointer(void *, int, GLenum, int, const void *);
+ static void glClientActiveTexture(void *, unsigned);
+ static void glTexCoordPointer(void *, int, GLenum, int, const void *);
+ static void glVertexAttribPointer(void *, unsigned, int, GLenum, int, int, const void *);
+
static void glBindBuffer(void *, GLenum, unsigned);
static void glBufferData(void *, GLenum, int, const void *, GLenum);
static void glBufferSubData(void *, GLenum, int, int, const void *);
+ static void glDeleteBuffers(void *, int, const unsigned *);
};
#endif