Adding rtree support to the bench_pictures utility
Review URL: https://codereview.appspot.com/6775080

git-svn-id: http://skia.googlecode.com/svn/trunk@6267 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/tools/PictureRenderer.cpp b/tools/PictureRenderer.cpp
index e6d86dd..064557b 100644
--- a/tools/PictureRenderer.cpp
+++ b/tools/PictureRenderer.cpp
@@ -18,6 +18,7 @@
 #include "SkImageEncoder.h"
 #include "SkMatrix.h"
 #include "SkPicture.h"
+#include "SkRTree.h"
 #include "SkScalar.h"
 #include "SkString.h"
 #include "SkTemplates.h"
@@ -45,6 +46,7 @@
     }
 
     fPicture = pict;
+    fPicture->ref();
     fCanvas.reset(this->setupCanvas());
 }
 
@@ -78,10 +80,28 @@
 
 void PictureRenderer::end() {
     this->resetState();
+    SkSafeUnref(fPicture);
     fPicture = NULL;
     fCanvas.reset(NULL);
 }
 
+/** Converts fPicture to a picture that uses a BBoxHierarchy.
+ *  PictureRenderer subclasses that are used to test picture playback
+ *  should call this method during init.
+ */
+void PictureRenderer::buildBBoxHierarchy() {
+    SkASSERT(NULL != fPicture);
+    if (kNone_BBoxHierarchyType != fBBoxHierarchyType && NULL != fPicture) {
+        SkPicture* newPicture = this->createPicture();
+        SkCanvas* recorder = newPicture->beginRecording(fPicture->width(), fPicture->height(),
+                                                        this->recordFlags());
+        fPicture->draw(recorder);
+        newPicture->endRecording();
+        fPicture->unref();
+        fPicture = newPicture;
+    }
+}
+
 void PictureRenderer::resetState() {
 #if SK_SUPPORT_GPU
     if (this->isUsingGpuDevice()) {
@@ -99,6 +119,11 @@
 #endif
 }
 
+uint32_t PictureRenderer::recordFlags() {
+    return kNone_BBoxHierarchyType == fBBoxHierarchyType ? 0 :
+        SkPicture::kOptimizeForClippedPlayback_RecordingFlag;
+}
+
 /**
  * Write the canvas to the specified path.
  * @param canvas Must be non-null. Canvas to be written to a file.
@@ -140,10 +165,11 @@
 ///////////////////////////////////////////////////////////////////////////////////////////////
 
 bool RecordPictureRenderer::render(const SkString*) {
-    SkPicture replayer;
-    SkCanvas* recorder = replayer.beginRecording(fPicture->width(), fPicture->height());
+    SkAutoTUnref<SkPicture> replayer(this->createPicture());
+    SkCanvas* recorder = replayer->beginRecording(fPicture->width(), fPicture->height(),
+                                                  this->recordFlags());
     fPicture->draw(recorder);
-    replayer.endRecording();
+    replayer->endRecording();
     // Since this class does not actually render, return false.
     return false;
 }
@@ -171,6 +197,11 @@
 
 ///////////////////////////////////////////////////////////////////////////////////////////////
 
+void SimplePictureRenderer::init(SkPicture* picture) {
+    INHERITED::init(picture);
+    this->buildBBoxHierarchy();
+}
+
 bool SimplePictureRenderer::render(const SkString* path) {
     SkASSERT(fCanvas.get() != NULL);
     SkASSERT(fPicture != NULL);
@@ -210,6 +241,10 @@
     // Do not call INHERITED::init(), which would create a (potentially large) canvas which is not
     // used by bench_pictures.
     fPicture = pict;
+    fPicture->ref();
+    if (!fUsePipe) {
+        this->buildBBoxHierarchy();
+    }
 
     if (fTileWidthPercentage > 0) {
         fTileWidth = sk_float_ceil2int(float(fTileWidthPercentage * fPicture->width() / 100));
@@ -521,14 +556,42 @@
 ///////////////////////////////////////////////////////////////////////////////////////////////
 
 void PlaybackCreationRenderer::setup() {
-    SkCanvas* recorder = fReplayer.beginRecording(fPicture->width(), fPicture->height());
+    fReplayer.reset(this->createPicture());
+    SkCanvas* recorder = fReplayer->beginRecording(fPicture->width(), fPicture->height(),
+                                                   this->recordFlags());
     fPicture->draw(recorder);
 }
 
 bool PlaybackCreationRenderer::render(const SkString*) {
-    fReplayer.endRecording();
+    fReplayer->endRecording();
     // Since this class does not actually render, return false.
     return false;
 }
 
+///////////////////////////////////////////////////////////////////////////////////////////////
+// SkPicture variants for each BBoxHierarchy type
+
+class RTreePicture : public SkPicture {
+public:
+    virtual SkBBoxHierarchy* createBBoxHierarchy() const SK_OVERRIDE{
+        static const int kRTreeMinChildren = 6;
+        static const int kRTreeMaxChildren = 11;
+        SkScalar aspectRatio = SkScalarDiv(SkIntToScalar(fWidth),
+                                           SkIntToScalar(fHeight));
+        return SkRTree::Create(kRTreeMinChildren, kRTreeMaxChildren,
+                               aspectRatio);
+    }
+};
+
+SkPicture* PictureRenderer::createPicture() {
+    switch (fBBoxHierarchyType) {
+        case kNone_BBoxHierarchyType:
+            return SkNEW(SkPicture);
+        case kRTree_BBoxHierarchyType:
+            return SkNEW(RTreePicture);
+    }
+    SkASSERT(0); // invalid bbhType
+    return NULL;
 }
+
+} // namespace sk_tools