]> git.tdb.fi Git - gldbg.git/blobdiff - flavors/gl/source/glstate.cpp
Move the profiler and inspector tools to the gl flavor
[gldbg.git] / flavors / gl / source / glstate.cpp
diff --git a/flavors/gl/source/glstate.cpp b/flavors/gl/source/glstate.cpp
new file mode 100644 (file)
index 0000000..1459324
--- /dev/null
@@ -0,0 +1,414 @@
+/* $Id$
+
+This file is part of gldbg
+Copyright © 2009-2010  Mikko Rasa, Mikkosoft Productions
+Distributed under the GPL
+*/
+
+#include <msp/core/except.h>
+#include "glstate.h"
+
+using namespace std;
+using namespace Msp;
+
+namespace {
+
+template<typename T>
+float normalize(T v);
+
+template<>
+float normalize<GLubyte>(GLubyte v)
+{ return v/255.0f; }
+
+template<>
+float normalize<GLbyte>(GLbyte v)
+{ return (2*v+1)/255.0f; }
+
+template<typename T, void (*func)(void *, float)>
+void wrap_normalized(void *user_data, T v0)
+{ func(user_data, v0); }
+
+template<typename T, void (*func)(void *, float, float)>
+void wrap_normalized(void *user_data, T v0, T v1)
+{ func(user_data, v0, v1); }
+
+template<typename T, void (*func)(void *, float, float, float)>
+void wrap_normalized(void *user_data, T v0, T v1, T v2)
+{ func(user_data, v0, v1, v2); }
+
+template<typename T, void (*func)(void *, float, float, float, float)>
+void wrap_normalized(void *user_data, T v0, T v1, T v2, T v3)
+{ func(user_data, v0, v1, v2, v3); }
+
+template<typename T, void (*func)(void *, T)>
+void wrap_array(void *user_data, const T *v)
+{ func(user_data, v[0]); }
+
+template<typename T, void (*func)(void *, T, T)>
+void wrap_array(void *user_data, const T *v)
+{ func(user_data, v[0], v[1]); }
+
+template<typename T, void (*func)(void *, T, T, T)>
+void wrap_array(void *user_data, const T *v)
+{ func(user_data, v[0], v[1], v[2]); }
+
+template<typename T, void (*func)(void *, T, T, T, T)>
+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),
+       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->glColor4ubv = wrap_array<GLubyte, wrap_normalized<GLubyte, glColor4f> >;
+       decoder->glColor3f = glColor3f;
+       decoder->glColor3fv = wrap_array<float, glColor3f>;
+       decoder->glColor4f = glColor4f;
+       decoder->glColor4fv = wrap_array<float, glColor4f>;
+       decoder->glTexCoord1f = glTexCoord1f;
+       decoder->glTexCoord1fv = wrap_array<float, glTexCoord1f>;
+       decoder->glTexCoord2f = glTexCoord2f;
+       decoder->glTexCoord2fv = wrap_array<float, glTexCoord2f>;
+       decoder->glTexCoord3f = glTexCoord3f;
+       decoder->glTexCoord3fv = wrap_array<float, glTexCoord3f>;
+       decoder->glTexCoord4f = glTexCoord4f;
+       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->glTexImage2D = glTexImage2D;
+       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()
+{
+       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<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);
+}
+
+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;
+}
+
+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];
+       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;
+}
+
+// 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)
+{ 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<GlState *>(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<GlState *>(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<GlState *>(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<GlState *>(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<GlState *>(user_data)->active_tex = index-GL_TEXTURE0;
+}
+
+void GlState::glBindTexture(void *user_data, GLenum target, unsigned 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 *)
+{
+       if(TextureState *tex = reinterpret_cast<GlState *>(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<GlState *>(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<count; ++i)
+               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)
+{ reinterpret_cast<GlState *>(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<GlState *>(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<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]);
+}