Basic DrawArrays support.
authorJosé Fonseca <jose.r.fonseca@gmail.com>
Sun, 20 Feb 2011 23:32:22 +0000 (23:32 +0000)
committerJosé Fonseca <jose.r.fonseca@gmail.com>
Tue, 22 Feb 2011 07:15:58 +0000 (07:15 +0000)
glretrace.py
glsize.hpp
gltrace.py
glxtrace.py
trace.py
trace_model.cpp
trace_model.hpp
wgltrace.py

index 451c938..40ac1cd 100644 (file)
@@ -68,8 +68,7 @@ class GlRetracer(Retracer):
     ])
 
     def call_function(self, function):
-        if (function.name in self.draw_array_function_names or 
-            function.name in self.draw_elements_function_names):
+        if function.name in self.draw_elements_function_names:
             print '    GLint __array_buffer = 0;'
             print '    glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);'
             print '    if (!__array_buffer) {'
@@ -106,31 +105,34 @@ class GlRetracer(Retracer):
 
     pointer_function_names = set([
         "glColorPointer",
-        "glColorPointerEXT",
+        #"glColorPointerEXT",
         "glEdgeFlagPointer",
-        "glEdgeFlagPointerEXT",
+        #"glEdgeFlagPointerEXT",
         "glFogCoordPointer",
-        "glFogCoordPointerEXT",
+        #"glFogCoordPointerEXT",
         "glIndexPointer",
-        "glIndexPointerEXT",
-        "glMatrixIndexPointerARB",
+        #"glIndexPointerEXT",
+        #"glMatrixIndexPointerARB",
         "glNormalPointer",
-        "glNormalPointerEXT",
+        #"glNormalPointerEXT",
         "glSecondaryColorPointer",
-        "glSecondaryColorPointerEXT",
+        #"glSecondaryColorPointerEXT",
         "glTexCoordPointer",
-        "glTexCoordPointerEXT",
-        "glVertexAttribLPointer",
-        "glVertexAttribPointer",
-        "glVertexAttribPointerARB",
-        "glVertexAttribPointerNV",
+        #"glTexCoordPointerEXT",
+        #"glVertexAttribLPointer",
+        #"glVertexAttribPointer",
+        #"glVertexAttribPointerARB",
+        #"glVertexAttribPointerNV",
         "glVertexPointer",
-        "glVertexPointerEXT",
+        #"glVertexPointerEXT",
     ])
 
     def extract_arg(self, function, arg, arg_type, lvalue, rvalue):
-        if (function.name in self.pointer_function_names and arg.name == 'pointer' or
-            function.name in self.draw_elements_function_names and arg.name == 'indices'):
+        if function.name in self.pointer_function_names and arg.name == 'pointer':
+            print '    %s = dynamic_cast<void *>(&%s);' % (lvalue, rvalue)
+            return
+
+        if function.name in self.draw_elements_function_names and arg.name == 'indices':
             print '    if (dynamic_cast<Trace::Null *>(&%s)) {' % rvalue
             print '        %s = 0;' % (lvalue)
             print '    } else {'
index ead293b..edcd78a 100644 (file)
 
 
 static inline size_t
-__glCallLists_size(GLsizei n, GLenum type)
+__gl_type_size(GLenum type)
 {
-    size_t bytes;
-    switch(type) {
+    switch (type) {
+    case GL_BOOL:
     case GL_BYTE:
     case GL_UNSIGNED_BYTE:
-        bytes = 1;
+        return 1;
         break;
     case GL_SHORT:
     case GL_UNSIGNED_SHORT:
     case GL_2_BYTES:
     case GL_HALF_FLOAT:
-        bytes = 2;
+        return 2;
         break;
     case GL_3_BYTES:
-        bytes = 3;
+        return 3;
         break;
     case GL_INT:
     case GL_UNSIGNED_INT:
     case GL_FLOAT:
     case GL_4_BYTES:
-        bytes = 4;
+        return 4;
+        break;
+    case GL_DOUBLE:
+        return 8;
         break;
     default:
         OS::DebugMessage("warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, type);
-        bytes = 0;
+        return 0;
+    }
+}
+
+static inline size_t
+__glArrayPointer_size(GLint size, GLenum type, GLsizei stride, GLsizei maxIndex)
+{
+    GLsizei elementSize = size*__gl_type_size(type);
+    if (!stride) {
+        stride = elementSize;
     }
+    return stride*maxIndex + elementSize;
+}
 
-    return n*bytes;
+static inline size_t
+__glCallLists_size(GLsizei n, GLenum type)
+{
+    return n*__gl_type_size(type);
 }
 
 static inline size_t
index 9a7c2f2..3e3a2be 100644 (file)
@@ -33,24 +33,43 @@ from trace import Tracer, dump_instance
 
 class GlTracer(Tracer):
 
+    def header(self, api):
+        Tracer.header(self, api)
+        self.state_tracker_decl(api)
+
+    def footer(self, api):
+        Tracer.footer(self, api)
+        self.state_tracker_impl(api)
+
+    array_names = {
+        "VERTEX": "glVertexPointer",
+        "NORMAL": "glNormalPointer",
+        "COLOR": "glColorPointer",
+        "INDEX": "glIndexPointer",
+        "TEX_COORD": "glTexCoordPointer",
+        "EDGE_FLAG": "glEdgeFlagPointer",
+        "FOG_COORD": "glFogCoordPointer",
+        "SECONDARY_COLOR": "glSecondaryColorPointer",
+    }
+
     pointer_function_names = {
-        "glVertexPointer": "VertexPointer",
-        "glVertexPointerEXT": "VertexPointer",
-        "glNormalPointer": "NormalPointer",
-        "glNormalPointerEXT": "NormalPointer",
-        "glColorPointer": "ColorPointer",
-        "glColorPointerEXT": "ColorPointer",
-        "glIndexPointer": "IndexPointer",
-        "glIndexPointerEXT": "IndexPointer",
-        "glTexCoordPointer": "TexCoordPointer",
-        "glTexCoordPointerEXT": "TexCoordPointer",
-        "glEdgeFlagPointer": "EdgeFlagPointer",
-        "glEdgeFlagPointerEXT": "EdgeFlagPointer",
-        "glFogCoordPointer": "FogCoordPointer",
-        "glFogCoordPointerEXT": "FogCoordPointer",
-        "glSecondaryColorPointer": "SecondaryColorPointer",
-        "glSecondaryColorPointerEXT": "SecondaryColorPointer",
-        "glInterleavedArrays": "InterleavedArrays",
+        "glVertexPointer": "VERTEX",
+        "glNormalPointer": "NORMAL",
+        "glColorPointer": "COLOR",
+        "glIndexPointer": "INDEX",
+        "glTexCoordPointer": "TEX_COORD",
+        "glEdgeFlagPointer": "EDGE_FLAG",
+        "glFogCoordPointer": "FOG_COORD",
+        "glSecondaryColorPointer": "SECONDARY_COLOR",
+        #"glInterleavedArrays": ("InterleavedArrays", None)
+        #"glVertexPointerEXT": "VERTEX",
+        #"glNormalPointerEXT": "NORMAL",
+        #"glColorPointerEXT": "COLOR",
+        #"glIndexPointerEXT": "INDEX",
+        #"glTexCoordPointerEXT": "TEX_COORD",
+        #"glEdgeFlagPointerEXT": "EDGE_FLAG",
+        #"glFogCoordPointerEXT": "FOG_COORD",
+        #"glSecondaryColorPointerEXT": "SECONDARY_COLOR",
 
         #"glVertexAttribPointer": "VertexAttribPointer",
         #"glVertexAttribPointerARB": "VertexAttribPointer",
@@ -60,60 +79,139 @@ class GlTracer(Tracer):
         #"glMatrixIndexPointerARB": "MatrixIndexPointer",
     }
 
-    def header(self, api):
-        Tracer.header(self, api)
-        self.state_tracker_decl(api)
-
-    def footer(self, api):
-        Tracer.footer(self, api)
-        self.state_tracker_impl(api)
+    bind_buffer_enums = [
+        'ARRAY_BUFFER',
+        'ELEMENT_ARRAY_BUFFER',
+        'PIXEL_PACK_BUFFER',
+        'PIXEL_UNPACK_BUFFER',
+    ]
+
+    client_state_enums = [
+         'COLOR_ARRAY',
+         'EDGE_FLAG_ARRAY', 
+         'FOG_COORD_ARRAY', 
+         'INDEX_ARRAY', 
+         'NORMAL_ARRAY', 
+         'SECONDARY_COLOR_ARRAY', 
+         'TEXTURE_COORD_ARRAY', 
+         'VERTEX_ARRAY',
+    ]
 
     def state_tracker_decl(self, api):
         # A simple state tracker to track the pointer values
 
-        atoms = list(set(self.pointer_function_names.itervalues()))
-        atoms.sort()
-
         # define the NEW_XXXX dirty flags
-        for i in range(len(atoms)):
-            atom = atoms[i]
-            dirtyflag = "NEW_%s" % atom.upper()
-            print '#define %s 0x%x' % (dirtyflag, 1 << i)
+        value = 1
+        for array_name in self.array_names.iterkeys():
+            dirtyflag = "NEW_%s" % array_name.upper()
+            print '#define %s 0x%x' % (dirtyflag, value)
+            value <<= 1
         print
 
         # declare the state structure
         print 'struct {'
-        for atom in atoms:
-            function = api.get_function_by_name('gl%s' % atom)
+        for enum in self.bind_buffer_enums:
+            print '    GLuint %s;' % (enum.lower(),)
+        for enum in self.client_state_enums:
+            print '    GLboolean %s;' % (enum.lower(),)
+        for array_name, function_name in self.array_names.iteritems():
+            function = api.get_function_by_name(function_name)
             print '    struct {'
             for arg in function.args:
                 print '        %s %s;' % (arg.type, arg.name)
-            print '    } %s;' % atom
+            print '    } %s;' % array_name.lower()
         print '    unsigned dirty;'
         print '} __state;'
         print
+        print 'static void __state_update(GLsizei maxIndex);'
+        print
+    
+    def trace_function_impl_body(self, function):
+        # Track bound VBOs
+        if function.name in ('glBindBuffer', 'glBindBufferARB'):
+            print '    switch(%s) {' % function.args[0].name
+            for enum in self.bind_buffer_enums:
+                print '    case GL_%s:' % enum
+                print '        __state.%s = %s;' % (enum.lower(), function.args[1].name)
+                print '        break;'
+            print '    }'
+
+        # Track enabled arrays
+        if function.name == 'glEnableClientState':
+            print '    switch(%s) {' % function.args[0].name
+            for enum in self.client_state_enums:
+                print '    case GL_%s:' % enum
+                print '        __state.%s = GL_TRUE;' % (enum.lower(),)
+                print '        break;'
+            print '    }'
+        if function.name == 'glDisableClientState':
+            print '    switch(%s) {' % function.args[0].name
+            for enum in self.client_state_enums:
+                print '    case GL_%s:' % enum
+                print '        __state.%s = GL_FALSE;' % (enum.lower(),)
+                print '        break;'
+            print '    }'
+
+        # Track array pointers
+        if function.name in self.pointer_function_names:
+            array_name = self.pointer_function_names[function.name]
+            dirtyflag = "NEW_%s" % array_name.upper()
+            for arg in function.args:
+                assert not arg.output
+                print '    __state.%s.%s = %s;' % (array_name.lower(), arg.name, arg.name)
+            print '    __state.dirty |= %s; ' % dirtyflag
+
+            # Defer tracing
+            self.dispatch_function(function)
+            return
+
+        if function.name == 'glDrawArrays':
+            print '   __state_update(first + count - 1);'
+        
+        Tracer.trace_function_impl_body(self, function)
 
     def state_tracker_impl(self, api):
         # A simple state tracker to track the pointer values
 
-        atoms = list(set(self.pointer_function_names.itervalues()))
-        atoms.sort()
-
         # update the state
-        print 'void __state_update(GLsizei )'
+        print 'static void __state_update(GLsizei maxIndex)'
         print '{'
         print '    GLint __array_buffer = 0;'
-        print '    glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);'
-        for atom in atoms:
-            function = api.get_function_by_name('gl%s' % atom)
-            dirtyflag = "NEW_%s" % atom.upper()
-            print '    if (__state.dirty & %s) {' % dirtyflag
+        print '    __glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);'
+        for array_name, function_name in self.array_names.iteritems():
+            function = api.get_function_by_name(function_name)
+            dirtyflag = "NEW_%s" % array_name.upper()
+            if array_name == 'TEX_COORD':
+                enableflag = 'TEXTURE_COORD_ARRAY'.lower()
+            else:
+                enableflag = '%s_array' % array_name.lower()
+            print '    if (__state.%s && (__state.dirty & %s)) {' % (enableflag, dirtyflag)
             print '        unsigned __call = Trace::BeginEnter(__%s_sig);' % (function.name,)
             for arg in function.args:
                 assert not arg.output
+                value = '__state.%s.%s' % (array_name.lower(), arg.name)
                 print '        Trace::BeginArg(%u);' % (arg.index,)
-                dump_instance(arg.type, '__state.%s.%s' % (atom, arg.name))
-                print '        Trace::EndArg();'
+                if arg.name != 'pointer':
+                    dump_instance(arg.type, value)
+                else:
+                    print '        if (__state.array_buffer) {'
+                    print '            Trace::LiteralOpaque((const void *)%s);' % value
+                    print '            __state.dirty &= ~%s;' % dirtyflag
+                    print '        } else {'
+                    if array_name in ('INDEX', 'EDGE_FLAG', 'FOG_COORD'):
+                        size = '1'
+                    elif array_name == 'NORMAL':
+                        size = '3'
+                    else:
+                        size = '__state.%s.size' % array_name.lower()
+                    if array_name == 'EDGE_FLAG':
+                        type = 'GL_BOOL'
+                    else:
+                        type = '__state.%s.type' % array_name.lower()
+                    stride = '__state.%s.stride' % array_name.lower()
+                    print '            Trace::LiteralBlob((const void *)%s, __glArrayPointer_size(%s, %s, %s, maxIndex));' % (value, size, type, stride)
+                    print '        }'
+                    print '        Trace::EndArg();'
             print '        Trace::EndEnter();'
             print '        Trace::BeginLeave(__call);'
             print '        Trace::EndLeave();'
index a7d0787..e1a5aa5 100644 (file)
@@ -40,16 +40,8 @@ class GlxTracer(GlTracer):
         return '__%s' % (function.name,)
 
     def wrap_ret(self, function, instance):
-        if function.name.startswith("glXGetProcAddress"):
-            print '    if (%s) {' % instance
-            for f in glxapi.functions:
-                ptype = function_pointer_type(f)
-                pvalue = function_pointer_value(f)
-                print '        if(!strcmp("%s", (const char *)procName)) {' % f.name
-                print '            %s = (%s)%s;' % (pvalue, ptype, instance)
-                print '            %s = (%s)&%s;' % (instance, function.type, f.name);
-                print '        }'
-            print '    }'
+        if function.name in ("glXGetProcAddress", "glXGetProcAddressARB"):
+            print '    %s = __unwrap_proc_addr(procName, %s);' % (instance, instance)
 
 
 if __name__ == '__main__':
@@ -65,10 +57,27 @@ if __name__ == '__main__':
     print
     print 'extern "C" {'
     print
+    print 'static __GLXextFuncPtr __unwrap_proc_addr(const GLubyte * procName, __GLXextFuncPtr procPtr);'
+    print
+
     api = API()
     api.add_api(glxapi)
     api.add_api(glapi)
     tracer = GlxTracer()
     tracer.trace_api(api)
+
+    print 'static __GLXextFuncPtr __unwrap_proc_addr(const GLubyte * procName, __GLXextFuncPtr procPtr) {'
+    print '    if (!procPtr) {'
+    print '        return procPtr;'
+    print '    }'
+    for f in api.functions:
+        ptype = function_pointer_type(f)
+        pvalue = function_pointer_value(f)
+        print '    if(!strcmp("%s", (const char *)procName)) {' % f.name
+        print '        %s = (%s)procPtr;' % (pvalue, ptype)
+        print '        return (__GLXextFuncPtr)&%s;' % (f.name,)
+        print '    }'
+    print '    return procPtr;'
+    print '}'
     print
     print '} /* extern "C" */'
index 3502258..95a9807 100644 (file)
--- a/trace.py
+++ b/trace.py
@@ -300,42 +300,37 @@ class Tracer:
         pass
 
     def trace_function_decl(self, function):
+        # Per-function declarations
+
         if function.args:
-            print '    static const char * __%s_args[%u] = {%s};' % (function.name, len(function.args), ', '.join(['"%s"' % arg.name for arg in function.args]))
+            print 'static const char * __%s_args[%u] = {%s};' % (function.name, len(function.args), ', '.join(['"%s"' % arg.name for arg in function.args]))
         else:
-            print '    static const char ** __%s_args = NULL;' % (function.name,)
-        print '    static const Trace::FunctionSig __%s_sig = {%u, "%s", %u, __%s_args};' % (function.name, int(function.id), function.name, len(function.args), function.name)
+            print 'static const char ** __%s_args = NULL;' % (function.name,)
+        print 'static const Trace::FunctionSig __%s_sig = {%u, "%s", %u, __%s_args};' % (function.name, int(function.id), function.name, len(function.args), function.name)
         print
 
-    def trace_function_fail(self, function):
-        if function.fail is not None:
-            if function.type is stdapi.Void:
-                assert function.fail == ''
-                print '            return;' 
-            else:
-                assert function.fail != ''
-                print '            return %s;' % function.fail
-        else:
-            print '            Trace::Abort();'
-
     def get_dispatch_function(self, function):
         return '__' + function.name
 
     def trace_function_impl(self, function):
         print 'extern "C" ' + function.prototype() + ' {'
-        if function.type is stdapi.Void:
-            result = ''
-        else:
+        if function.type is not stdapi.Void:
             print '    %s __result;' % function.type
-            result = '__result = '
+        self.trace_function_impl_body(function)
+        if function.type is not stdapi.Void:
+            self.wrap_ret(function, "__result")
+            print '    return __result;'
+        print '}'
+        print
+
+    def trace_function_impl_body(self, function):
         print '    unsigned __call = Trace::BeginEnter(__%s_sig);' % (function.name,)
         for arg in function.args:
             if not arg.output:
                 self.unwrap_arg(function, arg)
                 self.dump_arg(function, arg)
         print '    Trace::EndEnter();'
-        dispatch = self.get_dispatch_function(function)
-        print '    %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
+        self.dispatch_function(function)
         print '    Trace::BeginLeave(__call);'
         for arg in function.args:
             if arg.output:
@@ -344,11 +339,14 @@ class Tracer:
         if function.type is not stdapi.Void:
             self.dump_ret(function, "__result")
         print '    Trace::EndLeave();'
-        if function.type is not stdapi.Void:
-            self.wrap_ret(function, "__result")
-            print '    return __result;'
-        print '}'
-        print
+
+    def dispatch_function(self, function):
+        if function.type is stdapi.Void:
+            result = ''
+        else:
+            result = '__result = '
+        dispatch = self.get_dispatch_function(function)
+        print '    %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
 
     def dump_arg(self, function, arg):
         print '    Trace::BeginArg(%u);' % (arg.index,)
index 854e79f..07b0c49 100644 (file)
@@ -278,6 +278,11 @@ void * Value::blob(void) const {
     const Null *null = dynamic_cast<const Null *>(unwrap(this));
     if (null)
         return NULL;
+    const Pointer *pointer = dynamic_cast<const Pointer *>(unwrap(this));
+    if (pointer) {
+        assert(pointer->value  < 0x100000ULL);
+        return (void *)pointer->value;
+    }
     assert(0);
     return NULL;
 }
index 57ebcaa..0371681 100644 (file)
@@ -232,7 +232,8 @@ public:
     }
 
     ~Blob() {
-        delete [] buf;
+        // FIXME
+        //delete [] buf;
     }
 
     void visit(Visitor &visitor);
index cef2e1a..e95a31b 100644 (file)
@@ -46,7 +46,7 @@ class WglTracer(GlTracer):
         if function.name == "wglGetProcAddress":
             print '    if (%s) {' % instance
         
-            func_dict = dict([(f.name, f) for f in wglapi.functions])
+            func_dict = dict([(f.name, f) for f in glapi.functions + wglapi.functions])
 
             def handle_case(function_name):
                 f = func_dict[function_name]