Allow render_pictures to render using multiple threads.
Make write() a static function so it can be used by the
thread entry functions.
Add a helper function to append a number to a string and
call write to share code.
Review URL: https://codereview.appspot.com/6589062
git-svn-id: http://skia.googlecode.com/svn/trunk@5789 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/tools/render_pictures_main.cpp b/tools/render_pictures_main.cpp
index da0740a..477272d 100644
--- a/tools/render_pictures_main.cpp
+++ b/tools/render_pictures_main.cpp
@@ -23,8 +23,10 @@
SkDebugf("\n"
"Usage: \n"
" %s <input>... <outputDir> \n"
-" [--mode pipe | pow2tile minWidth height[%] | simple\n"
+" [--mode pow2tile minWidth height[%] | simple\n"
" | tile width[%] height[%]]\n"
+" [--pipe]\n"
+" [--multi count]\n"
" [--device bitmap"
#if SK_SUPPORT_GPU
" | gpu"
@@ -38,12 +40,10 @@
SkDebugf(
" outputDir: directory to write the rendered images.\n\n");
SkDebugf(
-" --mode pipe | pow2tile minWidth height[%] | simple\n"
+" --mode pow2tile minWidth height[%] | simple\n"
" | tile width[%] height[%]: Run in the corresponding mode.\n"
" Default is simple.\n");
SkDebugf(
-" pipe, Render using a SkGPipe.\n");
- SkDebugf(
" pow2tile minWidth height[%], Creates tiles with widths\n"
" that are all a power of two\n"
" such that they minimize the\n"
@@ -59,6 +59,10 @@
" with the given dimensions.\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"
+" --pipe: Benchmark SkGPipe rendering. Compatible with tiled, multithreaded rendering.\n");
+ SkDebugf(
" --device bitmap"
#if SK_SUPPORT_GPU
" | gpu"
@@ -152,6 +156,14 @@
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;
+ bool isPowerOf2Mode = false;
+ const char* mode = NULL;
+
for (++argv; argv < stop; ++argv) {
if (0 == strcmp(*argv, "--mode")) {
SkDELETE(renderer);
@@ -163,90 +175,55 @@
exit(-1);
}
- if (0 == strcmp(*argv, "pipe")) {
- renderer = SkNEW(sk_tools::PipePictureRenderer);
- } else if (0 == strcmp(*argv, "simple")) {
+ if (0 == strcmp(*argv, "simple")) {
renderer = SkNEW(sk_tools::SimplePictureRenderer);
} else if ((0 == strcmp(*argv, "tile")) || (0 == strcmp(*argv, "pow2tile"))) {
- char* mode = *argv;
- bool isPowerOf2Mode = false;
+ useTiles = true;
+ mode = *argv;
if (0 == strcmp(*argv, "pow2tile")) {
isPowerOf2Mode = true;
}
- sk_tools::TiledPictureRenderer* tileRenderer =
- SkNEW(sk_tools::TiledPictureRenderer);
++argv;
if (argv >= stop) {
- SkDELETE(tileRenderer);
SkDebugf("Missing width for --mode %s\n", mode);
usage(argv0);
exit(-1);
}
- if (isPowerOf2Mode) {
- int minWidth = atoi(*argv);
-
- if (!SkIsPow2(minWidth) || minWidth <= 0) {
- SkDELETE(tileRenderer);
- SkDebugf("--mode %s must be given a width"
- " value that is a power of two\n", mode);
- exit(-1);
- }
-
- tileRenderer->setTileMinPowerOf2Width(minWidth);
- } else if (sk_tools::is_percentage(*argv)) {
- tileRenderer->setTileWidthPercentage(atof(*argv));
- if (!(tileRenderer->getTileWidthPercentage() > 0)) {
- SkDELETE(tileRenderer);
- SkDebugf("--mode %s must be given a width percentage > 0\n", mode);
- exit(-1);
- }
- } else {
- tileRenderer->setTileWidth(atoi(*argv));
- if (!(tileRenderer->getTileWidth() > 0)) {
- SkDELETE(tileRenderer);
- SkDebugf("--mode %s must be given a width > 0\n", mode);
- exit(-1);
- }
- }
-
+ widthString = *argv;
++argv;
if (argv >= stop) {
- SkDELETE(tileRenderer);
- SkDebugf("Missing height for --mode %s\n", mode);
+ SkDebugf("Missing height for --mode tile\n");
usage(argv0);
exit(-1);
}
-
- if (sk_tools::is_percentage(*argv)) {
- tileRenderer->setTileHeightPercentage(atof(*argv));
- if (!(tileRenderer->getTileHeightPercentage() > 0)) {
- SkDELETE(tileRenderer);
- SkDebugf(
- "--mode %s must be given a height percentage > 0\n", mode);
- exit(-1);
- }
- } else {
- tileRenderer->setTileHeight(atoi(*argv));
- if (!(tileRenderer->getTileHeight() > 0)) {
- SkDELETE(tileRenderer);
- SkDebugf("--mode %s must be given a height > 0\n", mode);
- exit(-1);
- }
- }
-
- renderer = tileRenderer;
+ heightString = *argv;
} else {
SkDebugf("%s is not a valid mode for --mode\n", *argv);
usage(argv0);
exit(-1);
}
+ } else if (0 == strcmp(*argv, "--pipe")) {
+ usePipe = true;
+ } else if (0 == strcmp(*argv, "--multi")) {
+ ++argv;
+ if (argv >= stop) {
+ SkDebugf("Missing arg for --multi\n");
+ usage(argv0);
+ exit(-1);
+ }
+ numThreads = atoi(*argv);
+ if (numThreads < 2) {
+ SkDebugf("Number of threads must be at least 2.\n");
+ usage(argv0);
+ exit(-1);
+ }
} else if (0 == strcmp(*argv, "--device")) {
++argv;
if (argv >= stop) {
- SkDebugf("Missing mode for --deivce\n");
+ SkDebugf("Missing mode for --device\n");
usage(argv0);
exit(-1);
}
@@ -274,6 +251,79 @@
}
}
+ if (numThreads > 1 && !useTiles) {
+ SkDebugf("Multithreaded drawing requires tiled rendering.\n");
+ usage(argv0);
+ exit(-1);
+ }
+
+ if (useTiles) {
+ SkASSERT(NULL == renderer);
+ sk_tools::TiledPictureRenderer* 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)) {
+ tiledRenderer->setTileWidthPercentage(atof(widthString));
+ if (!(tiledRenderer->getTileWidthPercentage() > 0)) {
+ tiledRenderer->unref();
+ SkDebugf("--mode tile must be given a width percentage > 0\n");
+ usage(argv0);
+ exit(-1);
+ }
+ } else {
+ tiledRenderer->setTileWidth(atoi(widthString));
+ if (!(tiledRenderer->getTileWidth() > 0)) {
+ tiledRenderer->unref();
+ SkDebugf("--mode tile must be given a width > 0\n");
+ usage(argv0);
+ exit(-1);
+ }
+ }
+
+ if (sk_tools::is_percentage(heightString)) {
+ tiledRenderer->setTileHeightPercentage(atof(heightString));
+ if (!(tiledRenderer->getTileHeightPercentage() > 0)) {
+ tiledRenderer->unref();
+ SkDebugf("--mode tile must be given a height percentage > 0\n");
+ usage(argv0);
+ exit(-1);
+ }
+ } else {
+ tiledRenderer->setTileHeight(atoi(heightString));
+ if (!(tiledRenderer->getTileHeight() > 0)) {
+ tiledRenderer->unref();
+ SkDebugf("--mode tile must be given a height > 0\n");
+ usage(argv0);
+ exit(-1);
+ }
+ }
+ if (numThreads > 1) {
+#if SK_SUPPORT_GPU
+ if (sk_tools::PictureRenderer::kGPU_DeviceType == deviceType) {
+ tiledRenderer->unref();
+ SkDebugf("GPU not compatible with multithreaded tiling.\n");
+ usage(argv0);
+ exit(-1);
+ }
+#endif
+ tiledRenderer->setNumberOfThreads(numThreads);
+ }
+ tiledRenderer->setUsePipe(usePipe);
+ renderer = tiledRenderer;
+ } else if (usePipe) {
+ renderer = SkNEW(sk_tools::PipePictureRenderer);
+ }
+
if (inputs->count() < 2) {
SkDELETE(renderer);
usage(argv0);