Culling API

*** SKP format breaking change ***

Adding a couple of culling primitives: pushCull(SkRect) & popCull().

These are currently only plumbed for SKP playback quickreject.

At record time, we perform a couple of optimizations to trim down the
number of redundant culls:

  * collapse empty pushCull/popCull pairs
  * skip pushCull/popCull pairs nested within an identical cull rect

Things still missing/to consider:

  * use an inlineable, simplified quickreject (Mike's old prototype)
  * debugger visualization for cull boxes
  * BBH integration: the initial prototype had some minimal BBH support,
    but since the optimizations required expensive rewinds and culling
    is expected to be a BBH alternative, it got dropped.

R=bsalomon@google.com, reed@google.com, robertphillips@google.com, caryclark@google.com, tomhudson@google.com, iancottrell@google.com

Author: fmalita@chromium.org

Review URL: https://codereview.chromium.org/138013009

git-svn-id: http://skia.googlecode.com/svn/trunk@13611 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/utils/SkDumpCanvas.cpp b/src/utils/SkDumpCanvas.cpp
index c8a94f4..d768137 100644
--- a/src/utils/SkDumpCanvas.cpp
+++ b/src/utils/SkDumpCanvas.cpp
@@ -297,6 +297,15 @@
     return this->INHERITED::clipRegion(deviceRgn, op);
 }
 
+void SkDumpCanvas::onPushCull(const SkRect& cullRect) {
+    SkString str;
+    toString(cullRect, &str);
+    this->dump(kCull_Verb, NULL, "pushCull(%s)", str.c_str());
+}
+
+void SkDumpCanvas::onPopCull() {
+    this->dump(kCull_Verb, NULL, "popCull()");
+}
 ///////////////////////////////////////////////////////////////////////////////
 
 void SkDumpCanvas::drawPaint(const SkPaint& paint) {
diff --git a/src/utils/debugger/SkDebugCanvas.cpp b/src/utils/debugger/SkDebugCanvas.cpp
index 58b609a..15165c2 100644
--- a/src/utils/debugger/SkDebugCanvas.cpp
+++ b/src/utils/debugger/SkDebugCanvas.cpp
@@ -430,6 +430,14 @@
                    texs, colors, NULL, indices, indexCount, paint));
 }
 
+void SkDebugCanvas::onPushCull(const SkRect& cullRect) {
+    this->addDrawCommand(new SkPushCullCommand(cullRect));
+}
+
+void SkDebugCanvas::onPopCull() {
+    this->addDrawCommand(new SkPopCullCommand());
+}
+
 void SkDebugCanvas::restore() {
     addDrawCommand(new SkRestoreCommand());
 }
diff --git a/src/utils/debugger/SkDebugCanvas.h b/src/utils/debugger/SkDebugCanvas.h
index 94316d5..7d49627 100644
--- a/src/utils/debugger/SkDebugCanvas.h
+++ b/src/utils/debugger/SkDebugCanvas.h
@@ -235,6 +235,8 @@
 
 protected:
     virtual void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) SK_OVERRIDE;
+    virtual void onPushCull(const SkRect& cullRect) SK_OVERRIDE;
+    virtual void onPopCull() SK_OVERRIDE;
 
 private:
     SkTDArray<SkDrawCommand*> fCommandVector;
diff --git a/src/utils/debugger/SkDrawCommand.cpp b/src/utils/debugger/SkDrawCommand.cpp
index 4e410d1..16b8556 100644
--- a/src/utils/debugger/SkDrawCommand.cpp
+++ b/src/utils/debugger/SkDrawCommand.cpp
@@ -65,6 +65,8 @@
         case COMMENT: return "Comment";
         case END_COMMENT_GROUP: return "EndCommentGroup";
         case DRAW_DRRECT: return "Draw DRRect";
+        case PUSH_CULL: return "PushCull";
+        case POP_CULL: return "PopCull";
         default:
             SkDebugf("DrawType error 0x%08x\n", type);
             SkASSERT(0);
@@ -936,3 +938,22 @@
 void SkTranslateCommand::execute(SkCanvas* canvas) {
     canvas->translate(fDx, fDy);
 }
+
+SkPushCullCommand::SkPushCullCommand(const SkRect& cullRect)
+    : fCullRect(cullRect) {
+    fDrawType = PUSH_CULL;
+    fInfo.push(SkObjectParser::RectToString(cullRect));
+}
+
+void SkPushCullCommand::execute(SkCanvas* canvas) {
+    //FIXME: add visualization overlay.
+    canvas->pushCull(fCullRect);
+}
+
+SkPopCullCommand::SkPopCullCommand() {
+    fDrawType = POP_CULL;
+}
+
+void SkPopCullCommand::execute(SkCanvas* canvas) {
+    canvas->popCull();
+}
diff --git a/src/utils/debugger/SkDrawCommand.h b/src/utils/debugger/SkDrawCommand.h
index e03eb07..f3f29be 100644
--- a/src/utils/debugger/SkDrawCommand.h
+++ b/src/utils/debugger/SkDrawCommand.h
@@ -571,4 +571,24 @@
     typedef SkDrawCommand INHERITED;
 };
 
+class SkPushCullCommand : public SkDrawCommand {
+public:
+    SkPushCullCommand(const SkRect&);
+    virtual void execute(SkCanvas*) SK_OVERRIDE;
+
+private:
+    SkRect fCullRect;
+
+    typedef SkDrawCommand INHERITED;
+};
+
+class SkPopCullCommand : public SkDrawCommand {
+public:
+    SkPopCullCommand();
+    virtual void execute(SkCanvas* canvas) SK_OVERRIDE;
+
+private:
+    typedef SkDrawCommand INHERITED;
+};
+
 #endif