From ba7bb0d584f82da2de0db2af720c037ca386c945 Mon Sep 17 00:00:00 2001 From: Andreas Hartmetz Date: Sun, 7 Jul 2013 22:51:12 +0200 Subject: [PATCH] Introduce AttribArray, a code generator for pseudo-type attrib_list. 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 | 11 +++++++++- specs/stdapi.py | 19 +++++++++++++++++ wrappers/trace.py | 54 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 1 deletion(-) diff --git a/specs/glxapi.py b/specs/glxapi.py index 42df486..b06082d 100644 --- a/specs/glxapi.py +++ b/specs/glxapi.py @@ -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")]), diff --git a/specs/stdapi.py b/specs/stdapi.py index 990c651..795f0cf 100644 --- a/specs/stdapi.py +++ b/specs/stdapi.py @@ -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 diff --git a/wrappers/trace.py b/wrappers/trace.py index 31087e9..17e4e9c 100644 --- a/wrappers/trace.py +++ b/wrappers/trace.py @@ -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)) -- 2.43.0