land https://codereview.appspot.com/6349043/
git-svn-id: http://skia.googlecode.com/svn/trunk@4375 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gyp/tools.gyp b/gyp/tools.gyp
index 93eab7d..f30f311 100644
--- a/gyp/tools.gyp
+++ b/gyp/tools.gyp
@@ -19,6 +19,7 @@
'skhello',
'skimage',
'render_pictures',
+ 'bench_pictures',
'pinspect',
],
},
@@ -78,6 +79,23 @@
],
},
{
+ 'target_name': 'bench_pictures',
+ 'type': 'executable',
+ 'sources': [
+ '../tools/bench_pictures_main.cpp'
+ ],
+ 'include_dirs': [
+ '../bench',
+ ],
+ 'dependencies': [
+ 'core.gyp:core',
+ 'ports.gyp:ports',
+ 'images.gyp:images',
+ 'tools.gyp:picture_utils',
+ 'bench.gyp:bench_timer',
+ ],
+ },
+ {
'target_name': 'picture_utils',
'type': 'static_library',
'sources': [
diff --git a/tools/bench_pictures_main.cpp b/tools/bench_pictures_main.cpp
new file mode 100644
index 0000000..355deb6
--- /dev/null
+++ b/tools/bench_pictures_main.cpp
@@ -0,0 +1,236 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "BenchTimer.h"
+#include "SkBitmap.h"
+#include "SkCanvas.h"
+#include "SkOSFile.h"
+#include "SkPicture.h"
+#include "SkStream.h"
+#include "SkTArray.h"
+#include "picture_utils.h"
+
+const int DEFAULT_REPEATS = 100;
+const int DEFAULT_TILE_WIDTH = 256;
+const int DEFAULT_TILE_HEIGHT = 256;
+
+struct Options;
+static void run_simple_benchmark(SkPicture* picture, const SkBitmap&,
+ const Options&);
+
+struct Options {
+ int fRepeats;
+ void (*fBenchmark) (SkPicture*, const SkBitmap& bitmap,
+ const Options& options);
+ int fTileWidth;
+ int fTileHeight;
+
+ Options() : fRepeats(DEFAULT_REPEATS), fBenchmark(run_simple_benchmark),
+ fTileWidth(DEFAULT_TILE_WIDTH), fTileHeight(DEFAULT_TILE_HEIGHT){}
+};
+
+static void usage(const char* argv0) {
+ SkDebugf("SkPicture benchmarking tool\n");
+ SkDebugf("\n"
+"Usage: \n"
+" %s <inputDir>\n"
+" [--repeat] [--tile width height]"
+, argv0);
+ SkDebugf("\n\n");
+ SkDebugf(
+" inputDir: directory to read the serialized SkPicture files."
+" Files are expected to have the .skp extension.\n\n");
+ SkDebugf(
+" --repeat : "
+"Set the number of times to repeat each test."
+" Default is %i.\n", DEFAULT_REPEATS);
+ SkDebugf(
+" --tile width height: "
+"Set to use the tiling size and specify the dimensions of each tile."
+" Default is to not use tiling\n");
+}
+
+static void run_simple_benchmark(SkPicture* picture,
+ const SkBitmap& bitmap,
+ const Options& options) {
+ SkCanvas canvas(bitmap);
+
+ // We throw this away to remove first time effects (such as paging in this
+ // program)
+ canvas.drawPicture(*picture);
+
+ BenchTimer timer = BenchTimer(NULL);
+ timer.start();
+ for (int i = 0; i < options.fRepeats; ++i) {
+ canvas.drawPicture(*picture);
+ }
+ timer.end();
+
+ printf("simple: cmsecs = %6.2f\n", timer.fWall / options.fRepeats);
+}
+
+struct TileInfo {
+ SkBitmap* fBitmap;
+ SkCanvas* fCanvas;
+};
+
+static void setup_single_tile(const SkBitmap& bitmap, const Options& options,
+ SkTArray<TileInfo>* tiles,
+ int tile_x_start, int tile_y_start) {
+ TileInfo& tile = tiles->push_back();
+ tile.fBitmap = new SkBitmap();
+ SkIRect rect = SkIRect::MakeXYWH(tile_x_start, tile_y_start,
+ options.fTileWidth,
+ options.fTileHeight);
+ bitmap.extractSubset(tile.fBitmap, rect);
+ tile.fCanvas = new SkCanvas(*(tile.fBitmap));
+ tile.fCanvas->translate(-tile_x_start, -tile_y_start);
+}
+
+static void setup_tiles(SkPicture* picture, const SkBitmap& bitmap,
+ const Options& options, SkTArray<TileInfo>* tiles) {
+ for (int tile_y_start = 0; tile_y_start < picture->height();
+ tile_y_start += options.fTileHeight) {
+ for (int tile_x_start = 0; tile_x_start < picture->width();
+ tile_x_start += options.fTileWidth) {
+ setup_single_tile(bitmap, options, tiles, tile_x_start,
+ tile_y_start);
+ }
+ }
+
+}
+
+static void run_tile_benchmark(SkPicture* picture, const SkBitmap& bitmap,
+ const Options& options) {
+ SkTArray<TileInfo> tiles;
+ setup_tiles(picture, bitmap, options, &tiles);
+
+ // We throw this away to remove first time effects (such as paging in this
+ // program)
+ for (int j = 0; j < tiles.count(); ++j) {
+ tiles[j].fCanvas->drawPicture(*picture);
+ }
+
+ BenchTimer timer = BenchTimer(NULL);
+ timer.start();
+ for (int i = 0; i < options.fRepeats; ++i) {
+ for (int j = 0; j < tiles.count(); ++j) {
+ tiles[j].fCanvas->drawPicture(*picture);
+ }
+ }
+ timer.end();
+
+ for (int i = 0; i < tiles.count(); ++i) {
+ delete tiles[i].fCanvas;
+ delete tiles[i].fBitmap;
+ }
+
+ printf("tile%ix%i: cmsecs = %6.2f\n", options.fTileWidth,
+ options.fTileHeight, timer.fWall / options.fRepeats);
+}
+
+static void run_benchmark(const char* inputDir,
+ const SkString& inputFilename,
+ const Options& options) {
+ SkFILEStream inputStream;
+
+ SkString inputPath;
+ sk_tools::make_filepath(&inputPath, inputDir, inputFilename);
+ inputStream.setPath(inputPath.c_str());
+ if (!inputStream.isValid()) {
+ SkDebugf("Could not open file %s\n", inputPath.c_str());
+ return;
+ }
+
+ SkPicture picture(&inputStream);
+ SkBitmap bitmap;
+ sk_tools::setup_bitmap(&bitmap, picture.width(), picture.height());
+
+ printf("running bench [%i %i] %s ", picture.width(), picture.height(),
+ inputFilename.c_str());
+ options.fBenchmark(&picture, bitmap, options);
+}
+
+static void parse_commandline(int argc, char* const argv[],
+ const char** inputDir, Options* options) {
+ const char* argv0 = argv[0];
+ char* const* stop = argv + argc;
+
+ for (++argv; argv < stop; ++argv) {
+ if (0 == strcmp(*argv, "--repeat")) {
+ ++argv;
+ if (argv < stop) {
+ options->fRepeats = atoi(*argv);
+ if (options->fRepeats < 1) {
+ SkDebugf("--repeat must be given a value > 0\n");
+ exit(-1);
+ }
+ } else {
+ SkDebugf("Missing arg for --repeat\n");
+ usage(argv0);
+ exit(-1);
+ }
+ } else if (0 == strcmp(*argv, "--tile")) {
+ options->fBenchmark = run_tile_benchmark;
+ ++argv;
+ if (argv < stop) {
+ options->fTileWidth = atoi(*argv);
+ if (options->fTileWidth < 1) {
+ SkDebugf("--tile must be given a width with a value > 0\n");
+ exit(-1);
+ }
+ } else {
+ SkDebugf("Missing width for --tile\n");
+ usage(argv0);
+ exit(-1);
+ }
+ ++argv;
+ if (argv < stop) {
+ options->fTileHeight = atoi(*argv);
+ if (options->fTileHeight < 1) {
+ SkDebugf("--tile must be given a height with a value > 0"
+ "\n");
+ exit(-1);
+ }
+ } else {
+ SkDebugf("Missing height for --tile\n");
+ usage(argv0);\
+ exit(-1);
+ }
+ } else if (0 == strcmp(*argv, "--help") || 0 == strcmp(*argv, "-h")) {
+ usage(argv0);
+ exit(0);
+ } else {
+ if (NULL == *inputDir) {
+ *inputDir = *argv;
+ } else {
+ usage(argv0);
+ exit(-1);
+ }
+ }
+ }
+
+ if (NULL == *inputDir) {
+ usage(argv0);
+ exit(-1);
+ }
+
+}
+
+int main(int argc, char* const argv[]) {
+ const char* inputDir = NULL;
+ Options options;
+
+ parse_commandline(argc, argv, &inputDir, &options);
+
+ SkOSFile::Iter iter(inputDir, "skp");
+ SkString inputFilename;
+
+ while(iter.next(&inputFilename)) {
+ run_benchmark(inputDir, inputFilename, options);
+ }
+}