]> git.cworth.org Git - apitrace/blobdiff - glstate.py
Update drawable on variations of glViewport (issue #71)
[apitrace] / glstate.py
index 38084151979f6ad62aaed2381efc687b1738cfaa..ad8e25887c25ed17e62ee9d599c291fbd40441df 100644 (file)
 '''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')
@@ -175,6 +189,7 @@ 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):
@@ -183,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 '    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();'
@@ -237,6 +252,7 @@ class StateDumper:
         print '#include "glproc.hpp"'
         print '#include "glsize.hpp"'
         print '#include "glstate.hpp"'
+        print '#include "glstate_internal.hpp"'
         print
         print 'namespace glstate {'
         print
@@ -244,7 +260,7 @@ class StateDumper:
         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,6 +270,13 @@ class StateDumper:
         print '}'
         print
 
+        print 'static void'
+        print 'dumpFramebufferAttachementParameters(JSONWriter &json, GLenum target, GLenum attachment)'
+        print '{'
+        self.dump_attachment_parameters('target', 'attachment')
+        print '}'
+        print
+
         print 'void'
         print 'dumpEnum(JSONWriter &json, GLenum pname)'
         print '{'
@@ -266,7 +289,7 @@ class StateDumper:
         print '}'
         print
 
-        print 'void dumpParameters(JSONWriter &json)'
+        print 'void dumpParameters(JSONWriter &json, Context &context)'
         print '{'
         print '    json.beginMember("parameters");'
         print '    json.beginObject();'
@@ -276,9 +299,9 @@ class StateDumper:
         self.dump_material_params()
         self.dump_light_params()
         self.dump_vertex_attribs()
-        self.dump_texenv_params()
         self.dump_program_params()
         self.dump_texture_parameters()
+        self.dump_framebuffer_parameters()
 
         print '    json.endObject();'
         print '    json.endMember(); // parameters'
@@ -288,11 +311,13 @@ class StateDumper:
         print '} /*namespace glstate */'
 
     def dump_material_params(self):
+        print '    if (!context.ES) {'
         for face in ['GL_FRONT', 'GL_BACK']:
             print '    json.beginMember("%s");' % face
             print '    json.beginObject();'
             self.dump_atoms(glGetMaterial, face)
             print '    json.endObject();'
+        print '    }'
         print
 
     def dump_light_params(self):
@@ -312,15 +337,22 @@ class StateDumper:
         print '    }'
         print
 
+    def texenv_param_target(self, name):
+        if name == 'GL_TEXTURE_LOD_BIAS':
+           return 'GL_TEXTURE_FILTER_CONTROL'
+        elif name == 'GL_COORD_REPLACE':
+           return 'GL_POINT_SPRITE'
+        else:
+           return 'GL_TEXTURE_ENV'
+
     def dump_texenv_params(self):
         for target in ['GL_TEXTURE_ENV', 'GL_TEXTURE_FILTER_CONTROL', 'GL_POINT_SPRITE']:
-            if target != 'GL_TEXTURE_FILTER_CONTROL':
-                print '    if (glIsEnabled(%s)) {' % target
-            else:
-                print '    {'
+            print '    if (!context.ES) {'
             print '        json.beginMember("%s");' % target
             print '        json.beginObject();'
-            self.dump_atoms(glGetTexEnv, target)
+            for _, _, name in glGetTexEnv.iter():
+                if self.texenv_param_target(name) == target:
+                    self.dump_atom(glGetTexEnv, target, name) 
             print '        json.endObject();'
             print '    }'
 
@@ -367,22 +399,32 @@ class StateDumper:
         print '            json.beginMember(name);'
         print '            glActiveTexture(GL_TEXTURE0 + unit);'
         print '            json.beginObject();'
-        print '            GLint texture;'
+        print '            GLboolean enabled;'
+        print '            GLint binding;'
         print
         for target, binding in texture_targets:
             print '            // %s' % target
-            print '            texture = 0;'
-            print '            glGetIntegerv(%s, &texture);' % binding
-            print '            if (glIsEnabled(%s) || texture) {' % target
+            print '            enabled = GL_FALSE;'
+            print '            glGetBooleanv(%s, &enabled);' % target
+            print '            json.writeBoolMember("%s", enabled);' % target
+            print '            binding = 0;'
+            print '            glGetIntegerv(%s, &binding);' % binding
+            print '            json.writeNumberMember("%s", binding);' % binding
+            print '            if (enabled || binding) {'
             print '                json.beginMember("%s");' % target
             print '                json.beginObject();'
             self.dump_atoms(glGetTexParameter, target)
+            print '                if (!context.ES) {'
             # We only dump the first level parameters
             self.dump_atoms(glGetTexLevelParameter, target, "0")
+            print '                }'
             print '                json.endObject();'
             print '                json.endMember(); // %s' % target
             print '            }'
             print
+        print '            if (unit < max_texture_coords) {'
+        self.dump_texenv_params()
+        print '            }'
         print '            json.endObject();'
         print '            json.endMember(); // GL_TEXTUREi'
         print '        }'
@@ -390,25 +432,71 @@ class StateDumper:
         print '    }'
         print
 
-    def dump_atoms(self, getter, *args):
-        for function, type, count, name in parameters:
-            inflection = getter.inflector.radical + getter.suffix
-            if inflection not in function.split(','):
-                continue
-            if type is X:
-                continue
-            print '        // %s' % name
-            print '        {'
-            type, value = getter(*(args + (name,)))
-            print '            if (glGetError() != GL_NO_ERROR) {'
-            #print '                std::cerr << "warning: %s(%s) failed\\n";' % (inflection, name)
-            print '            } else {'
-            print '                json.beginMember("%s");' % name
-            JsonWriter().visit(type, value)
-            print '                json.endMember();'
+    def dump_framebuffer_parameters(self):
+        print '    {'
+        print '        GLint max_color_attachments = 0;'
+        print '        glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &max_color_attachments);'
+        print '        GLint framebuffer;'
+        for target, binding in framebuffer_targets:
+            print '            // %s' % target
+            print '            framebuffer = 0;'
+            print '            glGetIntegerv(%s, &framebuffer);' % binding
+            print '            if (framebuffer) {'
+            print '                json.beginMember("%s");' % target
+            print '                json.beginObject();'
+            print '                for (GLint i = 0; i < max_color_attachments; ++i) {'
+            print '                    GLint color_attachment = GL_COLOR_ATTACHMENT0 + i;'
+            print '                    dumpFramebufferAttachementParameters(json, %s, color_attachment);' % target
+            print '                }'
+            print '                dumpFramebufferAttachementParameters(json, %s, GL_DEPTH_ATTACHMENT);' % target
+            print '                dumpFramebufferAttachementParameters(json, %s, GL_STENCIL_ATTACHMENT);' % target
+            print '                json.endObject();'
+            print '                json.endMember(); // %s' % target
             print '            }'
-            print '        }'
             print
+        print '    }'
+        print
+
+    def dump_attachment_parameters(self, target, attachment):
+        print '            {'
+        print '                GLint object_type = GL_NONE;'
+        print '                glGetFramebufferAttachmentParameteriv(%s, %s, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &object_type);' % (target, attachment)
+        print '                if (object_type != GL_NONE) {'
+        print '                    json.beginMember(enumToString(%s));' % attachment
+        print '                    json.beginObject();'
+        self.dump_atoms(glGetFramebufferAttachmentParameter, target, attachment)
+        print '                    json.endObject();'
+        print '                    json.endMember(); // GL_x_ATTACHMENT'
+        print '                }'
+        print '            }'
+
+    def dump_atoms(self, getter, *args):
+        for _, _, name in getter.iter():
+            self.dump_atom(getter, *(args + (name,))) 
+
+    def dump_atom(self, getter, *args):
+        name = args[-1]
+
+        # Avoid crash on MacOSX
+        # XXX: The right fix would be to look at the support extensions..
+        import platform
+        if name == 'GL_SAMPLER_BINDING' and platform.system() == 'Darwin':
+            return
+
+        print '        // %s' % name
+        print '        {'
+        #print '            assert(glGetError() == GL_NO_ERROR);'
+        type, value = getter(*args)
+        print '            if (glGetError() != GL_NO_ERROR) {'
+        #print '                std::cerr << "warning: %s(%s) failed\\n";' % (inflection, name)
+        print '                while (glGetError() != GL_NO_ERROR) {}'
+        print '            } else {'
+        print '                json.beginMember("%s");' % name
+        JsonWriter().visit(type, value)
+        print '                json.endMember();'
+        print '            }'
+        print '        }'
+        print
 
 
 if __name__ == '__main__':