X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=glstate.py;h=0caba470130f7fbe10f2a6520684f70cf305a0b1;hb=9bde72eb176831d6d4b185ec7880ec35e61147f8;hp=82f8b9f05ea289b1479fa466cb17cc47ae13b974;hpb=32871ed473727ee7628bda7cad6a9e4130d0374a;p=apitrace diff --git a/glstate.py b/glstate.py index 82f8b9f..0caba47 100644 --- a/glstate.py +++ b/glstate.py @@ -26,15 +26,15 @@ from stdapi import * -from glenum import GLenum +from glapi import * X = None # To be determined -B = Bool -I = Int +B = GLboolean +I = GLint E = GLenum -F = Float -D = Double +F = GLfloat +D = GLdouble P = OpaquePointer(Void) S = CString @@ -327,11 +327,11 @@ parameters = [ ("glGet", E, 1, "GL_FEEDBACK_BUFFER_TYPE"), # 0x0DF2 ("glGet", P, 1, "GL_SELECTION_BUFFER_POINTER"), # 0x0DF3 ("glGet", I, 1, "GL_SELECTION_BUFFER_SIZE"), # 0x0DF4 - ("glGetTexLevelParameter", X, 1, "GL_TEXTURE_WIDTH"), # 0x1000 - ("glGetTexLevelParameter", X, 1, "GL_TEXTURE_HEIGHT"), # 0x1001 - ("glGetTexLevelParameter", X, 1, "GL_TEXTURE_INTERNAL_FORMAT"), # 0x1003 - ("glGet", X, 1, "GL_TEXTURE_BORDER_COLOR"), # 0x1004 - ("glGetTexLevelParameter", X, 1, "GL_TEXTURE_BORDER"), # 0x1005 + ("glGetTexLevelParameter", I, 1, "GL_TEXTURE_WIDTH"), # 0x1000 + ("glGetTexLevelParameter", I, 1, "GL_TEXTURE_HEIGHT"), # 0x1001 + ("glGetTexLevelParameter", E, 1, "GL_TEXTURE_INTERNAL_FORMAT"), # 0x1003 + ("glGetTexParameter", F, 4, "GL_TEXTURE_BORDER_COLOR"), # 0x1004 + ("glGetTexLevelParameter", I, 1, "GL_TEXTURE_BORDER"), # 0x1005 ("glGet", X, 1, "GL_DONT_CARE"), # 0x1100 ("glGet", X, 1, "GL_FASTEST"), # 0x1101 ("glGet", X, 1, "GL_NICEST"), # 0x1102 @@ -462,10 +462,10 @@ parameters = [ ("glGet", X, 1, "GL_LINEAR_MIPMAP_NEAREST"), # 0x2701 ("glGet", X, 1, "GL_NEAREST_MIPMAP_LINEAR"), # 0x2702 ("glGet", X, 1, "GL_LINEAR_MIPMAP_LINEAR"), # 0x2703 - ("glGet", X, 1, "GL_TEXTURE_MAG_FILTER"), # 0x2800 - ("glGet", X, 1, "GL_TEXTURE_MIN_FILTER"), # 0x2801 - ("glGet", X, 1, "GL_TEXTURE_WRAP_S"), # 0x2802 - ("glGet", X, 1, "GL_TEXTURE_WRAP_T"), # 0x2803 + ("glGetTexParameter", E, 1, "GL_TEXTURE_MAG_FILTER"), # 0x2800 + ("glGetTexParameter", E, 1, "GL_TEXTURE_MIN_FILTER"), # 0x2801 + ("glGetTexParameter", E, 1, "GL_TEXTURE_WRAP_S"), # 0x2802 + ("glGetTexParameter", E, 1, "GL_TEXTURE_WRAP_T"), # 0x2803 ("glGet", X, 1, "GL_CLAMP"), # 0x2900 ("glGet", X, 1, "GL_REPEAT"), # 0x2901 ("glGet", F, 1, "GL_POLYGON_OFFSET_UNITS"), # 0x2A00 @@ -594,18 +594,18 @@ parameters = [ ("glGet", X, 1, "GL_RGB10_A2"), # 0x8059 ("glGet", X, 1, "GL_RGBA12"), # 0x805A ("glGet", X, 1, "GL_RGBA16"), # 0x805B - ("glGet", X, 1, "GL_TEXTURE_RED_SIZE"), # 0x805C - ("glGet", X, 1, "GL_TEXTURE_GREEN_SIZE"), # 0x805D - ("glGet", X, 1, "GL_TEXTURE_BLUE_SIZE"), # 0x805E - ("glGet", X, 1, "GL_TEXTURE_ALPHA_SIZE"), # 0x805F - ("glGet", X, 1, "GL_TEXTURE_LUMINANCE_SIZE"), # 0x8060 - ("glGet", X, 1, "GL_TEXTURE_INTENSITY_SIZE"), # 0x8061 + ("glGetTexLevelParameter", I, 1, "GL_TEXTURE_RED_SIZE"), # 0x805C + ("glGetTexLevelParameter", I, 1, "GL_TEXTURE_GREEN_SIZE"), # 0x805D + ("glGetTexLevelParameter", I, 1, "GL_TEXTURE_BLUE_SIZE"), # 0x805E + ("glGetTexLevelParameter", I, 1, "GL_TEXTURE_ALPHA_SIZE"), # 0x805F + ("glGetTexLevelParameter", I, 1, "GL_TEXTURE_LUMINANCE_SIZE"), # 0x8060 + ("glGetTexLevelParameter", I, 1, "GL_TEXTURE_INTENSITY_SIZE"), # 0x8061 ("glGet", X, 1, "GL_REPLACE_EXT"), # 0x8062 ("glGet", X, 1, "GL_PROXY_TEXTURE_1D"), # 0x8063 ("glGet", X, 1, "GL_PROXY_TEXTURE_2D"), # 0x8064 ("glGet", X, 1, "GL_TEXTURE_TOO_LARGE_EXT"), # 0x8065 - ("glGet", X, 1, "GL_TEXTURE_PRIORITY"), # 0x8066 - ("glGet", X, 1, "GL_TEXTURE_RESIDENT"), # 0x8067 + ("glGetTexParameter", I, 1, "GL_TEXTURE_PRIORITY"), # 0x8066 + ("glGetTexParameter", B, 1, "GL_TEXTURE_RESIDENT"), # 0x8067 ("glGet", I, 1, "GL_TEXTURE_BINDING_1D"), # 0x8068 ("glGet", I, 1, "GL_TEXTURE_BINDING_2D"), # 0x8069 ("glGet", I, 1, "GL_TEXTURE_BINDING_3D"), # 0x806A @@ -615,8 +615,8 @@ parameters = [ ("glGet", F, 1, "GL_UNPACK_IMAGE_HEIGHT"), # 0x806E ("glGet", B, 1, "GL_TEXTURE_3D"), # 0x806F ("glGet", X, 1, "GL_PROXY_TEXTURE_3D"), # 0x8070 - ("glGet", X, 1, "GL_TEXTURE_DEPTH"), # 0x8071 - ("glGet", X, 1, "GL_TEXTURE_WRAP_R"), # 0x8072 + ("glGetTexLevelParameter", I, 1, "GL_TEXTURE_DEPTH"), # 0x8071 + ("glGetTexParameter", E, 1, "GL_TEXTURE_WRAP_R"), # 0x8072 ("glGet", I, 1, "GL_MAX_3D_TEXTURE_SIZE"), # 0x8073 ("glGet", B, 1, "GL_VERTEX_ARRAY"), # 0x8074 ("glGet", B, 1, "GL_NORMAL_ARRAY"), # 0x8075 @@ -775,10 +775,10 @@ parameters = [ ("glGet", X, 1, "GL_TEXTURE_WRAP_Q_SGIS"), # 0x8137 ("glGet", I, 1, "GL_MAX_4D_TEXTURE_SIZE_SGIS"), # 0x8138 ("glGet", I, 1, "GL_PIXEL_TEX_GEN_SGIX"), # 0x8139 - ("glGet", X, 1, "GL_TEXTURE_MIN_LOD"), # 0x813A - ("glGet", X, 1, "GL_TEXTURE_MAX_LOD"), # 0x813B - ("glGet", X, 1, "GL_TEXTURE_BASE_LEVEL"), # 0x813C - ("glGet", X, 1, "GL_TEXTURE_MAX_LEVEL"), # 0x813D + ("glGetTexParameter", F, 1, "GL_TEXTURE_MIN_LOD"), # 0x813A + ("glGetTexParameter", F, 1, "GL_TEXTURE_MAX_LOD"), # 0x813B + ("glGetTexParameter", F, 1, "GL_TEXTURE_BASE_LEVEL"), # 0x813C + ("glGetTexParameter", F, 1, "GL_TEXTURE_MAX_LEVEL"), # 0x813D ("glGet", I, 1, "GL_PIXEL_TILE_BEST_ALIGNMENT_SGIX"), # 0x813E ("glGet", I, 1, "GL_PIXEL_TILE_CACHE_INCREMENT_SGIX"), # 0x813F ("glGet", I, 1, "GL_PIXEL_TILE_WIDTH_SGIX"), # 0x8140 @@ -854,7 +854,7 @@ parameters = [ ("glGet", X, 1, "GL_TEXTURE_LOD_BIAS_S_SGIX"), # 0x818E ("glGet", X, 1, "GL_TEXTURE_LOD_BIAS_T_SGIX"), # 0x818F ("glGet", X, 1, "GL_TEXTURE_LOD_BIAS_R_SGIX"), # 0x8190 - ("glGet", X, 1, "GL_GENERATE_MIPMAP"), # 0x8191 + ("glGetTexParameter", B, 1, "GL_GENERATE_MIPMAP"), # 0x8191 ("glGet", E, 1, "GL_GENERATE_MIPMAP_HINT"), # 0x8192 ("glGet", X, 1, "GL_GEOMETRY_DEFORMATION_SGIX"), # 0x8194 ("glGet", X, 1, "GL_TEXTURE_DEFORMATION_SGIX"), # 0x8195 @@ -1346,7 +1346,7 @@ parameters = [ ("glGet", X, 1, "GL_SLICE_ACCUM_SUN"), # 0x85CC ("glGet", X, 1, "GL_QUAD_MESH_SUN"), # 0x8614 ("glGet", X, 1, "GL_TRIANGLE_MESH_SUN"), # 0x8615 - ("glGet", X, 1, "GL_VERTEX_PROGRAM_ARB"), # 0x8620 + ("glGet", B, 1, "GL_VERTEX_PROGRAM_ARB"), # 0x8620 ("glGet", X, 1, "GL_VERTEX_STATE_PROGRAM_NV"), # 0x8621 ("glGetVertexAttrib", B, 1, "GL_VERTEX_ATTRIB_ARRAY_ENABLED"), # 0x8622 ("glGetVertexAttrib", I, 1, "GL_VERTEX_ATTRIB_ARRAY_SIZE"), # 0x8623 @@ -1360,8 +1360,8 @@ parameters = [ ("glGet", X, 1, "GL_INVERSE_NV"), # 0x862B ("glGet", X, 1, "GL_TRANSPOSE_NV"), # 0x862C ("glGet", X, 1, "GL_INVERSE_TRANSPOSE_NV"), # 0x862D - ("glGet", X, 1, "GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB"), # 0x862E - ("glGet", X, 1, "GL_MAX_PROGRAM_MATRICES_ARB"), # 0x862F + ("glGet", I, 1, "GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB"), # 0x862E + ("glGet", I, 1, "GL_MAX_PROGRAM_MATRICES_ARB"), # 0x862F ("glGet", X, 1, "GL_MATRIX0_NV"), # 0x8630 ("glGet", X, 1, "GL_MATRIX1_NV"), # 0x8631 ("glGet", X, 1, "GL_MATRIX2_NV"), # 0x8632 @@ -1372,8 +1372,8 @@ parameters = [ ("glGet", X, 1, "GL_MATRIX7_NV"), # 0x8637 ("glGet", X, 1, "GL_CURRENT_MATRIX_STACK_DEPTH_ARB"), # 0x8640 ("glGet", X, 1, "GL_CURRENT_MATRIX_ARB"), # 0x8641 - ("glGet", X, 1, "GL_VERTEX_PROGRAM_POINT_SIZE"), # 0x8642 - ("glGet", X, 1, "GL_VERTEX_PROGRAM_TWO_SIDE"), # 0x8643 + ("glGet", B, 1, "GL_VERTEX_PROGRAM_POINT_SIZE"), # 0x8642 + ("glGet", B, 1, "GL_VERTEX_PROGRAM_TWO_SIDE"), # 0x8643 ("glGet", X, 1, "GL_PROGRAM_PARAMETER_NV"), # 0x8644 ("glGetVertexAttrib", P, 1, "GL_VERTEX_ATTRIB_ARRAY_POINTER"), # 0x8645 ("glGet", X, 1, "GL_PROGRAM_TARGET_NV"), # 0x8646 @@ -1435,7 +1435,7 @@ parameters = [ ("glGet", X, 1, "GL_MAP2_VERTEX_ATTRIB14_4_NV"), # 0x867E ("glGet", X, 1, "GL_MAP2_VERTEX_ATTRIB15_4_NV"), # 0x867F ("glGet", X, 1, "GL_TEXTURE_COMPRESSED_IMAGE_SIZE"), # 0x86A0 - ("glGet", X, 1, "GL_TEXTURE_COMPRESSED"), # 0x86A1 + ("glGetTexLevelParameter", B, 1, "GL_TEXTURE_COMPRESSED"), # 0x86A1 ("glGet", X, 1, "GL_NUM_COMPRESSED_TEXTURE_FORMATS"), # 0x86A2 #XXX: the list is GL_NUM_COMPRESSED_TEXTURES #("glGet", E, 1, "GL_COMPRESSED_TEXTURE_FORMATS"), # 0x86A3 @@ -1754,7 +1754,7 @@ parameters = [ ("glGet", E, 1, "GL_STENCIL_BACK_FAIL"), # 0x8801 ("glGet", E, 1, "GL_STENCIL_BACK_PASS_DEPTH_FAIL"), # 0x8802 ("glGet", E, 1, "GL_STENCIL_BACK_PASS_DEPTH_PASS"), # 0x8803 - ("glGet", X, 1, "GL_FRAGMENT_PROGRAM_ARB"), # 0x8804 + ("glGet", B, 1, "GL_FRAGMENT_PROGRAM_ARB"), # 0x8804 ("glGet", X, 1, "GL_PROGRAM_ALU_INSTRUCTIONS_ARB"), # 0x8805 ("glGet", X, 1, "GL_PROGRAM_TEX_INSTRUCTIONS_ARB"), # 0x8806 ("glGet", X, 1, "GL_PROGRAM_TEX_INDIRECTIONS_ARB"), # 0x8807 @@ -1809,11 +1809,11 @@ parameters = [ ("glGet", E, 1, "GL_MATRIX_INDEX_ARRAY_TYPE_ARB"), # 0x8847 ("glGet", X, 1, "GL_MATRIX_INDEX_ARRAY_STRIDE_ARB"), # 0x8848 ("glGet", X, 1, "GL_MATRIX_INDEX_ARRAY_POINTER_ARB"), # 0x8849 - ("glGet", X, 1, "GL_TEXTURE_DEPTH_SIZE"), # 0x884A - ("glGet", X, 1, "GL_DEPTH_TEXTURE_MODE"), # 0x884B - ("glGet", X, 1, "GL_TEXTURE_COMPARE_MODE"), # 0x884C - ("glGet", X, 1, "GL_TEXTURE_COMPARE_FUNC"), # 0x884D - ("glGet", X, 1, "GL_COMPARE_R_TO_TEXTURE"), # 0x884E + ("glGetTexLevelParameter", I, 1, "GL_TEXTURE_DEPTH_SIZE"), # 0x884A + ("glGetTexParameter", E, 1, "GL_DEPTH_TEXTURE_MODE"), # 0x884B + ("glGetTexParameter", E, 1, "GL_TEXTURE_COMPARE_MODE"), # 0x884C + ("glGetTexParameter", E, 1, "GL_TEXTURE_COMPARE_FUNC"), # 0x884D + (None, X, 1, "GL_COMPARE_R_TO_TEXTURE"), # 0x884E ("glGet", X, 1, "GL_TEXTURE_CUBE_MAP_SEAMLESS"), # 0x884F ("glGet", X, 1, "GL_OFFSET_PROJECTIVE_TEXTURE_2D_NV"), # 0x8850 ("glGet", X, 1, "GL_OFFSET_PROJECTIVE_TEXTURE_2D_SCALE_NV"), # 0x8851 @@ -1850,7 +1850,7 @@ parameters = [ ("glGet", I, 1, "GL_MAX_TEXTURE_COORDS"), # 0x8871 ("glGet", I, 1, "GL_MAX_TEXTURE_IMAGE_UNITS"), # 0x8872 ("glGet", I, 1, "GL_FRAGMENT_PROGRAM_BINDING_NV"), # 0x8873 - ("glGet", X, 1, "GL_PROGRAM_ERROR_STRING_ARB"), # 0x8874 + ("glGet", S, 1, "GL_PROGRAM_ERROR_STRING_ARB"), # 0x8874 ("glGet", X, 1, "GL_PROGRAM_FORMAT_ASCII_ARB"), # 0x8875 ("glGet", X, 1, "GL_PROGRAM_FORMAT_ARB"), # 0x8876 ("glGet", X, 1, "GL_WRITE_PIXEL_DATA_RANGE_NV"), # 0x8878 @@ -2837,67 +2837,112 @@ texture_targets = [ ] -class GlGetter(Visitor): - '''Type visitor - Determine which glGet*v function that matches the specified type.''' +class GetInflector: + '''Objects that describes how to inflect.''' - def __init__(self, prefix = 'glGet', long_suffix = True): - self.prefix = prefix - self.long_suffix = long_suffix + reduced_types = { + B: I, + E: I, + I: F, + } - if prefix == 'glGet': - self.suffixes = { - 'GLboolean': 'Booleanv', - 'GLint': 'Intv', - 'GLfloat': 'Floatv', - 'GLdouble': 'Doublev', - 'GLstring': 'String', - } - else: - self.suffixes = { - 'GLint': 'iv', - 'GLfloat': 'fv', - 'GLdouble': 'Doublev', - 'GLstring': 'String', - } - - - def visit_const(self, const): - return self.visit(const.type) - - def visit_alias(self, alias): - if alias.expr == 'GLboolean': - if self.long_suffix: - return self.prefix + 'Booleanv', alias.expr - else: - return self.prefix + 'iv', 'GLint' - elif alias.expr == 'GLdouble': - if self.long_suffix: - return self.prefix + 'Doublev', alias.expr - else: - return self.prefix + 'dv', alias.expr - elif alias.expr == 'GLfloat': - if self.long_suffix: - return self.prefix + 'Floatv', alias.expr - else: - return self.prefix + 'fv', alias.expr - elif alias.expr in ('GLint', 'GLuint', 'GLsizei'): - if self.long_suffix: - return self.prefix + 'Integerv', 'GLint' - else: - return self.prefix + 'iv', 'GLint' + def __init__(self, radical, suffixes): + self.radical = radical + self.suffixes = suffixes + + def reduced_type(self, type): + if type in self.suffixes: + return type + if type in self.reduced_types: + return self.reduced_type(self.reduced_types[type]) + raise NotImplementedError + + def inflect(self, type): + return self.radical + self.suffix(type) + + def suffix(self, type): + type = self.reduced_type(type) + assert type in self.suffixes + return self.suffixes[type] + + +glGet = GetInflector('glGet', { + B: 'Booleanv', + I: 'Integerv', + F: 'Floatv', + D: 'Doublev', + S: 'String', + P: 'Pointerv', +}) + +glGetTexParameter = GetInflector('glGetTexParameter', {I: 'iv', F: 'fv'}) + + + +class StateGetter(Visitor): + '''Type visitor that is able to extract the state via one of the glGet* + functions. + + It will declare any temporary variable + ''' + + def __init__(self, inflector): + self.inflector = inflector + + def temp_name(self, pname): + '''Return the name of a temporary variable to hold the state.''' + + return pname[3:].lower() + + def visit_const(self, const, pname): + return self.visit(const.type, pname) + + def visit_scalar(self, type, pname): + temp_name = self.temp_name(pname) + elem_type = self.inflector.reduced_type(type) + inflection = self.inflector.inflect(type) + if inflection.endswith('v'): + print ' %s %s = 0;' % (elem_type, temp_name) + print ' %s(%s, &%s);' % (inflection, pname, temp_name) else: - print alias.expr - assert False - - def visit_enum(self, enum): - return self.visit(glapi.GLint) + print ' %s %s = %s(%s);' % (elem_type, temp_name, inflection, pname) + return temp_name - def visit_bitmask(self, bitmask): - return self.visit(glapi.GLint) + def visit_string(self, string, pname): + temp_name = self.temp_name(pname) + inflection = self.inflector.inflect(string) + assert not inflection.endswith('v') + print ' %s %s = (%s)%s(%s);' % (string, temp_name, string, inflection, pname) + return temp_name - def visit_opaque(self, pointer): - return self.prefix + 'Pointerv', 'GLvoid *' + def visit_alias(self, alias, pname): + return self.visit_scalar(alias, pname) + + def visit_enum(self, enum, pname): + return self.visit(GLint, pname) + + def visit_bitmask(self, bitmask, pname): + return self.visit(GLint, pname) + + def visit_array(self, array, pname): + temp_name = self.temp_name(pname) + 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 ' memset(%s, 0, %s * sizeof *%s);' % (temp_name, array.length, temp_name) + print ' %s(%s, %s);' % (inflection, pname, temp_name) + return temp_name + + def visit_opaque(self, pointer, pname): + temp_name = self.temp_name(pname) + inflection = self.inflector.inflect(pointer) + assert inflection.endswith('v') + print ' GLvoid *%s;' % temp_name + print ' %s(%s, &%s);' % (inflection, pname, temp_name) + return temp_name class JsonWriter(Visitor): @@ -2947,6 +2992,8 @@ class JsonWriter(Visitor): class StateDumper: + '''Class to generate code to dump all GL state in JSON format via + stdout.''' def __init__(self): self.level = 0 @@ -2958,90 +3005,152 @@ class StateDumper: print '#include "json.hpp"' print '#include "glimports.hpp"' print '#include "glproc.hpp"' + print '#include "glsize.hpp"' print '#include "glretrace.hpp"' print - print 'static void' - print 'writeEnum(JSONWriter &json, GLenum pname)' + print 'static const char *' + print '_enum_string(GLenum pname)' print '{' print ' switch(pname) {' for name in GLenum.values: print ' case %s:' % name - print ' json.writeString("%s");' % name - print ' break;' + print ' return "%s";' % name print ' default:' - print ' json.writeNumber(pname);' + print ' return NULL;' print ' }' print '}' print - # shaders - print 'static void' - print 'writeShader(JSONWriter &json, GLuint shader)' + print 'static const char *' + print 'enum_string(GLenum pname)' print '{' - print ' if (!shader) {' - print ' json.writeNull();' - print ' return;' - print ' }' - print - print ' json.beginObject();' - print ' GLint source_length = 0;' - print ' glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &source_length);' - print ' json.beginMember("source");' - print ' if (source_length) {' - print ' GLchar *source = new GLchar[source_length];' - print ' GLsizei length = 0;' - print ' source[0] = 0;' - print ' glGetShaderSource(shader, source_length, &length, source);' - print ' json.writeString(source);' - print ' delete [] source;' + print ' const char *s = _enum_string(pname);' + print ' if (s) {' + print ' return s;' print ' } else {' - print ' json.writeNull();' + print ' static char buf[16];' + print ' snprintf(buf, sizeof buf, "0x%04x", pname);' + print ' return buf;' print ' }' - print ' json.endMember(); // source' - print ' json.endObject();' print '}' print - # programs print 'static inline void' - print 'writeProgram(JSONWriter &json, GLuint program)' + print 'writeEnum(JSONWriter &json, GLenum pname)' print '{' - print ' if (!program) {' - print ' json.writeNull();' - print ' return;' - print ' }' - print - print ' json.beginObject();' - print ' json.beginMember("attached_shaders");' - print ' GLint attached_shaders = 0;' - print ' glGetProgramiv(program, GL_ATTACHED_SHADERS, &attached_shaders);' - print ' json.beginArray();' - print ' if (attached_shaders) {' - print ' GLuint *shaders = new GLuint[attached_shaders];' - print ' GLsizei count = 0;' - print ' glGetAttachedShaders(program, attached_shaders, &count, shaders);' - print ' for (GLsizei i = 0; i < count; ++ i) {' - print ' writeShader(json, shaders[i]);' - print ' }' - print ' delete [] shaders;' + print ' const char *s = _enum_string(pname);' + print ' if (s) {' + print ' json.writeString(s);' + print ' } else {' + print ' json.writeNumber(pname);' print ' }' - print ' json.endArray();' - print ' json.endMember();' - print ' json.endObject();' 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 = 0, height = 0; + GLint width, height = 1, depth = 1; + + width = 0; glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &width); - glGetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &height); - if (!width || !height) { + 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) { json.writeNull(); } else { json.beginObject(); @@ -3051,46 +3160,78 @@ writeTextureImage(JSONWriter &json, GLenum target, GLint level) json.writeNumberMember("__width__", width); json.writeNumberMember("__height__", height); - json.writeNumberMember("__depth__", 1); + json.writeNumberMember("__depth__", depth); // Hardcoded for now, but we could chose types more adequate to the // texture internal format - json.writeStringMember("__type__", "float"); + json.writeStringMember("__type__", "uint8"); + json.writeBoolMember("__normalized__", true); json.writeNumberMember("__channels__", 4); - float *pixels = new float[width*height*4]; + GLubyte *pixels = new GLubyte[depth*width*height*4]; - glGetTexImage(target, level, GL_RGBA, GL_FLOAT, pixels); - - if (0) { - json.writeStringMember("__encoding__", "array"); - json.beginMember("__data__"); - - json.beginArray(); - for (GLint y = 0; y < height; ++y) { - json.beginArray(); - for (GLint x = 0; x < width; ++x) { - json.beginArray(); - for (GLint chan = 0; chan < 4; ++chan) { - json.writeNumber(pixels[(y*width + x)*4 + chan]); - } - json.endArray(); - } - json.endArray(); - } - json.endArray(); - json.endMember(); // __data__ - } else { - json.writeStringMember("__encoding__", "base64"); - json.beginMember("__data__"); - json.writeBase64(pixels, width * height * 4 * sizeof *pixels); - json.endMember(); // __data__ - } + glGetTexImage(target, level, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + json.beginMember("__data__"); + json.writeBase64(pixels, depth * width * height * 4 * sizeof *pixels); + 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__"); + json.writeBase64(pixels, width * height * channels * sizeof *pixels); + json.endMember(); // __data__ delete [] pixels; json.endObject(); } } + ''' # textures @@ -3106,6 +3247,16 @@ writeTextureImage(JSONWriter &json, GLenum target, GLint level) print print ' json.beginObject();' print + print ' GLfloat param;' + for function, type, count, name in parameters: + if function != 'glGetTexParameter' or count != 1: + continue + print ' glGetTexParameterfv(target, %s, ¶m);' % name + print ' json.beginMember("%s");' % name + JsonWriter().visit(type, 'param') + print ' json.endMember();' + print + print print ' json.beginMember("levels");' print ' json.beginArray();' print ' GLint level = 0;' @@ -3124,14 +3275,15 @@ writeTextureImage(JSONWriter &json, GLenum target, GLint level) print ' json.writeNumber(texture);' print ' json.endMember();' print - print ' json.beginMember("GL_TEXTURE_WIDTH");' - print ' json.writeNumber(width);' - print ' json.endMember();' - print - print ' json.beginMember("GL_TEXTURE_HEIGHT");' - print ' json.writeNumber(height);' - print ' json.endMember();' - print + # TODO: Generalize this + for function, type, count, name in parameters: + if function != 'glGetTexLevelParameter' or count != 1: + continue + print ' glGetTexLevelParameterfv(target, level, %s, ¶m);' % name + print ' json.beginMember("%s");' % name + JsonWriter().visit(type, 'param') + print ' json.endMember();' + print print ' json.beginMember("image");' print ' writeTextureImage(json, target, level);' print ' json.endMember();' @@ -3152,19 +3304,11 @@ writeTextureImage(JSONWriter &json, GLenum target, GLint level) self.dump_parameters() self.dump_current_program() self.dump_textures() + self.dump_framebuffer() print '}' print def dump_parameters(self): - print ' const GLubyte * sparams[1];' - print ' GLboolean bparams[16];' - print ' GLint iparams[16];' - print ' GLfloat fparams[16];' - print ' GLdouble dparams[16];' - print ' GLvoid * pparams[16];' - print - print ' (void)dparams;' - print print ' json.beginMember("parameters");' print ' json.beginObject();' for function, type, count, name in parameters: @@ -3172,55 +3316,33 @@ writeTextureImage(JSONWriter &json, GLenum target, GLint level) continue if type is X: continue - elif type is B: - buf = 'bparams' - getter = 'glGetBooleanv' - elif type is I: - buf = 'iparams' - getter = 'glGetIntegerv' - elif type is E: - buf = 'iparams' - getter = 'glGetIntegerv' - elif type is F: - buf = 'fparams' - getter = 'glGetFloatv' - elif type is D: - buf = 'dparams' - getter = 'glGetDoublev' - elif type is P: - buf = 'pparams' - getter = 'glGetPointerv' - elif type is S: - buf = 'sparams' - getter = 'glGetString' - else: - raise NotImplementedError - print ' memset(%s, 0, %u * sizeof *%s);' % (buf, count, buf) - if getter.endswith('v'): - print ' %s(%s, %s);' % (getter, name, buf) - else: - assert count == 1 - print ' %s[0] = %s(%s);' % (buf, getter, name) - print ' if (glGetError() != GL_NO_ERROR) {' - #print ' std::cerr << "warning: %s(%s) failed\\n";' % (getter, name) - print ' } else {' - print ' json.beginMember("%s");' % name - if count == 1: - JsonWriter().visit(type, '%s[0]' % buf) - else: - JsonWriter().visit(Array(type, str(count)), buf) - print ' json.endMember();' + if count != 1: + type = Array(type, str(count)) + + print ' // %s' % name + print ' {' + value = StateGetter(glGet).visit(type, name) + print ' if (glGetError() != GL_NO_ERROR) {' + #print ' std::cerr << "warning: %s(%s) failed\\n";' % (glGet.radical, name) + print ' } else {' + print ' json.beginMember("%s");' % name + JsonWriter().visit(type, value) + print ' json.endMember();' + print ' }' print ' }' + print print ' json.endObject();' print ' json.endMember(); // parameters' print def dump_current_program(self): - print ' GLint current_program = 0;' - print ' glGetIntegerv(GL_CURRENT_PROGRAM, ¤t_program);' - print ' json.beginMember("current_program");' - print ' writeProgram(json, current_program);' - print ' json.endMember();' + print ' json.beginMember("shaders");' + print ' json.beginObject();' + print ' writeCurrentProgram(json);' + print ' writeArbProgram(json, GL_FRAGMENT_PROGRAM_ARB);' + print ' writeArbProgram(json, GL_VERTEX_PROGRAM_ARB);' + print ' json.endObject();' + print ' json.endMember(); //shaders' print def dump_textures(self): @@ -3244,6 +3366,35 @@ writeTextureImage(JSONWriter &json, GLenum target, GLint level) print ' json.endMember(); // texture' print + def dump_framebuffer(self): + print ' json.beginMember("framebuffer");' + print ' json.beginObject();' + # TODO: Handle real FBOs + print + print ' json.beginMember("GL_RGBA");' + print ' writeDrawBufferImage(json, GL_RGBA);' + print ' json.endMember();' + print + print ' GLint depth_bits = 0;' + print ' glGetIntegerv(GL_DEPTH_BITS, &depth_bits);' + print ' if (depth_bits) {' + print ' json.beginMember("GL_DEPTH_COMPONENT");' + print ' writeDrawBufferImage(json, GL_DEPTH_COMPONENT);' + print ' json.endMember();' + print ' }' + print + print ' GLint stencil_bits = 0;' + print ' glGetIntegerv(GL_STENCIL_BITS, &stencil_bits);' + print ' if (stencil_bits) {' + print ' json.beginMember("GL_STENCIL_INDEX");' + print ' writeDrawBufferImage(json, GL_STENCIL_INDEX);' + print ' json.endMember();' + print ' }' + print + print ' json.endObject();' + print ' json.endMember(); // framebuffer' + pass + def write_line(s): self.write(' '*self.level + s + '\n')