Add benchmark to compare different BBH query patterns.

On my laptop:
maxrss	loops	min	median	mean	max	stddev	samples   	config	bench
  37M	1	14ms	14.2ms	14.6ms	18.2ms	9%	▁█▁▁▁▁▂▂▂▁	gpu	tiled_playback_tilegrid_tiled
  40M	1	17ms	17.2ms	17.2ms	17.6ms	1%	▆▃▁█▄▇▂▁▁▁	gpu	tiled_playback_tilegrid_random
  40M	1	14.6ms	14.9ms	15.8ms	19.1ms	11%	▂▁▁▁▁▁▁█▅█	gpu	tiled_playback_rtree_tiled
  43M	1	16.5ms	16.7ms	16.8ms	17.4ms	1%	▂▃▅█▃▂▁▃▃▂	gpu	tiled_playback_rtree_random
  43M	1	15.9ms	16.1ms	16.5ms	18.7ms	6%	▁▁█▇▁▁▁▂▁▁	gpu	tiled_playback_none_tiled
  44M	1	17.9ms	17.9ms	18ms	18.1ms	1%	▂▁▅▁▇▃▁▂█▇	gpu	tiled_playback_none_random

TileGrid and RTree perform pretty much the same, both beating no BBH.

BUG=skia:3085

Review URL: https://codereview.chromium.org/699313006
diff --git a/bench/PicturePlaybackBench.cpp b/bench/PicturePlaybackBench.cpp
index 947a784..d500029 100644
--- a/bench/PicturePlaybackBench.cpp
+++ b/bench/PicturePlaybackBench.cpp
@@ -11,6 +11,7 @@
 #include "SkPicture.h"
 #include "SkPictureRecorder.h"
 #include "SkPoint.h"
+#include "SkRandom.h"
 #include "SkRect.h"
 #include "SkString.h"
 
@@ -139,3 +140,85 @@
 DEF_BENCH( return new TextPlaybackBench(); )
 DEF_BENCH( return new PosTextPlaybackBench(true); )
 DEF_BENCH( return new PosTextPlaybackBench(false); )
+
+// Chrome draws into small tiles with impl-side painting.
+// This benchmark measures the relative performance of our bounding-box hierarchies,
+// both when querying tiles perfectly and when not.
+enum BBH  { kNone, kRTree, kTileGrid };
+enum Mode { kTiled, kRandom };
+class TiledPlaybackBench : public Benchmark {
+public:
+    TiledPlaybackBench(BBH bbh, Mode mode) : fBBH(bbh), fMode(mode), fName("tiled_playback") {
+        switch (fBBH) {
+            case kNone:     fName.append("_none"    ); break;
+            case kRTree:    fName.append("_rtree"   ); break;
+            case kTileGrid: fName.append("_tilegrid"); break;
+        }
+        switch (fMode) {
+            case kTiled:  fName.append("_tiled" ); break;
+            case kRandom: fName.append("_random"); break;
+        }
+    }
+
+    virtual const char* onGetName() SK_OVERRIDE { return fName.c_str(); }
+    virtual SkIPoint onGetSize() SK_OVERRIDE { return SkIPoint::Make(1024,1024); }
+
+    virtual void onPreDraw() SK_OVERRIDE {
+        SkTileGridFactory::TileGridInfo info = { { 256, 256 }, {0,0}, {0,0} };
+        SkAutoTDelete<SkBBHFactory> factory;
+        switch (fBBH) {
+            case kNone:                                                 break;
+            case kRTree:    factory.reset(new SkRTreeFactory);          break;
+            case kTileGrid: factory.reset(new SkTileGridFactory(info)); break;
+        }
+
+        SkPictureRecorder recorder;
+        SkCanvas* canvas = recorder.beginRecording(1024, 1024, factory);
+            SkRandom rand;
+            for (int i = 0; i < 10000; i++) {
+                SkScalar x = rand.nextRangeScalar(0, 1024),
+                         y = rand.nextRangeScalar(0, 1024),
+                         w = rand.nextRangeScalar(0, 128),
+                         h = rand.nextRangeScalar(0, 128);
+                SkPaint paint;
+                paint.setColor(rand.nextU());
+                paint.setAlpha(0xFF);
+                canvas->drawRect(SkRect::MakeXYWH(x,y,w,h), paint);
+            }
+        fPic.reset(recorder.endRecording());
+    }
+
+    virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+        for (int i = 0; i < loops; i++) {
+            // This inner loop guarantees we make the same choices for all bench variants.
+            SkRandom rand;
+            for (int j = 0; j < 10; j++) {
+                SkScalar x = 0, y = 0;
+                switch (fMode) {
+                    case kTiled:  x = SkScalar(256 * rand.nextULessThan(4));
+                                  y = SkScalar(256 * rand.nextULessThan(4));
+                                  break;
+                    case kRandom: x = rand.nextRangeScalar(0, 768);
+                                  y = rand.nextRangeScalar(0, 768);
+                                  break;
+                }
+                SkAutoCanvasRestore ar(canvas, true/*save now*/);
+                canvas->clipRect(SkRect::MakeXYWH(x,y,256,256));
+                fPic->playback(canvas);
+            }
+        }
+    }
+
+private:
+    BBH                      fBBH;
+    Mode                     fMode;
+    SkString                 fName;
+    SkAutoTDelete<SkPicture> fPic;
+};
+
+DEF_BENCH( return new TiledPlaybackBench(kNone,     kRandom); )
+DEF_BENCH( return new TiledPlaybackBench(kNone,     kTiled ); )
+DEF_BENCH( return new TiledPlaybackBench(kRTree,    kRandom); )
+DEF_BENCH( return new TiledPlaybackBench(kRTree,    kTiled ); )
+DEF_BENCH( return new TiledPlaybackBench(kTileGrid, kRandom); )
+DEF_BENCH( return new TiledPlaybackBench(kTileGrid, kTiled ); )