]> git.cworth.org Git - apitrace/commitdiff
More complete glDrawArrays and glDrawElements support.
authorJosé Fonseca <jose.r.fonseca@gmail.com>
Tue, 22 Mar 2011 22:15:46 +0000 (22:15 +0000)
committerJosé Fonseca <jose.r.fonseca@gmail.com>
Tue, 22 Mar 2011 22:15:46 +0000 (22:15 +0000)
glretrace.py
glsize.hpp
gltrace.py
trace.py
trace_format.hpp
trace_model.cpp
trace_model.hpp
trace_parser.hpp

index 40ac1cdb91724480e1706a202c2322330e32629f..ea8d71fcb4f71a350830438973f40ef9b4660975 100644 (file)
@@ -61,14 +61,17 @@ class GlRetracer(Retracer):
         "glDrawRangeElements",
         "glDrawRangeElementsBaseVertex",
         "glDrawRangeElementsEXT",
-        "glMultiDrawElements",
-        "glMultiDrawElementsBaseVertex",
-        "glMultiDrawElementsEXT",
-        "glMultiModeDrawElementsIBM",
+        #"glMultiDrawElements",
+        #"glMultiDrawElementsBaseVertex",
+        #"glMultiDrawElementsEXT",
+        #"glMultiModeDrawElementsIBM",
     ])
 
     def call_function(self, function):
-        if function.name in self.draw_elements_function_names:
+        print '    if (Trace::Parser::version < 1) {'
+
+        if function.name in self.draw_array_function_names or \
+           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) {'
@@ -82,6 +85,8 @@ class GlRetracer(Retracer):
             self.fail_function(function)
             print '    }'
 
+        print '    }'
+
         if function.name == "glViewport":
             print '    if (x + width > __window_width) {'
             print '        __window_width = x + width;'
@@ -129,15 +134,11 @@ class GlRetracer(Retracer):
 
     def extract_arg(self, function, arg, arg_type, lvalue, rvalue):
         if function.name in self.pointer_function_names and arg.name == 'pointer':
-            print '    %s = dynamic_cast<void *>(&%s);' % (lvalue, rvalue)
+            print '    %s = %s.blob();' % (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 {'
-            print '        %s = (%s)(uintptr_t)(%s);' % (lvalue, arg_type, rvalue)
-            print '    }'
+            print '    %s = %s.blob();' % (lvalue, rvalue)
             return
 
         if function.name.startswith('glUniform') and function.args[0].name == arg.name == 'location':
index edcd78a2a7a6dd7606b7f139d59235e5afcb9046..1f20aba7b5dcf925a8b5a3a5baef127bd5407136 100644 (file)
@@ -86,6 +86,61 @@ __glArrayPointer_size(GLint size, GLenum type, GLsizei stride, GLsizei maxIndex)
     return stride*maxIndex + elementSize;
 }
 
+#define __glVertexPointer_size(size, type, stride, maxIndex) __glArrayPointer_size(size, type, stride, maxIndex)
+#define __glNormalPointer_size(type, stride, maxIndex) __glArrayPointer_size(3, type, stride, maxIndex)
+#define __glColorPointer_size(size, type, stride, maxIndex) __glArrayPointer_size(size, type, stride, maxIndex)
+#define __glIndexPointer_size(type, stride, maxIndex) __glArrayPointer_size(1, type, stride, maxIndex)
+#define __glTexCoordPointer_size(size, type, stride, maxIndex) __glArrayPointer_size(size, type, stride, maxIndex)
+#define __glEdgeFlagPointer_size(stride, maxIndex) __glArrayPointer_size(1, GL_BOOL, stride, maxIndex)
+#define __glFogCoordPointer_size(type, stride, maxIndex) __glArrayPointer_size(1, type, stride, maxIndex)
+#define __glSecondaryColorPointer_size(size, type, stride, maxIndex) __glArrayPointer_size(size, type, stride, maxIndex)
+
+static inline size_t
+__glDrawArrays_maxindex(GLint first, GLsizei count)
+{
+    return first + count - 1;
+}
+
+static inline size_t
+__glDrawElements_maxindex(GLsizei count, GLenum type, const GLvoid *_indices)
+{
+    size_t maxindex = 0;
+    unsigned i;
+
+    if (type == GL_UNSIGNED_BYTE) {
+        const GLubyte *indices = (const GLubyte *)_indices;
+        for (i = 0; i < count; ++i) {
+            if (indices[i] > maxindex) {
+                maxindex = indices[i];
+            }
+        }
+    } else if (type == GL_UNSIGNED_SHORT) {
+        const GLushort *indices = (const GLushort *)_indices;
+        for (i = 0; i < count; ++i) {
+            if (indices[i] > maxindex) {
+                maxindex = indices[i];
+            }
+        }
+    } else if (type == GL_UNSIGNED_INT) {
+        const GLuint *indices = (const GLuint *)_indices;
+        for (i = 0; i < count; ++i) {
+            if (indices[i] > maxindex) {
+                maxindex = indices[i];
+            }
+        }
+    } else {
+        OS::DebugMessage("warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, type);
+    }
+
+    return maxindex;
+}
+
+static inline size_t
+__glDrawRangeElements_maxindex(GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid * indices)
+{
+    return __glDrawElements_maxindex(count, type, indices);
+}
+
 static inline size_t
 __glCallLists_size(GLsizei n, GLenum type)
 {
index 3e3a2be817b54e3ff99b84c537702c9a3889308a..0aa60cd6e81fb84643053d4d7436e3be265dddf8 100644 (file)
 """GL tracing generator."""
 
 
+import stdapi
+import glapi
 from glxapi import glxapi
 from trace import Tracer, dump_instance
 
 
+class TypeGetter(stdapi.Visitor):
+    '''Determine which glGet*v function that matches the specified type.'''
+
+    def visit_const(self, const):
+        return self.visit(const.type)
+
+    def visit_alias(self, alias):
+        if alias.expr == 'GLboolean':
+            return 'glGetBooleanv', alias.expr
+        elif alias.expr == 'GLdouble':
+            return 'glGetDoublev', alias.expr
+        elif alias.expr == 'GLfloat':
+            return 'glGetFloatv', alias.expr
+        elif alias.expr in ('GLint', 'GLsizei'):
+            return 'glGetIntegerv', 'GLint'
+        else:
+            print alias.expr
+            assert False
+    
+    def visit_enum(self, enum):
+        return 'glGetIntegerv', 'GLint'
+
+    def visit_bitmask(self, bitmask):
+        return 'glGetIntegerv', 'GLint'
+
+    def visit_opaque(self, pointer):
+        return 'glGetPointerv', 'GLvoid *'
+
+
 class GlTracer(Tracer):
 
     def header(self, api):
@@ -41,181 +72,129 @@ class GlTracer(Tracer):
         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": "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",
-        #"glVertexAttribPointerNV": "VertexAttribPointer",
-        #"glVertexAttribLPointer": "VertexAttribLPointer",
-        
-        #"glMatrixIndexPointerARB": "MatrixIndexPointer",
-    }
-
-    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',
+    arrays = [
+        ("Vertex", "VERTEX"),
+        ("Normal", "NORMAL"),
+        ("Color", "COLOR"),
+        ("Index", "INDEX"),
+        ("TexCoord", "TEXTURE_COORD"),
+        ("EdgeFlag", "EDGE_FLAG"),
+        ("FogCoord", "FOG_COORD"),
+        ("SecondaryColor", "SECONDARY_COLOR"),
     ]
 
     def state_tracker_decl(self, api):
         # A simple state tracker to track the pointer values
 
-        # define the NEW_XXXX dirty flags
-        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 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;' % array_name.lower()
-        print '    unsigned dirty;'
-        print '} __state;'
-        print
-        print 'static void __state_update(GLsizei maxIndex);'
+        print 'static void __trace_arrays(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 '    }'
+    array_pointer_function_names = set((
+        "glVertexPointer",
+        "glNormalPointer",
+        "glColorPointer",
+        "glIndexPointer",
+        "glTexCoordPointer",
+        "glEdgeFlagPointer",
+        "glFogCoordPointer",
+        "glSecondaryColorPointer",
+
+        "glInterleavedArrays",
+
+        #"glVertexPointerEXT",
+        #"glNormalPointerEXT",
+        #"glColorPointerEXT",
+        #"glIndexPointerEXT",
+        #"glTexCoordPointerEXT",
+        #"glEdgeFlagPointerEXT",
+        #"glFogCoordPointerEXT",
+        #"glSecondaryColorPointerEXT",
+
+        #"glVertexAttribPointer",
+        #"glVertexAttribPointerARB",
+        #"glVertexAttribPointerNV",
+        #"glVertexAttribLPointer",
+        
+        #"glMatrixIndexPointerARB",
+    ))
 
-        # 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
+    draw_function_names = set((
+        'glDrawArrays',
+        'glDrawElements',
+        'glDrawRangeElements',
+    ))
 
-            # Defer tracing
+    def trace_function_impl_body(self, function):
+        # Defer tracing of array pointers
+        if function.name in self.array_pointer_function_names:
+            print '    GLint __array_buffer = 0;'
+            print '    __glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);'
+            print '    if (!__array_buffer) {'
             self.dispatch_function(function)
-            return
+            print '        return;'
+            print '    }'
 
-        if function.name == 'glDrawArrays':
-            print '   __state_update(first + count - 1);'
+        if function.name in self.draw_function_names:
+            arg_names = ', '.join([arg.name for arg in function.args[1:]])
+            print '    __trace_arrays(__%s_maxindex(%s));' % (function.name, arg_names)
         
         Tracer.trace_function_impl_body(self, function)
 
+    def dump_arg_instance(self, function, arg):
+        if function.name in self.draw_function_names and arg.name == 'indices':
+            print '    Trace::LiteralBlob((const void *)%s, count*__gl_type_size(type));' % (arg.name)
+        else:
+            dump_instance(arg.type, arg.name)
+
     def state_tracker_impl(self, api):
         # A simple state tracker to track the pointer values
 
         # update the state
-        print 'static void __state_update(GLsizei maxIndex)'
+        print 'static void __trace_arrays(GLsizei maxindex)'
         print '{'
-        print '    GLint __array_buffer = 0;'
-        print '    __glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);'
-        for array_name, function_name in self.array_names.iteritems():
+        for camelcase_name, uppercase_name in self.arrays:
+            function_name = 'gl%sPointer' % camelcase_name
+            enable_name = 'GL_%s_ARRAY' % uppercase_name
+            binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
             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,)
+
+            print '    // %s' % function.name
+            print '    {'
+            print '        GLboolean __enabled = GL_FALSE;'
+            print '        __glGetBooleanv(%s, &__enabled);' % enable_name
+            print '        if (__enabled) {'
+            print '            GLint __binding = 0;'
+            print '            __glGetIntegerv(%s, &__binding);' % binding_name
+            print '            if (!__binding) {'
+
+            # Get the arguments via glGet*
+            for arg in function.args:
+                arg_get_enum = 'GL_%s_ARRAY_%s' % (uppercase_name, arg.name.upper())
+                arg_get_function, arg_type = TypeGetter().visit(arg.type)
+                print '                %s %s = 0;' % (arg_type, arg.name)
+                print '                __%s(%s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
+            
+            arg_names = ', '.join([arg.name for arg in function.args[:-1]])
+            print '                size_t __size = __%s_size(%s, maxindex);' % (function.name, arg_names)
+
+            # Emit a fake function
+            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,)
+                print '                Trace::BeginArg(%u);' % (arg.index,)
                 if arg.name != 'pointer':
-                    dump_instance(arg.type, value)
+                    dump_instance(arg.type, arg.name)
                 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();'
+                    print '                Trace::LiteralBlob((const void *)%s, __size);' % (arg.name)
+                print '                Trace::EndArg();'
+            
+            print '                Trace::EndEnter();'
+            print '                Trace::BeginLeave(__call);'
+            print '                Trace::EndLeave();'
+            print '            }'
+            print '        }'
             print '    }'
+            print
         print '}'
         print
 
index 95a9807ff160f6d01eeb5a1094da83c64a7265e2..5711fa0ae508cabaea359e6d16a2ca53f695c218 100644 (file)
--- a/trace.py
+++ b/trace.py
@@ -350,9 +350,12 @@ class Tracer:
 
     def dump_arg(self, function, arg):
         print '    Trace::BeginArg(%u);' % (arg.index,)
-        dump_instance(arg.type, arg.name)
+        self.dump_arg_instance(function, arg)
         print '    Trace::EndArg();'
 
+    def dump_arg_instance(self, function, arg):
+        dump_instance(arg.type, arg.name)
+
     def wrap_arg(self, function, arg):
         wrap_instance(arg.type, arg.name)
 
index ba57a51055a2ae0cad959c5bb06bbf7220ce5d2e..3a3787b5b292eed2fe389ef4217e562077be01a3 100644 (file)
@@ -32,7 +32,7 @@
 
 namespace Trace {
 
-#define TRACE_VERSION 0
+#define TRACE_VERSION 1
 
 enum Event {
     EVENT_ENTER = 0,
index 07b0c495690aee48896e10ee1cfd4e4b075efa84..70039c6aa2e6d245fd494800b1230a7a4b3f0ac3 100644 (file)
@@ -55,6 +55,11 @@ Array::~Array() {
     }
 }
 
+Blob::~Blob() {
+    // FIXME
+    //delete [] buf;
+}
+
 
 void Null::visit(Visitor &visitor) { visitor.visit(this); }
 void Bool::visit(Visitor &visitor) { visitor.visit(this); } 
index 0371681c23bf380b9e8e7c0403b033e9c2d3eb30..f978435f74f4907f9b97c4376660d8a27bd7bbb4 100644 (file)
@@ -231,10 +231,7 @@ public:
         buf = new char[_size];
     }
 
-    ~Blob() {
-        // FIXME
-        //delete [] buf;
-    }
+    ~Blob();
 
     void visit(Visitor &visitor);
 
index 538ff6c49f57bf8447aacb6806d84895a2b36957..dfaf42e4e29d31b9881b6e0283ff5b8e86ef0dc1 100644 (file)
@@ -69,6 +69,8 @@ protected:
     unsigned next_call_no;
 
 public:
+    static unsigned long long version;
+
     Parser() {
         file = NULL;
         next_call_no = 0;
@@ -79,15 +81,13 @@ public:
     }
 
     bool open(const char *filename) {
-        unsigned long long version;
-
         file = gzopen(filename, "rb");
         if (!file) {
             return false;
         }
 
         version = read_uint();
-        if (version != TRACE_VERSION) {
+        if (version > TRACE_VERSION) {
             std::cerr << "error: unsupported format version" << version << "\n";
             return false;
         }
@@ -400,6 +400,9 @@ public:
 };
 
 
+unsigned long long Trace::Parser::version = 0;
+
+
 } /* namespace Trace */
 
 #endif /* _TRACE_PARSER_HPP_ */