aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--bench/benchmain.cpp10
-rw-r--r--gyp/tools.gyp4
-rw-r--r--tools/CopyTilesRenderer.h2
-rw-r--r--tools/PictureBenchmark.cpp4
-rw-r--r--tools/PictureBenchmark.h2
-rw-r--r--tools/PictureRenderer.h5
-rw-r--r--tools/PictureRenderingFlags.cpp311
-rw-r--r--tools/PictureRenderingFlags.h34
-rw-r--r--tools/SkFlags.cpp135
-rw-r--r--tools/SkFlags.h345
-rw-r--r--tools/bench_pictures.cfg6
-rw-r--r--tools/bench_pictures_cfg_helper.py4
-rw-r--r--tools/bench_pictures_main.cpp766
-rw-r--r--tools/render_pictures_main.cpp622
14 files changed, 1067 insertions, 1183 deletions
diff --git a/bench/benchmain.cpp b/bench/benchmain.cpp
index 96db07d465..459f34038a 100644
--- a/bench/benchmain.cpp
+++ b/bench/benchmain.cpp
@@ -278,7 +278,7 @@ static bool skip_name(const SkTDArray<const char*> array, const char name[]) {
}
static void help() {
- SkDebugf("Usage: bench [-o outDir] [--repeat nr] [--logPerIter 1|0] "
+ SkDebugf("Usage: bench [-o outDir] [--repeat nr] [--logPerIter] "
"[--timers [wcgWC]*] [--rotate]\n"
" [--scale] [--clip] [--min] [--forceAA 1|0] [--forceFilter 1|0]\n"
" [--forceDither 1|0] [--forceBlend 1|0] [--strokeWidth width]\n"
@@ -288,7 +288,7 @@ static void help() {
SkDebugf("\n\n");
SkDebugf(" -o outDir : Image of each bench will be put in outDir.\n");
SkDebugf(" --repeat nr : Each bench repeats for nr times.\n");
- SkDebugf(" --logPerIter 1|0 : "
+ SkDebugf(" --logPerIter : "
"Log each repeat timer instead of mean, default is disabled.\n");
SkDebugf(" --timers [wcgWC]* : "
"Display wall, cpu, gpu, truncated wall or truncated cpu time for each bench.\n");
@@ -388,11 +388,7 @@ int tool_main(int argc, char** argv) {
return -1;
}
} else if (strcmp(*argv, "--logPerIter") == 0) {
- if (!parse_bool_arg(++argv, stop, &logPerIter)) {
- logger.logError("missing arg for --logPerIter\n");
- help();
- return -1;
- }
+ logPerIter = true;
} else if (strcmp(*argv, "--timers") == 0) {
argv++;
if (argv < stop) {
diff --git a/gyp/tools.gyp b/gyp/tools.gyp
index 121779bbf2..074efd1433 100644
--- a/gyp/tools.gyp
+++ b/gyp/tools.gyp
@@ -128,8 +128,12 @@
'sources': [
'../tools/PictureRenderer.h',
'../tools/PictureRenderer.cpp',
+ '../tools/PictureRenderingFlags.h',
+ '../tools/PictureRenderingFlags.cpp',
'../tools/CopyTilesRenderer.h',
'../tools/CopyTilesRenderer.cpp',
+ '../tools/SkFlags.h',
+ '../tools/SkFlags.cpp',
'../src/pipe/utils/SamplePipeControllers.h',
'../src/pipe/utils/SamplePipeControllers.cpp',
],
diff --git a/tools/CopyTilesRenderer.h b/tools/CopyTilesRenderer.h
index 5546604ee8..9a8b3745bd 100644
--- a/tools/CopyTilesRenderer.h
+++ b/tools/CopyTilesRenderer.h
@@ -31,6 +31,8 @@ namespace sk_tools {
*/
virtual bool render(const SkString* path, SkBitmap** out) SK_OVERRIDE;
+ virtual bool supportsTimingIndividualTiles() SK_OVERRIDE { return false; }
+
private:
int fXTilesPerLargeTile;
int fYTilesPerLargeTile;
diff --git a/tools/PictureBenchmark.cpp b/tools/PictureBenchmark.cpp
index b47cf961df..a358ad4179 100644
--- a/tools/PictureBenchmark.cpp
+++ b/tools/PictureBenchmark.cpp
@@ -79,8 +79,8 @@ void PictureBenchmark::run(SkPicture* pict) {
if (fTimeIndividualTiles) {
TiledPictureRenderer* tiledRenderer = fRenderer->getTiledRenderer();
- SkASSERT(tiledRenderer);
- if (NULL == tiledRenderer) {
+ SkASSERT(tiledRenderer && tiledRenderer->supportsTimingIndividualTiles());
+ if (NULL == tiledRenderer || !tiledRenderer->supportsTimingIndividualTiles()) {
return;
}
int xTiles, yTiles;
diff --git a/tools/PictureBenchmark.h b/tools/PictureBenchmark.h
index b2764e0f79..70c56d9949 100644
--- a/tools/PictureBenchmark.h
+++ b/tools/PictureBenchmark.h
@@ -39,7 +39,7 @@ public:
* drawn fRepeats times. Requires the PictureRenderer set by setRenderer to be a
* TiledPictureRenderer.
*/
- void setTimeIndividualTiles(bool indiv) { fTimeIndividualTiles = true; }
+ void setTimeIndividualTiles(bool indiv) { fTimeIndividualTiles = indiv; }
bool timeIndividualTiles() { return fTimeIndividualTiles; }
diff --git a/tools/PictureRenderer.h b/tools/PictureRenderer.h
index 72367c0569..b073252199 100644
--- a/tools/PictureRenderer.h
+++ b/tools/PictureRenderer.h
@@ -8,6 +8,7 @@
#ifndef PictureRenderer_DEFINED
#define PictureRenderer_DEFINED
+#include "SkCanvas.h"
#include "SkCountdown.h"
#include "SkDrawFilter.h"
#include "SkMath.h"
@@ -421,6 +422,8 @@ public:
virtual TiledPictureRenderer* getTiledRenderer() SK_OVERRIDE { return this; }
+ virtual bool supportsTimingIndividualTiles() { return true; }
+
/**
* Report the number of tiles in the x and y directions. Must not be called before init.
* @param x Output parameter identifying the number of tiles in the x direction.
@@ -493,6 +496,8 @@ public:
virtual void end() SK_OVERRIDE;
+ virtual bool supportsTimingIndividualTiles() SK_OVERRIDE { return false; }
+
private:
virtual SkString getConfigNameInternal() SK_OVERRIDE;
diff --git a/tools/PictureRenderingFlags.cpp b/tools/PictureRenderingFlags.cpp
new file mode 100644
index 0000000000..d8522013cf
--- /dev/null
+++ b/tools/PictureRenderingFlags.cpp
@@ -0,0 +1,311 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "PictureRenderingFlags.h"
+
+#include "CopyTilesRenderer.h"
+#include "PictureRenderer.h"
+#include "picture_utils.h"
+
+#include "SkFlags.h"
+
+// Alphabetized list of flags used by this file or bench_ and render_pictures.
+DEFINE_string(bbh, "none", "bbhType [width height]: Set the bounding box hierarchy type to "
+ "be used. Accepted values are: none, rtree, grid. "
+ "Not compatible with --pipe. With value "
+ "'grid', width and height must be specified. 'grid' can "
+ "only be used with modes tile, record, and "
+ "playbackCreation.");
+// Although this config does not support all the same options as gm, the names should be kept
+// consistent.
+#if SK_ANGLE
+// ANGLE assumes GPU
+DEFINE_string(config, "8888", "[8888|gpu|angle]: Use the corresponding config.");
+#elif SK_SUPPORT_GPU
+DEFINE_string(config, "8888", "[8888|gpu]: Use the corresponding config.");
+#else
+DEFINE_string(config, "8888", "[8888]: Use the corresponding config.");
+#endif
+
+DEFINE_bool(deferImageDecoding, false, "Defer decoding until drawing images. "
+ "Has no effect if the provided skp does not have its images encoded.");
+DEFINE_string(mode, "simple", "Run in the corresponding mode:\n"
+ "simple: Simple rendering.\n"
+ "tile width height: Use tiles with the given dimensions or percentages.\n"
+ "pow2tile minWidth height: Use tiles with widths that are all a power\n"
+ "\tof two such that they minimize the amount of wasted tile space.\n"
+ "\tminWidth must be a power of two.\n"
+ "copyTile width height: Draw the picture, then copy into tiles. If the\n"
+ "\tpicture is large enough, it is broken into larger tiles to avoid\n"
+ "\tcreating a large canvas.\n"
+// TODO: If bench_pictures and render_pictures were two separate targets, we could use build flags
+// to determine which modes to display.
+ "record: (Only in bench_pictures) Time recording from a picture to a new\n"
+ "\tpicture.\n"
+ "playbackCreation: (Only in bench_pictures) Time creation of the \n"
+ "\tSkPicturePlayback.\n"
+ "rerecord: (Only in render_pictures) Record the picture as a new skp,\n"
+ "\twith the bitmaps PNG encoded.\n");
+DEFINE_int32(multi, 1, "Set the number of threads for multi threaded drawing. "
+ "If > 1, requires tiled rendering.");
+DEFINE_bool(pipe, false, "Use SkGPipe rendering. Currently incompatible with \"mode\".");
+DEFINE_string(r, "", "skp files or directories of skp files to process.");
+DEFINE_double(scale, 1, "Set the scale factor.");
+DEFINE_string(tiles, "", "Used with --mode copyTile to specify number of tiles per larger tile "
+ "in the x and y directions.");
+DEFINE_string(viewport, "", "width height: Set the viewport.");
+
+sk_tools::PictureRenderer* parseRenderer(SkString& error, PictureTool tool) {
+ error.reset();
+
+ if (FLAGS_multi <= 0) {
+ error.printf("--multi must be > 0, was %i", FLAGS_multi);
+ return NULL;
+ }
+
+ bool useTiles = false;
+ const char* widthString = NULL;
+ const char* heightString = NULL;
+ bool isPowerOf2Mode = false;
+ bool isCopyMode = false;
+ const char* mode = NULL;
+ bool gridSupported = false;
+
+ SkAutoTUnref<sk_tools::PictureRenderer> renderer;
+ if (FLAGS_mode.count() >= 1) {
+ mode = FLAGS_mode[0];
+ if (0 == strcmp(mode, "record")) {
+ renderer.reset(SkNEW(sk_tools::RecordPictureRenderer));
+ gridSupported = true;
+ // undocumented
+ } else if (0 == strcmp(mode, "clone")) {
+ renderer.reset(sk_tools::CreatePictureCloneRenderer());
+ } else if (0 == strcmp(mode, "tile") || 0 == strcmp(mode, "pow2tile")
+ || 0 == strcmp(mode, "copyTile")) {
+ useTiles = true;
+
+ if (0 == strcmp(mode, "pow2tile")) {
+ isPowerOf2Mode = true;
+ } else if (0 == strcmp(mode, "copyTile")) {
+ isCopyMode = true;
+ } else {
+ gridSupported = true;
+ }
+
+ if (FLAGS_mode.count() < 2) {
+ error.printf("Missing width for --mode %s\n", mode);
+ return NULL;
+ }
+
+ widthString = FLAGS_mode[1];
+ if (FLAGS_mode.count() < 3) {
+ error.printf("Missing height for --mode %s\n", mode);
+ return NULL;
+ }
+
+ heightString = FLAGS_mode[2];
+ } else if (0 == strcmp(mode, "playbackCreation") && kBench_PictureTool == tool) {
+ renderer.reset(SkNEW(sk_tools::PlaybackCreationRenderer));
+ gridSupported = true;
+ // undocumented
+ } else if (0 == strcmp(mode, "gatherPixelRefs") && kBench_PictureTool == tool) {
+ renderer.reset(sk_tools::CreateGatherPixelRefsRenderer());
+ } else if (0 == strcmp(mode, "rerecord") && kRender_PictureTool == tool) {
+ renderer.reset(SkNEW(sk_tools::RecordPictureRenderer));
+ // Allow 'mode' to be set to 'simple', but do not create a renderer, so we can
+ // ensure that pipe does not override a mode besides simple. The renderer will
+ // be created below.
+ } else if (0 != strcmp(mode, "simple")) {
+ error.printf("%s is not a valid mode for --mode\n", mode);
+ return NULL;
+ }
+ }
+
+ if (useTiles) {
+ SkASSERT(NULL == renderer);
+ SkAutoTUnref<sk_tools::TiledPictureRenderer> tiledRenderer;
+ if (isCopyMode) {
+ int xTiles = -1;
+ int yTiles = -1;
+ if (FLAGS_tiles.count() > 0) {
+ if (FLAGS_tiles.count() != 2) {
+ error.printf("--tiles requires an x value and a y value.\n");
+ return NULL;
+ }
+ xTiles = atoi(FLAGS_tiles[0]);
+ yTiles = atoi(FLAGS_tiles[1]);
+ }
+
+ int x, y;
+ if (xTiles != -1 && yTiles != -1) {
+ x = xTiles;
+ y = yTiles;
+ if (x <= 0 || y <= 0) {
+ error.printf("--tiles must be given values > 0\n");
+ return NULL;
+ }
+ } else {
+ x = y = 4;
+ }
+ tiledRenderer.reset(SkNEW_ARGS(sk_tools::CopyTilesRenderer, (x, y)));
+ } else if (FLAGS_multi > 1) {
+ tiledRenderer.reset(SkNEW_ARGS(sk_tools::MultiCorePictureRenderer,
+ (FLAGS_multi)));
+ } else {
+ tiledRenderer.reset(SkNEW(sk_tools::TiledPictureRenderer));
+ }
+
+ if (isPowerOf2Mode) {
+ int minWidth = atoi(widthString);
+ if (!SkIsPow2(minWidth) || minWidth < 0) {
+ SkString err;
+ error.printf("-mode %s must be given a width"
+ " value that is a power of two\n", mode);
+ return NULL;
+ }
+ tiledRenderer->setTileMinPowerOf2Width(minWidth);
+ } else if (sk_tools::is_percentage(widthString)) {
+ if (isCopyMode) {
+ error.printf("--mode %s does not support percentages.\n", mode);
+ return NULL;
+ }
+ tiledRenderer->setTileWidthPercentage(atof(widthString));
+ if (!(tiledRenderer->getTileWidthPercentage() > 0)) {
+ error.printf("--mode %s must be given a width percentage > 0\n", mode);
+ return NULL;
+ }
+ } else {
+ tiledRenderer->setTileWidth(atoi(widthString));
+ if (!(tiledRenderer->getTileWidth() > 0)) {
+ error.printf("--mode %s must be given a width > 0\n", mode);
+ return NULL;
+ }
+ }
+
+ if (sk_tools::is_percentage(heightString)) {
+ if (isCopyMode) {
+ error.printf("--mode %s does not support percentages.\n", mode);
+ return NULL;
+ }
+ tiledRenderer->setTileHeightPercentage(atof(heightString));
+ if (!(tiledRenderer->getTileHeightPercentage() > 0)) {
+ error.printf("--mode %s must be given a height percentage > 0\n", mode);
+ return NULL;
+ }
+ } else {
+ tiledRenderer->setTileHeight(atoi(heightString));
+ if (!(tiledRenderer->getTileHeight() > 0)) {
+ SkString err;
+ error.printf("--mode %s must be given a height > 0\n", mode);
+ return NULL;
+ }
+ }
+
+ renderer.reset(tiledRenderer.detach());
+ if (FLAGS_pipe) {
+ error.printf("Pipe rendering is currently not compatible with tiling.\n"
+ "Turning off pipe.\n");
+ }
+
+ } else { // useTiles
+ if (FLAGS_multi > 1) {
+ error.printf("Multithreaded drawing requires tiled rendering.\n");
+ return NULL;
+ }
+ if (FLAGS_pipe) {
+ if (renderer != NULL) {
+ error.printf("Pipe is incompatible with other modes.\n");
+ return NULL;
+ }
+ renderer.reset(SkNEW(sk_tools::PipePictureRenderer));
+ }
+ }
+
+ if (NULL == renderer) {
+ renderer.reset(SkNEW(sk_tools::SimplePictureRenderer));
+ }
+
+ if (FLAGS_viewport.count() > 0) {
+ if (FLAGS_viewport.count() != 2) {
+ error.printf("--viewport requires a width and a height.\n");
+ return NULL;
+ }
+ SkISize viewport;
+ viewport.fWidth = atoi(FLAGS_viewport[0]);
+ viewport.fHeight = atoi(FLAGS_viewport[1]);
+ renderer->setViewport(viewport);
+ }
+
+ sk_tools::PictureRenderer::SkDeviceTypes deviceType =
+ sk_tools::PictureRenderer::kBitmap_DeviceType;
+ if (FLAGS_config.count() > 0) {
+ if (0 == strcmp(FLAGS_config[0], "8888")) {
+ deviceType = sk_tools::PictureRenderer::kBitmap_DeviceType;
+ }
+#if SK_SUPPORT_GPU
+ else if (0 == strcmp(FLAGS_config[0], "gpu")) {
+ deviceType = sk_tools::PictureRenderer::kGPU_DeviceType;
+ if (FLAGS_multi > 1) {
+ error.printf("GPU not compatible with multithreaded tiling.\n");
+ return NULL;
+ }
+ }
+#if SK_ANGLE
+ else if (0 == strcmp(FLAGS_config[0], "angle")) {
+ deviceType = sk_tools::PictureRenderer::kAngle_DeviceType;
+ if (FLAGS_multi > 1) {
+ error.printf("Angle not compatible with multithreaded tiling.\n");
+ return NULL;
+ }
+ }
+#endif
+#endif
+ else {
+ error.printf("%s is not a valid mode for --config\n", FLAGS_config[0]);
+ return NULL;
+ }
+ renderer->setDeviceType(deviceType);
+ }
+
+
+ sk_tools::PictureRenderer::BBoxHierarchyType bbhType
+ = sk_tools::PictureRenderer::kNone_BBoxHierarchyType;
+ if (FLAGS_bbh.count() > 0) {
+ const char* type = FLAGS_bbh[0];
+ if (0 == strcmp(type, "none")) {
+ bbhType = sk_tools::PictureRenderer::kNone_BBoxHierarchyType;
+ } else if (0 == strcmp(type, "rtree")) {
+ bbhType = sk_tools::PictureRenderer::kRTree_BBoxHierarchyType;
+ } else if (0 == strcmp(type, "grid")) {
+ if (!gridSupported) {
+ error.printf("'--bbh grid' is not compatible with --mode=%s.\n", mode);
+ return NULL;
+ }
+ bbhType = sk_tools::PictureRenderer::kTileGrid_BBoxHierarchyType;
+ if (FLAGS_bbh.count() != 3) {
+ error.printf("--bbh grid requires a width and a height.\n");
+ return NULL;
+ }
+ int gridWidth = atoi(FLAGS_bbh[1]);
+ int gridHeight = atoi(FLAGS_bbh[2]);
+ renderer->setGridSize(gridWidth, gridHeight);
+
+ } else {
+ error.printf("%s is not a valid value for --bbhType\n", type);
+ return NULL;
+ }
+ if (FLAGS_pipe && sk_tools::PictureRenderer::kNone_BBoxHierarchyType != bbhType) {
+ error.printf("--pipe and --bbh cannot be used together\n");
+ return NULL;
+ }
+ }
+ renderer->setBBoxHierarchyType(bbhType);
+ renderer->setScaleFactor(SkDoubleToScalar(FLAGS_scale));
+
+ return renderer.detach();
+}
+
diff --git a/tools/PictureRenderingFlags.h b/tools/PictureRenderingFlags.h
new file mode 100644
index 0000000000..6b6d249b24
--- /dev/null
+++ b/tools/PictureRenderingFlags.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef PICTURE_RENDERING_FLAGS
+#define PICTURE_RENDERING_FLAGS
+
+#include "SkString.h"
+
+namespace sk_tools {
+ class PictureRenderer;
+}
+
+enum PictureTool {
+ kBench_PictureTool,
+ kRender_PictureTool,
+};
+
+/**
+ * Uses SkFlags to parse the command line, and returns a PictureRenderer
+ * reflecting the flags used. Assumes that SkFlags::ParseCommandLine has
+ * been called.
+ * @param error If there is an error or warning, it will be stored in error.
+ * @param tool Which tool is being used.
+ * @return PictureRenderer A PictureRenderer with the settings specified
+ * on the command line, or NULL if the command line is invalid.
+ */
+sk_tools::PictureRenderer* parseRenderer(SkString& error, PictureTool tool);
+
+#endif // PICTURE_RENDERING_FLAGS
+
diff --git a/tools/SkFlags.cpp b/tools/SkFlags.cpp
new file mode 100644
index 0000000000..0c52269fab
--- /dev/null
+++ b/tools/SkFlags.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkFlags.h"
+
+SkFlagInfo* SkFlags::gHead;
+SkString SkFlags::gUsage;
+
+void SkFlags::SetUsage(const char* usage) {
+ gUsage.set(usage);
+}
+
+// Maximum line length for the help message.
+#define LINE_LENGTH 80
+
+void SkFlags::ParseCommandLine(int argc, char** argv) {
+ // Only allow calling this function once.
+ static bool gOnce;
+ if (gOnce) {
+ SkDebugf("ParseCommandLine should only be called once at the beginning"
+ " of main!\n");
+ SkASSERT(false);
+ return;
+ }
+ gOnce = true;
+
+ bool helpPrinted = false;
+ // Loop over argv, starting with 1, since the first is just the name of the program.
+ for (int i = 1; i < argc; i++) {
+ if (0 == strcmp("-h", argv[i]) || 0 == strcmp("--h", argv[i])
+ || 0 == strcmp("-help", argv[i]) || 0 == strcmp("--help", argv[i])) {
+ // Print help message.
+ SkDebugf("%s\n%s\n", argv[0], gUsage.c_str());
+ SkDebugf("Flags:\n");
+ SkFlagInfo* flag = SkFlags::gHead;
+ while (flag != NULL) {
+ SkDebugf("\t--%s:\ttype: %s\tdefault: %s\n", flag->name().c_str(),
+ flag->typeAsString().c_str(), flag->defaultValue().c_str());
+ const SkString& help = flag->help();
+ size_t length = help.size();
+ const char* currLine = help.c_str();
+ const char* stop = currLine + length;
+ while (currLine < stop) {
+ if (strlen(currLine) < LINE_LENGTH) {
+ // Only one line length's worth of text left.
+ SkDebugf("\t\t%s\n", currLine);
+ break;
+ }
+ int lineBreak = SkStrFind(currLine, "\n");
+ if (lineBreak < 0 || lineBreak > LINE_LENGTH) {
+ // No line break within line length. Will need to insert one.
+ // Find a space before the line break.
+ int spaceIndex = LINE_LENGTH - 1;
+ while (spaceIndex > 0 && currLine[spaceIndex] != ' ') {
+ spaceIndex--;
+ }
+ int gap;
+ if (0 == spaceIndex) {
+ // No spaces on the entire line. Go ahead and break mid word.
+ spaceIndex = LINE_LENGTH;
+ gap = 0;
+ } else {
+ // Skip the space on the next line
+ gap = 1;
+ }
+ SkDebugf("\t\t%.*s\n", spaceIndex, currLine);
+ currLine += spaceIndex + gap;
+ } else {
+ // the line break is within the limit. Break there.
+ lineBreak++;
+ SkDebugf("\t\t%.*s", lineBreak, currLine);
+ currLine += lineBreak;
+ }
+ }
+ SkDebugf("\n");
+ flag = flag->next();
+ }
+ helpPrinted = true;
+ }
+ if (!helpPrinted) {
+ bool flagMatched = false;
+ SkFlagInfo* flag = gHead;
+ while (flag != NULL) {
+ if (flag->match(argv[i])) {
+ flagMatched = true;
+ switch (flag->getFlagType()) {
+ case SkFlagInfo::kBool_FlagType:
+ // Handled by match, above
+ break;
+ case SkFlagInfo::kString_FlagType:
+ flag->resetStrings();
+ // Add all arguments until another flag is reached.
+ while (i+1 < argc && !SkStrStartsWith(argv[i+1], '-')) {
+ i++;
+ flag->append(argv[i]);
+ }
+ break;
+ case SkFlagInfo::kInt_FlagType:
+ i++;
+ flag->setInt(atoi(argv[i]));
+ break;
+ case SkFlagInfo::kDouble_FlagType:
+ i++;
+ flag->setDouble(atof(argv[i]));
+ break;
+ default:
+ SkASSERT(!"Invalid flag type");
+ }
+ break;
+ }
+ flag = flag->next();
+ }
+ if (!flagMatched) {
+ SkDebugf("skipping unknown flag %s\n", argv[i]);
+ }
+ }
+ }
+ // Since all of the flags have been set, release the memory used by each
+ // flag. FLAGS_x can still be used after this.
+ SkFlagInfo* flag = gHead;
+ gHead = NULL;
+ while (flag != NULL) {
+ SkFlagInfo* next = flag->next();
+ SkDELETE(flag);
+ flag = next;
+ }
+ if (helpPrinted) {
+ exit(0);
+ }
+}
+
diff --git a/tools/SkFlags.h b/tools/SkFlags.h
new file mode 100644
index 0000000000..f68a9c199f
--- /dev/null
+++ b/tools/SkFlags.h
@@ -0,0 +1,345 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SK_FLAGS_H
+#define SK_FLAGS_H
+
+#include "SkString.h"
+#include "SkTDArray.h"
+
+/**
+ * Including this file (and compiling SkFlags.cpp) provides command line
+ * parsing. In order to use it, use the following macros in global
+ * namespace:
+ *
+ * DEFINE_bool(name, defaultValue, helpString);
+ * DEFINE_string(name, defaultValue, helpString);
+ * DEFINE_int32(name, defaultValue, helpString);
+ * DEFINE_double(name, defaultValue, helpString);
+ *
+ * Then, in main, call SkFlags::SetUsage() to describe usage and call
+ * SkFlags::ParseCommandLine() to parse the flags. Henceforth, each flag can
+ * be referenced using
+ *
+ * FLAGS_name
+ *
+ * For example, the line
+ *
+ * DEFINE_bool(boolean, false, "The variable boolean does such and such");
+ *
+ * will create the following variable:
+ *
+ * bool FLAGS_boolean;
+ *
+ * which will initially be set to false, and can be set to true by using the
+ * flag "--boolean" on the commandline. "--noboolean" will set FLAGS_boolean
+ * to false. (Single dashes are also permitted for this and other flags.) The
+ * helpString will be printed if the help flag (-h or -help) is used.
+ *
+ * Similarly, the line
+ *
+ * DEFINE_int32(integer, .., ..);
+ *
+ * will create
+ *
+ * int32_t FLAGS_integer;
+ *
+ * and
+ *
+ * DEFINE_double(real, .., ..);
+ *
+ * will create
+ *
+ * double FLAGS_real;
+ *
+ * These flags can be set by specifying, for example, "--integer 7" and
+ * "--real 3.14" on the command line.
+ *
+ * Unlike the others, the line
+ *
+ * DEFINE_string(args, .., ..);
+ *
+ * creates an array:
+ *
+ * SkTDArray<const char*> FLAGS_args;
+ *
+ * If the default value is the empty string, FLAGS_args will default to a size
+ * of zero. Otherwise it will default to a size of 1 with the default string
+ * as its value. All strings that follow the flag on the command line (until
+ * a string that begins with '-') will be entries in the array.
+ *
+ * Any flag can be referenced from another file after using the following:
+ *
+ * DECLARE_x(name);
+ *
+ * (where 'x' is the type specified in the DEFINE).
+ *
+ * Inspired by gflags (https://code.google.com/p/gflags/). Is not quite as
+ * robust as gflags, but suits our purposes. For example, allows creating
+ * a flag -h or -help which will never be used, since SkFlags handles it.
+ * SkFlags will also allow creating --flag and --noflag. Uses the same input
+ * format as gflags and creates similarly named variables (i.e. FLAGS_name).
+ * Strings are handled differently (resulting variable will be an array of
+ * strings) so that a flag can be followed by multiple parameters.
+ */
+
+
+class SkFlagInfo;
+
+class SkFlags {
+
+public:
+ /**
+ * Call to set the help message to be displayed. Should be called before
+ * ParseCommandLine.
+ */
+ static void SetUsage(const char* usage);
+
+ /**
+ * Call at the beginning of main to parse flags created by DEFINE_x, above.
+ * Must only be called once.
+ */
+ static void ParseCommandLine(int argc, char** argv);
+
+private:
+ static SkFlagInfo* gHead;
+ static SkString gUsage;
+
+ // For access to gHead.
+ friend class SkFlagInfo;
+};
+
+#define TO_STRING2(s) #s
+#define TO_STRING(s) TO_STRING2(s)
+
+#define DEFINE_bool(name, defaultValue, helpString) \
+bool FLAGS_##name; \
+static bool unused_##name = SkFlagInfo::CreateBoolFlag(TO_STRING(name), \
+ &FLAGS_##name, \
+ defaultValue, \
+ helpString)
+
+#define DECLARE_bool(name) extern bool FLAGS_##name;
+
+#define DEFINE_string(name, defaultValue, helpString) \
+SkTDArray<const char*> FLAGS_##name; \
+static bool unused_##name = SkFlagInfo::CreateStringFlag(TO_STRING(name), \
+ &FLAGS_##name, \
+ defaultValue, \
+ helpString)
+
+#define DECLARE_string(name) extern SkTDArray<const char*> FLAGS_##name;
+
+#define DEFINE_int32(name, defaultValue, helpString) \
+int32_t FLAGS_##name; \
+static bool unused_##name = SkFlagInfo::CreateIntFlag(TO_STRING(name), \
+ &FLAGS_##name, \
+ defaultValue, \
+ helpString)
+
+#define DECLARE_int32(name) extern int32_t FLAGS_##name;
+
+#define DEFINE_double(name, defaultValue, helpString) \
+double FLAGS_##name; \
+static bool unused_##name = SkFlagInfo::CreateDoubleFlag(TO_STRING(name), \
+ &FLAGS_##name, \
+ defaultValue, \
+ helpString)
+
+#define DECLARE_double(name) extern double FLAGS_##name;
+
+class SkFlagInfo {
+
+public:
+ enum FlagTypes {
+ kBool_FlagType,
+ kString_FlagType,
+ kInt_FlagType,
+ kDouble_FlagType,
+ };
+
+ // Create flags of the desired type, and append to the list.
+ static bool CreateBoolFlag(const char* name, bool* pBool,
+ bool defaultValue, const char* helpString) {
+ SkFlagInfo* info = SkNEW_ARGS(SkFlagInfo, (name, kBool_FlagType, helpString));
+ info->fBoolValue = pBool;
+ *info->fBoolValue = info->fDefaultBool = defaultValue;
+ return true;
+ }
+
+ static bool CreateStringFlag(const char* name, SkTDArray<const char*>* pStrings,
+ const char* defaultValue, const char* helpString) {
+ SkFlagInfo* info = SkNEW_ARGS(SkFlagInfo, (name, kString_FlagType, helpString));
+ info->fDefaultString.set(defaultValue);
+
+ info->fStrings = pStrings;
+ info->fStrings->reset();
+ // If default is "", leave the array empty.
+ if (info->fDefaultString.size() > 0) {
+ info->fStrings->append(1, &defaultValue);
+ }
+ return true;
+ }
+
+ static bool CreateIntFlag(const char* name, int32_t* pInt,
+ int32_t defaultValue, const char* helpString) {
+ SkFlagInfo* info = SkNEW_ARGS(SkFlagInfo, (name, kInt_FlagType, helpString));
+ info->fIntValue = pInt;
+ *info->fIntValue = info->fDefaultInt = defaultValue;
+ return true;
+ }
+
+ static bool CreateDoubleFlag(const char* name, double* pDouble,
+ double defaultValue, const char* helpString) {
+ SkFlagInfo* info = SkNEW_ARGS(SkFlagInfo, (name, kDouble_FlagType, helpString));
+ info->fDoubleValue = pDouble;
+ *info->fDoubleValue = info->fDefaultDouble = defaultValue;
+ return true;
+ }
+
+ /**
+ * Returns true if the string matches this flag. For a bool, also sets the
+ * value, since a bool is specified as true or false by --name or --noname.
+ */
+ bool match(const char* string) {
+ if (SkStrStartsWith(string, '-')) {
+ string++;
+ // Allow one or two dashes
+ if (SkStrStartsWith(string, '-')) {
+ string++;
+ }
+ if (kBool_FlagType == fFlagType) {
+ // In this case, go ahead and set the value.
+ if (fName.equals(string)) {
+ *fBoolValue = true;
+ return true;
+ }
+ SkString noname(fName);
+ noname.prepend("no");
+ if (noname.equals(string)) {
+ *fBoolValue = false;
+ return true;
+ }
+ return false;
+ }
+ return fName.equals(string);
+ } else {
+ // Has no dash
+ return false;
+ }
+ return false;
+ }
+
+ FlagTypes getFlagType() const { return fFlagType; }
+
+ void resetStrings() {
+ if (kString_FlagType == fFlagType) {
+ fStrings->reset();
+ } else {
+ SkASSERT(!"Can only call resetStrings on kString_FlagType");
+ }
+ }
+
+ void append(const char* string) {
+ if (kString_FlagType == fFlagType) {
+ fStrings->append(1, &string);
+ } else {
+ SkASSERT(!"Can only append to kString_FlagType");
+ }
+ }
+
+ void setInt(int32_t value) {
+ if (kInt_FlagType == fFlagType) {
+ *fIntValue = value;
+ } else {
+ SkASSERT(!"Can only call setInt on kInt_FlagType");
+ }
+ }
+
+ void setDouble(double value) {
+ if (kDouble_FlagType == fFlagType) {
+ *fDoubleValue = value;
+ } else {
+ SkASSERT(!"Can only call setDouble on kDouble_FlagType");
+ }
+ }
+
+ SkFlagInfo* next() { return fNext; }
+
+ const SkString& name() const { return fName; }
+
+ const SkString& help() const { return fHelpString; }
+
+ SkString defaultValue() const {
+ SkString result;
+ switch (fFlagType) {
+ case SkFlagInfo::kBool_FlagType:
+ result.printf("%s", fDefaultBool ? "true" : "false");
+ break;
+ case SkFlagInfo::kString_FlagType:
+ return fDefaultString;
+ case SkFlagInfo::kInt_FlagType:
+ result.printf("%i", fDefaultInt);
+ break;
+ case SkFlagInfo::kDouble_FlagType:
+ result.printf("%2.2f", fDefaultDouble);
+ break;
+ default:
+ SkASSERT(!"Invalid flag type");
+ }
+ return result;
+ }
+
+ SkString typeAsString() const {
+ switch (fFlagType) {
+ case SkFlagInfo::kBool_FlagType:
+ return SkString("bool");
+ case SkFlagInfo::kString_FlagType:
+ return SkString("string");
+ case SkFlagInfo::kInt_FlagType:
+ return SkString("int");
+ case SkFlagInfo::kDouble_FlagType:
+ return SkString("double");
+ default:
+ SkASSERT(!"Invalid flag type");
+ return SkString();
+ }
+ }
+
+private:
+ SkFlagInfo(const char* name, FlagTypes type, const char* helpString)
+ : fName(name)
+ , fFlagType(type)
+ , fHelpString(helpString)
+ , fBoolValue(NULL)
+ , fDefaultBool(false)
+ , fIntValue(NULL)
+ , fDefaultInt(0)
+ , fDoubleValue(NULL)
+ , fDefaultDouble(0)
+ , fStrings(NULL) {
+ fNext = SkFlags::gHead;
+ SkFlags::gHead = this;
+ }
+ // Name of the flag, without initial dashes
+ SkString fName;
+ FlagTypes fFlagType;
+ SkString fHelpString;
+ bool* fBoolValue;
+ bool fDefaultBool;
+ int32_t* fIntValue;
+ int32_t fDefaultInt;
+ double* fDoubleValue;
+ double fDefaultDouble;
+ SkTDArray<const char*>* fStrings;
+ // Both for the help string and in case fStrings is empty.
+ SkString fDefaultString;
+
+ // In order to keep a linked list.
+ SkFlagInfo* fNext;
+};
+#endif // SK_FLAGS_H
diff --git a/tools/bench_pictures.cfg b/tools/bench_pictures.cfg
index f525ceb650..102c7448d4 100644
--- a/tools/bench_pictures.cfg
+++ b/tools/bench_pictures.cfg
@@ -103,10 +103,10 @@ def AndroidConfigList(tile_size, scale, cores, viewport, do_gpu=True):
# a dictionary of key/value pairs directly corresponding to the command-line
# flags passed to bench_pictures.
bench_pictures_cfg = {
- 'angle': [TiledConfig(DEFAULT_TILE_X, DEFAULT_TILE_Y, device='angle')],
+ 'angle': [TiledConfig(DEFAULT_TILE_X, DEFAULT_TILE_Y, config='angle')],
'debug': [TiledBitmapConfig(DEFAULT_TILE_X, DEFAULT_TILE_Y)],
'default': default_configs,
- 'no_gpu': [cfg for cfg in default_configs if cfg['device'] != 'gpu'],
+ 'no_gpu': [cfg for cfg in default_configs if cfg['config'] != 'gpu'],
'nexus_s': AndroidConfigList((256, 256), 0.4897, [], (480, 800),
do_gpu=False),
'xoom': AndroidConfigList((256, 256), 1.2244, [], (1200, 800)),
@@ -114,4 +114,4 @@ bench_pictures_cfg = {
'nexus_4': AndroidConfigList((256, 256), 0.7836, [], (768, 1280)),
'nexus_7': AndroidConfigList((256, 256), 1.3061, [2], (1280, 800)),
'nexus_10': AndroidConfigList((512, 512), 2.6122, [], (2560, 1600)),
-} \ No newline at end of file
+}
diff --git a/tools/bench_pictures_cfg_helper.py b/tools/bench_pictures_cfg_helper.py
index d67c93098b..07b1e1e5c7 100644
--- a/tools/bench_pictures_cfg_helper.py
+++ b/tools/bench_pictures_cfg_helper.py
@@ -20,11 +20,11 @@ def TileArgs(tile_x, tile_y):
def BitmapConfig(**kwargs):
- return Config(device='bitmap', **kwargs)
+ return Config(config='8888', **kwargs)
def GPUConfig(**kwargs):
- return Config(device='gpu', **kwargs)
+ return Config(config='gpu', **kwargs)
def TiledBitmapConfig(tile_x, tile_y, **kwargs):
diff --git a/tools/bench_pictures_main.cpp b/tools/bench_pictures_main.cpp
index 60d79fcd8c..ffcab74772 100644
--- a/tools/bench_pictures_main.cpp
+++ b/tools/bench_pictures_main.cpp
@@ -8,9 +8,11 @@
#include "BenchTimer.h"
#include "CopyTilesRenderer.h"
#include "PictureBenchmark.h"
+#include "PictureRenderingFlags.h"
#include "SkBenchLogger.h"
#include "SkBitmapFactory.h"
#include "SkCanvas.h"
+#include "SkFlags.h"
#include "SkGraphics.h"
#include "SkImageDecoder.h"
#include "SkMath.h"
@@ -20,7 +22,28 @@
#include "SkTArray.h"
#include "picture_utils.h"
-const int DEFAULT_REPEATS = 1;
+
+SkBenchLogger gLogger;
+
+// Flags used by this file, in alphabetical order.
+DECLARE_bool(deferImageDecoding);
+DEFINE_string(filter, "",
+ "type:flag : Enable canvas filtering to disable a paint flag, "
+ "use no blur or low quality blur, or use no hinting or "
+ "slight hinting. For all flags except AAClip, specify the "
+ "type of primitive to effect, or choose all. for AAClip "
+ "alone, the filter affects all clips independent of type. "
+ "Specific flags are listed above.");
+DEFINE_string(logFile, "", "Destination for writing log output, in addition to stdout.");
+DEFINE_bool(logPerIter, false, "Log each repeat timer instead of mean.");
+DEFINE_bool(min, false, "Print the minimum times (instead of average).");
+DECLARE_int32(multi);
+DECLARE_string(r);
+DEFINE_int32(repeat, 1, "Set the number of times to repeat each test.");
+DEFINE_bool(timeIndividualTiles, false, "Report times for drawing individual tiles, rather than "
+ "times for drawing the whole page. Requires tiled rendering.");
+DEFINE_string(timers, "", "[wcgWC]*: Display wall, cpu, gpu, truncated wall or truncated cpu time"
+ " for each picture.");
static char const * const gFilterTypes[] = {
"paint",
@@ -105,7 +128,7 @@ static SkString filterFlagsUsage() {
for (size_t index = 0; index < kFilterFlagsCount; ++index) {
result += gFilterFlags[index];
if (result.size() - len >= 72) {
- result += "\n ";
+ result += "\n\t\t";
len = result.size();
}
if (index < kFilterFlagsCount - 1) {
@@ -115,124 +138,6 @@ static SkString filterFlagsUsage() {
return result;
}
-static void usage(const char* argv0) {
- SkDebugf("SkPicture benchmarking tool\n");
- SkDebugf("\n"
-"Usage: \n"
-" %s <inputDir>...\n"
-" [--logFile filename][--timers [wcgWC]*][--logPerIter 1|0][--min]\n"
-" [--repeat][--timeIndividualTiles] \n"
-" [--mode pow2tile minWidth height | record | simple\n"
-" | tile width height | playbackCreation]\n"
-" [--pipe]\n"
-" [--bbh bbhType]\n"
-" [--multi numThreads]\n"
-" [--enable-deferred-image-decoding]\n"
-" [--viewport width height][--scale sf]\n"
-" [--device bitmap"
-#if SK_SUPPORT_GPU
-" | gpu"
-#if SK_ANGLE
-" | angle"
-#endif
-#endif
-"]\n"
-" [--filter [%s]:\n [%s]]\n"
-, argv0, filterTypesUsage().c_str(), filterFlagsUsage().c_str());
- SkDebugf("\n");
- SkDebugf(
-" inputDir: A list of directories and files to use as input. Files are\n"
-" expected to have the .skp extension.\n\n"
-" --logFile filename : destination for writing log output, in addition to stdout.\n");
- SkDebugf(" --logPerIter 1|0 : "
- "Log each repeat timer instead of mean, default is disabled.\n");
- SkDebugf(" --min : Print the minimum times (instead of average).\n");
- SkDebugf(" --timers [wcgWC]* : "
- "Display wall, cpu, gpu, truncated wall or truncated cpu time for each picture.\n");
- SkDebugf(" --timeIndividualTiles : Report times for drawing individual tiles, rather than\n"
-" times for drawing the whole page.\n"
-" Requires --mode tile\n");
- SkDebugf(
-" --mode pow2tile minWidth height | copyTile width height | record | simple\n"
-" | tile width height | playbackCreation:\n"
-" Run in the corresponding mode.\n"
-" Default is simple.\n");
- SkDebugf(
-" pow2tile minWidth height, Creates tiles with widths\n"
-" that are all a power of two\n"
-" such that they minimize the\n"
-" amount of wasted tile space.\n"
-" minWidth is the minimum width\n"
-" of these tiles and must be a\n"
-" power of two. Simple\n"
-" rendering using these tiles\n"
-" is benchmarked.\n");
- SkDebugf(
-" record, Benchmark picture to picture recording.\n");
- SkDebugf(
-" simple, Benchmark a simple rendering.\n");
- SkDebugf(
-" tile width height, Benchmark simple rendering using\n"
-" tiles with the given dimensions.\n"
-" copyTile width height, Draw the picture, then copy it into tiles.\n"
-" Does not support percentages.\n"
-" If the picture is large enough, breaks it into\n"
-" larger tiles (and draws the picture once per\n"
-" larger tile) to avoid creating a large canvas.\n"
-" Add --tiles x y to specify the number of tiles\n"
-" per larger tile in the x and y direction.\n"
- );
- SkDebugf(
-" playbackCreation, Benchmark creation of the SkPicturePlayback.\n");
- SkDebugf("\n");
- SkDebugf(
-" --multi numThreads : Set the number of threads for multi threaded drawing. Must be greater\n"
-" than 1. Only works with tiled rendering.\n"
-" --enable-deferred-image-decoding : Defer decoding until drawing images. Has no effect if\n"
-" the provided skp does not have its images encoded.\n"
-" --viewport width height : Set the viewport.\n"
-" --scale sf : Scale drawing by sf.\n"
-" --pipe: Benchmark SkGPipe rendering. Currently incompatible with \"mode\".\n");
- SkDebugf(
-" --bbh bbhType [width height]: Set the bounding box hierarchy type to\n"
-" be used. Accepted values are: none, rtree, grid. Default\n"
-" value is none. Not compatible with --pipe. With value\n"
-" 'grid', width and height must be specified. 'grid' can\n"
-" only be used with modes tile, record, and\n"
-" playbackCreation.");
- SkDebugf(
-" --device bitmap"
-#if SK_SUPPORT_GPU
-" | gpu"
-#endif
-": Use the corresponding device. Default is bitmap.\n");
- SkDebugf(
-" bitmap, Render to a bitmap.\n");
-#if SK_SUPPORT_GPU
- SkDebugf(
-" gpu, Render to the GPU.\n");
-#if SK_ANGLE
- SkDebugf(
-" angle, Render using Angle.\n");
-#endif
-#endif
- SkDebugf("\n");
- SkDebugf(
-" --repeat: "
-"Set the number of times to repeat each test."
-" Default is %i.\n", DEFAULT_REPEATS);
- SkDebugf(
-" --filter type:flag : Enable canvas filtering to disable a paint flag,\n"
-" use no blur or low quality blur, or use no hinting or\n"
-" slight hinting. For all flags except AAClip, specify the\n"
-" type of primitive to effect, or choose all. for AAClip\n"
-" alone, the filter affects all clips independent of type.\n");
-}
-
-SkBenchLogger gLogger;
-
-bool lazy_decode = false;
-
#include "SkData.h"
#include "SkLruImageCache.h"
@@ -261,7 +166,7 @@ static bool run_single_benchmark(const SkString& inputPath,
bool success = false;
SkPicture* picture;
- if (lazy_decode) {
+ if (FLAGS_deferImageDecoding) {
picture = SkNEW_ARGS(SkPicture, (&inputStream, &success, &lazy_decode_bitmap));
} else {
picture = SkNEW_ARGS(SkPicture, (&inputStream, &success, &SkImageDecoder::DecodeMemory));
@@ -287,539 +192,156 @@ static bool run_single_benchmark(const SkString& inputPath,
return true;
}
-#define PRINT_USAGE_AND_EXIT \
- do { \
- usage(argv0); \
- exit(-1); \
- } while (0)
-
-static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>* inputs,
- sk_tools::PictureBenchmark* benchmark) {
- const char* argv0 = argv[0];
- char* const* stop = argv + argc;
-
- int repeats = DEFAULT_REPEATS;
- sk_tools::PictureRenderer::SkDeviceTypes deviceType =
- sk_tools::PictureRenderer::kBitmap_DeviceType;
-
- SkAutoTUnref<sk_tools::PictureRenderer> renderer(NULL);
-
- // Create a string to show our current settings.
- // TODO: Make it prettier. Currently it just repeats the command line.
- SkString commandLine("bench_pictures:");
- for (int i = 1; i < argc; i++) {
- commandLine.appendf(" %s", *(argv+i));
- }
- commandLine.append("\n");
-
- bool usePipe = false;
- int numThreads = 1;
- bool useTiles = false;
- const char* widthString = NULL;
- const char* heightString = NULL;
- int gridWidth = 0;
- int gridHeight = 0;
- bool isPowerOf2Mode = false;
- bool isCopyMode = false;
- const char* xTilesString = NULL;
- const char* yTilesString = NULL;
- const char* mode = NULL;
- bool gridSupported = false;
- sk_tools::PictureRenderer::BBoxHierarchyType bbhType =
- sk_tools::PictureRenderer::kNone_BBoxHierarchyType;
+static void setup_benchmark(sk_tools::PictureBenchmark* benchmark) {
sk_tools::PictureRenderer::DrawFilterFlags drawFilters[SkDrawFilter::kTypeCount];
sk_bzero(drawFilters, sizeof(drawFilters));
- SkISize viewport;
- viewport.setEmpty();
- SkScalar scaleFactor = SK_Scalar1;
- for (++argv; argv < stop; ++argv) {
- if (0 == strcmp(*argv, "--repeat")) {
- ++argv;
- if (argv < stop) {
- repeats = atoi(*argv);
- if (repeats < 1) {
- gLogger.logError("--repeat must be given a value > 0\n");
- PRINT_USAGE_AND_EXIT;
- }
- } else {
- gLogger.logError("Missing arg for --repeat\n");
- PRINT_USAGE_AND_EXIT;
- }
- } else if (0 == strcmp(*argv, "--pipe")) {
- usePipe = true;
- } else if (0 == strcmp(*argv, "--logFile")) {
- argv++;
- if (argv < stop) {
- if (!gLogger.SetLogFile(*argv)) {
- SkString str;
- str.printf("Could not open %s for writing.", *argv);
- gLogger.logError(str);
- usage(argv0);
- // TODO(borenet): We're disabling this for now, due to
- // write-protected Android devices. The very short-term
- // solution is to ignore the fact that we have no log file.
- //exit(-1);
+
+ if (FLAGS_filter.count() > 0) {
+ const char* filters = FLAGS_filter[0];
+ const char* colon = strchr(filters, ':');
+ if (colon) {
+ int type = -1;
+ size_t typeLen = colon - filters;
+ for (size_t tIndex = 0; tIndex < kFilterTypesCount; ++tIndex) {
+ if (typeLen == strlen(gFilterTypes[tIndex])
+ && !strncmp(filters, gFilterTypes[tIndex], typeLen)) {
+ type = tIndex;
+ break;
}
- } else {
- gLogger.logError("Missing arg for --logFile\n");
- PRINT_USAGE_AND_EXIT;
- }
- } else if (0 == strcmp(*argv, "--multi")) {
- ++argv;
- if (argv >= stop) {
- gLogger.logError("Missing arg for --multi\n");
- PRINT_USAGE_AND_EXIT;
- }
- numThreads = atoi(*argv);
- if (numThreads < 2) {
- gLogger.logError("Number of threads must be at least 2.\n");
- PRINT_USAGE_AND_EXIT;
- }
- } else if (0 == strcmp(*argv, "--bbh")) {
- ++argv;
- if (argv >= stop) {
- gLogger.logError("Missing value for --bbh\n");
- PRINT_USAGE_AND_EXIT;
}
- if (0 == strcmp(*argv, "none")) {
- bbhType = sk_tools::PictureRenderer::kNone_BBoxHierarchyType;
- } else if (0 == strcmp(*argv, "rtree")) {
- bbhType = sk_tools::PictureRenderer::kRTree_BBoxHierarchyType;
- } else if (0 == strcmp(*argv, "grid")) {
- bbhType = sk_tools::PictureRenderer::kTileGrid_BBoxHierarchyType;
- ++argv;
- if (argv >= stop) {
- gLogger.logError("Missing width for --bbh grid\n");
- PRINT_USAGE_AND_EXIT;
- }
- gridWidth = atoi(*argv);
- ++argv;
- if (argv >= stop) {
- gLogger.logError("Missing height for --bbh grid\n");
- PRINT_USAGE_AND_EXIT;
- }
- gridHeight = atoi(*argv);
- } else {
+ if (type < 0) {
SkString err;
- err.printf("%s is not a valid value for --bbhType\n", *argv);
+ err.printf("Unknown type for --filter %s\n", filters);
gLogger.logError(err);
- PRINT_USAGE_AND_EXIT;
- }
-
- } else if (0 == strcmp(*argv, "--mode")) {
- if (renderer.get() != NULL) {
- SkDebugf("Cannot combine modes.\n");
- PRINT_USAGE_AND_EXIT;
- }
-
- ++argv;
- if (argv >= stop) {
- gLogger.logError("Missing mode for --mode\n");
- PRINT_USAGE_AND_EXIT;
- }
-
- if (0 == strcmp(*argv, "record")) {
- renderer.reset(SkNEW(sk_tools::RecordPictureRenderer));
- gridSupported = true;
- } else if (0 == strcmp(*argv, "clone")) {
- renderer.reset(sk_tools::CreatePictureCloneRenderer());
- } else if (0 == strcmp(*argv, "simple")) {
- renderer.reset(SkNEW(sk_tools::SimplePictureRenderer));
- } else if ((0 == strcmp(*argv, "tile")) || (0 == strcmp(*argv, "pow2tile"))
- || 0 == strcmp(*argv, "copyTile")) {
- useTiles = true;
- mode = *argv;
-
- if (0 == strcmp(*argv, "pow2tile")) {
- isPowerOf2Mode = true;
- } else if (0 == strcmp(*argv, "copyTile")) {
- isCopyMode = true;
- } else {
- gridSupported = true;
- }
-
- ++argv;
- if (argv >= stop) {
- SkString err;
- err.printf("Missing width for --mode %s\n", mode);
- gLogger.logError(err);
- PRINT_USAGE_AND_EXIT;
- }
-
- widthString = *argv;
- ++argv;
- if (argv >= stop) {
- SkString err;
- err.appendf("Missing height for --mode %s\n", mode);
- gLogger.logError(err);
- PRINT_USAGE_AND_EXIT;
+ exit(-1);
+ }
+ int flag = -1;
+ size_t flagLen = strlen(filters) - typeLen - 1;
+ for (size_t fIndex = 0; fIndex < kFilterFlagsCount; ++fIndex) {
+ if (flagLen == strlen(gFilterFlags[fIndex])
+ && !strncmp(colon + 1, gFilterFlags[fIndex], flagLen)) {
+ flag = 1 << fIndex;
+ break;
}
- heightString = *argv;
- } else if (0 == strcmp(*argv, "playbackCreation")) {
- renderer.reset(SkNEW(sk_tools::PlaybackCreationRenderer));
- gridSupported = true;
- } else if (0 == strcmp(*argv, "gatherPixelRefs")) {
- renderer.reset(sk_tools::CreateGatherPixelRefsRenderer());
- } else {
- SkString err;
- err.printf("%s is not a valid mode for --mode\n", *argv);
- gLogger.logError(err);
- PRINT_USAGE_AND_EXIT;
- }
- } else if (0 == strcmp(*argv, "--viewport")) {
- ++argv;
- if (argv >= stop) {
- gLogger.logError("Missing width for --viewport\n");
- PRINT_USAGE_AND_EXIT;
- }
- viewport.fWidth = atoi(*argv);
- ++argv;
- if (argv >= stop) {
- gLogger.logError("Missing height for --viewport\n");
- PRINT_USAGE_AND_EXIT;
}
- viewport.fHeight = atoi(*argv);
- } else if (0 == strcmp(*argv, "--scale")) {
- ++argv;
- if (argv >= stop) {
- gLogger.logError("Missing scaleFactor for --scale\n");
- PRINT_USAGE_AND_EXIT;
- }
- scaleFactor = SkDoubleToScalar(atof(*argv));
- } else if (0 == strcmp(*argv, "--tiles")) {
- ++argv;
- if (argv >= stop) {
- gLogger.logError("Missing x for --tiles\n");
- PRINT_USAGE_AND_EXIT;
- }
- xTilesString = *argv;
- ++argv;
- if (argv >= stop) {
- gLogger.logError("Missing y for --tiles\n");
- PRINT_USAGE_AND_EXIT;
- }
- yTilesString = *argv;
- } else if (0 == strcmp(*argv, "--device")) {
- ++argv;
- if (argv >= stop) {
- gLogger.logError("Missing mode for --device\n");
- PRINT_USAGE_AND_EXIT;
- }
-
- if (0 == strcmp(*argv, "bitmap")) {
- deviceType = sk_tools::PictureRenderer::kBitmap_DeviceType;
- }
-#if SK_SUPPORT_GPU
- else if (0 == strcmp(*argv, "gpu")) {
- deviceType = sk_tools::PictureRenderer::kGPU_DeviceType;
- }
-#endif
-#if SK_ANGLE
- else if (0 == strcmp(*argv, "angle")) {
- deviceType = sk_tools::PictureRenderer::kAngle_DeviceType;
- }
-#endif
- else {
+ if (flag < 0) {
SkString err;
- err.printf("%s is not a valid mode for --device\n", *argv);
+ err.printf("Unknown flag for --filter %s\n", filters);
gLogger.logError(err);
- PRINT_USAGE_AND_EXIT;
+ exit(-1);
}
- } else if (0 == strcmp(*argv, "--timers")) {
- ++argv;
- if (argv < stop) {
- bool timerWall = false;
- bool truncatedTimerWall = false;
- bool timerCpu = false;
- bool truncatedTimerCpu = false;
- bool timerGpu = false;
- for (char* t = *argv; *t; ++t) {
- switch (*t) {
- case 'w':
- timerWall = true;
- break;
- case 'c':
- timerCpu = true;
- break;
- case 'W':
- truncatedTimerWall = true;
- break;
- case 'C':
- truncatedTimerCpu = true;
- break;
- case 'g':
- timerGpu = true;
- break;
- default: {
- break;
- }
- }
+ for (int index = 0; index < SkDrawFilter::kTypeCount; ++index) {
+ if (type != SkDrawFilter::kTypeCount && index != type) {
+ continue;
}
- benchmark->setTimersToShow(timerWall, truncatedTimerWall, timerCpu,
- truncatedTimerCpu, timerGpu);
- } else {
- gLogger.logError("Missing arg for --timers\n");
- PRINT_USAGE_AND_EXIT;
- }
- } else if (0 == strcmp(*argv, "--timeIndividualTiles")) {
- benchmark->setTimeIndividualTiles(true);
- } else if (0 == strcmp(*argv, "--min")) {
- benchmark->setPrintMin(true);
- } else if (0 == strcmp(*argv, "--enable-deferred-image-decoding")) {
- lazy_decode = true;
- } else if (0 == strcmp(*argv, "--logPerIter")) {
- ++argv;
- if (argv < stop) {
- bool log = atoi(*argv) != 0;
- benchmark->setLogPerIter(log);
- } else {
- gLogger.logError("Missing arg for --logPerIter\n");
- PRINT_USAGE_AND_EXIT;
+ drawFilters[index] = (sk_tools::PictureRenderer::DrawFilterFlags)
+ (drawFilters[index] | flag);
}
- } else if (0 == strcmp(*argv, "--filter")) {
- ++argv;
- if (argv < stop) {
- const char* colon = strchr(*argv, ':');
- if (colon) {
- int type = -1;
- size_t typeLen = colon - *argv;
- for (size_t tIndex = 0; tIndex < kFilterTypesCount; ++tIndex) {
- if (typeLen == strlen(gFilterTypes[tIndex])
- && !strncmp(*argv, gFilterTypes[tIndex], typeLen)) {
- type = tIndex;
- break;
- }
- }
- if (type < 0) {
- SkString err;
- err.printf("Unknown type for --filter %s\n", *argv);
- gLogger.logError(err);
- PRINT_USAGE_AND_EXIT;
- }
- int flag = -1;
- size_t flagLen = strlen(*argv) - typeLen - 1;
- for (size_t fIndex = 0; fIndex < kFilterFlagsCount; ++fIndex) {
- if (flagLen == strlen(gFilterFlags[fIndex])
- && !strncmp(colon + 1, gFilterFlags[fIndex], flagLen)) {
- flag = 1 << fIndex;
- break;
- }
- }
- if (flag < 0) {
- SkString err;
- err.printf("Unknown flag for --filter %s\n", *argv);
- gLogger.logError(err);
- PRINT_USAGE_AND_EXIT;
- }
- for (int index = 0; index < SkDrawFilter::kTypeCount; ++index) {
- if (type != SkDrawFilter::kTypeCount && index != type) {
- continue;
- }
- drawFilters[index] = (sk_tools::PictureRenderer::DrawFilterFlags)
- (drawFilters[index] | flag);
- }
- } else {
- SkString err;
- err.printf("Unknown arg for --filter %s : missing colon\n", *argv);
- gLogger.logError(err);
- PRINT_USAGE_AND_EXIT;
- }
- } else {
- gLogger.logError("Missing arg for --filter\n");
- PRINT_USAGE_AND_EXIT;
- }
- } else if (0 == strcmp(*argv, "--help") || 0 == strcmp(*argv, "-h")) {
- PRINT_USAGE_AND_EXIT;
} else {
- inputs->push_back(SkString(*argv));
+ SkString err;
+ err.printf("Unknown arg for --filter %s : missing colon\n", filters);
+ gLogger.logError(err);
+ exit(-1);
}
}
- if (numThreads > 1 && !useTiles) {
- gLogger.logError("Multithreaded drawing requires tiled rendering.\n");
- PRINT_USAGE_AND_EXIT;
+ if (FLAGS_timers.count() > 0) {
+ size_t index = 0;
+ bool timerWall = false;
+ bool truncatedTimerWall = false;
+ bool timerCpu = false;
+ bool truncatedTimerCpu = false;
+ bool timerGpu = false;
+ while (index < strlen(FLAGS_timers[0])) {
+ switch (FLAGS_timers[0][index]) {
+ case 'w':
+ timerWall = true;
+ break;
+ case 'c':
+ timerCpu = true;
+ break;
+ case 'W':
+ truncatedTimerWall = true;
+ break;
+ case 'C':
+ truncatedTimerCpu = true;
+ break;
+ case 'g':
+ timerGpu = true;
+ break;
+ default:
+ SkDebugf("mystery character\n");
+ break;
+ }
+ index++;
+ }
+ benchmark->setTimersToShow(timerWall, truncatedTimerWall, timerCpu, truncatedTimerCpu,
+ timerGpu);
}
- if (usePipe && sk_tools::PictureRenderer::kNone_BBoxHierarchyType != bbhType) {
- gLogger.logError("--pipe and --bbh cannot be used together\n");
- PRINT_USAGE_AND_EXIT;
+ SkString errorString;
+ SkAutoTUnref<sk_tools::PictureRenderer> renderer(parseRenderer(errorString,
+ kBench_PictureTool));
+
+ if (errorString.size() > 0) {
+ gLogger.logError(errorString);
}
- if (sk_tools::PictureRenderer::kTileGrid_BBoxHierarchyType == bbhType &&
- !gridSupported) {
- gLogger.logError("'--bbh grid' is not compatible with specified --mode.\n");
- PRINT_USAGE_AND_EXIT;
+ if (NULL == renderer.get()) {
+ exit(-1);
}
- if (useTiles) {
- SkASSERT(NULL == renderer);
- sk_tools::TiledPictureRenderer* tiledRenderer;
- if (isCopyMode) {
- int x, y;
- if (xTilesString != NULL) {
- SkASSERT(yTilesString != NULL);
- x = atoi(xTilesString);
- y = atoi(yTilesString);
- if (x <= 0 || y <= 0) {
- gLogger.logError("--tiles must be given values > 0\n");
- PRINT_USAGE_AND_EXIT;
- }
- } else {
- x = y = 4;
- }
- tiledRenderer = SkNEW_ARGS(sk_tools::CopyTilesRenderer, (x, y));
- if (benchmark->timeIndividualTiles()) {
- gLogger.logError("timeIndividualTiles is not compatible with copyTile\n");
- PRINT_USAGE_AND_EXIT;
- }
- } else if (numThreads > 1) {
- tiledRenderer = SkNEW_ARGS(sk_tools::MultiCorePictureRenderer, (numThreads));
- } else {
- tiledRenderer = SkNEW(sk_tools::TiledPictureRenderer);
+ if (FLAGS_timeIndividualTiles) {
+ if (FLAGS_multi > 1) {
+ gLogger.logError("Cannot time individual tiles with more than one thread.\n");
+ exit(-1);
}
- if (isPowerOf2Mode) {
- int minWidth = atoi(widthString);
- if (!SkIsPow2(minWidth) || minWidth < 0) {
- tiledRenderer->unref();
- SkString err;
- err.printf("-mode %s must be given a width"
- " value that is a power of two\n", mode);
- gLogger.logError(err);
- PRINT_USAGE_AND_EXIT;
- }
- tiledRenderer->setTileMinPowerOf2Width(minWidth);
- } else if (sk_tools::is_percentage(widthString)) {
- if (isCopyMode) {
- tiledRenderer->unref();
- SkString err;
- err.printf("--mode %s does not support percentages.\n", mode);
- gLogger.logError(err.c_str());
- PRINT_USAGE_AND_EXIT;
- }
- tiledRenderer->setTileWidthPercentage(atof(widthString));
- if (!(tiledRenderer->getTileWidthPercentage() > 0)) {
- tiledRenderer->unref();
- SkString err;
- err.appendf("--mode %s must be given a width percentage > 0\n", mode);
- gLogger.logError(err);
- PRINT_USAGE_AND_EXIT;
- }
- } else {
- tiledRenderer->setTileWidth(atoi(widthString));
- if (!(tiledRenderer->getTileWidth() > 0)) {
- tiledRenderer->unref();
- SkString err;
- err.appendf("--mode %s must be given a width > 0\n", mode);
- gLogger.logError(err);
- PRINT_USAGE_AND_EXIT;
- }
+ sk_tools::TiledPictureRenderer* tiledRenderer = renderer->getTiledRenderer();
+ if (NULL == tiledRenderer) {
+ gLogger.logError("--timeIndividualTiles requires tiled rendering.\n");
+ exit(-1);
}
-
- if (sk_tools::is_percentage(heightString)) {
- if (isCopyMode) {
- tiledRenderer->unref();
- SkString err;
- err.printf("--mode %s does not support percentages.\n", mode);
- gLogger.logError(err.c_str());
- PRINT_USAGE_AND_EXIT;
- }
- tiledRenderer->setTileHeightPercentage(atof(heightString));
- if (!(tiledRenderer->getTileHeightPercentage() > 0)) {
- tiledRenderer->unref();
- SkString err;
- err.appendf("--mode %s must be given a height percentage > 0\n", mode);
- gLogger.logError(err);
- PRINT_USAGE_AND_EXIT;
- }
- } else {
- tiledRenderer->setTileHeight(atoi(heightString));
- if (!(tiledRenderer->getTileHeight() > 0)) {
- tiledRenderer->unref();
- SkString err;
- err.appendf("--mode %s must be given a height > 0\n", mode);
- gLogger.logError(err);
- PRINT_USAGE_AND_EXIT;
- }
- }
- if (numThreads > 1) {
- switch (deviceType) {
-#if SK_SUPPORT_GPU
- case sk_tools::PictureRenderer::kGPU_DeviceType:
- // fall through
-#endif
-#if SK_ANGLE
- case sk_tools::PictureRenderer::kAngle_DeviceType:
-#endif
- tiledRenderer->unref();
- gLogger.logError("GPU not compatible with multithreaded tiling.\n");
- PRINT_USAGE_AND_EXIT;
- break;
- default:
- break;
- }
+ if (!tiledRenderer->supportsTimingIndividualTiles()) {
+ gLogger.logError("This renderer does not support --timeIndividualTiles.\n");
+ exit(-1);
}
- renderer.reset(tiledRenderer);
- if (usePipe) {
- gLogger.logError("Pipe rendering is currently not compatible with tiling.\n"
- "Turning off pipe.\n");
- }
- } else {
- if (benchmark->timeIndividualTiles()) {
- gLogger.logError("timeIndividualTiles requires tiled rendering.\n");
- PRINT_USAGE_AND_EXIT;
- }
- if (usePipe) {
- if (renderer.get() != NULL) {
- gLogger.logError("Pipe is incompatible with other modes.\n");
- PRINT_USAGE_AND_EXIT;
- }
- renderer.reset(SkNEW(sk_tools::PipePictureRenderer));
- }
- }
- if (inputs->count() < 1) {
- PRINT_USAGE_AND_EXIT;
+ benchmark->setTimeIndividualTiles(true);
}
- if (NULL == renderer) {
- renderer.reset(SkNEW(sk_tools::SimplePictureRenderer));
+ if (FLAGS_r.count() < 1) {
+ gLogger.logError(".skp files or directories are required.\n");
+ exit(-1);
}
- renderer->setBBoxHierarchyType(bbhType);
renderer->setDrawFilters(drawFilters, filtersName(drawFilters));
- renderer->setGridSize(gridWidth, gridHeight);
- renderer->setViewport(viewport);
- renderer->setScaleFactor(scaleFactor);
- if (!renderer->setDeviceType(deviceType)) {
- gLogger.logError("Invalid deviceType.\n");
- PRINT_USAGE_AND_EXIT;
- }
+ benchmark->setPrintMin(FLAGS_min);
+ benchmark->setLogPerIter(FLAGS_logPerIter);
benchmark->setRenderer(renderer);
- benchmark->setRepeats(repeats);
+ benchmark->setRepeats(FLAGS_repeat);
benchmark->setLogger(&gLogger);
- // Report current settings:
- gLogger.logProgress(commandLine);
}
-static int process_input(const SkString& input,
+static int process_input(const char* input,
sk_tools::PictureBenchmark& benchmark) {
- SkOSFile::Iter iter(input.c_str(), "skp");
+ SkString inputAsSkString(input);
+ SkOSFile::Iter iter(input, "skp");
SkString inputFilename;
int failures = 0;
if (iter.next(&inputFilename)) {
do {
SkString inputPath;
- sk_tools::make_filepath(&inputPath, input, inputFilename);
+ sk_tools::make_filepath(&inputPath, inputAsSkString, inputFilename);
if (!run_single_benchmark(inputPath, benchmark)) {
++failures;
}
} while(iter.next(&inputFilename));
- } else if (SkStrEndsWith(input.c_str(), ".skp")) {
- if (!run_single_benchmark(input, benchmark)) {
+ } else if (SkStrEndsWith(input, ".skp")) {
+ if (!run_single_benchmark(inputAsSkString, benchmark)) {
++failures;
}
} else {
SkString warning;
- warning.printf("Warning: skipping %s\n", input.c_str());
+ warning.printf("Warning: skipping %s\n", input);
gLogger.logError(warning);
}
return failures;
@@ -827,19 +349,45 @@ static int process_input(const SkString& input,
int tool_main(int argc, char** argv);
int tool_main(int argc, char** argv) {
+ SkString usage;
+ usage.printf("Time drawing .skp files.\n"
+ "\tPossible arguments for --filter: [%s]\n\t\t[%s]",
+ filterTypesUsage().c_str(), filterFlagsUsage().c_str());
+ SkFlags::SetUsage(usage.c_str());
+ SkFlags::ParseCommandLine(argc, argv);
+
+ if (FLAGS_repeat < 1) {
+ SkString error;
+ error.printf("--repeats must be >= 1. Was %i\n", FLAGS_repeat);
+ gLogger.logError(error);
+ exit(-1);
+ }
+
+ if (FLAGS_logFile.count() == 1) {
+ if (!gLogger.SetLogFile(FLAGS_logFile[0])) {
+ SkString str;
+ str.printf("Could not open %s for writing.\n", FLAGS_logFile[0]);
+ gLogger.logError(str);
+ // TODO(borenet): We're disabling this for now, due to
+ // write-protected Android devices. The very short-term
+ // solution is to ignore the fact that we have no log file.
+ //exit(-1);
+ }
+ }
+
+
#if SK_ENABLE_INST_COUNT
gPrintInstCount = true;
#endif
SkAutoGraphics ag;
- SkTArray<SkString> inputs;
sk_tools::PictureBenchmark benchmark;
- parse_commandline(argc, argv, &inputs, &benchmark);
+ setup_benchmark(&benchmark);
int failures = 0;
- for (int i = 0; i < inputs.count(); ++i) {
- failures += process_input(inputs[i], benchmark);
+ for (int i = 0; i < FLAGS_r.count(); ++i) {
+ failures += process_input(FLAGS_r[i], benchmark);
}
if (failures != 0) {
diff --git a/tools/render_pictures_main.cpp b/tools/render_pictures_main.cpp
index 146b04552f..5d64e74bb0 100644
--- a/tools/render_pictures_main.cpp
+++ b/tools/render_pictures_main.cpp
@@ -10,6 +10,7 @@
#include "SkBitmapFactory.h"
#include "SkCanvas.h"
#include "SkDevice.h"
+#include "SkFlags.h"
#include "SkGraphics.h"
#include "SkImageDecoder.h"
#include "SkImageEncoder.h"
@@ -20,109 +21,21 @@
#include "SkString.h"
#include "SkTArray.h"
#include "PictureRenderer.h"
+#include "PictureRenderingFlags.h"
#include "picture_utils.h"
-static void usage(const char* argv0) {
- SkDebugf("SkPicture rendering tool\n");
- SkDebugf("\n"
-"Usage: \n"
-" %s <input>... \n"
-" [-w <outputDir>]\n"
-" [--mode pow2tile minWidth height | copyTile width height | simple\n"
-" | tile width height]\n"
-" [--pipe]\n"
-" [--bbh bbhType]\n"
-" [--multi count]\n"
-" [--validate [--maxComponentDiff n]]\n"
-" [--writeWholeImage]\n"
-" [--clone n]\n"
-" [--enable-deferred-image-decoding]\n"
-" [--viewport width height][--scale sf]\n"
-" [--device bitmap"
-#if SK_SUPPORT_GPU
-" | gpu"
-#endif
-#if SK_ANGLE
-" | angle"
-#endif
-"]"
-, argv0);
- SkDebugf("\n\n");
- SkDebugf(
-" input: A list of directories and files to use as input. Files are\n"
-" expected to have the .skp extension.\n\n");
- SkDebugf(
-" outputDir: directory to write the rendered images.\n\n");
- SkDebugf(
-" --mode pow2tile minWidth height | copyTile width height | simple\n"
-" | tile width height | rerecord: Run in the corresponding mode.\n"
-" Default is simple.\n");
- SkDebugf(
-" pow2tile minWidth height, Creates tiles with widths\n"
-" that are all a power of two\n"
-" such that they minimize the\n"
-" amount of wasted tile space.\n"
-" minWidth is the minimum width\n"
-" of these tiles and must be a\n"
-" power of two. A simple render\n"
-" is done with these tiles.\n");
- SkDebugf(
-" simple, Render using the default rendering method.\n"
-" rerecord, Record the picture as a new skp, with the bitmaps PNG encoded.\n"
- );
- SkDebugf(
-" tile width height, Do a simple render using tiles\n"
-" with the given dimensions.\n"
-" copyTile width height, Draw the picture, then copy it into tiles.\n"
-" Does not support percentages.\n"
-" If the picture is large enough, breaks it into\n"
-" larger tiles (and draws the picture once per\n"
-" larger tile) to avoid creating a large canvas.\n"
-" Add --tiles x y to specify the number of tiles\n"
-" per larger tile in the x and y direction.\n"
- );
- SkDebugf("\n");
- SkDebugf(
-" --multi count : Set the number of threads for multi threaded drawing. Must be greater\n"
-" than 1. Only works with tiled rendering.\n"
-" --enable-deferred-image-decoding : Defer decoding until drawing images. Has no effect if\n"
-" the provided skp does not have its images encoded.\n"
-" --viewport width height : Set the viewport.\n"
-" --scale sf : Scale drawing by sf.\n"
-" --pipe: Benchmark SkGPipe rendering. Currently incompatible with \"mode\".\n");
- SkDebugf(
-" --validate: Verify that the rendered image contains the same pixels as "
-"the picture rendered in simple mode.\n"
-" --maxComponentDiff: maximum diff on a component. Default is 256, "
-"which means we report but we do not generate an error.\n"
-" --writeWholeImage: In tile mode, write the entire rendered image to a "
-"file, instead of an image for each tile.\n");
- SkDebugf(
-" --clone n: Clone the picture n times before rendering.\n");
- SkDebugf(
-" --bbh bbhType [width height]: Set the bounding box hierarchy type to\n"
-" be used. Accepted values are: none, rtree, grid. Default\n"
-" value is none. Not compatible with --pipe. With value\n"
-" 'grid', width and height must be specified. 'grid' can\n"
-" only be used with modes tile, record, and\n"
-" playbackCreation.");
- SkDebugf(
-" --device bitmap"
-#if SK_SUPPORT_GPU
-" | gpu"
-#endif
-": Use the corresponding device. Default is bitmap.\n");
- SkDebugf(
-" bitmap, Render to a bitmap.\n");
-#if SK_SUPPORT_GPU
- SkDebugf(
-" gpu, Render to the GPU.\n");
-#endif
-#if SK_ANGLE
- SkDebugf(
-" angle, Render using angle.\n");
-#endif
-}
+// Flags used by this file, alphabetically:
+DEFINE_int32(clone, 0, "Clone the picture n times before rendering.");
+DECLARE_bool(deferImageDecoding);
+DEFINE_int32(maxComponentDiff, 256, "Maximum diff on a component, 0 - 256. Components that differ "
+ "by more than this amount are considered errors, though all diffs are reported. "
+ "Requires --validate.");
+DECLARE_string(r);
+DEFINE_string(w, "", "Directory to write the rendered images.");
+DEFINE_bool(writeWholeImage, false, "In tile mode, write the entire rendered image to a "
+ "file, instead of an image for each tile.");
+DEFINE_bool(validate, false, "Verify that the rendered image contains the same pixels as "
+ "the picture rendered in simple mode.");
static void make_output_filepath(SkString* path, const SkString& dir,
const SkString& name) {
@@ -131,8 +44,6 @@ static void make_output_filepath(SkString* path, const SkString& dir,
path->remove(path->size() - 4, 4);
}
-bool lazy_decode = false;
-
#include "SkData.h"
#include "SkLruImageCache.h"
@@ -166,8 +77,7 @@ static bool lazy_decode_bitmap(const void* buffer, size_t size, SkBitmap* bitmap
static bool render_picture(const SkString& inputPath, const SkString* outputDir,
sk_tools::PictureRenderer& renderer,
- SkBitmap** out,
- int clones) {
+ SkBitmap** out) {
SkString inputFilename;
sk_tools::get_basename(&inputFilename, inputPath);
@@ -180,7 +90,7 @@ static bool render_picture(const SkString& inputPath, const SkString* outputDir,
bool success = false;
SkPicture* picture;
- if (lazy_decode) {
+ if (FLAGS_deferImageDecoding) {
picture = SkNEW_ARGS(SkPicture, (&inputStream, &success, &lazy_decode_bitmap));
} else {
picture = SkNEW_ARGS(SkPicture, (&inputStream, &success, &SkImageDecoder::DecodeMemory));
@@ -190,7 +100,7 @@ static bool render_picture(const SkString& inputPath, const SkString* outputDir,
return false;
}
- for (int i = 0; i < clones; ++i) {
+ for (int i = 0; i < FLAGS_clone; ++i) {
SkPicture* clone = picture->clone();
SkDELETE(picture);
picture = clone;
@@ -203,7 +113,7 @@ static bool render_picture(const SkString& inputPath, const SkString* outputDir,
renderer.setup();
SkString* outputPath = NULL;
- if (NULL != outputDir) {
+ if (NULL != outputDir && outputDir->size() > 0) {
outputPath = SkNEW(SkString);
make_output_filepath(outputPath, *outputDir, inputFilename);
}
@@ -233,28 +143,25 @@ static int MaxByteDiff(uint32_t v1, uint32_t v2) {
}
static bool render_picture(const SkString& inputPath, const SkString* outputDir,
- sk_tools::PictureRenderer& renderer,
- bool validate, int maxComponentDiff,
- bool writeWholeImage,
- int clones) {
+ sk_tools::PictureRenderer& renderer) {
int diffs[256] = {0};
SkBitmap* bitmap = NULL;
bool success = render_picture(inputPath,
- writeWholeImage ? NULL : outputDir,
+ FLAGS_writeWholeImage ? NULL : outputDir,
renderer,
- validate || writeWholeImage ? &bitmap : NULL, clones);
+ FLAGS_validate || FLAGS_writeWholeImage ? &bitmap : NULL);
- if (!success || ((validate || writeWholeImage) && bitmap == NULL)) {
+ if (!success || ((FLAGS_validate || FLAGS_writeWholeImage) && bitmap == NULL)) {
SkDebugf("Failed to draw the picture.\n");
SkDELETE(bitmap);
return false;
}
- if (validate) {
+ if (FLAGS_validate) {
SkBitmap* referenceBitmap = NULL;
sk_tools::SimplePictureRenderer referenceRenderer;
success = render_picture(inputPath, NULL, referenceRenderer,
- &referenceBitmap, 0);
+ &referenceBitmap);
if (!success || !referenceBitmap) {
SkDebugf("Failed to draw the reference picture.\n");
@@ -285,10 +192,10 @@ static bool render_picture(const SkString& inputPath, const SkString* outputDir,
SkASSERT(diff >= 0 && diff <= 255);
diffs[diff]++;
- if (diff > maxComponentDiff) {
+ if (diff > FLAGS_maxComponentDiff) {
SkDebugf("Expected pixel at (%i %i) exceedds maximum "
"component diff of %i: 0x%x, actual 0x%x\n",
- x, y, maxComponentDiff,
+ x, y, FLAGS_maxComponentDiff,
*referenceBitmap->getAddr32(x, y),
*bitmap->getAddr32(x, y));
SkDELETE(bitmap);
@@ -306,9 +213,9 @@ static bool render_picture(const SkString& inputPath, const SkString* outputDir,
}
}
- if (writeWholeImage) {
+ if (FLAGS_writeWholeImage) {
sk_tools::force_all_opaque(*bitmap);
- if (NULL != outputDir && writeWholeImage) {
+ if (NULL != outputDir && FLAGS_writeWholeImage) {
SkString inputFilename;
sk_tools::get_basename(&inputFilename, inputPath);
SkString outputPath;
@@ -327,479 +234,80 @@ static bool render_picture(const SkString& inputPath, const SkString* outputDir,
}
-static int process_input(const SkString& input, const SkString* outputDir,
- sk_tools::PictureRenderer& renderer,
- bool validate, int maxComponentDiff,
- bool writeWholeImage, int clones) {
- SkOSFile::Iter iter(input.c_str(), "skp");
+static int process_input(const char* input, const SkString* outputDir,
+ sk_tools::PictureRenderer& renderer) {
+ SkOSFile::Iter iter(input, "skp");
SkString inputFilename;
int failures = 0;
- SkDebugf("process_input, %s\n", input.c_str());
+ SkDebugf("process_input, %s\n", input);
if (iter.next(&inputFilename)) {
do {
SkString inputPath;
- sk_tools::make_filepath(&inputPath, input, inputFilename);
- if (!render_picture(inputPath, outputDir, renderer,
- validate, maxComponentDiff,
- writeWholeImage, clones)) {
+ SkString inputAsSkString(input);
+ sk_tools::make_filepath(&inputPath, inputAsSkString, inputFilename);
+ if (!render_picture(inputPath, outputDir, renderer)) {
++failures;
}
} while(iter.next(&inputFilename));
- } else if (SkStrEndsWith(input.c_str(), ".skp")) {
+ } else if (SkStrEndsWith(input, ".skp")) {
SkString inputPath(input);
- if (!render_picture(inputPath, outputDir, renderer,
- validate, maxComponentDiff,
- writeWholeImage, clones)) {
+ if (!render_picture(inputPath, outputDir, renderer)) {
++failures;
}
} else {
SkString warning;
- warning.printf("Warning: skipping %s\n", input.c_str());
+ warning.printf("Warning: skipping %s\n", input);
SkDebugf(warning.c_str());
}
return failures;
}
-static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>* inputs,
- sk_tools::PictureRenderer*& renderer, SkString*& outputDir,
- bool* validate, int* maxComponentDiff,
- bool* writeWholeImage,
- int* clones){
- const char* argv0 = argv[0];
- char* const* stop = argv + argc;
-
- sk_tools::PictureRenderer::SkDeviceTypes deviceType =
- sk_tools::PictureRenderer::kBitmap_DeviceType;
-
- bool usePipe = false;
- int numThreads = 1;
- bool useTiles = false;
- const char* widthString = NULL;
- const char* heightString = NULL;
- int gridWidth = 0;
- int gridHeight = 0;
- bool isPowerOf2Mode = false;
- bool isCopyMode = false;
- const char* xTilesString = NULL;
- const char* yTilesString = NULL;
- const char* mode = NULL;
- bool gridSupported = false;
- sk_tools::PictureRenderer::BBoxHierarchyType bbhType =
- sk_tools::PictureRenderer::kNone_BBoxHierarchyType;
- *validate = false;
- *maxComponentDiff = 256;
- *writeWholeImage = false;
- *clones = 0;
- SkISize viewport;
- viewport.setEmpty();
- SkScalar scaleFactor = SK_Scalar1;
-
- for (++argv; argv < stop; ++argv) {
- if (0 == strcmp(*argv, "--mode")) {
- if (renderer != NULL) {
- renderer->unref();
- SkDebugf("Cannot combine modes.\n");
- usage(argv0);
- exit(-1);
- }
-
- ++argv;
- if (argv >= stop) {
- SkDebugf("Missing mode for --mode\n");
- usage(argv0);
- exit(-1);
- }
-
- if (0 == strcmp(*argv, "simple")) {
- renderer = SkNEW(sk_tools::SimplePictureRenderer);
- } else if ((0 == strcmp(*argv, "tile")) || (0 == strcmp(*argv, "pow2tile"))
- || 0 == strcmp(*argv, "copyTile")) {
- useTiles = true;
- mode = *argv;
-
- if (0 == strcmp(*argv, "pow2tile")) {
- isPowerOf2Mode = true;
- } else if (0 == strcmp(*argv, "copyTile")) {
- isCopyMode = true;
- } else {
- gridSupported = true;
- }
-
- ++argv;
- if (argv >= stop) {
- SkDebugf("Missing width for --mode %s\n", mode);
- usage(argv0);
- exit(-1);
- }
-
- widthString = *argv;
- ++argv;
- if (argv >= stop) {
- SkDebugf("Missing height for --mode %s\n", mode);
- usage(argv0);
- exit(-1);
- }
- heightString = *argv;
- } else if (0 == strcmp(*argv, "rerecord")) {
- renderer = SkNEW(sk_tools::RecordPictureRenderer);
- } else {
- SkDebugf("%s is not a valid mode for --mode\n", *argv);
- usage(argv0);
- exit(-1);
- }
- } else if (0 == strcmp(*argv, "--bbh")) {
- ++argv;
- if (argv >= stop) {
- SkDebugf("Missing value for --bbh\n");
- usage(argv0);
- exit(-1);
- }
- if (0 == strcmp(*argv, "none")) {
- bbhType = sk_tools::PictureRenderer::kNone_BBoxHierarchyType;
- } else if (0 == strcmp(*argv, "rtree")) {
- bbhType = sk_tools::PictureRenderer::kRTree_BBoxHierarchyType;
- } else if (0 == strcmp(*argv, "grid")) {
- bbhType = sk_tools::PictureRenderer::kTileGrid_BBoxHierarchyType;
- ++argv;
- if (argv >= stop) {
- SkDebugf("Missing width for --bbh grid\n");
- usage(argv0);
- exit(-1);
- }
- gridWidth = atoi(*argv);
- ++argv;
- if (argv >= stop) {
- SkDebugf("Missing height for --bbh grid\n");
- usage(argv0);
- exit(-1);
- }
- gridHeight = atoi(*argv);
- } else {
- SkDebugf("%s is not a valid value for --bbhType\n", *argv);
- usage(argv0);
- exit(-1);;
- }
- } else if (0 == strcmp(*argv, "--viewport")) {
- ++argv;
- if (argv >= stop) {
- SkDebugf("Missing width for --viewport\n");
- usage(argv0);
- exit(-1);
- }
- viewport.fWidth = atoi(*argv);
- ++argv;
- if (argv >= stop) {
- SkDebugf("Missing height for --viewport\n");
- usage(argv0);
- exit(-1);
- }
- viewport.fHeight = atoi(*argv);
- } else if (0 == strcmp(*argv, "--scale")) {
- ++argv;
- if (argv >= stop) {
- SkDebugf("Missing scaleFactor for --scale\n");
- usage(argv0);
- exit(-1);
- }
- scaleFactor = SkDoubleToScalar(atof(*argv));
- } else if (0 == strcmp(*argv, "--tiles")) {
- ++argv;
- if (argv >= stop) {
- SkDebugf("Missing x for --tiles\n");
- usage(argv0);
- exit(-1);
- }
- xTilesString = *argv;
- ++argv;
- if (argv >= stop) {
- SkDebugf("Missing y for --tiles\n");
- usage(argv0);
- exit(-1);
- }
- yTilesString = *argv;
- } else if (0 == strcmp(*argv, "--pipe")) {
- usePipe = true;
- } else if (0 == strcmp(*argv, "--multi")) {
- ++argv;
- if (argv >= stop) {
- SkSafeUnref(renderer);
- SkDebugf("Missing arg for --multi\n");
- usage(argv0);
- exit(-1);
- }
- numThreads = atoi(*argv);
- if (numThreads < 2) {
- SkSafeUnref(renderer);
- SkDebugf("Number of threads must be at least 2.\n");
- usage(argv0);
- exit(-1);
- }
- } else if (0 == strcmp(*argv, "--clone")) {
- ++argv;
- if (argv >= stop) {
- SkSafeUnref(renderer);
- SkDebugf("Missing arg for --clone\n");
- usage(argv0);
- exit(-1);
- }
- *clones = atoi(*argv);
- if (*clones < 0) {
- SkSafeUnref(renderer);
- SkDebugf("Number of clones must be at least 0.\n");
- usage(argv0);
- exit(-1);
- }
- } else if (0 == strcmp(*argv, "--device")) {
- ++argv;
- if (argv >= stop) {
- SkSafeUnref(renderer);
- SkDebugf("Missing mode for --device\n");
- usage(argv0);
- exit(-1);
- }
-
- if (0 == strcmp(*argv, "bitmap")) {
- deviceType = sk_tools::PictureRenderer::kBitmap_DeviceType;
- }
-#if SK_SUPPORT_GPU
- else if (0 == strcmp(*argv, "gpu")) {
- deviceType = sk_tools::PictureRenderer::kGPU_DeviceType;
- }
-#endif
-#if SK_ANGLE
- else if (0 == strcmp(*argv, "angle")) {
- deviceType = sk_tools::PictureRenderer::kAngle_DeviceType;
- }
-#endif
- else {
- SkSafeUnref(renderer);
- SkDebugf("%s is not a valid mode for --device\n", *argv);
- usage(argv0);
- exit(-1);
- }
- } else if (0 == strcmp(*argv, "--enable-deferred-image-decoding")) {
- lazy_decode = true;
- } else if ((0 == strcmp(*argv, "-h")) || (0 == strcmp(*argv, "--help"))) {
- SkSafeUnref(renderer);
- usage(argv0);
- exit(-1);
- } else if (0 == strcmp(*argv, "-w")) {
- ++argv;
- if (argv >= stop) {
- SkDebugf("Missing output directory for -w\n");
- usage(argv0);
- exit(-1);
- }
- outputDir = SkNEW_ARGS(SkString, (*argv));
- } else if (0 == strcmp(*argv, "--validate")) {
- *validate = true;
- } else if (0 == strcmp(*argv, "--maxComponentDiff")) {
- if (!*validate) {
- SkDebugf("--maxComponentDiff must be used only with --validate\n");
- usage(argv0);
- exit(-1);
- }
- ++argv;
- if (argv >= stop) {
- SkDebugf("Missing arg for --maxComponentDiff\n");
- usage(argv0);
- exit(-1);
- }
- *maxComponentDiff = atoi(*argv);
- if (*maxComponentDiff < 0 || *maxComponentDiff > 256) {
- SkSafeUnref(renderer);
- SkDebugf("maxComponentDiff: 0 - 256.\n");
- usage(argv0);
- exit(-1);
- }
- } else if (0 == strcmp(*argv, "--writeWholeImage")) {
- *writeWholeImage = true;
- } else {
- inputs->push_back(SkString(*argv));
- }
- }
+int tool_main(int argc, char** argv);
+int tool_main(int argc, char** argv) {
+ SkFlags::SetUsage("Render .skp files.");
+ SkFlags::ParseCommandLine(argc, argv);
- if (numThreads > 1 && !useTiles) {
- SkSafeUnref(renderer);
- SkDebugf("Multithreaded drawing requires tiled rendering.\n");
- usage(argv0);
+ if (FLAGS_r.isEmpty()) {
+ SkDebugf(".skp files or directories are required.\n");
exit(-1);
}
- if (usePipe && sk_tools::PictureRenderer::kNone_BBoxHierarchyType != bbhType) {
- SkDebugf("--pipe and --bbh cannot be used together\n");
- usage(argv0);
+ if (FLAGS_maxComponentDiff < 0 || FLAGS_maxComponentDiff > 256) {
+ SkDebugf("--maxComponentDiff must be between 0 and 256\n");
exit(-1);
}
- if (sk_tools::PictureRenderer::kTileGrid_BBoxHierarchyType == bbhType &&
- !gridSupported) {
- SkDebugf("'--bbh grid' is not compatible with specified --mode.\n");
- usage(argv0);
+ if (FLAGS_maxComponentDiff != 256 && !FLAGS_validate) {
+ SkDebugf("--maxComponentDiff requires --validate\n");
exit(-1);
}
- if (useTiles) {
- SkASSERT(NULL == renderer);
- sk_tools::TiledPictureRenderer* tiledRenderer;
- if (isCopyMode) {
- int x, y;
- if (xTilesString != NULL) {
- SkASSERT(yTilesString != NULL);
- x = atoi(xTilesString);
- y = atoi(yTilesString);
- if (x <= 0 || y <= 0) {
- SkDebugf("--tiles must be given values > 0\n");
- usage(argv0);
- exit(-1);
- }
- } else {
- x = y = 4;
- }
- tiledRenderer = SkNEW_ARGS(sk_tools::CopyTilesRenderer, (x, y));
- } else if (numThreads > 1) {
- tiledRenderer = SkNEW_ARGS(sk_tools::MultiCorePictureRenderer, (numThreads));
- } else {
- tiledRenderer = SkNEW(sk_tools::TiledPictureRenderer);
- }
- if (isPowerOf2Mode) {
- int minWidth = atoi(widthString);
- if (!SkIsPow2(minWidth) || minWidth < 0) {
- tiledRenderer->unref();
- SkString err;
- err.printf("-mode %s must be given a width"
- " value that is a power of two\n", mode);
- SkDebugf(err.c_str());
- usage(argv0);
- exit(-1);
- }
- tiledRenderer->setTileMinPowerOf2Width(minWidth);
- } else if (sk_tools::is_percentage(widthString)) {
- if (isCopyMode) {
- tiledRenderer->unref();
- SkString err;
- err.printf("--mode %s does not support percentages.\n", mode);
- SkDebugf(err.c_str());
- usage(argv0);
- exit(-1);
- }
- tiledRenderer->setTileWidthPercentage(atof(widthString));
- if (!(tiledRenderer->getTileWidthPercentage() > 0)) {
- tiledRenderer->unref();
- SkDebugf("--mode %s must be given a width percentage > 0\n", mode);
- usage(argv0);
- exit(-1);
- }
- } else {
- tiledRenderer->setTileWidth(atoi(widthString));
- if (!(tiledRenderer->getTileWidth() > 0)) {
- tiledRenderer->unref();
- SkDebugf("--mode %s must be given a width > 0\n", mode);
- usage(argv0);
- exit(-1);
- }
- }
-
- if (sk_tools::is_percentage(heightString)) {
- if (isCopyMode) {
- tiledRenderer->unref();
- SkString err;
- err.printf("--mode %s does not support percentages.\n", mode);
- SkDebugf(err.c_str());
- usage(argv0);
- exit(-1);
- }
- tiledRenderer->setTileHeightPercentage(atof(heightString));
- if (!(tiledRenderer->getTileHeightPercentage() > 0)) {
- tiledRenderer->unref();
- SkDebugf("--mode %s must be given a height percentage > 0\n", mode);
- usage(argv0);
- exit(-1);
- }
- } else {
- tiledRenderer->setTileHeight(atoi(heightString));
- if (!(tiledRenderer->getTileHeight() > 0)) {
- tiledRenderer->unref();
- SkDebugf("--mode %s must be given a height > 0\n", mode);
- usage(argv0);
- exit(-1);
- }
- }
- if (numThreads > 1) {
- switch (deviceType) {
-#if SK_SUPPORT_GPU
- case sk_tools::PictureRenderer::kGPU_DeviceType:
- // fall through
-#endif
-#if SK_ANGLE
- case sk_tools::PictureRenderer::kAngle_DeviceType:
-#endif
- tiledRenderer->unref();
- SkDebugf("GPU not compatible with multithreaded tiling.\n");
- usage(argv0);
- exit(-1);
- break;
- default:
- break;
- }
- }
- renderer = tiledRenderer;
- if (usePipe) {
- SkDebugf("Pipe rendering is currently not compatible with tiling.\n"
- "Turning off pipe.\n");
- }
- } else if (usePipe) {
- if (renderer != NULL) {
- renderer->unref();
- SkDebugf("Pipe is incompatible with other modes.\n");
- usage(argv0);
- exit(-1);
- }
- renderer = SkNEW(sk_tools::PipePictureRenderer);
- }
-
- if (inputs->empty()) {
- SkSafeUnref(renderer);
- if (NULL != outputDir) {
- SkDELETE(outputDir);
- }
- usage(argv0);
+ if (FLAGS_clone < 0) {
+ SkDebugf("--clone must be >= 0. Was %i\n", FLAGS_clone);
exit(-1);
}
- if (NULL == renderer) {
- renderer = SkNEW(sk_tools::SimplePictureRenderer);
+ SkString errorString;
+ SkAutoTUnref<sk_tools::PictureRenderer> renderer(parseRenderer(errorString,
+ kRender_PictureTool));
+ if (errorString.size() > 0) {
+ SkDebugf("%s\n", errorString.c_str());
}
- renderer->setBBoxHierarchyType(bbhType);
- renderer->setGridSize(gridWidth, gridHeight);
- renderer->setViewport(viewport);
- renderer->setScaleFactor(scaleFactor);
- if (!renderer->setDeviceType(deviceType)) {
- SkDebugf("Invalid device type.\n");
+ if (renderer.get() == NULL) {
exit(-1);
}
-}
-int tool_main(int argc, char** argv);
-int tool_main(int argc, char** argv) {
SkAutoGraphics ag;
- SkTArray<SkString> inputs;
- sk_tools::PictureRenderer* renderer = NULL;
- SkString* outputDir = NULL;
- bool validate = false;
- int maxComponentDiff = 256;
- bool writeWholeImage = false;
- int clones = 0;
- parse_commandline(argc, argv, &inputs, renderer, outputDir,
- &validate, &maxComponentDiff, &writeWholeImage, &clones);
- SkASSERT(renderer);
+
+ SkString outputDir;
+ if (FLAGS_w.count() == 1) {
+ outputDir.set(FLAGS_w[0]);
+ }
int failures = 0;
- for (int i = 0; i < inputs.count(); i ++) {
- failures += process_input(inputs[i], outputDir, *renderer,
- validate, maxComponentDiff,
- writeWholeImage, clones);
+ for (int i = 0; i < FLAGS_r.count(); i ++) {
+ failures += process_input(FLAGS_r[i], &outputDir, *renderer.get());
}
if (failures != 0) {
SkDebugf("Failed to render %i pictures.\n", failures);
@@ -814,10 +322,6 @@ int tool_main(int argc, char** argv) {
}
#endif
#endif
- if (NULL != outputDir) {
- SkDELETE(outputDir);
- }
- SkDELETE(renderer);
return 0;
}