Some cleanups of VisualBench

BUG=skia:

Review URL: https://codereview.chromium.org/1240633005
diff --git a/tools/VisualBench/VisualBench.cpp b/tools/VisualBench/VisualBench.cpp
index d8713e7..895569c 100644
--- a/tools/VisualBench/VisualBench.cpp
+++ b/tools/VisualBench/VisualBench.cpp
@@ -170,15 +170,24 @@
 
     canvas->clear(0xffffffff);
     fBenchmark->preDraw();
-    fBenchmark->perCanvasPreDraw(canvas);
     fRecords.push_back();
     return true;
 }
 
+inline void VisualBench::nextState(State nextState) {
+    fState = nextState;
+}
+
+void VisualBench::perCanvasPreDraw(SkCanvas* canvas, State nextState) {
+    fBenchmark->perCanvasPreDraw(canvas);
+    fCurrentFrame = 0;
+    this->nextState(nextState);
+}
+
 void VisualBench::preWarm(State nextState) {
     if (fCurrentFrame >= FLAGS_gpuFrameLag) {
         // we currently time across all frames to make sure we capture all GPU work
-        fState = nextState;
+        this->nextState(nextState);
         fCurrentFrame = 0;
         fTimer.start();
     } else {
@@ -193,33 +202,20 @@
     }
     this->renderFrame(canvas);
     switch (fState) {
+        case kPreWarmLoopsPerCanvasPreDraw_State: {
+            this->perCanvasPreDraw(canvas, kPreWarmLoops_State);
+            break;
+        }
         case kPreWarmLoops_State: {
             this->preWarm(kTuneLoops_State);
             break;
         }
         case kTuneLoops_State: {
-            if (1 << 30 == fLoops) {
-                // We're about to wrap.  Something's wrong with the bench.
-                SkDebugf("InnerLoops wrapped\n");
-                fLoops = 0;
-            } else {
-                fTimer.end();
-                double elapsed = fTimer.fWall;
-                if (elapsed > FLAGS_loopMs) {
-                    fState = kPreWarmTiming_State;
-
-                    // Scale back the number of loops
-                    fLoops = (int)ceil(fLoops * FLAGS_loopMs / elapsed);
-                    fFlushes = (int)ceil(FLAGS_flushMs / elapsed);
-                } else {
-                    fState = kPreWarmLoops_State;
-                    fLoops *= 2;
-                }
-
-                fCurrentFrame = 0;
-                fTimer = WallTimer();
-                this->resetContext();
-            }
+            this->tuneLoops();
+            break;
+        }
+        case kPreWarmTimingPerCanvasPreDraw_State: {
+            this->perCanvasPreDraw(canvas, kPreWarmTiming_State);
             break;
         }
         case kPreWarmTiming_State: {
@@ -227,27 +223,7 @@
             break;
         }
         case kTiming_State: {
-            if (fCurrentFrame >= FLAGS_frames) {
-                fTimer.end();
-                fRecords.back().fMeasurements.push_back(
-                        fTimer.fWall / (FLAGS_frames * fLoops * fFlushes));
-                if (fCurrentSample++ >= FLAGS_samples) {
-                    fState = kPreWarmLoops_State;
-                    this->printStats();
-                    fBenchmark->perCanvasPostDraw(canvas);
-                    fBenchmark.reset(NULL);
-                    fCurrentSample = 0;
-                    fFlushes = 1;
-                    fLoops = 1;
-                } else {
-                    fState = kPreWarmTiming_State;
-                }
-                fTimer = WallTimer();
-                this->resetContext();
-                fCurrentFrame = 0;
-            } else {
-                fCurrentFrame++;
-            }
+            this->timing(canvas);
             break;
         }
     }
@@ -256,6 +232,70 @@
     this->inval(NULL);
 }
 
+inline double VisualBench::elapsed() {
+    fTimer.end();
+    return fTimer.fWall;
+}
+
+void VisualBench::resetTimingState() {
+    fCurrentFrame = 0;
+    fTimer = WallTimer();
+    this->resetContext();
+}
+
+void VisualBench::scaleLoops(double elapsedMs) {
+    // Scale back the number of loops
+    fLoops = (int)ceil(fLoops * FLAGS_loopMs / elapsedMs);
+    fFlushes = (int)ceil(FLAGS_flushMs / elapsedMs);
+}
+
+inline void VisualBench::tuneLoops() {
+    if (1 << 30 == fLoops) {
+        // We're about to wrap.  Something's wrong with the bench.
+        SkDebugf("InnerLoops wrapped\n");
+        fLoops = 0;
+    } else {
+        double elapsedMs = this->elapsed();
+        if (elapsedMs > FLAGS_loopMs) {
+            this->scaleLoops(elapsedMs);
+            this->nextState(kPreWarmTimingPerCanvasPreDraw_State);
+        } else {
+            fLoops *= 2;
+            this->nextState(kPreWarmLoops_State);
+        }
+        this->resetTimingState();
+    }
+}
+
+void VisualBench::recordMeasurement() {
+    double measurement = this->elapsed() / (FLAGS_frames * fLoops * fFlushes);
+    fRecords.back().fMeasurements.push_back(measurement);
+}
+
+void VisualBench::postDraw(SkCanvas* canvas) {
+    fBenchmark->perCanvasPostDraw(canvas);
+    fBenchmark.reset(NULL);
+    fCurrentSample = 0;
+    fFlushes = 1;
+    fLoops = 1;
+}
+
+inline void VisualBench::timing(SkCanvas* canvas) {
+    if (fCurrentFrame >= FLAGS_frames) {
+        this->recordMeasurement();
+        if (fCurrentSample++ >= FLAGS_samples) {
+            this->printStats();
+            this->postDraw(canvas);
+            this->nextState(kPreWarmLoopsPerCanvasPreDraw_State);
+        } else {
+            this->nextState(kPreWarmTimingPerCanvasPreDraw_State);
+        }
+        this->resetTimingState();
+    } else {
+        fCurrentFrame++;
+    }
+}
+
 void VisualBench::onSizeChange() {
     this->setupRenderTarget();
 }
diff --git a/tools/VisualBench/VisualBench.h b/tools/VisualBench/VisualBench.h
index b8cd2bd..9843693 100644
--- a/tools/VisualBench/VisualBench.h
+++ b/tools/VisualBench/VisualBench.h
@@ -39,6 +39,34 @@
     void onSizeChange() override;
 
 private:
+    /*
+     * The heart of visual bench is an event driven timing loop.
+     * kPreWarmLoopsPerCanvasPreDraw_State:  Before we begin timing, Benchmarks have a hook to
+     *                                       access the canvas.  Then we prewarm before the autotune
+     *                                       loops step.
+     * kPreWarmLoops_State:                  We prewarm the gpu before auto tuning to enter a steady
+     *                                       work state
+     * kTuneLoops_State:                     Then we tune the loops of the benchmark to ensure we
+     *                                       are doing a measurable amount of work
+     * kPreWarmTimingPerCanvasPreDraw_State: Because reset the context after tuning loops to ensure
+     *                                       coherent state, we need to give the benchmark
+     *                                       another hook
+     * kPreWarmTiming_State:                 We prewarm the gpu again to enter a steady state
+     * kTiming_State:                        Finally we time the benchmark.  When finished timing
+     *                                       if we have enough samples then we'll start the next
+     *                                       benchmark in the kPreWarmLoopsPerCanvasPreDraw_State.
+     *                                       otherwise, we enter the
+     *                                       kPreWarmTimingPerCanvasPreDraw_State for another sample
+     *                                       In either case we reset the context.
+     */
+    enum State {
+        kPreWarmLoopsPerCanvasPreDraw_State,
+        kPreWarmLoops_State,
+        kTuneLoops_State,
+        kPreWarmTimingPerCanvasPreDraw_State,
+        kPreWarmTiming_State,
+        kTiming_State,
+    };
     void setTitle();
     bool setupBackend();
     void resetContext();
@@ -47,19 +75,21 @@
     void printStats();
     bool advanceRecordIfNecessary(SkCanvas*);
     inline void renderFrame(SkCanvas*);
+    inline void nextState(State);
+    void perCanvasPreDraw(SkCanvas*, State);
+    void preWarm(State nextState);
+    void scaleLoops(double elapsedMs);
+    inline void tuneLoops();
+    inline void timing(SkCanvas*);
+    inline double elapsed();
+    void resetTimingState();
+    void postDraw(SkCanvas*);
+    void recordMeasurement();
 
     struct Record {
         SkTArray<double> fMeasurements;
     };
 
-    enum State {
-        kPreWarmLoops_State,
-        kTuneLoops_State,
-        kPreWarmTiming_State,
-        kTiming_State,
-    };
-    void preWarm(State nextState);
-
     int fCurrentSample;
     int fCurrentFrame;
     int fFlushes;