blob: eb5726a6ea3a79d814ff5ad46ca6285f809707eb [file] [log] [blame]
reed@google.com006db0f2012-06-27 19:33:29 +00001/*
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"
keyar@chromium.orgcf6c44c2012-07-09 19:37:40 +00009#include "SamplePipeControllers.h"
reed@google.com006db0f2012-06-27 19:33:29 +000010#include "SkBitmap.h"
11#include "SkCanvas.h"
keyar@chromium.orgcf6c44c2012-07-09 19:37:40 +000012#include "SkGPipe.h"
reed@google.com006db0f2012-06-27 19:33:29 +000013#include "SkOSFile.h"
14#include "SkPicture.h"
15#include "SkStream.h"
16#include "SkTArray.h"
17#include "picture_utils.h"
18
19const int DEFAULT_REPEATS = 100;
20const int DEFAULT_TILE_WIDTH = 256;
21const int DEFAULT_TILE_HEIGHT = 256;
22
23struct Options;
keyar@chromium.orga4091ba2012-07-10 19:53:59 +000024static void run_simple_benchmark(SkPicture* picture, const Options&);
reed@google.com006db0f2012-06-27 19:33:29 +000025
26struct Options {
27 int fRepeats;
keyar@chromium.orga4091ba2012-07-10 19:53:59 +000028 void (*fBenchmark) (SkPicture*, const Options& options);
reed@google.com006db0f2012-06-27 19:33:29 +000029 int fTileWidth;
30 int fTileHeight;
keyar@chromium.org0665f252012-07-10 18:30:18 +000031 double fTileWidthPercentage;
32 double fTileHeightPercentage;
reed@google.com006db0f2012-06-27 19:33:29 +000033
34 Options() : fRepeats(DEFAULT_REPEATS), fBenchmark(run_simple_benchmark),
keyar@chromium.org0665f252012-07-10 18:30:18 +000035 fTileWidth(DEFAULT_TILE_WIDTH), fTileHeight(DEFAULT_TILE_HEIGHT),
36 fTileWidthPercentage(0), fTileHeightPercentage(0){}
reed@google.com006db0f2012-06-27 19:33:29 +000037};
38
39static void usage(const char* argv0) {
40 SkDebugf("SkPicture benchmarking tool\n");
41 SkDebugf("\n"
42"Usage: \n"
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +000043" %s <inputDir>...\n"
reed@google.com006db0f2012-06-27 19:33:29 +000044" [--repeat] [--tile width height]"
45, argv0);
46 SkDebugf("\n\n");
47 SkDebugf(
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +000048" inputDir: A list of directories and files to use as input.\n"
49" Files are expected to have the .skp extension.\n\n");
reed@google.com006db0f2012-06-27 19:33:29 +000050 SkDebugf(
keyar@chromium.orgcf6c44c2012-07-09 19:37:40 +000051" --pipe : "
52"Set to use piping."
53" Default is to not use piping.\n");
54 SkDebugf(
reed@google.com006db0f2012-06-27 19:33:29 +000055" --repeat : "
56"Set the number of times to repeat each test."
57" Default is %i.\n", DEFAULT_REPEATS);
58 SkDebugf(
keyar@chromium.org0665f252012-07-10 18:30:18 +000059" --tile width[%] height[%]: "
60"Set to use the tiling size and specify the dimensions of each tile.\n"
61" Default is to not use tiling\n");
reed@google.com006db0f2012-06-27 19:33:29 +000062}
63
keyar@chromium.orga4091ba2012-07-10 19:53:59 +000064static void run_simple_benchmark(SkPicture* picture, const Options& options) {
65 SkBitmap bitmap;
66 sk_tools::setup_bitmap(&bitmap, picture->width(), picture->height());
67
reed@google.com006db0f2012-06-27 19:33:29 +000068 SkCanvas canvas(bitmap);
69
70 // We throw this away to remove first time effects (such as paging in this
71 // program)
72 canvas.drawPicture(*picture);
73
74 BenchTimer timer = BenchTimer(NULL);
75 timer.start();
76 for (int i = 0; i < options.fRepeats; ++i) {
77 canvas.drawPicture(*picture);
78 }
79 timer.end();
80
81 printf("simple: cmsecs = %6.2f\n", timer.fWall / options.fRepeats);
82}
83
84struct TileInfo {
85 SkBitmap* fBitmap;
86 SkCanvas* fCanvas;
87};
88
keyar@chromium.org70b42222012-07-09 19:51:05 +000089static void clip_tile(SkPicture* picture, const TileInfo& tile) {
robertphillips@google.com59f46b82012-07-10 17:30:58 +000090 SkRect clip = SkRect::MakeWH(SkIntToScalar(picture->width()),
91 SkIntToScalar(picture->height()));
keyar@chromium.org70b42222012-07-09 19:51:05 +000092 tile.fCanvas->clipRect(clip);
93}
94
95static void setup_single_tile(SkPicture* picture, const SkBitmap& bitmap,
96 const Options& options, SkTArray<TileInfo>* tiles,
reed@google.com006db0f2012-06-27 19:33:29 +000097 int tile_x_start, int tile_y_start) {
98 TileInfo& tile = tiles->push_back();
99 tile.fBitmap = new SkBitmap();
100 SkIRect rect = SkIRect::MakeXYWH(tile_x_start, tile_y_start,
keyar@chromium.org70b42222012-07-09 19:51:05 +0000101 options.fTileWidth, options.fTileHeight);
reed@google.com006db0f2012-06-27 19:33:29 +0000102 bitmap.extractSubset(tile.fBitmap, rect);
103 tile.fCanvas = new SkCanvas(*(tile.fBitmap));
robertphillips@google.com59f46b82012-07-10 17:30:58 +0000104 tile.fCanvas->translate(SkIntToScalar(-tile_x_start),
105 SkIntToScalar(-tile_y_start));
keyar@chromium.org70b42222012-07-09 19:51:05 +0000106
107 clip_tile(picture, tile);
reed@google.com006db0f2012-06-27 19:33:29 +0000108}
109
110static void setup_tiles(SkPicture* picture, const SkBitmap& bitmap,
111 const Options& options, SkTArray<TileInfo>* tiles) {
112 for (int tile_y_start = 0; tile_y_start < picture->height();
113 tile_y_start += options.fTileHeight) {
114 for (int tile_x_start = 0; tile_x_start < picture->width();
115 tile_x_start += options.fTileWidth) {
keyar@chromium.org70b42222012-07-09 19:51:05 +0000116 setup_single_tile(picture, bitmap, options, tiles, tile_x_start,
reed@google.com006db0f2012-06-27 19:33:29 +0000117 tile_y_start);
118 }
119 }
120
121}
122
keyar@chromium.orga4091ba2012-07-10 19:53:59 +0000123static void run_tile_benchmark(SkPicture* picture, const Options& options) {
124 SkBitmap bitmap;
125 sk_tools::setup_bitmap(&bitmap, picture->width(), picture->height());
126
reed@google.com006db0f2012-06-27 19:33:29 +0000127 SkTArray<TileInfo> tiles;
128 setup_tiles(picture, bitmap, options, &tiles);
129
130 // We throw this away to remove first time effects (such as paging in this
131 // program)
132 for (int j = 0; j < tiles.count(); ++j) {
133 tiles[j].fCanvas->drawPicture(*picture);
134 }
135
136 BenchTimer timer = BenchTimer(NULL);
137 timer.start();
138 for (int i = 0; i < options.fRepeats; ++i) {
139 for (int j = 0; j < tiles.count(); ++j) {
140 tiles[j].fCanvas->drawPicture(*picture);
141 }
142 }
143 timer.end();
144
145 for (int i = 0; i < tiles.count(); ++i) {
146 delete tiles[i].fCanvas;
147 delete tiles[i].fBitmap;
148 }
149
keyar@chromium.org2724ae02012-07-10 15:13:21 +0000150 printf("%i_tiles_%ix%i: cmsecs = %6.2f\n", tiles.count(), options.fTileWidth,
reed@google.com006db0f2012-06-27 19:33:29 +0000151 options.fTileHeight, timer.fWall / options.fRepeats);
152}
153
keyar@chromium.orgcf6c44c2012-07-09 19:37:40 +0000154static void pipe_run(SkPicture* picture, SkCanvas* canvas) {
155 PipeController pipeController(canvas);
156 SkGPipeWriter writer;
157 SkCanvas* pipeCanvas = writer.startRecording(&pipeController);
158 pipeCanvas->drawPicture(*picture);
159 writer.endRecording();
160}
161
keyar@chromium.orga4091ba2012-07-10 19:53:59 +0000162static void run_pipe_benchmark(SkPicture* picture, const Options& options) {
163 SkBitmap bitmap;
164 sk_tools::setup_bitmap(&bitmap, picture->width(), picture->height());
165
keyar@chromium.orgcf6c44c2012-07-09 19:37:40 +0000166 SkCanvas canvas(bitmap);
167
168 // We throw this away to remove first time effects (such as paging in this
169 // program)
170 pipe_run(picture, &canvas);
171
172 BenchTimer timer = BenchTimer(NULL);
173 timer.start();
174 for (int i = 0; i < options.fRepeats; ++i) {
175 pipe_run(picture, &canvas);
176 }
177 timer.end();
178
179 printf("pipe: cmsecs = %6.2f\n", timer.fWall / options.fRepeats);
180}
181
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000182static void run_single_benchmark(const SkString& inputPath,
keyar@chromium.org0665f252012-07-10 18:30:18 +0000183 Options* options) {
reed@google.com006db0f2012-06-27 19:33:29 +0000184 SkFILEStream inputStream;
185
reed@google.com006db0f2012-06-27 19:33:29 +0000186 inputStream.setPath(inputPath.c_str());
187 if (!inputStream.isValid()) {
188 SkDebugf("Could not open file %s\n", inputPath.c_str());
189 return;
190 }
191
192 SkPicture picture(&inputStream);
reed@google.com006db0f2012-06-27 19:33:29 +0000193
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000194 SkString filename;
195 sk_tools::get_basename(&filename, inputPath);
reed@google.com006db0f2012-06-27 19:33:29 +0000196 printf("running bench [%i %i] %s ", picture.width(), picture.height(),
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000197 filename.c_str());
198
keyar@chromium.org0665f252012-07-10 18:30:18 +0000199 if (options->fTileWidthPercentage > 0) {
200 options->fTileWidth = sk_float_ceil2int(options->fTileWidthPercentage * picture.width()
201 / 100);
202 }
203 if (options->fTileHeightPercentage > 0) {
204 options->fTileHeight = sk_float_ceil2int(options->fTileHeightPercentage * picture.height()
205 / 100);
206 }
207
keyar@chromium.orga4091ba2012-07-10 19:53:59 +0000208 options->fBenchmark(&picture, *options);
keyar@chromium.org0665f252012-07-10 18:30:18 +0000209}
210
211static bool is_percentage(char* const string) {
212 SkString skString(string);
213 return skString.endsWith("%");
reed@google.com006db0f2012-06-27 19:33:29 +0000214}
215
216static void parse_commandline(int argc, char* const argv[],
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000217 SkTArray<SkString>* inputs, Options* options) {
reed@google.com006db0f2012-06-27 19:33:29 +0000218 const char* argv0 = argv[0];
219 char* const* stop = argv + argc;
220
221 for (++argv; argv < stop; ++argv) {
222 if (0 == strcmp(*argv, "--repeat")) {
223 ++argv;
224 if (argv < stop) {
225 options->fRepeats = atoi(*argv);
226 if (options->fRepeats < 1) {
227 SkDebugf("--repeat must be given a value > 0\n");
228 exit(-1);
229 }
230 } else {
231 SkDebugf("Missing arg for --repeat\n");
232 usage(argv0);
233 exit(-1);
234 }
235 } else if (0 == strcmp(*argv, "--tile")) {
236 options->fBenchmark = run_tile_benchmark;
237 ++argv;
238 if (argv < stop) {
keyar@chromium.org0665f252012-07-10 18:30:18 +0000239 if (is_percentage(*argv)) {
240 options->fTileWidthPercentage = atof(*argv);
241 if (!(options->fTileWidthPercentage > 0)) {
242 SkDebugf("--tile must be given a width percentage > 0\n");
243 exit(-1);
244 }
245 } else {
246 options->fTileWidth = atoi(*argv);
247 if (!(options->fTileWidth > 0)) {
248 SkDebugf("--tile must be given a width > 0\n");
249 exit(-1);
250 }
reed@google.com006db0f2012-06-27 19:33:29 +0000251 }
252 } else {
253 SkDebugf("Missing width for --tile\n");
254 usage(argv0);
255 exit(-1);
256 }
257 ++argv;
258 if (argv < stop) {
keyar@chromium.org0665f252012-07-10 18:30:18 +0000259 if (is_percentage(*argv)) {
260 options->fTileHeightPercentage = atof(*argv);
261 if (!(options->fTileHeightPercentage > 0)) {
262 SkDebugf(
263 "--tile must be given a height percentage > 0\n");
264 exit(-1);
265 }
266 } else {
267 options->fTileHeight = atoi(*argv);
268 if (!(options->fTileHeight > 0)) {
269 SkDebugf("--tile must be given a height > 0\n");
270 exit(-1);
271 }
reed@google.com006db0f2012-06-27 19:33:29 +0000272 }
273 } else {
274 SkDebugf("Missing height for --tile\n");
keyar@chromium.org0665f252012-07-10 18:30:18 +0000275 usage(argv0);
reed@google.com006db0f2012-06-27 19:33:29 +0000276 exit(-1);
277 }
keyar@chromium.orgcf6c44c2012-07-09 19:37:40 +0000278 } else if (0 == strcmp(*argv, "--pipe")) {
279 options->fBenchmark = run_pipe_benchmark;
reed@google.com006db0f2012-06-27 19:33:29 +0000280 } else if (0 == strcmp(*argv, "--help") || 0 == strcmp(*argv, "-h")) {
281 usage(argv0);
282 exit(0);
283 } else {
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000284 inputs->push_back(SkString(*argv));
reed@google.com006db0f2012-06-27 19:33:29 +0000285 }
286 }
287
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000288 if (inputs->count() < 1) {
reed@google.com006db0f2012-06-27 19:33:29 +0000289 usage(argv0);
290 exit(-1);
291 }
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000292}
reed@google.com006db0f2012-06-27 19:33:29 +0000293
keyar@chromium.org0665f252012-07-10 18:30:18 +0000294static void process_input(const SkString& input, Options* options) {
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000295 SkOSFile::Iter iter(input.c_str(), "skp");
296 SkString inputFilename;
297
298 if (iter.next(&inputFilename)) {
299 do {
300 SkString inputPath;
301 sk_tools::make_filepath(&inputPath, input.c_str(),
302 inputFilename);
303 run_single_benchmark(inputPath, options);
304 } while(iter.next(&inputFilename));
305 } else {
306 run_single_benchmark(input, options);
307 }
reed@google.com006db0f2012-06-27 19:33:29 +0000308}
309
310int main(int argc, char* const argv[]) {
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000311 SkTArray<SkString> inputs;
reed@google.com006db0f2012-06-27 19:33:29 +0000312 Options options;
313
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000314 parse_commandline(argc, argv, &inputs, &options);
reed@google.com006db0f2012-06-27 19:33:29 +0000315
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000316 for (int i = 0; i < inputs.count(); ++i) {
keyar@chromium.org0665f252012-07-10 18:30:18 +0000317 process_input(inputs[i], &options);
reed@google.com006db0f2012-06-27 19:33:29 +0000318 }
319}