]> git.cworth.org Git - apitrace/commitdiff
Introduce AttribArray, a code generator for pseudo-type attrib_list.
authorAndreas Hartmetz <ahartmetz@gmail.com>
Sun, 7 Jul 2013 20:51:12 +0000 (22:51 +0200)
committerAndreas Hartmetz <ahartmetz@gmail.com>
Mon, 8 Jul 2013 11:24:23 +0000 (13:24 +0200)
Also use it for glXCreateConfigAttribsARB, which gives the expected
correct dumps in qapitrace and glretrace dump.
Nothing needs to change in dump code because it just reads whatever
types were written during tracing. Writing different types into
different array elements is allowed by the format, and it turns out
that even older versions of apitrace will correctly display dumps
created with this patch.

specs/glxapi.py
specs/stdapi.py
wrappers/trace.py

index 42df48696042c2f74f6461ae1e1a610b18bf0097..b06082d57a55b51d2c28d1406fa6c052b8d621f1 100644 (file)
@@ -206,6 +206,13 @@ GLXbuffer = Flags(Int, [
     "GLX_PBUFFER_CLOBBER_MASK",
 ])
 
+GLXContextAttribs = AttribArray(GLXEnum, [
+    ('GLX_CONTEXT_MAJOR_VERSION_ARB', Int),
+    ('GLX_CONTEXT_MINOR_VERSION_ARB', Int),
+    ('GLX_CONTEXT_FLAGS_ARB', Flags(Int, ["GLX_CONTEXT_DEBUG_BIT_ARB", "GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB"])),
+    ('GLX_CONTEXT_PROFILE_MASK_ARB', Flags(Int, ["GLX_CONTEXT_CORE_PROFILE_BIT_ARB", "GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB"]))
+])
+
 glxapi = Module("GLX")
 
 PROC = Opaque("__GLXextFuncPtr")
@@ -273,7 +280,9 @@ glxapi.addFunctions([
                                            Out(Pointer(ULong), "mask")]),
 
     # GLX_ARB_create_context
-    Function(GLXContext, "glXCreateContextAttribsARB", [(Display, "dpy"), (GLXFBConfig, "config"), (GLXContext, "share_context"), (Bool, "direct"), (Array(Const(GLXEnum), "_AttribPairList_size(attrib_list)"), "attrib_list")]),
+    Function(GLXContext, "glXCreateContextAttribsARB", [(Display, "dpy"), (GLXFBConfig, "config"),
+                                                        (GLXContext, "share_context"), (Bool, "direct"),
+                                                        (GLXContextAttribs,  "attrib_list")]),
 
     # GLX_SGI_swap_control
     Function(Int, "glXSwapIntervalSGI", [(Int, "interval")]),
index 990c6510ca6a914cce8eba23998ba4599edf826e..795f0cfa2776f7e7f24c7cf0803f85cad2e8f8b8 100644 (file)
@@ -270,6 +270,18 @@ class Array(Type):
         return visitor.visitArray(self, *args, **kwargs)
 
 
+class AttribArray(Type):
+
+    def __init__(self, keyType, valueTypes):
+        Type.__init__(self, (Pointer(Const(Int))).expr)
+        self.type = (Pointer(Const(Int))) # for function prototypes and such
+        self.keyType = keyType
+        self.valueTypes = valueTypes
+
+    def visit(self, visitor, *args, **kwargs):
+        return visitor.visitAttribArray(self, *args, **kwargs)
+
+
 class Blob(Type):
 
     def __init__(self, type, size):
@@ -572,6 +584,9 @@ class Visitor:
     def visitArray(self, array, *args, **kwargs):
         raise NotImplementedError
 
+    def visitAttribArray(self, array, *args, **kwargs):
+        raise NotImplementedError
+
     def visitBlob(self, blob, *args, **kwargs):
         raise NotImplementedError
 
@@ -776,6 +791,10 @@ class Traverser(Visitor):
     def visitArray(self, array, *args, **kwargs):
         self.visit(array.type, *args, **kwargs)
 
+    def visitAttribArray(self, attribs, *args, **kwargs):
+        for key, valueType in attribs.valueTypes:
+            self.visit(valueType, *args, **kwargs)
+
     def visitBlob(self, array, *args, **kwargs):
         pass
 
index 31087e92b722c9ef4b6991078172a67551d1500f..17e4e9c9baf03a0158dbc4ebf02ee6a3afdd02f8 100644 (file)
@@ -83,6 +83,9 @@ class ComplexValueSerializer(stdapi.OnceVisitor):
     def visitArray(self, array):
         self.visit(array.type)
 
+    def visitAttribArray(self, array):
+        pass
+
     def visitBlob(self, array):
         pass
 
@@ -203,6 +206,57 @@ class ValueSerializer(stdapi.Visitor, stdapi.ExpanderMixin):
         print '        trace::localWriter.writeNull();'
         print '    }'
 
+    def visitAttribArray(self, array, instance):
+        # iterate element by element and for each, decide if it is a key or value (which depends on the
+        # previous key). If it is a value, look up what it means and store it as the right type - usually
+        # int, some bitfield, or some enum.
+
+        # determine the array length, which is unfortunately needed by writeArray() up front
+        count = '_c' + array.keyType.tag
+        print '    int %s;' % count
+        print '    for (%(c)s = 0; %(array)s && %(array)s[%(c)s]; %(c)s++) {' % {'c': count, 'array': instance}
+        print '        switch (%(array)s[%(c)s]) {' % {'array': instance, 'c': count}
+        for key, valueType in array.valueTypes:
+            if valueType is not None:
+                print '        case %s:' % key
+        print '            %s++;' % count # only a null key marks the end; skip null values
+        print '            break;'
+        print '        }'
+        print '    }'
+        # ### not handling null attrib_list differently from empty
+        print '    trace::localWriter.beginArray(%s);' % count
+
+        # for each key / key-value pair write the key and the value, if the key requires one
+
+        index = '_i' + array.keyType.tag
+        print '    for (int %(i)s = 0; %(i)s < %(count)s; %(i)s++) {' % {'i': index, 'count': count}
+        self.visitEnum(array.keyType, "%(array)s[%(i)s]" % {'array': instance, 'i': index})
+        print '        switch (%(array)s[%(i)s]) {' % {'array': instance, 'i': index}
+        # write generic value the usual way
+        for key, valueType in array.valueTypes:
+            if valueType is not None:
+                print '        case %s:' % key
+                print '            %s++;' % index
+                print '            trace::localWriter.beginElement();'
+                self.visitElement(index, valueType, '(%(array)s)[%(i)s]' % {'array': instance, 'i': index})
+                print '            trace::localWriter.endElement();'
+                print '            break;'
+        # unknown key, write an int value
+        print '        default:'
+        print '            %s++;' % index
+        print '            trace::localWriter.beginElement();'
+        print '            trace::localWriter.writeSInt(%(array)s[%(i)s]);'  % {'array': instance, 'i': index}
+        print '            trace::localWriter.endElement();'
+        # known key with no value, do nothing
+        for key, valueType in array.valueTypes:
+            if valueType is None:
+                print '        case %s:' % key
+        print '            break;'
+        print '        }'
+        print '    }'
+        print '    trace::localWriter.endArray();'
+
+
     def visitBlob(self, blob, instance):
         print '    trace::localWriter.writeBlob(%s, %s);' % (instance, self.expand(blob.size))