-/* $Id$
-
-This file is part of gldbg
-Copyright © 2009-2011 Mikko Rasa, Mikkosoft Productions
-Distributed under the GPL
-*/
-
#include <stdexcept>
#include "glstate.h"
active_tex(0),
client_active_tex(0),
array_buffer(0),
- element_buffer(0)
+ element_buffer(0),
+ uniform_buffer(0),
+ uniform_bind_points(64)
{
vertex_array.kind = GL_VERTEX_ARRAY;
normal_array.kind = GL_NORMAL_ARRAY;
decoder->glBindBuffer = glBindBuffer;
decoder->glBindBufferARB = glBindBuffer;
+ decoder->glBindBufferBase = glBindBufferBase;
+ decoder->glBindBufferRange = glBindBufferRange;
decoder->glBufferData = glBufferData;
decoder->glBufferDataARB = glBufferData;
decoder->glBufferSubData = glBufferSubData;
decoder->glDrawElements = glDrawElements;
decoder->glDrawRangeElements = glDrawRangeElements;
decoder->glDrawRangeElementsEXT = glDrawRangeElements;
+
+ 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()
return i->second;
}
+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");
+}
+
const ArrayState &GlState::get_array(GLenum array) const
{
if(array==GL_VERTEX_ARRAY)
throw runtime_error("Unknown attribute array");
}
+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;
+}
+
const BufferState *GlState::get_current_buffer(GLenum target) const
{
return const_cast<GlState *>(this)->get_current_buffer(target);
return texunits[active_tex].get_current_texture(target);
}
+BufferState *GlState::get_buffer_object(unsigned id)
+{
+ BufferMap::iterator i = buffers.find(id);
+ return (i==buffers.end() ? 0 : &i->second);
+}
+
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;
+}
+
+BufferBindingState *GlState::get_buffer_binding(GLenum target, unsigned index)
+{
+ if(target==GL_UNIFORM_BUFFER)
+ return &uniform_bind_points[index];
return 0;
}
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)
return array;
}
+ShaderState *GlState::get_shader(unsigned id, bool create)
+{
+ 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::delete_shader(unsigned id)
+{
+ ShaderMap::iterator i = shaders.find(id);
+ if(i==shaders.end())
+ return;
+
+ for(ProgramMap::const_iterator j=programs.begin(); j!=programs.end(); ++j)
+ {
+ const vector<ShaderState *> &prog_shaders = j->second.shaders;
+ for(vector<ShaderState *>::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::delete_program(unsigned id)
+{
+ ProgramMap::iterator i = programs.find(id);
+ if(i==programs.end())
+ return;
+
+ vector<ShaderState *> prog_shaders = i->second.shaders;
+ programs.erase(i);
+ for(vector<ShaderState *>::const_iterator j=prog_shaders.begin(); j!=prog_shaders.end(); ++j)
+ if((*j)->pending_delete)
+ delete_shader((*j)->id);
+}
+
+ProgramState *GlState::get_program(unsigned id, bool create)
+{
+ 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);
+}
+
// Boolean state
void GlState::glEnableClientState(void *user_data, GLenum state)
void GlState::glBindBuffer(void *user_data, GLenum target, unsigned id)
{ reinterpret_cast<GlState *>(user_data)->set_current_buffer(target, id); }
+void GlState::glBindBufferBase(void *user_data, GLenum target, unsigned index, unsigned id)
+{
+ if(BufferState *buffer = reinterpret_cast<GlState *>(user_data)->get_buffer_object(id))
+ glBindBufferRange(user_data, target, index, id, 0, buffer->size);
+}
+
+void GlState::glBindBufferRange(void *user_data, GLenum target, unsigned index, unsigned id, int offset, int size)
+{
+ GlState *self = reinterpret_cast<GlState *>(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::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))
if(BufferState *buf = reinterpret_cast<GlState *>(user_data)->element_buffer)
buf->content.update_elements(type);
}
+
+// Shaders
+
+void GlState::glCreateShader(void *user_data, unsigned id, GLenum type)
+{
+ if(ShaderState *shader = reinterpret_cast<GlState *>(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<GlState *>(user_data)->get_shader(id, false))
+ {
+ shader->source.clear();
+ for(int i=0; i<count; ++i)
+ {
+ if(!length || length[i]<0)
+ shader->source.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<GlState *>(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<GlState *>(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<GlState *>(user_data)->get_shader(id, false))
+ shader->info_log = log;
+}
+
+void GlState::glDeleteShader(void *user_data, unsigned id)
+{
+ reinterpret_cast<GlState *>(user_data)->delete_shader(id);
+}
+
+void GlState::glCreateProgram(void *user_data, unsigned id)
+{
+ reinterpret_cast<GlState *>(user_data)->get_program(id, true);
+}
+
+void GlState::glAttachShader(void *user_data, unsigned prog_id, unsigned shader_id)
+{
+ GlState *self = reinterpret_cast<GlState *>(user_data);
+ 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<GlState *>(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<GlState *>(user_data)->get_program(id, false))
+ {
+ if(pname==GL_LINK_STATUS)
+ program->link_status = *param;
+ }
+}
+
+void GlState::glGetProgramInfoLog(void *user_data, unsigned id, int, int *, char *log)
+{
+ if(ProgramState *program = reinterpret_cast<GlState *>(user_data)->get_program(id, false))
+ program->info_log = log;
+}
+
+void GlState::glDeleteProgram(void *user_data, unsigned id)
+{
+ reinterpret_cast<GlState *>(user_data)->delete_program(id);
+}
+
+void GlState::glDeleteObjectARB(void *user_data, unsigned id)
+{
+ GlState *self = reinterpret_cast<GlState *>(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<GlState *>(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<GlState *>(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);
+}