Measure picture recording speed in nanobench.

Today we measure SkPicture playback speed, but not the time it takes to record
the SkPicture.  This fixes that by reading SKPs from disk and re-recording them.

On the console, recording shows up first as the nonrendering skp benches,
followed later by the usual playback benches:

maxrss  loops   min median  mean    max stddev  samples     config  bench
51M  2   165µs   168µs   169µs   178µs   3%  ▆▄▃█▂▄▁▂▁▁  nonrendering    tabl_slashdot.skp
57M  1   9.72ms  9.77ms  9.79ms  9.97ms  1%  █▂▂▅▃▂▁▄▂▁  nonrendering    desk_pokemonwiki.skp
57M  32  2.92µs  2.96µs  3.03µs  3.46µs  6%  ▅▁▁▁▁▁▁█▂▁  nonrendering    desk_yahoosports.skp
...
147M 1   3.86ms  3.87ms  3.97ms  4.81ms  7%  █▁▁▁▁▁▁▁▁▁  8888    tabl_slashdot.skp_1
147M 1   4.54ms  4.56ms  4.55ms  4.56ms  0%  █▅▇▅█▅▂▁▅▁  565     tabl_slashdot.skp_1
147M 2   3.08ms  3.24ms  4.17ms  8.18ms  50% █▁▁█▁▁▁▁▁▁  gpu     tabl_slashdot.skp_1
147M 1   1.61ms  1.62ms  1.69ms  2.33ms  13% █▁▁▁▁▁▁▁▁▁  8888    desk_pokemonwiki.skp_1
147M 1   1.44ms  1.44ms  1.45ms  1.47ms  1%  ▅▂█▂▂▅▁▁▂▁  565     desk_pokemonwiki.skp_1
...

On skiaperf.com, they'll also be separated out from playback benches by bench_type.

BUG=skia:
R=reed@google.com, mtklein@google.com, jcgregorio@google.com

Author: mtklein@chromium.org

Review URL: https://codereview.chromium.org/559153002
diff --git a/bench/nanobench.cpp b/bench/nanobench.cpp
index 853492b..67646c2 100644
--- a/bench/nanobench.cpp
+++ b/bench/nanobench.cpp
@@ -12,6 +12,7 @@
 #include "GMBench.h"
 #include "ProcStats.h"
 #include "ResultsWriter.h"
+#include "RecordingBench.h"
 #include "SKPBench.h"
 #include "Stats.h"
 #include "Timer.h"
@@ -407,6 +408,7 @@
 public:
     BenchmarkStream() : fBenches(BenchRegistry::Head())
                       , fGMs(skiagm::GMRegistry::Head())
+                      , fCurrentRecording(0)
                       , fCurrentScale(0)
                       , fCurrentSKP(0) {
         for (int i = 0; i < FLAGS_skps.count(); i++) {
@@ -435,11 +437,33 @@
         }
     }
 
+    static bool ReadPicture(const char* path, SkAutoTUnref<SkPicture>* pic) {
+        // Not strictly necessary, as it will be checked again later,
+        // but helps to avoid a lot of pointless work if we're going to skip it.
+        if (SkCommandLineFlags::ShouldSkip(FLAGS_match, path)) {
+            return false;
+        }
+
+        SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
+        if (stream.get() == NULL) {
+            SkDebugf("Could not read %s.\n", path);
+            return false;
+        }
+
+        pic->reset(SkPicture::CreateFromStream(stream.get()));
+        if (pic->get() == NULL) {
+            SkDebugf("Could not read %s as an SkPicture.\n", path);
+            return false;
+        }
+        return true;
+    }
+
     Benchmark* next() {
         if (fBenches) {
             Benchmark* bench = fBenches->factory()(NULL);
             fBenches = fBenches->next();
             fSourceType = "bench";
+            fBenchType  = "micro";
             return bench;
         }
 
@@ -448,34 +472,32 @@
             fGMs = fGMs->next();
             if (gm->getFlags() & skiagm::GM::kAsBench_Flag) {
                 fSourceType = "gm";
+                fBenchType  = "micro";
                 return SkNEW_ARGS(GMBench, (gm.detach()));
             }
         }
 
+        // First add all .skps as RecordingBenches.
+        while (fCurrentRecording < fSKPs.count()) {
+            const SkString& path = fSKPs[fCurrentRecording++];
+            SkAutoTUnref<SkPicture> pic;
+            if (!ReadPicture(path.c_str(), &pic)) {
+                continue;
+            }
+            SkString name = SkOSPath::Basename(path.c_str());
+            fSourceType = "skp";
+            fBenchType  = "recording";
+            return SkNEW_ARGS(RecordingBench, (name.c_str(), pic.get(), FLAGS_bbh));
+        }
+
+        // Then once each for each scale as SKPBenches (playback).
         while (fCurrentScale < fScales.count()) {
             while (fCurrentSKP < fSKPs.count()) {
                 const SkString& path = fSKPs[fCurrentSKP++];
-
-                // Not strictly necessary, as it will be checked again later,
-                // but helps to avoid a lot of pointless work if we're going to skip it.
-                if (SkCommandLineFlags::ShouldSkip(FLAGS_match, path.c_str())) {
+                SkAutoTUnref<SkPicture> pic;
+                if (!ReadPicture(path.c_str(), &pic)) {
                     continue;
                 }
-
-                SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path.c_str()));
-                if (stream.get() == NULL) {
-                    SkDebugf("Could not read %s.\n", path.c_str());
-                    exit(1);
-                }
-
-                SkAutoTUnref<SkPicture> pic(SkPicture::CreateFromStream(stream.get()));
-                if (pic.get() == NULL) {
-                    SkDebugf("Could not read %s as an SkPicture.\n", path.c_str());
-                    exit(1);
-                }
-
-                SkString name = SkOSPath::Basename(path.c_str());
-
                 if (FLAGS_bbh) {
                     // The SKP we read off disk doesn't have a BBH.  Re-record so it grows one.
                     // Here we use an SkTileGrid with parameters optimized for FLAGS_clip.
@@ -491,8 +513,9 @@
                                                           &factory));
                     pic.reset(recorder.endRecording());
                 }
-
+                SkString name = SkOSPath::Basename(path.c_str());
                 fSourceType = "skp";
+                fBenchType  = "playback";
                 return SkNEW_ARGS(SKPBench,
                         (name.c_str(), pic.get(), fClip, fScales[fCurrentScale]));
             }
@@ -505,6 +528,7 @@
 
     void fillCurrentOptions(ResultsWriter* log) const {
         log->configOption("source_type", fSourceType);
+        log->configOption("bench_type",  fBenchType);
         if (0 == strcmp(fSourceType, "skp")) {
             log->configOption("clip",
                     SkStringPrintf("%d %d %d %d", fClip.fLeft, fClip.fTop,
@@ -520,7 +544,9 @@
     SkTArray<SkScalar> fScales;
     SkTArray<SkString> fSKPs;
 
-    const char* fSourceType;
+    const char* fSourceType;  // What we're benching: bench, GM, SKP, ...
+    const char* fBenchType;   // How we bench it: micro, recording, playback, ...
+    int fCurrentRecording;
     int fCurrentScale;
     int fCurrentSKP;
 };