Perform multi core rendering in bench_pictures.

Add a flag in SkGPipeWriter for threadsafe drawing.

Add a deferred pipe controller to SamplePipeControllers, which can
be called to play back in multiple threads.

Depends on http://codereview.appspot.com/6459105/

Review URL: https://codereview.appspot.com/6482068

git-svn-id: http://skia.googlecode.com/svn/trunk@5371 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/tools/bench_pictures_main.cpp b/tools/bench_pictures_main.cpp
index 1579f69..084a971 100644
--- a/tools/bench_pictures_main.cpp
+++ b/tools/bench_pictures_main.cpp
@@ -23,8 +23,9 @@
 "Usage: \n"
 "     %s <inputDir>...\n"
 "     [--repeat] \n"
-"     [--mode pipe | pow2tile minWidth height[%] | record | simple\n"
-"         | tile width[%] height[%] | unflatten]\n"
+"     [--mode pow2tile minWidth height[] (multi) | record | simple\n"
+"             | tile width[] height[] (multi) | unflatten]\n"
+"     [--pipe]\n"
 "     [--device bitmap"
 #if SK_SUPPORT_GPU
 " | gpu"
@@ -36,32 +37,37 @@
 "     inputDir:  A list of directories and files to use as input. Files are\n"
 "                expected to have the .skp extension.\n\n");
     SkDebugf(
-"     --mode pipe | pow2tile minWidht height[%] | record | simple\n"
-"        | tile width[%] height[%] | unflatten: Run in the corresponding mode.\n"
-"                                               Default is simple.\n");
+"     --mode pow2tile minWidht height[] (multi) | record | simple\n"
+"            | tile width[] height[] (multi) | unflatten:\n"
+"            Run in the corresponding mode.\n"
+"            Default is simple.\n");
     SkDebugf(
-"                     pipe, Benchmark SkGPipe rendering.\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");
+"                     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"
+"                                                 Append \"multi\" for multithreaded\n"
+"                                                 drawing.\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");
+"                     tile width[] height[], Benchmark simple rendering using\n"
+"                                            tiles with the given dimensions.\n"
+"                                            Append \"multi\" for multithreaded\n"
+"                                            drawing.\n");
     SkDebugf(
 "                     unflatten, Benchmark picture unflattening.\n");
     SkDebugf("\n");
     SkDebugf(
+"     --pipe: Benchmark SkGPipe rendering. Compatible with tiled, multithreaded rendering.\n");
+    SkDebugf(
 "     --device bitmap"
 #if SK_SUPPORT_GPU
 " | gpu"
@@ -112,6 +118,13 @@
     sk_tools::PictureRenderer::SkDeviceTypes deviceType =
         sk_tools::PictureRenderer::kBitmap_DeviceType;
 
+    bool usePipe = false;
+    bool multiThreaded = false;
+    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, "--repeat")) {
             ++argv;
@@ -128,6 +141,8 @@
                 usage(argv0);
                 exit(-1);
             }
+        } else if (0 == strcmp(*argv, "--pipe")) {
+            usePipe = true;
         } else if (0 == strcmp(*argv, "--mode")) {
             SkDELETE(benchmark);
 
@@ -138,82 +153,40 @@
                 exit(-1);
             }
 
-            if (0 == strcmp(*argv, "pipe")) {
-                benchmark = SkNEW(sk_tools::PipePictureBenchmark);
-            } else if (0 == strcmp(*argv, "record")) {
+            if (0 == strcmp(*argv, "record")) {
                 benchmark = SkNEW(sk_tools::RecordPictureBenchmark);
             } else if (0 == strcmp(*argv, "simple")) {
                 benchmark = SkNEW(sk_tools::SimplePictureBenchmark);
             } 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::TiledPictureBenchmark* tileBenchmark =
-                    SkNEW(sk_tools::TiledPictureBenchmark);
                 ++argv;
                 if (argv >= stop) {
-                    SkDELETE(tileBenchmark);
                     SkDebugf("Missing width for --mode %s\n", mode);
                     usage(argv0);
                     exit(-1);
                 }
 
-                if (isPowerOf2Mode) {
-                    int minWidth = atoi(*argv);
-
-                    if (!SkIsPow2(minWidth) || minWidth <= 0) {
-                        SkDELETE(tileBenchmark);
-                        SkDebugf("--mode %s must be given a width"
-                                 " value that is a power of two\n", mode);
-                        exit(-1);
-                    }
-
-                    tileBenchmark->setTileMinPowerOf2Width(minWidth);
-                } else if (sk_tools::is_percentage(*argv)) {
-                    tileBenchmark->setTileWidthPercentage(atof(*argv));
-                    if (!(tileBenchmark->getTileWidthPercentage() > 0)) {
-                        SkDELETE(tileBenchmark);
-                        SkDebugf("--mode %s must be given a width percentage > 0\n", mode);
-                        exit(-1);
-                    }
-                } else {
-                    tileBenchmark->setTileWidth(atoi(*argv));
-                    if (!(tileBenchmark->getTileWidth() > 0)) {
-                        SkDELETE(tileBenchmark);
-                        SkDebugf("--mode %s must be given a width > 0\n", mode);
-                        exit(-1);
-                    }
-                }
-
+                widthString = *argv;
                 ++argv;
                 if (argv >= stop) {
-                    SkDELETE(tileBenchmark);
-                    SkDebugf("Missing height for --mode %s\n", mode);
+                    SkDebugf("Missing height for --mode tile\n");
                     usage(argv0);
                     exit(-1);
                 }
+                heightString = *argv;
 
-                if (sk_tools::is_percentage(*argv)) {
-                    tileBenchmark->setTileHeightPercentage(atof(*argv));
-                    if (!(tileBenchmark->getTileHeightPercentage() > 0)) {
-                        SkDELETE(tileBenchmark);
-                        SkDebugf("--mode %s must be given a height percentage > 0\n", mode);
-                        exit(-1);
-                    }
+                ++argv;
+                if (argv < stop && 0 == strcmp(*argv, "multi")) {
+                    multiThreaded = true;
                 } else {
-                    tileBenchmark->setTileHeight(atoi(*argv));
-                    if (!(tileBenchmark->getTileHeight() > 0)) {
-                        SkDELETE(tileBenchmark);
-                        SkDebugf("--mode %s must be given a height > 0\n", mode);
-                        exit(-1);
-                    }
+                    --argv;
                 }
-
-                benchmark = tileBenchmark;
             } else if (0 == strcmp(*argv, "unflatten")) {
                 benchmark = SkNEW(sk_tools::UnflattenPictureBenchmark);
             } else {
@@ -252,6 +225,55 @@
         }
     }
 
+    if (useTiles) {
+        sk_tools::TiledPictureBenchmark* tileBenchmark = SkNEW(sk_tools::TiledPictureBenchmark);
+        if (isPowerOf2Mode) {
+            int minWidth = atoi(widthString);
+            if (!SkIsPow2(minWidth) || minWidth < 0) {
+                SkDELETE(tileBenchmark);
+                SkDebugf("--mode %s must be given a width"
+                         " value that is a power of two\n", mode);
+                exit(-1);
+            }
+            tileBenchmark->setTileMinPowerOf2Width(minWidth);
+        } else if (sk_tools::is_percentage(widthString)) {
+            tileBenchmark->setTileWidthPercentage(atof(widthString));
+            if (!(tileBenchmark->getTileWidthPercentage() > 0)) {
+                SkDELETE(tileBenchmark);
+                SkDebugf("--mode tile must be given a width percentage > 0\n");
+                exit(-1);
+            }
+        } else {
+            tileBenchmark->setTileWidth(atoi(widthString));
+            if (!(tileBenchmark->getTileWidth() > 0)) {
+                SkDELETE(tileBenchmark);
+                SkDebugf("--mode tile must be given a width > 0\n");
+                exit(-1);
+            }
+        }
+
+        if (sk_tools::is_percentage(heightString)) {
+            tileBenchmark->setTileHeightPercentage(atof(heightString));
+            if (!(tileBenchmark->getTileHeightPercentage() > 0)) {
+                SkDELETE(tileBenchmark);
+                SkDebugf("--mode tile must be given a height percentage > 0\n");
+                exit(-1);
+            }
+        } else {
+            tileBenchmark->setTileHeight(atoi(heightString));
+            if (!(tileBenchmark->getTileHeight() > 0)) {
+                SkDELETE(tileBenchmark);
+                SkDebugf("--mode tile must be given a height > 0\n");
+                exit(-1);
+            }
+        }
+        tileBenchmark->setThreading(multiThreaded);
+        tileBenchmark->setUsePipe(usePipe);
+        benchmark = tileBenchmark;
+    } else if (usePipe) {
+        SkDELETE(benchmark);
+        benchmark = SkNEW(sk_tools::PipePictureBenchmark);
+    }
     if (inputs->count() < 1) {
         SkDELETE(benchmark);
         usage(argv0);