X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=flavors%2Fgl%2Fsource%2Fglstate.cpp;h=750d70315835a45395512512ce04ff2a2963cf3d;hb=d72ef6d75a11f6cc05ab8ec039520719e1044741;hp=0163c2f884605603170f60303ad9d856e611ea28;hpb=73d29911044cfffdc7edad50aeb2a8d1175ecd11;p=gldbg.git diff --git a/flavors/gl/source/glstate.cpp b/flavors/gl/source/glstate.cpp index 0163c2f..750d703 100644 --- a/flavors/gl/source/glstate.cpp +++ b/flavors/gl/source/glstate.cpp @@ -63,28 +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), uniform_buffer(0), - uniform_bind_points(64) + 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 >; @@ -105,23 +102,23 @@ 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; @@ -133,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() @@ -148,27 +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; } -const BufferBindingState &GlState::get_buffer_binding(GLenum target, unsigned index) const +void GlState::glEnableClientState(void *user_data, GLenum state) { - if(target==GL_UNIFORM_BUFFER) - return uniform_bind_points[index]; - throw runtime_error("This buffer target does not have indexed binding points"); + 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 @@ -192,37 +343,41 @@ 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 +// Array draw commands + +void GlState::glDrawElements(void *user_data, GLenum, int, GLenum type, const void *) { - return const_cast(this)->get_current_buffer(target); + if(BufferState *buf = reinterpret_cast(user_data)->element_buffer) + buf->content.update_elements(type); } -bool &GlState::get_boolean_state(GLenum state) +void GlState::glDrawRangeElements(void *user_data, GLenum, unsigned, unsigned, int, GLenum type, const void *) { - 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; + if(BufferState *buf = reinterpret_cast(user_data)->element_buffer) + buf->content.update_elements(type); } -TextureState *GlState::get_current_texture(GLenum target) +// Buffer objects + +void GlState::set_current_buffer(GLenum target, unsigned id) { - return texunits[active_tex].get_current_texture(target); + 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; + else if(target==GL_UNIFORM_BUFFER) + uniform_buffer = buf; } BufferState *GlState::get_buffer_object(unsigned id) @@ -249,124 +404,91 @@ BufferBindingState *GlState::get_buffer_binding(GLenum target, unsigned index) return 0; } -void GlState::set_current_texture(GLenum target, unsigned id) +void GlState::glBindBuffer(void *user_data, 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); + reinterpret_cast(user_data)->set_current_buffer(target, id); } -void GlState::set_current_buffer(GLenum target, unsigned id) +void GlState::glBindBufferBase(void *user_data, GLenum target, unsigned index, 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; - else if(target==GL_UNIFORM_BUFFER) - uniform_buffer = buf; + if(BufferState *buffer = reinterpret_cast(user_data)->get_buffer_object(id)) + glBindBufferRange(user_data, target, index, id, 0, buffer->size); } -ArrayState &GlState::get_attrib_array(unsigned index) +void GlState::glBindBufferRange(void *user_data, GLenum target, unsigned index, unsigned id, int offset, int size) { - 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; + 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; + } } -// Boolean state - -void GlState::glEnableClientState(void *user_data, GLenum state) +void GlState::glBufferData(void *user_data, GLenum target, int size, const void *data, GLenum usage) { - reinterpret_cast(user_data)->get_boolean_state(state) = true; + if(BufferState *buf = reinterpret_cast(user_data)->get_current_buffer(target)) + buf->set_data(size, data, usage); } -void GlState::glDisableClientState(void *user_data, GLenum state) +void GlState::glBufferSubData(void *user_data, GLenum target, int offset, int size, const void *data) { - reinterpret_cast(user_data)->get_boolean_state(state) = false; + if(BufferState *buf = reinterpret_cast(user_data)->get_current_buffer(target)) + buf->set_sub_data(offset, size, data); } -void GlState::glEnableVertexAttribArray(void *user_data, unsigned index) +void GlState::glDeleteBuffers(void *user_data, int count, const unsigned *ids) { - reinterpret_cast(user_data)->attrib_arrays[index].enabled = true; + for(int i=0; i(user_data)->buffers.erase(ids[i]); } -void GlState::glDisableVertexAttribArray(void *user_data, unsigned index) +const BufferState &GlState::get_buffer(unsigned id) const { - reinterpret_cast(user_data)->attrib_arrays[index].enabled = false; + BufferMap::const_iterator i = buffers.find(id); + if(i==buffers.end()) + throw runtime_error("Unknown buffer"); + return i->second; } -// 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) +const BufferState *GlState::get_current_buffer(GLenum target) const { - Vector4 &color = reinterpret_cast(user_data)->color; - color.r = r; - color.g = g; - color.b = b; - color.a = a; + return const_cast(this)->get_current_buffer(target); } -void GlState::glNormal3f(void *user_data, float x, float y, float z) +const BufferBindingState &GlState::get_buffer_binding(GLenum target, unsigned index) const { - Vector3 &normal = reinterpret_cast(user_data)->normal; - normal.x = x; - normal.y = y; - normal.z = z; + if(target==GL_UNIFORM_BUFFER) + return uniform_bind_points[index]; + throw runtime_error("This buffer target does not have indexed binding points"); } -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); } +// 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; @@ -384,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) { @@ -398,91 +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) { - GlState *self = reinterpret_cast(user_data); - self->get_attrib_array(index).set(size, type, norm, stride, self->array_buffer, reinterpret_cast(data)); + 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; + } } -// Buffer objects +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::glBindBuffer(void *user_data, GLenum target, unsigned id) -{ reinterpret_cast(user_data)->set_current_buffer(target, id); } +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::glBindBufferBase(void *user_data, GLenum target, unsigned index, unsigned id) +void GlState::glGetShaderInfoLog(void *user_data, unsigned id, int, int *, char *log) { - if(BufferState *buffer = reinterpret_cast(user_data)->get_buffer_object(id)) - glBindBufferRange(user_data, target, index, id, 0, buffer->size); + if(ShaderState *shader = reinterpret_cast(user_data)->get_shader(id, false)) + shader->info_log = log; } -void GlState::glBindBufferRange(void *user_data, GLenum target, unsigned index, unsigned id, int offset, int size) +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); - if(BufferBindingState *binding = self->get_buffer_binding(target, index)) + if(ProgramState *prog = self->get_program(prog_id, false)) + if(ShaderState *shader = self->get_shader(shader_id, false)) + prog->shaders.push_back(shader); +} + +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::glGetProgramiv(void *user_data, unsigned id, GLenum pname, int *param) +{ + if(ProgramState *program = reinterpret_cast(user_data)->get_program(id, false)) { - binding->buffer = self->get_buffer_object(id); - binding->offset = offset; - binding->size = size; + 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; }