X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=glstate.py;h=90ef5b006a678537aad7fb839a0643940e6ad7c1;hb=93911de1f9909f1c9c8e10a8745c66fa6c27cc63;hp=89d92badf3c9500f4b38fc54f716b1e4890f1aeb;hpb=721dbc01b92f0f5b5e2ecb9154e1246aa75bc827;p=apitrace diff --git a/glstate.py b/glstate.py index 89d92ba..90ef5b0 100644 --- a/glstate.py +++ b/glstate.py @@ -27,10 +27,10 @@ '''Generate code to dump most GL state into JSON.''' -from stdapi import * +from specs.stdapi import * -from gltypes import * -from glparams import * +from specs.gltypes import * +from specs.glparams import * texture_targets = [ @@ -41,6 +41,10 @@ texture_targets = [ ('GL_TEXTURE_CUBE_MAP', 'GL_TEXTURE_BINDING_CUBE_MAP') ] +framebuffer_targets = [ + ('GL_DRAW_FRAMEBUFFER', 'GL_DRAW_FRAMEBUFFER_BINDING'), + ('GL_READ_FRAMEBUFFER', 'GL_READ_FRAMEBUFFER_BINDING'), +] class GetInflector: '''Objects that describes how to inflect.''' @@ -86,12 +90,19 @@ class StateGetter(Visitor): self.inflector = GetInflector(radical, inflections) self.suffix = suffix - def __call__(self, *args): - pname = args[-1] - + def iter(self): for function, type, count, name in parameters: + inflection = self.inflector.radical + self.suffix + if inflection not in function.split(','): + continue if type is X: continue + yield type, count, name + + def __call__(self, *args): + pname = args[-1] + + for type, count, name in self.iter(): if name == pname: if count != 1: type = Array(type, str(count)) @@ -106,10 +117,10 @@ class StateGetter(Visitor): return pname[3:].lower() - def visit_const(self, const, args): + def visitConst(self, const, args): return self.visit(const.type, args) - def visit_scalar(self, type, args): + def visitScalar(self, type, args): temp_name = self.temp_name(args) elem_type = self.inflector.reduced_type(type) inflection = self.inflector.inflect(type) @@ -120,35 +131,38 @@ class StateGetter(Visitor): print ' %s %s = %s(%s);' % (elem_type, temp_name, inflection + self.suffix, ', '.join(args)) return temp_name - def visit_string(self, string, args): + def visitString(self, string, args): temp_name = self.temp_name(args) inflection = self.inflector.inflect(string) assert not inflection.endswith('v') print ' %s %s = (%s)%s(%s);' % (string, temp_name, string, inflection + self.suffix, ', '.join(args)) return temp_name - def visit_alias(self, alias, args): - return self.visit_scalar(alias, args) + def visitAlias(self, alias, args): + return self.visitScalar(alias, args) - def visit_enum(self, enum, args): + def visitEnum(self, enum, args): return self.visit(GLint, args) - def visit_bitmask(self, bitmask, args): + def visitBitmask(self, bitmask, args): return self.visit(GLint, args) - def visit_array(self, array, args): + def visitArray(self, array, args): temp_name = self.temp_name(args) if array.length == '1': return self.visit(array.type) elem_type = self.inflector.reduced_type(array.type) inflection = self.inflector.inflect(array.type) assert inflection.endswith('v') - print ' %s %s[%s];' % (elem_type, temp_name, array.length) + print ' %s %s[%s + 1];' % (elem_type, temp_name, array.length) print ' memset(%s, 0, %s * sizeof *%s);' % (temp_name, array.length, temp_name) + print ' %s[%s] = (%s)0xdeadc0de;' % (temp_name, array.length, elem_type) print ' %s(%s, %s);' % (inflection + self.suffix, ', '.join(args), temp_name) + # Simple buffer overflow detection + print ' assert(%s[%s] == (%s)0xdeadc0de);' % (temp_name, array.length, elem_type) return temp_name - def visit_opaque(self, pointer, args): + def visitOpaque(self, pointer, args): temp_name = self.temp_name(args) inflection = self.inflector.inflect(pointer) assert inflection.endswith('v') @@ -172,7 +186,10 @@ glGetVertexAttrib = StateGetter('glGetVertexAttrib', {I: 'iv', F: 'fv', D: 'dv', glGetTexParameter = StateGetter('glGetTexParameter', {I: 'iv', F: 'fv'}) glGetTexEnv = StateGetter('glGetTexEnv', {I: 'iv', F: 'fv'}) glGetTexLevelParameter = StateGetter('glGetTexLevelParameter', {I: 'iv', F: 'fv'}) +glGetShader = StateGetter('glGetShaderiv', {I: 'iv'}) +glGetProgram = StateGetter('glGetProgram', {I: 'iv'}) glGetProgramARB = StateGetter('glGetProgram', {I: 'iv', F: 'fv', S: 'Stringv'}, 'ARB') +glGetFramebufferAttachmentParameter = StateGetter('glGetFramebufferAttachmentParameter', {I: 'iv'}) class JsonWriter(Visitor): @@ -181,36 +198,36 @@ class JsonWriter(Visitor): It expects a previously declared JSONWriter instance named "json".''' - def visit_literal(self, literal, instance): - if literal.format == 'Bool': + def visitLiteral(self, literal, instance): + if literal.kind == 'Bool': print ' json.writeBool(%s);' % instance - elif literal.format in ('SInt', 'Uint', 'Float', 'Double'): + elif literal.kind in ('SInt', 'Uint', 'Float', 'Double'): print ' json.writeNumber(%s);' % instance else: raise NotImplementedError - def visit_string(self, string, instance): + def visitString(self, string, instance): assert string.length is None print ' json.writeString((const char *)%s);' % instance - def visit_enum(self, enum, instance): + def visitEnum(self, enum, instance): if enum.expr == 'GLenum': - print ' writeEnum(json, %s);' % instance + print ' dumpEnum(json, %s);' % instance else: print ' json.writeNumber(%s);' % instance - def visit_bitmask(self, bitmask, instance): + def visitBitmask(self, bitmask, instance): raise NotImplementedError - def visit_alias(self, alias, instance): + def visitAlias(self, alias, instance): self.visit(alias.type, instance) - def visit_opaque(self, opaque, instance): + def visitOpaque(self, opaque, instance): print ' json.writeNumber((size_t)%s);' % instance __index = 0 - def visit_array(self, array, instance): + def visitArray(self, array, instance): index = '__i%u' % JsonWriter.__index JsonWriter.__index += 1 print ' json.beginArray();' @@ -230,21 +247,19 @@ class StateDumper: def dump(self): print '#include ' - print '#include ' - print '#include ' print - print '#include "image.hpp"' print '#include "json.hpp"' - print '#include "glimports.hpp"' print '#include "glproc.hpp"' print '#include "glsize.hpp"' - print '#include "glretrace.hpp"' + print '#include "glstate.hpp"' + print + print 'namespace glstate {' print - print 'static const char *' - print '_enum_string(GLenum pname)' + print 'const char *' + print 'enumToString(GLenum pname)' print '{' - print ' switch(pname) {' + print ' switch (pname) {' for name in GLenum.values: print ' case %s:' % name print ' return "%s";' % name @@ -254,24 +269,17 @@ class StateDumper: print '}' print - print 'static const char *' - print 'enum_string(GLenum pname)' + print 'static void' + print 'dumpFramebufferAttachementParameters(JSONWriter &json, GLenum target, GLenum attachment)' print '{' - print ' const char *s = _enum_string(pname);' - print ' if (s) {' - print ' return s;' - print ' } else {' - print ' static char buf[16];' - print ' snprintf(buf, sizeof buf, "0x%04x", pname);' - print ' return buf;' - print ' }' + self.dump_attachment_parameters('target', 'attachment') print '}' print - print 'static inline void' - print 'writeEnum(JSONWriter &json, GLenum pname)' + print 'void' + print 'dumpEnum(JSONWriter &json, GLenum pname)' print '{' - print ' const char *s = _enum_string(pname);' + print ' const char *s = enumToString(pname);' print ' if (s) {' print ' json.writeString(s);' print ' } else {' @@ -280,383 +288,8 @@ class StateDumper: print '}' print - # shaders - print ''' -static void -writeShader(JSONWriter &json, GLuint shader) -{ - if (!shader) { - return; - } - - GLint shader_type = 0; - glGetShaderiv(shader, GL_SHADER_TYPE, &shader_type); - if (!shader_type) { - return; - } - - GLint source_length = 0; - glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &source_length); - if (!source_length) { - return; - } - - GLchar *source = new GLchar[source_length]; - GLsizei length = 0; - source[0] = 0; - glGetShaderSource(shader, source_length, &length, source); - - json.beginMember(enum_string(shader_type)); - json.writeString(source); - json.endMember(); - - delete [] source; -} - -static inline void -writeCurrentProgram(JSONWriter &json) -{ - GLint program = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &program); - if (!program) { - return; - } - - GLint attached_shaders = 0; - glGetProgramiv(program, GL_ATTACHED_SHADERS, &attached_shaders); - if (!attached_shaders) { - return; - } - - GLuint *shaders = new GLuint[attached_shaders]; - GLsizei count = 0; - glGetAttachedShaders(program, attached_shaders, &count, shaders); - for (GLsizei i = 0; i < count; ++ i) { - writeShader(json, shaders[i]); - } - delete [] shaders; -} - -static inline void -writeArbProgram(JSONWriter &json, GLenum target) -{ - if (!glIsEnabled(target)) { - return; - } - - GLint program_length = 0; - glGetProgramivARB(target, GL_PROGRAM_LENGTH_ARB, &program_length); - if (!program_length) { - return; - } - - GLchar *source = new GLchar[program_length + 1]; - source[0] = 0; - glGetProgramStringARB(target, GL_PROGRAM_STRING_ARB, source); - source[program_length] = 0; - - json.beginMember(enum_string(target)); - json.writeString(source); - json.endMember(); - - delete [] source; -} -''' - - # texture image - print ''' -static inline void -writeTextureImage(JSONWriter &json, GLenum target, GLint level) -{ - GLint width, height = 1, depth = 1; - - width = 0; - glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &width); - - if (target != GL_TEXTURE_1D) { - height = 0; - glGetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &height); - if (target == GL_TEXTURE_3D) { - depth = 0; - glGetTexLevelParameteriv(target, level, GL_TEXTURE_DEPTH, &depth); - } - } - - if (width <= 0 || height <= 0 || depth <= 0) { - return; - } else { - char label[512]; - - GLint active_texture = GL_TEXTURE0; - glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture); - snprintf(label, sizeof label, "%s, %s, level = %i", _enum_string(active_texture), _enum_string(target), level); - - json.beginMember(label); - - json.beginObject(); - - // Tell the GUI this is no ordinary object, but an image - json.writeStringMember("__class__", "image"); - - json.writeNumberMember("__width__", width); - json.writeNumberMember("__height__", height); - json.writeNumberMember("__depth__", depth); - - // Hardcoded for now, but we could chose types more adequate to the - // texture internal format - json.writeStringMember("__type__", "uint8"); - json.writeBoolMember("__normalized__", true); - json.writeNumberMember("__channels__", 4); - - GLubyte *pixels = new GLubyte[depth*width*height*4]; - - glGetTexImage(target, level, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - - json.beginMember("__data__"); - char *pngBuffer; - int pngBufferSize; - Image::writePixelsToBuffer(pixels, width, height, 4, false, &pngBuffer, &pngBufferSize); - json.writeBase64(pngBuffer, pngBufferSize); - free(pngBuffer); - json.endMember(); // __data__ - - delete [] pixels; - json.endObject(); - } -} - -static inline void -writeDrawBufferImage(JSONWriter &json, GLenum format) -{ - GLint width = glretrace::window_width; - GLint height = glretrace::window_height; - - GLint channels = __gl_format_channels(format); - - if (!width || !height) { - json.writeNull(); - } else { - json.beginObject(); - - // Tell the GUI this is no ordinary object, but an image - json.writeStringMember("__class__", "image"); - - json.writeNumberMember("__width__", width); - json.writeNumberMember("__height__", height); - json.writeNumberMember("__depth__", 1); - - // Hardcoded for now, but we could chose types more adequate to the - // texture internal format - json.writeStringMember("__type__", "uint8"); - json.writeBoolMember("__normalized__", true); - json.writeNumberMember("__channels__", channels); - - GLubyte *pixels = new GLubyte[width*height*channels]; - - GLint drawbuffer = glretrace::double_buffer ? GL_BACK : GL_FRONT; - GLint readbuffer = glretrace::double_buffer ? GL_BACK : GL_FRONT; - glGetIntegerv(GL_DRAW_BUFFER, &drawbuffer); - glGetIntegerv(GL_READ_BUFFER, &readbuffer); - glReadBuffer(drawbuffer); - - glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); - glPixelStorei(GL_PACK_ALIGNMENT, 1); - - glReadPixels(0, 0, width, height, format, GL_UNSIGNED_BYTE, pixels); - - glPopClientAttrib(); - glReadBuffer(readbuffer); - - json.beginMember("__data__"); - char *pngBuffer; - int pngBufferSize; - Image::writePixelsToBuffer(pixels, width, height, channels, false, &pngBuffer, &pngBufferSize); - //std::cerr <<" Before = "<<(width * height * channels * sizeof *pixels) - // <<", after = "<