]> git.tdb.fi Git - gldbg.git/blobdiff - flavors/gl/source/glstate.cpp
Basic tracking and inspection of shaders and programs
[gldbg.git] / flavors / gl / source / glstate.cpp
index 0163c2f884605603170f60303ad9d856e611ea28..4f9eba5b9d2bd11d499e7b0920403ee00de19e5f 100644 (file)
@@ -136,6 +136,27 @@ GlState::GlState():
        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()
@@ -200,6 +221,22 @@ const ArrayState &GlState::get_attrib_array(unsigned index) const
        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);
@@ -297,6 +334,61 @@ 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)
@@ -486,3 +578,119 @@ void GlState::glDrawRangeElements(void *user_data, GLenum, unsigned, unsigned, i
        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);
+}