bench_pictures_main.cpp revision f4959ab11827bef99e8985031feb457cae1f987a
1/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "BenchTimer.h"
9#include "PictureBenchmark.h"
10#include "SkCanvas.h"
11#include "SkMath.h"
12#include "SkOSFile.h"
13#include "SkPicture.h"
14#include "SkStream.h"
15#include "SkTArray.h"
16#include "picture_utils.h"
17
18const int DEFAULT_REPEATS = 100;
19
20static void usage(const char* argv0) {
21    SkDebugf("SkPicture benchmarking tool\n");
22    SkDebugf("\n"
23"Usage: \n"
24"     %s <inputDir>...\n"
25"     [--repeat] \n"
26"     [--mode pipe | pow2tile minWidth height[%] | record | simple\n"
27"         | tile width[%] height[%] | unflatten]\n"
28"     [--device bitmap"
29#if SK_SUPPORT_GPU
30" | gpu"
31#endif
32"]"
33, argv0);
34    SkDebugf("\n\n");
35    SkDebugf(
36"     inputDir:  A list of directories and files to use as input. Files are\n"
37"                expected to have the .skp extension.\n\n");
38    SkDebugf(
39"     --mode pipe | pow2tile minWidht height[%] | record | simple\n"
40"        | tile width[%] height[%] | unflatten: Run in the corresponding mode.\n"
41"                                               Default is simple.\n");
42    SkDebugf(
43"                     pipe, Benchmark SkGPipe rendering.\n");
44    SkDebugf(
45"                     pow2tile minWidth height[%], Creates tiles with widths\n"
46"                                                  that are all a power of two\n"
47"                                                  such that they minimize the\n"
48"                                                  amount of wasted tile space.\n"
49"                                                  minWidth is the minimum width\n"
50"                                                  of these tiles and must be a\n"
51"                                                  power of two. Simple\n"
52"                                                  rendering using these tiles\n"
53"                                                  is benchmarked.\n");
54    SkDebugf(
55"                     record, Benchmark picture to picture recording.\n");
56    SkDebugf(
57"                     simple, Benchmark a simple rendering.\n");
58    SkDebugf(
59"                     tile width[%] height[%], Benchmark simple rendering using\n"
60"                                              tiles with the given dimensions.\n");
61    SkDebugf(
62"                     unflatten, Benchmark picture unflattening.\n");
63    SkDebugf("\n");
64    SkDebugf(
65"     --device bitmap"
66#if SK_SUPPORT_GPU
67" | gpu"
68#endif
69": Use the corresponding device. Default is bitmap.\n");
70    SkDebugf(
71"                     bitmap, Render to a bitmap.\n");
72#if SK_SUPPORT_GPU
73    SkDebugf(
74"                     gpu, Render to the GPU.\n");
75#endif
76    SkDebugf("\n");
77    SkDebugf(
78"     --repeat:  "
79"Set the number of times to repeat each test."
80" Default is %i.\n", DEFAULT_REPEATS);
81}
82
83static void run_single_benchmark(const SkString& inputPath,
84                                 sk_tools::PictureBenchmark& benchmark) {
85    SkFILEStream inputStream;
86
87    inputStream.setPath(inputPath.c_str());
88    if (!inputStream.isValid()) {
89        SkDebugf("Could not open file %s\n", inputPath.c_str());
90        return;
91    }
92
93    SkPicture picture(&inputStream);
94
95    SkString filename;
96    sk_tools::get_basename(&filename, inputPath);
97
98    SkString result;
99    result.printf("running bench [%i %i] %s ", picture.width(), picture.height(),
100                  filename.c_str());
101    sk_tools::print_msg(result.c_str());
102
103    benchmark.run(&picture);
104}
105
106static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>* inputs,
107                              sk_tools::PictureBenchmark*& benchmark) {
108    const char* argv0 = argv[0];
109    char* const* stop = argv + argc;
110
111    int repeats = DEFAULT_REPEATS;
112    sk_tools::PictureRenderer::SkDeviceTypes deviceType =
113        sk_tools::PictureRenderer::kBitmap_DeviceType;
114
115    for (++argv; argv < stop; ++argv) {
116        if (0 == strcmp(*argv, "--repeat")) {
117            ++argv;
118            if (argv < stop) {
119                repeats = atoi(*argv);
120                if (repeats < 1) {
121                    SkDELETE(benchmark);
122                    SkDebugf("--repeat must be given a value > 0\n");
123                    exit(-1);
124                }
125            } else {
126                SkDELETE(benchmark);
127                SkDebugf("Missing arg for --repeat\n");
128                usage(argv0);
129                exit(-1);
130            }
131        } else if (0 == strcmp(*argv, "--mode")) {
132            SkDELETE(benchmark);
133
134            ++argv;
135            if (argv >= stop) {
136                SkDebugf("Missing mode for --mode\n");
137                usage(argv0);
138                exit(-1);
139            }
140
141            if (0 == strcmp(*argv, "pipe")) {
142                benchmark = SkNEW(sk_tools::PipePictureBenchmark);
143            } else if (0 == strcmp(*argv, "record")) {
144                benchmark = SkNEW(sk_tools::RecordPictureBenchmark);
145            } else if (0 == strcmp(*argv, "simple")) {
146                benchmark = SkNEW(sk_tools::SimplePictureBenchmark);
147            } else if ((0 == strcmp(*argv, "tile")) || (0 == strcmp(*argv, "pow2tile"))) {
148                char* mode = *argv;
149                bool isPowerOf2Mode = false;
150
151                if (0 == strcmp(*argv, "pow2tile")) {
152                    isPowerOf2Mode = true;
153                }
154
155                sk_tools::TiledPictureBenchmark* tileBenchmark =
156                    SkNEW(sk_tools::TiledPictureBenchmark);
157                ++argv;
158                if (argv >= stop) {
159                    SkDELETE(tileBenchmark);
160                    SkDebugf("Missing width for --mode %s\n", mode);
161                    usage(argv0);
162                    exit(-1);
163                }
164
165                if (isPowerOf2Mode) {
166                    int minWidth = atoi(*argv);
167
168                    if (!SkIsPow2(minWidth) || minWidth <= 0) {
169                        SkDELETE(tileBenchmark);
170                        SkDebugf("--mode %s must be given a width"
171                                 " value that is a power of two\n", mode);
172                        exit(-1);
173                    }
174
175                    tileBenchmark->setTileMinPowerOf2Width(minWidth);
176                } else if (sk_tools::is_percentage(*argv)) {
177                    tileBenchmark->setTileWidthPercentage(atof(*argv));
178                    if (!(tileBenchmark->getTileWidthPercentage() > 0)) {
179                        SkDELETE(tileBenchmark);
180                        SkDebugf("--mode %s must be given a width percentage > 0\n", mode);
181                        exit(-1);
182                    }
183                } else {
184                    tileBenchmark->setTileWidth(atoi(*argv));
185                    if (!(tileBenchmark->getTileWidth() > 0)) {
186                        SkDELETE(tileBenchmark);
187                        SkDebugf("--mode %s must be given a width > 0\n", mode);
188                        exit(-1);
189                    }
190                }
191
192                ++argv;
193                if (argv >= stop) {
194                    SkDELETE(tileBenchmark);
195                    SkDebugf("Missing height for --mode %s\n", mode);
196                    usage(argv0);
197                    exit(-1);
198                }
199
200                if (sk_tools::is_percentage(*argv)) {
201                    tileBenchmark->setTileHeightPercentage(atof(*argv));
202                    if (!(tileBenchmark->getTileHeightPercentage() > 0)) {
203                        SkDELETE(tileBenchmark);
204                        SkDebugf("--mode %s must be given a height percentage > 0\n", mode);
205                        exit(-1);
206                    }
207                } else {
208                    tileBenchmark->setTileHeight(atoi(*argv));
209                    if (!(tileBenchmark->getTileHeight() > 0)) {
210                        SkDELETE(tileBenchmark);
211                        SkDebugf("--mode %s must be given a height > 0\n", mode);
212                        exit(-1);
213                    }
214                }
215
216                benchmark = tileBenchmark;
217            } else if (0 == strcmp(*argv, "unflatten")) {
218                benchmark = SkNEW(sk_tools::UnflattenPictureBenchmark);
219            } else {
220                SkDebugf("%s is not a valid mode for --mode\n", *argv);
221                usage(argv0);
222                exit(-1);
223            }
224        }  else if (0 == strcmp(*argv, "--device")) {
225            ++argv;
226            if (argv >= stop) {
227                SkDebugf("Missing mode for --deivce\n");
228                usage(argv0);
229                exit(-1);
230            }
231
232            if (0 == strcmp(*argv, "bitmap")) {
233                deviceType = sk_tools::PictureRenderer::kBitmap_DeviceType;
234            }
235#if SK_SUPPORT_GPU
236            else if (0 == strcmp(*argv, "gpu")) {
237                deviceType = sk_tools::PictureRenderer::kGPU_DeviceType;
238            }
239#endif
240            else {
241                SkDebugf("%s is not a valid mode for --device\n", *argv);
242                usage(argv0);
243                exit(-1);
244            }
245
246        } else if (0 == strcmp(*argv, "--help") || 0 == strcmp(*argv, "-h")) {
247            SkDELETE(benchmark);
248            usage(argv0);
249            exit(0);
250        } else {
251            inputs->push_back(SkString(*argv));
252        }
253    }
254
255    if (inputs->count() < 1) {
256        SkDELETE(benchmark);
257        usage(argv0);
258        exit(-1);
259    }
260
261    if (NULL == benchmark) {
262        benchmark = SkNEW(sk_tools::SimplePictureBenchmark);
263    }
264
265    benchmark->setRepeats(repeats);
266    benchmark->setDeviceType(deviceType);
267}
268
269static void process_input(const SkString& input, sk_tools::PictureBenchmark& benchmark) {
270    SkOSFile::Iter iter(input.c_str(), "skp");
271    SkString inputFilename;
272
273    if (iter.next(&inputFilename)) {
274        do {
275            SkString inputPath;
276            sk_tools::make_filepath(&inputPath, input, inputFilename);
277            run_single_benchmark(inputPath, benchmark);
278        } while(iter.next(&inputFilename));
279    } else {
280          run_single_benchmark(input, benchmark);
281    }
282}
283
284int main(int argc, char* const argv[]) {
285    SkTArray<SkString> inputs;
286    sk_tools::PictureBenchmark* benchmark = NULL;
287
288    parse_commandline(argc, argv, &inputs, benchmark);
289
290    for (int i = 0; i < inputs.count(); ++i) {
291        process_input(inputs[i], *benchmark);
292    }
293
294    SkDELETE(benchmark);
295}
296