1#!/usr/bin/env python
2
3# Copyright 2014 Google Inc.
4#
5# Use of this source code is governed by a BSD-style license that can be
6# found in the LICENSE file.
7
8"""Script to test out suitableForGpuRasterization (via gpuveto)"""
9
10import argparse
11import glob
12import os
13import re
14import subprocess
15import sys
16
17# Set the PYTHONPATH to include the tools directory.
18sys.path.append(
19    os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir))
20import find_run_binary
21
22def list_files(dir_or_file):
23    """Returns a list of all the files from the provided argument
24
25    @param dir_or_file: either a directory or skp file
26
27    @returns a list containing the files in the directory or a single file
28    """
29    files = []
30    for globbedpath in glob.iglob(dir_or_file): # useful on win32
31        if os.path.isdir(globbedpath):
32            for filename in os.listdir(globbedpath):
33                newpath = os.path.join(globbedpath, filename)
34                if os.path.isfile(newpath):
35                    files.append(newpath)
36        elif os.path.isfile(globbedpath):
37            files.append(globbedpath)
38    return files
39
40
41def execute_program(args):
42    """Executes a process and waits for it to complete.
43
44    @param args: is passed into subprocess.Popen().
45
46    @returns a tuple of the process output (returncode, output)
47    """
48    proc = subprocess.Popen(args, stdout=subprocess.PIPE,
49                            stderr=subprocess.STDOUT)
50    output, _ = proc.communicate()
51    errcode = proc.returncode
52    return (errcode, output)
53
54
55class GpuVeto(object):
56
57    def __init__(self):
58        self.bench_pictures = find_run_binary.find_path_to_program(
59            'bench_pictures')
60        sys.stdout.write('Running: %s\n' % (self.bench_pictures))
61        self.gpuveto = find_run_binary.find_path_to_program('gpuveto')
62        assert os.path.isfile(self.bench_pictures)
63        assert os.path.isfile(self.gpuveto)
64        self.indeterminate = 0
65        self.truePositives = 0
66        self.falsePositives = 0
67        self.trueNegatives = 0
68        self.falseNegatives = 0
69
70    def process_skps(self, dir_or_file):
71        for skp in enumerate(dir_or_file):
72            self.process_skp(skp[1])
73
74        sys.stdout.write('TP %d FP %d TN %d FN %d IND %d\n' % (self.truePositives,
75                                                               self.falsePositives,
76                                                               self.trueNegatives,
77                                                               self.falseNegatives,
78                                                               self.indeterminate))
79
80
81    def process_skp(self, skp_file):
82        assert os.path.isfile(skp_file)
83        #print skp_file
84
85        # run gpuveto on the skp
86        args = [self.gpuveto, '-r', skp_file]
87        returncode, output = execute_program(args)
88        if (returncode != 0):
89            return
90
91        if ('unsuitable' in output):
92            suitable = False
93        else:
94            assert 'suitable' in output
95            suitable = True
96
97        # run raster config
98        args = [self.bench_pictures, '-r', skp_file,
99                                     '--repeat', '20',
100                                     '--timers', 'w',
101                                     '--config', '8888']
102        returncode, output = execute_program(args)
103        if (returncode != 0):
104            return
105
106        matches = re.findall('[\d]+\.[\d]+', output)
107        if len(matches) != 1:
108            return
109
110        rasterTime = float(matches[0])
111
112        # run gpu config
113        args2 = [self.bench_pictures, '-r', skp_file,
114                                      '--repeat', '20',
115                                      '--timers', 'w',
116                                      '--config', 'gpu']
117        returncode, output = execute_program(args2)
118        if (returncode != 0):
119            return
120
121        matches = re.findall('[\d]+\.[\d]+', output)
122        if len(matches) != 1:
123            return
124
125        gpuTime = float(matches[0])
126
127        # happens if page is too big it will not render
128        if 0 == gpuTime:
129            return
130
131        tolerance = 0.05
132        tol_range = tolerance * gpuTime
133
134
135        if rasterTime > gpuTime - tol_range and rasterTime < gpuTime + tol_range:
136            result = "NONE"
137            self.indeterminate += 1
138        elif suitable:
139            if gpuTime < rasterTime:
140                self.truePositives += 1
141                result = "TP"
142            else:
143                self.falsePositives += 1
144                result = "FP"
145        else:
146            if gpuTime < rasterTime:
147                self.falseNegatives += 1
148                result = "FN"
149            else:
150                self.trueNegatives += 1
151                result = "TN"
152
153
154        sys.stdout.write('%s: gpuveto: %d raster %.2f gpu: %.2f  Result: %s\n' % (
155            skp_file, suitable, rasterTime, gpuTime, result))
156
157def main(main_argv):
158    parser = argparse.ArgumentParser()
159    parser.add_argument('--skp_path',
160                        help='Path to the SKP(s). Can either be a directory ' \
161                        'containing SKPs or a single SKP.',
162                        required=True)
163
164    args = parser.parse_args()
165    GpuVeto().process_skps(list_files(args.skp_path))
166
167if __name__ == '__main__':
168    sys.exit(main(sys.argv[1]))
169