]> 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 e3c9871c34c5ca5772a229f55c6c6107e288325d..4f9eba5b9d2bd11d499e7b0920403ee00de19e5f 100644 (file)
@@ -1,10 +1,3 @@
-/* $Id$
-
-This file is part of gldbg
-Copyright © 2009-2011  Mikko Rasa, Mikkosoft Productions
-Distributed under the GPL
-*/
-
 #include <stdexcept>
 #include "glstate.h"
 
@@ -73,7 +66,9 @@ GlState::GlState():
        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;
@@ -129,6 +124,8 @@ GlState::GlState():
 
        decoder->glBindBuffer = glBindBuffer;
        decoder->glBindBufferARB = glBindBuffer;
+       decoder->glBindBufferBase = glBindBufferBase;
+       decoder->glBindBufferRange = glBindBufferRange;
        decoder->glBufferData = glBufferData;
        decoder->glBufferDataARB = glBufferData;
        decoder->glBufferSubData = glBufferSubData;
@@ -139,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()
@@ -167,6 +185,13 @@ const BufferState &GlState::get_buffer(unsigned id) const
        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)
@@ -196,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);
@@ -221,12 +262,27 @@ TextureState *GlState::get_current_texture(GLenum 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;
 }
 
@@ -262,6 +318,8 @@ 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)
@@ -276,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)
@@ -419,6 +532,23 @@ void GlState::glVertexAttribPointer(void *user_data, unsigned index, int size, G
 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))
@@ -448,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);
+}