]> git.cworth.org Git - apitrace/blobdiff - scripts/retracediff.py
Use skiplist-based FastCallSet within trace::CallSet
[apitrace] / scripts / retracediff.py
index bed216c314921e386ec03bc849c7a1a3d2c59359..413ecac8fffd1ddcf356cfcdaf62907db5d6eac8 100755 (executable)
@@ -37,7 +37,7 @@ import sys
 from PIL import Image
 
 from snapdiff import Comparer
-from highlight import Highlighter
+from highlight import AutoHighlighter
 import jsondiff
 
 
@@ -58,6 +58,10 @@ class Setup:
         cmd = [
             options.retrace,
         ] + args + self.args
+        if self.env:
+            for name, value in self.env.iteritems():
+                sys.stderr.write('%s=%s ' % (name, value))
+        sys.stderr.write(' '.join(cmd) + '\n')
         try:
             return subprocess.Popen(cmd, env=self.env, stdout=subprocess.PIPE, stderr=NULL)
         except OSError, ex:
@@ -80,16 +84,16 @@ class Setup:
         p.wait()
         return state.get('parameters', {})
 
-    def diff_state(self, ref_call_no, src_call_no):
+    def diff_state(self, ref_call_no, src_call_no, stream):
         '''Compare the state between two calls.'''
 
         ref_state = self.dump_state(ref_call_no)
         src_state = self.dump_state(src_call_no)
 
-        sys.stdout.flush()
-        differ = jsondiff.Differ(sys.stdout)
+        stream.flush()
+        differ = jsondiff.Differ(stream)
         differ.visit(ref_state, src_state)
-        sys.stdout.write('\n')
+        stream.write('\n')
 
 
 def read_pnm(stream):
@@ -98,7 +102,15 @@ def read_pnm(stream):
     magic = stream.readline()
     if not magic:
         return None, None
-    assert magic.rstrip() == 'P6'
+    magic = magic.rstrip()
+    if magic == 'P5':
+        channels = 1
+        mode = 'L'
+    elif magic == 'P6':
+        channels = 3
+        mode = 'RGB'
+    else:
+        raise Exception('Unsupported magic `%s`' % magic)
     comment = ''
     line = stream.readline()
     while line.startswith('#'):
@@ -107,14 +119,17 @@ def read_pnm(stream):
     width, height = map(int, line.strip().split())
     maximum = int(stream.readline().strip())
     assert maximum == 255
-    data = stream.read(height * width * 3)
-    image = Image.frombuffer('RGB', (width, height), data, 'raw', 'RGB', 0, 1)
+    data = stream.read(height * width * channels)
+    image = Image.frombuffer(mode, (width, height), data, 'raw', mode, 0, 1)
     return image, comment
 
 
 def parse_env(optparser, entries):
     '''Translate a list of NAME=VALUE entries into an environment dictionary.'''
 
+    if not entries:
+        return None
+
     env = os.environ.copy()
     for entry in entries:
         try:
@@ -139,6 +154,22 @@ def main():
         '-r', '--retrace', metavar='PROGRAM',
         type='string', dest='retrace', default='glretrace',
         help='retrace command [default: %default]')
+    optparser.add_option(
+        '--ref-driver', metavar='DRIVER',
+        type='string', dest='ref_driver', default=None,
+        help='force reference driver')
+    optparser.add_option(
+        '--src-driver', metavar='DRIVER',
+        type='string', dest='src_driver', default=None,
+        help='force source driver')
+    optparser.add_option(
+        '--ref-arg', metavar='OPTION',
+        type='string', action='append', dest='ref_args', default=[],
+        help='pass argument to reference retrace')
+    optparser.add_option(
+        '--src-arg', metavar='OPTION',
+        type='string', action='append', dest='src_args', default=[],
+        help='pass argument to source retrace')
     optparser.add_option(
         '--ref-env', metavar='NAME=VALUE',
         type='string', action='append', dest='ref_env', default=[],
@@ -156,20 +187,34 @@ def main():
         type="float", dest="threshold", default=12.0,
         help="threshold precision  [default: %default]")
     optparser.add_option(
-        '-S', '--snapshot-frequency', metavar='FREQUENCY',
+        '-S', '--snapshot-frequency', metavar='CALLSET',
         type="string", dest="snapshot_frequency", default='draw',
-        help="snapshot frequency: frame, framebuffer, or draw  [default: %default]")
+        help="calls to compare [default: %default]")
+    optparser.add_option(
+        '-o', '--output', metavar='FILE',
+        type="string", dest="output",
+        help="output file [default: stdout]")
 
     (options, args) = optparser.parse_args(sys.argv[1:])
     ref_env = parse_env(optparser, options.ref_env)
     src_env = parse_env(optparser, options.src_env)
     if not args:
         optparser.error("incorrect number of arguments")
+    
+    if options.ref_driver:
+        options.ref_args.insert(0, '--driver=' + options.ref_driver)
+    if options.src_driver:
+        options.src_args.insert(0, '--driver=' + options.src_driver)
+
+    ref_setup = Setup(options.ref_args + args, ref_env)
+    src_setup = Setup(options.src_args + args, src_env)
 
-    ref_setup = Setup(args, ref_env)
-    src_setup = Setup(args, src_env)
+    if options.output:
+        output = open(options.output, 'wt')
+    else:
+        output = sys.stdout
 
-    highligher = Highlighter(sys.stdout)
+    highligher = AutoHighlighter(output)
 
     highligher.write('call\tprecision\n')
 
@@ -217,7 +262,7 @@ def main():
                         src_image.save(prefix + '.src.png')
                         comparer.write_diff(prefix + '.diff.png')
                     if last_bad < last_good:
-                        src_setup.diff_state(last_good, call_no)
+                        src_setup.diff_state(last_good, call_no, output)
                     last_bad = call_no
                 else:
                     last_good = call_no