X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=flavors%2Fgl%2Fsource%2Fglstate.cpp;h=750d70315835a45395512512ce04ff2a2963cf3d;hb=d72ef6d75a11f6cc05ab8ec039520719e1044741;hp=1459324232f36d3b6af583bfe1def2a3e0ffb22a;hpb=f53057ce9b5eb3c7256a4aca95b4944733e14503;p=gldbg.git diff --git a/flavors/gl/source/glstate.cpp b/flavors/gl/source/glstate.cpp index 1459324..750d703 100644 --- a/flavors/gl/source/glstate.cpp +++ b/flavors/gl/source/glstate.cpp @@ -1,15 +1,7 @@ -/* $Id$ - -This file is part of gldbg -Copyright © 2009-2010 Mikko Rasa, Mikkosoft Productions -Distributed under the GPL -*/ - -#include +#include #include "glstate.h" using namespace std; -using namespace Msp; namespace { @@ -71,19 +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->glColor3ub = wrap_normalized; decoder->glColor3ubv = wrap_array >; @@ -104,29 +102,62 @@ 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; decoder->glBufferSubDataARB = glBufferSubData; decoder->glDeleteBuffers = glDeleteBuffers; decoder->glDeleteBuffersARB = glDeleteBuffers; + + 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() @@ -139,26 +170,31 @@ 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 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; + 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_current_buffer(GLenum target) const -{ - return const_cast(this)->get_current_buffer(target); -} +// Boolean state bool &GlState::get_boolean_state(GLenum state) { @@ -175,18 +211,115 @@ bool &GlState::get_boolean_state(GLenum state) return dummy; } -TextureState *GlState::get_current_texture(GLenum target) +void GlState::glEnableClientState(void *user_data, GLenum state) { - return texunits[active_tex].get_current_texture(target); + reinterpret_cast(user_data)->get_boolean_state(state) = true; } -BufferState *GlState::get_current_buffer(GLenum target) +void GlState::glDisableClientState(void *user_data, GLenum state) { - if(target==GL_ARRAY_BUFFER) - return array_buffer; - else if(target==GL_ELEMENT_ARRAY_BUFFER) - return element_buffer; - return 0; + 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 @@ -200,7 +333,7 @@ const ArrayState &GlState::get_array(GLenum array) const else if(array==GL_TEXTURE_COORD_ARRAY) return texcoord_arrays[client_active_tex]; else - throw InvalidParameterValue("Invalid array"); + throw logic_error("Invalid array"); } const ArrayState &GlState::get_texture_coord_array(unsigned index) const @@ -210,32 +343,25 @@ 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; + return attrib_arrays[index]; +} - // XXX Return a dummy? - throw KeyError("Unknown attribute array"); +// Array draw commands + +void GlState::glDrawElements(void *user_data, GLenum, int, GLenum type, const void *) +{ + if(BufferState *buf = reinterpret_cast(user_data)->element_buffer) + buf->content.update_elements(type); } -void GlState::set_current_texture(GLenum target, unsigned id) +void GlState::glDrawRangeElements(void *user_data, GLenum, unsigned, unsigned, int, GLenum type, const void *) { - 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); + if(BufferState *buf = reinterpret_cast(user_data)->element_buffer) + buf->content.update_elements(type); } +// Buffer objects + void GlState::set_current_buffer(GLenum target, unsigned id) { BufferState *buf = 0; @@ -250,78 +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; } -// Boolean state - -void GlState::glEnableClientState(void *user_data, GLenum state) +BufferState *GlState::get_buffer_object(unsigned id) { - reinterpret_cast(user_data)->get_boolean_state(state) = true; + BufferMap::iterator i = buffers.find(id); + return (i==buffers.end() ? 0 : &i->second); } -void GlState::glDisableClientState(void *user_data, GLenum state) +BufferState *GlState::get_current_buffer(GLenum target) { - reinterpret_cast(user_data)->get_boolean_state(state) = false; + 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::glEnableVertexAttribArray(void *user_data, unsigned index) +BufferBindingState *GlState::get_buffer_binding(GLenum target, unsigned index) { - reinterpret_cast(user_data)->attrib_arrays[index].enabled = true; + if(target==GL_UNIFORM_BUFFER) + return &uniform_bind_points[index]; + return 0; } -void GlState::glDisableVertexAttribArray(void *user_data, unsigned index) +void GlState::glBindBuffer(void *user_data, GLenum target, unsigned id) { - reinterpret_cast(user_data)->attrib_arrays[index].enabled = false; + reinterpret_cast(user_data)->set_current_buffer(target, id); } -// Vertex attributes - -void GlState::glColor3f(void *user_data, float r, float g, float b) -{ glColor4f(user_data, r, g, b, 1.0f); } +void GlState::glBindBufferBase(void *user_data, GLenum target, unsigned index, unsigned id) +{ + if(BufferState *buffer = reinterpret_cast(user_data)->get_buffer_object(id)) + glBindBufferRange(user_data, target, index, id, 0, buffer->size); +} -void GlState::glColor4f(void *user_data, float r, float g, float b, float a) +void GlState::glBindBufferRange(void *user_data, GLenum target, unsigned index, unsigned id, int offset, int size) { - Vector4 &color = reinterpret_cast(user_data)->color; - color.r = r; - color.g = g; - color.b = b; - color.a = a; + 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; + } } -void GlState::glNormal3f(void *user_data, float x, float y, float z) +void GlState::glBufferData(void *user_data, GLenum target, int size, const void *data, GLenum usage) { - Vector3 &normal = reinterpret_cast(user_data)->normal; - normal.x = x; - normal.y = y; - normal.z = z; + if(BufferState *buf = reinterpret_cast(user_data)->get_current_buffer(target)) + buf->set_data(size, data, usage); } -void GlState::glTexCoord1f(void *user_data, float s) -{ glTexCoord4f(user_data, s, 0.0f, 0.0f, 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::glTexCoord2f(void *user_data, float s, float t) -{ glTexCoord4f(user_data, s, t, 0.0f, 1.0f); } +void GlState::glDeleteBuffers(void *user_data, int count, const unsigned *ids) +{ + for(int i=0; i(user_data)->buffers.erase(ids[i]); +} -void GlState::glTexCoord3f(void *user_data, float s, float t, float p) -{ glTexCoord4f(user_data, s, t, p, 1.0f); } +const BufferState &GlState::get_buffer(unsigned id) const +{ + BufferMap::const_iterator i = buffers.find(id); + if(i==buffers.end()) + throw runtime_error("Unknown buffer"); + return i->second; +} -void GlState::glTexCoord4f(void *user_data, float s, float t, float p, float q) +const BufferState *GlState::get_current_buffer(GLenum target) const { - unsigned index = reinterpret_cast(user_data)->active_tex; - glMultiTexCoord4f(user_data, index, s, t, p, q); + return const_cast(this)->get_current_buffer(target); } -void GlState::glMultiTexCoord4f(void *user_data, unsigned index, float s, float t, float p, float q) +const BufferBindingState &GlState::get_buffer_binding(GLenum target, unsigned index) const { - Vector4 &texcoord = reinterpret_cast(user_data)->texcoord[index]; - texcoord.s = s; - texcoord.t = t; - texcoord.p = p; - texcoord.q = q; + if(target==GL_UNIFORM_BUFFER) + return uniform_bind_points[index]; + throw runtime_error("This buffer target does not have indexed binding points"); } // Textures +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); +} + +TextureState *GlState::get_current_texture(GLenum target) +{ + return texunits[active_tex].get_current_texture(target); +} + void GlState::glActiveTexture(void *user_data, unsigned index) { reinterpret_cast(user_data)->active_tex = index-GL_TEXTURE0; @@ -339,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) { @@ -353,62 +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::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::glVertexAttribPointer(void *user_data, unsigned index, int size, GLenum type, int norm, int stride, const void *data) +void GlState::glAttachShader(void *user_data, unsigned prog_id, unsigned shader_id) { GlState *self = reinterpret_cast(user_data); - self->attrib_arrays[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::glGetObjectParameterivARB(void *user_data, unsigned id, GLenum pname, int *param) +{ + 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::glGetInfoLogARB(void *user_data, unsigned id, int bufsize, int *length, char *log) +{ + 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; }