X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=flavors%2Fgl%2Fsource%2Finspector.cpp;h=122c2e45298f340ddfe935a2f5e29375dcde480c;hb=d72ef6d75a11f6cc05ab8ec039520719e1044741;hp=5dcdf4147d3a6b670ffe8b57750a5ad256c993af;hpb=8ddb049bf9cb06c377857ab46b7af23c140f12a7;p=gldbg.git diff --git a/flavors/gl/source/inspector.cpp b/flavors/gl/source/inspector.cpp index 5dcdf41..122c2e4 100644 --- a/flavors/gl/source/inspector.cpp +++ b/flavors/gl/source/inspector.cpp @@ -1,21 +1,21 @@ -/* $Id$ - -This file is part of gldbg -Copyright © 2010 Mikko Rasa, Mikkosoft Productions -Distributed under the GPL -*/ - -#include +#include +#include +#include +#include "breakpoint.h" #include "enums.h" +#include "functions.h" #include "gldbg.h" #include "inspector.h" +#include "strformat.h" using namespace std; -using namespace Msp; -Inspector::Inspector(GlDbg &dbg) +Inspector::Inspector(GlDbg &d): + gldbg(d), + decoder(gldecoder_new(this, NULL)), + query_state(0) { - CommandInterpreter &cmd_interp = dbg.get_command_interpreter(); + CommandInterpreter &cmd_interp = gldbg.get_command_interpreter(); cmd_interp.register_command("state", this, &Inspector::cmd_state) .set_help("Inspects general GL state", @@ -37,47 +37,117 @@ Inspector::Inspector(GlDbg &dbg) " Lists buffer objects\n\n" "buffer ID\n" " Print information about a buffer object\n"); + + cmd_interp.register_command("shader", this, &Inspector::cmd_shader) + .set_help("Inspect shader object state", + "shader\n" + " List shader objects\n\n" + "shader ID\n" + " Print information about a shader object\n"); + + cmd_interp.register_command("program", this, &Inspector::cmd_program) + .set_help("Inspect program object state", + "program\n" + " List program objects\n\n" + "program ID\n" + " Print information about a program object\n"); + + decoder->gldBreak = gldBreak; } void Inspector::decode(const char *data, unsigned len) { + if(query_state) + gldecoder_decode(decoder, data, len); state.decode(data, len); } +void Inspector::process_started() +{ + gldbg.set_breakpoint(FUNC_GLXMAKECURRENT, BREAK_RETURN, this); + query_state = 1; +} + +void Inspector::process_stopped(int reason) +{ + if((reason>>8)==3 && query_state==2) + { + GlPacket *pkt = packet_begin(FUNC_GLDQUERYLIMITS); + gldbg.send(pkt); + query_state = 0; + gldbg.resume_from_break(this); + } +} + +void Inspector::gldBreak(void *user_data, unsigned short func, unsigned char flag) +{ + if(func==FUNC_GLXMAKECURRENT && flag==BREAK_RETURN) + ++reinterpret_cast(user_data)->query_state; +} + +void Inspector::print_indented(const string &str, unsigned indent) +{ + string spaces(indent, ' '); + string::size_type start = 0; + while(1) + { + string::size_type newline = str.find('\n', start); + string line = str.substr(start, newline-start); + if(newline!=string::npos || !line.empty()) + printf("%s%s\n", spaces.c_str(), line.c_str()); + if(newline==string::npos) + break; + start = newline+1; + } +} + void Inspector::cmd_state(const string &args) { const GlState &glstate = state; if(args=="vertex") { - IO::print("Current vertex attributes:\n"); + printf("Current vertex attributes:\n"); const Vector4 &color = glstate.get_color(); - IO::print(" Color: [%05.3f, %05.3f, %05.3f, %05.3f]\n", color.r, color.g, color.b, color.a); - for(unsigned i=0; i<8; ++i) + printf(" Color: [%05.3f, %05.3f, %05.3f, %05.3f]\n", color.r, color.g, color.b, color.a); + unsigned count = glstate.get_max_texture_units(); + for(unsigned i=0; iid : 0)); + printf(" GL_ARRAY_BUFFER: %d\n", (buf ? buf->id : 0)); buf = glstate.get_current_buffer(GL_ELEMENT_ARRAY_BUFFER); - IO::print(" GL_ELEMENT_ARRAY_BUFFER: %d\n", (buf ? buf->id : 0)); + printf(" GL_ELEMENT_ARRAY_BUFFER: %d\n", (buf ? buf->id : 0)); + buf = glstate.get_current_buffer(GL_UNIFORM_BUFFER); + printf(" GL_UNIFORM_BUFFER: %d\n", (buf ? buf->id : 0)); + count = glstate.get_max_uniform_buffer_bindings(); + for(unsigned i=0; iid, binding.size, binding.offset); + } } else - throw InvalidParameterValue("Invalid or missing argument"); + throw runtime_error("Invalid or missing argument"); } void Inspector::cmd_texture(const string &args) @@ -85,32 +155,37 @@ void Inspector::cmd_texture(const string &args) if(args.empty()) { const map &textures = state.get_textures(); - IO::print("%d texture objects:\n", textures.size()); + printf("%d texture objects:\n", textures.size()); for(map::const_iterator i = textures.begin(); i!=textures.end(); ++i) { const TextureState &tex = i->second; - IO::print(" %d: %s, %d images\n", i->first, tex.describe(), tex.images.size()); + string descr = tex.describe(); + printf(" %d: %s, %d images\n", i->first, descr.c_str(), tex.images.size()); } } else { - unsigned id = lexical_cast(args); + char *end = 0; + unsigned id = strtoul(args.c_str(), &end, 0); + if(end && *end) + throw runtime_error("Invalid texture id"); + const TextureState &tex = state.get_texture(id); - IO::print("Texture object %d\n", id); - IO::print(" Target: %s\n", describe_enum(tex.target, "TextureTarget")); - IO::print(" Images:\n"); + printf("Texture object %d\n", id); + printf(" Target: %s\n", describe_enum(tex.target, "TextureTarget")); + printf(" Images:\n"); for(unsigned i=0; ifirst, i->second.describe()); + { + string descr = i->second.describe(); + printf(" %d: %s\n", i->first, descr.c_str()); + } } else { - unsigned id = lexical_cast(args); + char *end = 0; + unsigned id = strtoul(args.c_str(), &end, 0); + if(end && *end) + throw runtime_error("Invalid buffer id"); + const BufferState &buf = state.get_buffer(id); - IO::print("Buffer %d:\n", id); - IO::print(" Size: %d bytes\n", buf.size); - IO::print(" Usage: %s\n", describe_enum(buf.usage, "")); + printf("Buffer %d:\n", id); + printf(" Size: %d bytes\n", buf.size); + printf(" Usage: %s\n", describe_enum(buf.usage, "")); if(buf.content.arrays.size()==1 && buf.content.arrays.front().kind==GL_ELEMENT_ARRAY_BUFFER) { const BufferContent::Array &array = buf.content.arrays.front(); - IO::print(" Arrays:\n"); - IO::print(" 0: Element indices, 1 %s\n", describe_enum(array.type, "DataType")); + printf(" Arrays:\n"); + printf(" 0: Element indices, 1 %s\n", describe_enum(array.type, "DataType")); - IO::print(" Data:\n"); + printf(" Data:\n"); unsigned width = 1+buf.content.stride*2; - string fmt = format(" %%%du", width); + char fmt[6]; + snprintf(fmt, sizeof(fmt), " %%%du", width); unsigned n_elems = buf.size/buf.content.stride; string line; const char *ptr = buf.data; @@ -148,39 +231,39 @@ void Inspector::cmd_buffer(const string &args) line = " "; if(array.type==GL_UNSIGNED_BYTE) - line += format(fmt, *(reinterpret_cast(ptr)+i)); + line += strformat(fmt, *(reinterpret_cast(ptr)+i)); else if(array.type==GL_UNSIGNED_SHORT) - line += format(fmt, *(reinterpret_cast(ptr)+i)); + line += strformat(fmt, *(reinterpret_cast(ptr)+i)); else if(array.type==GL_UNSIGNED_INT) - line += format(fmt, *(reinterpret_cast(ptr)+i)); + line += strformat(fmt, *(reinterpret_cast(ptr)+i)); if(line.size()+1+width>79) { - IO::print("%s\n", line); + printf("%s\n", line.c_str()); line.clear(); } } if(!line.empty()) - IO::print("%s\n", line); + printf("%s\n", line.c_str()); } else if(buf.content.stride) { - IO::print(" Stride: %d bytes\n", buf.content.stride); + printf(" Stride: %d bytes\n", buf.content.stride); - IO::print(" Arrays:\n"); + printf(" Arrays:\n"); const vector &arrays = buf.content.arrays; for(vector::const_iterator i=arrays.begin(); i!=arrays.end(); ++i) { if(i->kind) - IO::print(" %2d: %s, %d %s\n", i->offset, + printf(" %2d: %s, %d %s\n", i->offset, describe_enum(i->kind, ""), i->size, describe_enum(i->type, "DataType")); else - IO::print(" %2d: Attrib %d, %d %s\n", i->offset, + printf(" %2d: Attrib %d, %d %s\n", i->offset, i->index, i->size, describe_enum(i->type, "DataType")); } - IO::print(" Data:\n"); + printf(" Data:\n"); string header; for(vector::const_iterator i=arrays.begin(); i!=arrays.end(); ++i) { @@ -204,9 +287,9 @@ void Inspector::cmd_buffer(const string &args) else if(!i->kind) { if(i->size==1) - label = format("A %d", i->index); + label = strformat("A %d", i->index); else - label = format("Attrib %d", i->index); + label = strformat("Attrib %d", i->index); } unsigned width = i->size; @@ -220,7 +303,7 @@ void Inspector::cmd_buffer(const string &args) header += label; header.append((width-label.size()+1)/2, ' '); } - IO::print(" %s\n", header); + printf(" %s\n", header.c_str()); unsigned n_verts = buf.size/buf.content.stride; for(unsigned i=0; isize; ++k) { if(j->type==GL_FLOAT) - line += format(" %5.2f", *(reinterpret_cast(base)+k)); + line += strformat(" %5.2f", *(reinterpret_cast(base)+k)); else if(j->type==GL_UNSIGNED_BYTE) - line += format(" %3u", *(reinterpret_cast(base)+k)); + line += strformat(" %3u", *(reinterpret_cast(base)+k)); } } - IO::print("%3d:%s\n", i, line); + printf("%3d:%s\n", i, line.c_str()); } } } } + +void Inspector::cmd_shader(const string &args) +{ + if(args.empty()) + { + const GlState::ShaderMap &shaders = state.get_shaders(); + printf("%d shader objects:\n", shaders.size()); + for(GlState::ShaderMap::const_iterator i=shaders.begin(); i!=shaders.end(); ++i) + { + string descr = i->second.describe(); + printf(" %d: %s\n", i->first, descr.c_str()); + } + } + else + { + char *end = 0; + unsigned id = strtoul(args.c_str(), &end, 0); + if(end && *end) + throw runtime_error("Invalid shader id"); + + const ShaderState &shader = state.get_shader(id); + printf("Shader %d:\n", shader.id); + printf(" Type: %s\n", describe_enum(shader.type, "")); + unsigned n = 0; + for(vector::const_iterator i=shader.source.begin(); i!=shader.source.end(); ++i, ++n) + { + printf(" Source string %d:\n", n); + print_indented(*i, 4); + } + if(shader.source_changed) + printf(" Source changed since last compile\n"); + printf(" Compile status: %d\n", shader.compile_status); + if(shader.info_log.empty()) + printf(" Info log is empty\n"); + else + { + printf(" Info log:\n"); + print_indented(shader.info_log, 4); + } + if(shader.pending_delete) + printf(" Pending deletion\n"); + } +} + +void Inspector::cmd_program(const std::string &args) +{ + if(args.empty()) + { + const GlState::ProgramMap &programs = state.get_programs(); + printf("%d program objects:\n", programs.size()); + for(GlState::ProgramMap::const_iterator i=programs.begin(); i!=programs.end(); ++i) + { + string descr = i->second.describe(); + printf(" %d: %s\n", i->first, descr.c_str()); + } + } + else + { + char *end = 0; + unsigned id = strtoul(args.c_str(), &end, 0); + if(end && *end) + throw runtime_error("Invalid program id"); + + const ProgramState &program = state.get_program(id); + printf("Program %d:\n", program.id); + printf(" Attached shaders:\n"); + for(vector::const_iterator i=program.shaders.begin(); i!=program.shaders.end(); ++i) + { + string descr = (*i)->describe(); + printf(" %d: %s\n", (*i)->id, descr.c_str()); + } + if(program.shaders_changed) + printf(" Shaders changed since last compile\n"); + printf(" Link status: %d\n", program.link_status); + if(program.info_log.empty()) + printf(" Info log is empty\n"); + else + { + printf(" Info log:\n"); + print_indented(program.info_log, 4); + } + } +}