X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=flavors%2Fgl%2Fsource%2Fglstate.cpp;fp=flavors%2Fgl%2Fsource%2Fglstate.cpp;h=1459324232f36d3b6af583bfe1def2a3e0ffb22a;hb=f53057ce9b5eb3c7256a4aca95b4944733e14503;hp=0000000000000000000000000000000000000000;hpb=73c55fc88d8bad336fbd6cfecedc0cf18d06167c;p=gldbg.git diff --git a/flavors/gl/source/glstate.cpp b/flavors/gl/source/glstate.cpp new file mode 100644 index 0000000..1459324 --- /dev/null +++ b/flavors/gl/source/glstate.cpp @@ -0,0 +1,414 @@ +/* $Id$ + +This file is part of gldbg +Copyright © 2009-2010 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), + 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; + 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->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(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::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(user_data)->get_boolean_state(state) = true; +} + +void GlState::glDisableClientState(void *user_data, GLenum state) +{ + reinterpret_cast(user_data)->get_boolean_state(state) = false; +} + +void GlState::glEnableVertexAttribArray(void *user_data, unsigned index) +{ + reinterpret_cast(user_data)->attrib_arrays[index].enabled = true; +} + +void GlState::glDisableVertexAttribArray(void *user_data, unsigned index) +{ + reinterpret_cast(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(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-GL_TEXTURE0; +} + +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]); +} + +// Vertex arrays + +void GlState::glVertexPointer(void *user_data, int size, GLenum type, int stride, const void *data) +{ + GlState *self = reinterpret_cast(user_data); + self->vertex_array.set(size, type, false, stride, self->array_buffer, reinterpret_cast(data)); +} + +void GlState::glNormalPointer(void *user_data, GLenum type, int stride, const void *data) +{ + GlState *self = reinterpret_cast(user_data); + self->normal_array.set(3, type, true, stride, self->array_buffer, reinterpret_cast(data)); +} + +void GlState::glColorPointer(void *user_data, int size, GLenum type, int stride, const void *data) +{ + GlState *self = reinterpret_cast(user_data); + self->color_array.set(size, type, true, stride, self->array_buffer, reinterpret_cast(data)); +} + +void GlState::glClientActiveTexture(void *user_data, unsigned index) +{ + reinterpret_cast(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(user_data); + self->texcoord_arrays[self->client_active_tex].set(size, type, false, stride, self->array_buffer, reinterpret_cast(data)); +} + +void GlState::glVertexAttribPointer(void *user_data, unsigned index, int size, GLenum type, int norm, int stride, const void *data) +{ + GlState *self = reinterpret_cast(user_data); + self->attrib_arrays[index].set(size, type, norm, stride, self->array_buffer, reinterpret_cast(data)); +} + +// 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); +} + +void GlState::glDeleteBuffers(void *user_data, int count, const unsigned *ids) +{ + for(int i=0; i(user_data)->buffers.erase(ids[i]); +}