X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=flavors%2Fgl%2Fsource%2Fglstate.cpp;h=750d70315835a45395512512ce04ff2a2963cf3d;hb=d72ef6d75a11f6cc05ab8ec039520719e1044741;hp=e3c9871c34c5ca5772a229f55c6c6107e288325d;hpb=fffbad8853e5849c64227635db70e5ce980d2f26;p=gldbg.git diff --git a/flavors/gl/source/glstate.cpp b/flavors/gl/source/glstate.cpp index e3c9871..750d703 100644 --- a/flavors/gl/source/glstate.cpp +++ b/flavors/gl/source/glstate.cpp @@ -1,10 +1,3 @@ -/* $Id$ - -This file is part of gldbg -Copyright © 2009-2011 Mikko Rasa, Mikkosoft Productions -Distributed under the GPL -*/ - #include #include "glstate.h" @@ -70,26 +63,25 @@ Vector4::Vector4(): GlState::GlState(): decoder(gldecoder_new(this, NULL)), + texcoord(1), active_tex(0), client_active_tex(0), + texunits(1), array_buffer(0), - element_buffer(0) + element_buffer(0), + uniform_buffer(0), + texcoord_arrays(1) { 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; - } + texcoord_arrays[0].kind = GL_TEXTURE_COORD_ARRAY; + texcoord_arrays[0].index = 0; + + decoder->glGetIntegerv = glGetIntegerv; decoder->glEnableClientState = glEnableClientState; decoder->glDisableClientState = glDisableClientState; - decoder->glEnableVertexAttribArray = glEnableVertexAttribArray; - decoder->glEnableVertexAttribArrayARB = glEnableVertexAttribArray; - decoder->glDisableVertexAttribArray = glDisableVertexAttribArray; - decoder->glDisableVertexAttribArrayARB = glDisableVertexAttribArray; decoder->glColor3ub = wrap_normalized; decoder->glColor3ubv = wrap_array >; @@ -110,25 +102,27 @@ GlState::GlState(): 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->glEnableVertexAttribArray = glEnableVertexAttribArray; + decoder->glEnableVertexAttribArrayARB = glEnableVertexAttribArray; + decoder->glDisableVertexAttribArray = glDisableVertexAttribArray; + decoder->glDisableVertexAttribArrayARB = glDisableVertexAttribArray; decoder->glVertexAttribPointer = glVertexAttribPointer; decoder->glVertexAttribPointerARB = glVertexAttribPointer; + decoder->glDrawElements = glDrawElements; + decoder->glDrawRangeElements = glDrawRangeElements; + decoder->glDrawRangeElementsEXT = glDrawRangeElements; + decoder->glBindBuffer = glBindBuffer; decoder->glBindBufferARB = glBindBuffer; + decoder->glBindBufferBase = glBindBufferBase; + decoder->glBindBufferRange = glBindBufferRange; decoder->glBufferData = glBufferData; decoder->glBufferDataARB = glBufferData; decoder->glBufferSubData = glBufferSubData; @@ -136,9 +130,34 @@ GlState::GlState(): decoder->glDeleteBuffers = glDeleteBuffers; decoder->glDeleteBuffersARB = glDeleteBuffers; - decoder->glDrawElements = glDrawElements; - decoder->glDrawRangeElements = glDrawRangeElements; - decoder->glDrawRangeElementsEXT = glDrawRangeElements; + decoder->glActiveTexture = glActiveTexture; + decoder->glActiveTextureARB = glActiveTexture; + decoder->glBindTexture = glBindTexture; + decoder->glTexImage2D = glTexImage2D; + decoder->glTexParameteri = glTexParameteri; + decoder->glTexParameteriv = glTexParameteriv; + decoder->glDeleteTextures = glDeleteTextures; + + decoder->glCreateShader = glCreateShader; + decoder->glCreateShaderObjectARB = glCreateShader; + decoder->glShaderSource = glShaderSource; + decoder->glShaderSourceARB = glShaderSource; + decoder->glCompileShader = glCompileShader; + decoder->glCompileShaderARB = glCompileShader; + decoder->glGetShaderiv = glGetShaderiv; + decoder->glGetShaderInfoLog = glGetShaderInfoLog; + decoder->glDeleteShader = glDeleteShader; + decoder->glCreateProgram = glCreateProgram; + decoder->glCreateProgramObjectARB = glCreateProgram; + decoder->glAttachShader = glAttachShader; + decoder->glAttachObjectARB = glAttachShader; + decoder->glLinkProgram = glLinkProgram; + decoder->glLinkProgramARB = glLinkProgram; + decoder->glGetProgramiv = glGetProgramiv; + decoder->glGetProgramInfoLog = glGetProgramInfoLog; + decoder->glDeleteObjectARB = glDeleteObjectARB; + decoder->glGetObjectParameterivARB = glGetObjectParameterivARB; + decoder->glGetInfoLogARB = glGetInfoLogARB; } GlState::~GlState() @@ -151,20 +170,156 @@ int GlState::decode(const char *data, unsigned len) return gldecoder_decode(decoder, data, len); } -const TextureState &GlState::get_texture(unsigned id) const +void GlState::glGetIntegerv(void *user_data, GLenum pname, int *param) { - TextureMap::const_iterator i = textures.find(id); - if(i==textures.end()) - throw runtime_error("Unknown texture"); - return i->second; + GlState *self = reinterpret_cast(user_data); + if(pname==GL_MAX_TEXTURE_UNITS) + { + self->texcoord.resize(*param); + self->texunits.resize(*param); + self->texcoord_arrays.resize(*param); + for(unsigned i=0; itexcoord_arrays.size(); ++i) + { + self->texcoord_arrays[i].kind = GL_TEXTURE_COORD_ARRAY; + self->texcoord_arrays[i].index = i; + } + } + else if(pname==GL_MAX_VERTEX_ATTRIBS) + { + self->attrib_arrays.resize(*param); + for(unsigned i=0; iattrib_arrays.size(); ++i) + self->attrib_arrays[i].index = i; + } + else if(pname==GL_MAX_UNIFORM_BUFFER_BINDINGS) + self->uniform_bind_points.resize(*param); } -const BufferState &GlState::get_buffer(unsigned id) const +// Boolean state + +bool &GlState::get_boolean_state(GLenum state) { - BufferMap::const_iterator i = buffers.find(id); - if(i==buffers.end()) - throw runtime_error("Unknown buffer"); - return i->second; + 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; +} + +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; +} + +// 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; +} + +// 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::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; +} + +void GlState::glVertexAttribPointer(void *user_data, unsigned index, int size, GLenum type, unsigned char 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)); } const ArrayState &GlState::get_array(GLenum array) const @@ -188,65 +343,24 @@ const ArrayState &GlState::get_texture_coord_array(unsigned index) const 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 runtime_error("Unknown attribute array"); + return attrib_arrays[index]; } -const BufferState *GlState::get_current_buffer(GLenum target) const -{ - return const_cast(this)->get_current_buffer(target); -} +// Array draw commands -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) +void GlState::glDrawElements(void *user_data, GLenum, int, GLenum type, const void *) { - return texunits[active_tex].get_current_texture(target); + if(BufferState *buf = reinterpret_cast(user_data)->element_buffer) + buf->content.update_elements(type); } -BufferState *GlState::get_current_buffer(GLenum target) +void GlState::glDrawRangeElements(void *user_data, GLenum, unsigned, unsigned, int, GLenum type, const void *) { - if(target==GL_ARRAY_BUFFER) - return array_buffer; - else if(target==GL_ELEMENT_ARRAY_BUFFER) - return element_buffer; - return 0; + if(BufferState *buf = reinterpret_cast(user_data)->element_buffer) + buf->content.update_elements(type); } -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); -} +// Buffer objects void GlState::set_current_buffer(GLenum target, unsigned id) { @@ -262,90 +376,119 @@ void GlState::set_current_buffer(GLenum target, unsigned id) array_buffer = buf; else if(target==GL_ELEMENT_ARRAY_BUFFER) element_buffer = buf; + else if(target==GL_UNIFORM_BUFFER) + uniform_buffer = buf; } -ArrayState &GlState::get_attrib_array(unsigned index) +BufferState *GlState::get_buffer_object(unsigned id) { - map::iterator i = attrib_arrays.find(index); - if(i!=attrib_arrays.end()) - return i->second; - - ArrayState &array = attrib_arrays[index]; - array.index = index; - - return array; + BufferMap::iterator i = buffers.find(id); + return (i==buffers.end() ? 0 : &i->second); } -// Boolean state +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; + else if(target==GL_UNIFORM_BUFFER) + return uniform_buffer; + return 0; +} -void GlState::glEnableClientState(void *user_data, GLenum state) +BufferBindingState *GlState::get_buffer_binding(GLenum target, unsigned index) { - reinterpret_cast(user_data)->get_boolean_state(state) = true; + if(target==GL_UNIFORM_BUFFER) + return &uniform_bind_points[index]; + return 0; } -void GlState::glDisableClientState(void *user_data, GLenum state) +void GlState::glBindBuffer(void *user_data, GLenum target, unsigned id) { - reinterpret_cast(user_data)->get_boolean_state(state) = false; + reinterpret_cast(user_data)->set_current_buffer(target, id); } -void GlState::glEnableVertexAttribArray(void *user_data, unsigned index) +void GlState::glBindBufferBase(void *user_data, GLenum target, unsigned index, unsigned id) { - reinterpret_cast(user_data)->attrib_arrays[index].enabled = true; + if(BufferState *buffer = reinterpret_cast(user_data)->get_buffer_object(id)) + glBindBufferRange(user_data, target, index, id, 0, buffer->size); } -void GlState::glDisableVertexAttribArray(void *user_data, unsigned index) +void GlState::glBindBufferRange(void *user_data, GLenum target, unsigned index, unsigned id, int offset, int size) { - reinterpret_cast(user_data)->attrib_arrays[index].enabled = false; + GlState *self = reinterpret_cast(user_data); + if(BufferBindingState *binding = self->get_buffer_binding(target, index)) + { + binding->buffer = self->get_buffer_object(id); + binding->offset = offset; + binding->size = size; + } } -// Vertex attributes +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::glColor3f(void *user_data, float r, float g, float b) -{ glColor4f(user_data, r, g, b, 1.0f); } +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::glColor4f(void *user_data, float r, float g, float b, float a) +void GlState::glDeleteBuffers(void *user_data, int count, const unsigned *ids) { - Vector4 &color = reinterpret_cast(user_data)->color; - color.r = r; - color.g = g; - color.b = b; - color.a = a; + for(int i=0; i(user_data)->buffers.erase(ids[i]); } -void GlState::glNormal3f(void *user_data, float x, float y, float z) +const BufferState &GlState::get_buffer(unsigned id) const { - Vector3 &normal = reinterpret_cast(user_data)->normal; - normal.x = x; - normal.y = y; - normal.z = z; + BufferMap::const_iterator i = buffers.find(id); + if(i==buffers.end()) + throw runtime_error("Unknown buffer"); + return i->second; } -void GlState::glTexCoord1f(void *user_data, float s) -{ glTexCoord4f(user_data, s, 0.0f, 0.0f, 1.0f); } +const BufferState *GlState::get_current_buffer(GLenum target) const +{ + return const_cast(this)->get_current_buffer(target); +} -void GlState::glTexCoord2f(void *user_data, float s, float t) -{ glTexCoord4f(user_data, s, t, 0.0f, 1.0f); } +const BufferBindingState &GlState::get_buffer_binding(GLenum target, unsigned index) const +{ + if(target==GL_UNIFORM_BUFFER) + return uniform_bind_points[index]; + throw runtime_error("This buffer target does not have indexed binding points"); +} -void GlState::glTexCoord3f(void *user_data, float s, float t, float p) -{ glTexCoord4f(user_data, s, t, p, 1.0f); } +// Textures -void GlState::glTexCoord4f(void *user_data, float s, float t, float p, float q) +void GlState::set_current_texture(GLenum target, unsigned id) { - unsigned index = reinterpret_cast(user_data)->active_tex; - glMultiTexCoord4f(user_data, index, s, t, p, q); + 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::glMultiTexCoord4f(void *user_data, unsigned index, float s, float t, float p, float q) +TextureState *GlState::get_current_texture(GLenum target) { - Vector4 &texcoord = reinterpret_cast(user_data)->texcoord[index]; - texcoord.s = s; - texcoord.t = t; - texcoord.p = p; - texcoord.q = q; + return texunits[active_tex].get_current_texture(target); } -// Textures - void GlState::glActiveTexture(void *user_data, unsigned index) { reinterpret_cast(user_data)->active_tex = index-GL_TEXTURE0; @@ -363,7 +506,9 @@ void GlState::glTexImage2D(void *user_data, GLenum target, int level, int ifmt, } void GlState::glTexParameteri(void *user_data, GLenum target, GLenum param, int value) -{ glTexParameteriv(user_data, target, param, &value); } +{ + glTexParameteriv(user_data, target, param, &value); +} void GlState::glTexParameteriv(void *user_data, GLenum target, GLenum param, const int *values) { @@ -377,74 +522,197 @@ void GlState::glDeleteTextures(void *user_data, int count, const unsigned *ids) reinterpret_cast(user_data)->textures.erase(ids[i]); } -// Vertex arrays +const TextureState &GlState::get_texture(unsigned id) const +{ + TextureMap::const_iterator i = textures.find(id); + if(i==textures.end()) + throw runtime_error("Unknown texture"); + return i->second; +} -void GlState::glVertexPointer(void *user_data, int size, GLenum type, int stride, const void *data) +// Shaders + +ShaderState *GlState::get_shader(unsigned id, bool create) { - GlState *self = reinterpret_cast(user_data); - self->vertex_array.set(size, type, false, stride, self->array_buffer, reinterpret_cast(data)); + ShaderMap::iterator i = shaders.find(id); + if(i==shaders.end() && create) + { + i = shaders.insert(ShaderMap::value_type(id, ShaderState())).first; + i->second.id = id; + } + return (i!=shaders.end() ? &i->second : 0); } -void GlState::glNormalPointer(void *user_data, GLenum type, int stride, const void *data) +void GlState::delete_shader(unsigned id) { - GlState *self = reinterpret_cast(user_data); - self->normal_array.set(3, type, true, stride, self->array_buffer, reinterpret_cast(data)); + ShaderMap::iterator i = shaders.find(id); + if(i==shaders.end()) + return; + + for(ProgramMap::const_iterator j=programs.begin(); j!=programs.end(); ++j) + { + const vector &prog_shaders = j->second.shaders; + for(vector::const_iterator k=prog_shaders.begin(); k!=prog_shaders.end(); ++k) + if(*k==&i->second) + { + i->second.pending_delete = true; + return; + } + } + + shaders.erase(i); } -void GlState::glColorPointer(void *user_data, int size, GLenum type, int stride, const void *data) +ProgramState *GlState::get_program(unsigned id, bool create) { - GlState *self = reinterpret_cast(user_data); - self->color_array.set(size, type, true, stride, self->array_buffer, reinterpret_cast(data)); + ProgramMap::iterator i = programs.find(id); + if(i==programs.end() && create) + { + i = programs.insert(ProgramMap::value_type(id, ProgramState())).first; + i->second.id = id; + } + return (i!=programs.end() ? &i->second : 0); } -void GlState::glClientActiveTexture(void *user_data, unsigned index) +void GlState::delete_program(unsigned id) { - reinterpret_cast(user_data)->client_active_tex = index-GL_TEXTURE0; + ProgramMap::iterator i = programs.find(id); + if(i==programs.end()) + return; + + vector prog_shaders = i->second.shaders; + programs.erase(i); + for(vector::const_iterator j=prog_shaders.begin(); j!=prog_shaders.end(); ++j) + if((*j)->pending_delete) + delete_shader((*j)->id); } -void GlState::glTexCoordPointer(void *user_data, int size, GLenum type, int stride, const void *data) +void GlState::glCreateShader(void *user_data, unsigned id, GLenum type) { - GlState *self = reinterpret_cast(user_data); - self->texcoord_arrays[self->client_active_tex].set(size, type, false, stride, self->array_buffer, reinterpret_cast(data)); + if(ShaderState *shader = reinterpret_cast(user_data)->get_shader(id, true)) + shader->type = type; } -void GlState::glVertexAttribPointer(void *user_data, unsigned index, int size, GLenum type, unsigned char norm, int stride, const void *data) +void GlState::glShaderSource(void *user_data, unsigned id, int count, const char **str, const int *length) +{ + if(ShaderState *shader = reinterpret_cast(user_data)->get_shader(id, false)) + { + shader->source.clear(); + for(int i=0; isource.push_back(str[i]); + else + shader->source.push_back(string(str[i], length[i])); + } + shader->source_changed = true; + } +} + +void GlState::glCompileShader(void *user_data, unsigned id) +{ + if(ShaderState *shader = reinterpret_cast(user_data)->get_shader(id, false)) + shader->source_changed = false; +} + +void GlState::glGetShaderiv(void *user_data, unsigned id, GLenum pname, int *param) +{ + if(ShaderState *shader = reinterpret_cast(user_data)->get_shader(id, false)) + { + if(pname==GL_COMPILE_STATUS) + shader->compile_status = *param; + } +} + +void GlState::glGetShaderInfoLog(void *user_data, unsigned id, int, int *, char *log) +{ + if(ShaderState *shader = reinterpret_cast(user_data)->get_shader(id, false)) + shader->info_log = log; +} + +void GlState::glDeleteShader(void *user_data, unsigned id) +{ + reinterpret_cast(user_data)->delete_shader(id); +} + +void GlState::glCreateProgram(void *user_data, unsigned id) +{ + reinterpret_cast(user_data)->get_program(id, true); +} + +void GlState::glAttachShader(void *user_data, unsigned prog_id, unsigned shader_id) { GlState *self = reinterpret_cast(user_data); - self->get_attrib_array(index).set(size, type, norm, stride, self->array_buffer, reinterpret_cast(data)); + if(ProgramState *prog = self->get_program(prog_id, false)) + if(ShaderState *shader = self->get_shader(shader_id, false)) + prog->shaders.push_back(shader); } -// Buffer objects +void GlState::glLinkProgram(void *user_data, unsigned id) +{ + if(ProgramState *program = reinterpret_cast(user_data)->get_program(id, false)) + program->shaders_changed = false; +} -void GlState::glBindBuffer(void *user_data, GLenum target, unsigned id) -{ reinterpret_cast(user_data)->set_current_buffer(target, id); } +void GlState::glGetProgramiv(void *user_data, unsigned id, GLenum pname, int *param) +{ + if(ProgramState *program = reinterpret_cast(user_data)->get_program(id, false)) + { + if(pname==GL_LINK_STATUS) + program->link_status = *param; + } +} -void GlState::glBufferData(void *user_data, GLenum target, int size, const void *data, GLenum usage) +void GlState::glGetProgramInfoLog(void *user_data, unsigned id, int, int *, char *log) { - if(BufferState *buf = reinterpret_cast(user_data)->get_current_buffer(target)) - buf->set_data(size, data, usage); + if(ProgramState *program = reinterpret_cast(user_data)->get_program(id, false)) + program->info_log = log; } -void GlState::glBufferSubData(void *user_data, GLenum target, int offset, int size, const void *data) +void GlState::glDeleteProgram(void *user_data, unsigned id) { - if(BufferState *buf = reinterpret_cast(user_data)->get_current_buffer(target)) - buf->set_sub_data(offset, size, data); + reinterpret_cast(user_data)->delete_program(id); } -void GlState::glDeleteBuffers(void *user_data, int count, const unsigned *ids) +void GlState::glDeleteObjectARB(void *user_data, unsigned id) { - for(int i=0; i(user_data)->buffers.erase(ids[i]); + GlState *self = reinterpret_cast(user_data); + if(self->shaders.count(id)) + self->delete_shader(id); + else if(self->programs.count(id)) + self->delete_program(id); } -void GlState::glDrawElements(void *user_data, GLenum, int, GLenum type, const void *) +void GlState::glGetObjectParameterivARB(void *user_data, unsigned id, GLenum pname, int *param) { - if(BufferState *buf = reinterpret_cast(user_data)->element_buffer) - buf->content.update_elements(type); + GlState *self = reinterpret_cast(user_data); + if(self->shaders.count(id)) + glGetShaderiv(user_data, id, pname, param); + else if(self->programs.count(id)) + glGetProgramiv(user_data, id, pname, param); } -void GlState::glDrawRangeElements(void *user_data, GLenum, unsigned, unsigned, int, GLenum type, const void *) +void GlState::glGetInfoLogARB(void *user_data, unsigned id, int bufsize, int *length, char *log) { - if(BufferState *buf = reinterpret_cast(user_data)->element_buffer) - buf->content.update_elements(type); + GlState *self = reinterpret_cast(user_data); + if(self->shaders.count(id)) + glGetShaderInfoLog(user_data, id, bufsize, length, log); + else if(self->programs.count(id)) + glGetProgramInfoLog(user_data, id, bufsize, length, log); +} + +const ShaderState &GlState::get_shader(unsigned id) const +{ + ShaderMap::const_iterator i = shaders.find(id); + if(i==shaders.end()) + throw runtime_error("Unknown shader"); + return i->second; +} + +const ProgramState &GlState::get_program(unsigned id) const +{ + ProgramMap::const_iterator i = programs.find(id); + if(i==programs.end()) + throw runtime_error("Unknown program"); + return i->second; }