The new "mega" viz mode both adds visualization and forces all drawing to the visible canvas (by replacing the active saveLayers with saves).

R=bsalomon@google.com

Author: robertphillips@google.com

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

git-svn-id: http://skia.googlecode.com/svn/trunk@13640 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/debugger/QT/SkDebuggerGUI.cpp b/debugger/QT/SkDebuggerGUI.cpp
index 0311948..a30cde2 100644
--- a/debugger/QT/SkDebuggerGUI.cpp
+++ b/debugger/QT/SkDebuggerGUI.cpp
@@ -97,6 +97,7 @@
     connect(&fSettingsWidget, SIGNAL(texFilterSettingsChanged()), this, SLOT(actionTextureFilter()));
     connect(fSettingsWidget.getRasterCheckBox(), SIGNAL(toggled(bool)), this, SLOT(actionRasterWidget(bool)));
     connect(fSettingsWidget.getOverdrawVizCheckBox(), SIGNAL(toggled(bool)), this, SLOT(actionOverdrawVizWidget(bool)));
+    connect(fSettingsWidget.getMegaVizCheckBox(), SIGNAL(toggled(bool)), this, SLOT(actionMegaVizWidget(bool)));
     connect(&fActionPause, SIGNAL(toggled(bool)), this, SLOT(pauseDrawing(bool)));
     connect(&fActionCreateBreakpoint, SIGNAL(activated()), this, SLOT(toggleBreakpoint()));
     connect(&fActionShowDeletes, SIGNAL(triggered()), this, SLOT(showDeletes()));
@@ -521,6 +522,11 @@
     fCanvasWidget.update();
 }
 
+void SkDebuggerGUI::actionMegaVizWidget(bool isToggled) {
+    fDebugger.setMegaViz(isToggled);
+    fCanvasWidget.update();
+}
+
 void SkDebuggerGUI::actionTextureFilter() {
     SkPaint::FilterLevel level;
     bool enabled = fSettingsWidget.getFilterOverride(&level);
diff --git a/debugger/QT/SkDebuggerGUI.h b/debugger/QT/SkDebuggerGUI.h
index cdda861..50ebfc2 100644
--- a/debugger/QT/SkDebuggerGUI.h
+++ b/debugger/QT/SkDebuggerGUI.h
@@ -142,6 +142,11 @@
     void actionOverdrawVizWidget(bool isToggled);
 
     /**
+        Toggles the the mega visualization on and off
+     */
+    void actionMegaVizWidget(bool isToggled);
+
+    /**
         Applies the new texture filter override
      */
     void actionTextureFilter();
diff --git a/debugger/QT/SkSettingsWidget.cpp b/debugger/QT/SkSettingsWidget.cpp
index dc40b40..29026cf 100644
--- a/debugger/QT/SkSettingsWidget.cpp
+++ b/debugger/QT/SkSettingsWidget.cpp
@@ -62,6 +62,10 @@
     fOverdrawVizLabel.setMinimumWidth(178);
     fOverdrawVizLabel.setMaximumWidth(178);
 
+    fMegaVizLabel.setText("         Mega Viz: ");
+    fMegaVizLabel.setMinimumWidth(178);
+    fMegaVizLabel.setMaximumWidth(178);
+
 #if SK_SUPPORT_GPU
     fGLLabel.setText("OpenGL: ");
     fGLLabel.setMinimumWidth(178);
@@ -109,8 +113,10 @@
     fRasterLayout.addWidget(&fRasterLabel);
     fRasterLayout.addWidget(&fRasterCheckBox);
 
-    fOverdrawVizLayout.addWidget(&fOverdrawVizLabel);
-    fOverdrawVizLayout.addWidget(&fOverdrawVizCheckBox);
+    fVizLayout.addWidget(&fOverdrawVizLabel);
+    fVizLayout.addWidget(&fOverdrawVizCheckBox);
+    fVizLayout.addWidget(&fMegaVizLabel);
+    fVizLayout.addWidget(&fMegaVizCheckBox);
 
 #if SK_SUPPORT_GPU
     fGLLayout.addWidget(&fGLLabel);
@@ -120,7 +126,7 @@
     fCanvasLayout.setSpacing(6);
     fCanvasLayout.setContentsMargins(11,11,11,11);
     fCanvasLayout.addLayout(&fRasterLayout);
-    fCanvasLayout.addLayout(&fOverdrawVizLayout);
+    fCanvasLayout.addLayout(&fVizLayout);
 #if SK_SUPPORT_GPU
     fCanvasLayout.addLayout(&fGLLayout);
     fCanvasLayout.addWidget(&fGLMSAAButtonGroup);
diff --git a/debugger/QT/SkSettingsWidget.h b/debugger/QT/SkSettingsWidget.h
index 2310011..660da77 100644
--- a/debugger/QT/SkSettingsWidget.h
+++ b/debugger/QT/SkSettingsWidget.h
@@ -70,6 +70,10 @@
         return &fOverdrawVizCheckBox;
     }
 
+    QCheckBox* getMegaVizCheckBox() {
+        return &fMegaVizCheckBox;
+    }
+
 private slots:
     void updateCommand(int newCommand);
     void updateHit(int newHit);
@@ -113,9 +117,11 @@
     QLabel fRasterLabel;
     QCheckBox fRasterCheckBox;
 
-    QHBoxLayout fOverdrawVizLayout;
+    QHBoxLayout fVizLayout;
     QLabel fOverdrawVizLabel;
     QCheckBox fOverdrawVizCheckBox;
+    QLabel fMegaVizLabel;
+    QCheckBox fMegaVizCheckBox;
 
 #if SK_SUPPORT_GPU
     QHBoxLayout fGLLayout;
diff --git a/debugger/SkDebugger.h b/debugger/SkDebugger.h
index 182f226..20c4a78 100644
--- a/debugger/SkDebugger.h
+++ b/debugger/SkDebugger.h
@@ -107,6 +107,12 @@
         }
     }
 
+    void setMegaViz(bool megaViz) {
+        if (NULL != fDebugCanvas) {
+            fDebugCanvas->setMegaVizMode(megaViz);
+        }
+    }
+
     void setTexFilterOverride(bool texFilterOverride, SkPaint::FilterLevel level) {
         if (NULL != fDebugCanvas) {
             fDebugCanvas->overrideTexFiltering(texFilterOverride, level);
diff --git a/src/utils/debugger/SkDebugCanvas.cpp b/src/utils/debugger/SkDebugCanvas.cpp
index fedef69..db2b7dc 100644
--- a/src/utils/debugger/SkDebugCanvas.cpp
+++ b/src/utils/debugger/SkDebugCanvas.cpp
@@ -19,6 +19,7 @@
         , fWidth(width)
         , fHeight(height)
         , fFilter(false)
+        , fMegaVizMode(false)
         , fIndex(0)
         , fOverdrawViz(false)
         , fOverdrawFilter(NULL)
@@ -161,6 +162,62 @@
     typedef SkDrawFilter INHERITED;
 };
 
+class SkDebugClipVisitor : public SkCanvas::ClipVisitor {
+public:
+    SkDebugClipVisitor(SkCanvas* canvas) : fCanvas(canvas) {}
+
+    virtual void clipRect(const SkRect& r, SkRegion::Op, bool doAA) SK_OVERRIDE {
+        SkPaint p;
+        p.setColor(SK_ColorRED);
+        p.setStyle(SkPaint::kStroke_Style);
+        p.setAntiAlias(doAA);
+        fCanvas->drawRect(r, p);
+    }
+    virtual void clipRRect(const SkRRect& rr, SkRegion::Op, bool doAA) SK_OVERRIDE {
+        SkPaint p;
+        p.setColor(SK_ColorGREEN);
+        p.setStyle(SkPaint::kStroke_Style);
+        p.setAntiAlias(doAA);
+        fCanvas->drawRRect(rr, p);
+    }
+    virtual void clipPath(const SkPath& path, SkRegion::Op, bool doAA) SK_OVERRIDE {
+        SkPaint p;
+        p.setColor(SK_ColorBLUE);
+        p.setStyle(SkPaint::kStroke_Style);
+        p.setAntiAlias(doAA);
+        fCanvas->drawPath(path, p);
+    }
+
+protected:
+    SkCanvas* fCanvas;
+
+private:
+    typedef SkCanvas::ClipVisitor INHERITED;
+};
+
+// set up the saveLayer commands so that the active ones
+// return true in their 'active' method
+void SkDebugCanvas::markActiveSaveLayers(int index) {
+    SkTDArray<SkDrawCommand*> activeLayers;
+
+    for (int i = 0; i < fCommandVector.count(); ++i) {
+        fCommandVector[i]->setActive(false);
+    }
+
+    for (int i = 0; i < index; ++i) {
+        SkDrawCommand::Action result = fCommandVector[i]->action();
+        if (SkDrawCommand::kPush_Action == result) {
+            activeLayers.push(fCommandVector[i]);
+        } else if (SkDrawCommand::kPop_Action == result) {
+            activeLayers.pop();
+        }
+    }
+
+    for (int i = 0; i < activeLayers.count(); ++i) {
+        activeLayers[i]->setActive(true);
+    }
+}
+
 void SkDebugCanvas::drawTo(SkCanvas* canvas, int index) {
     SkASSERT(!fCommandVector.isEmpty());
     SkASSERT(index < fCommandVector.count());
@@ -171,7 +228,7 @@
     // and restores.
     // The visibility filter also requires a full re-draw - otherwise we can
     // end up drawing the filter repeatedly.
-    if (fIndex < index && !fFilter) {
+    if (fIndex < index && !fFilter && !fMegaVizMode) {
         i = fIndex + 1;
     } else {
         for (int j = 0; j < fOutstandingSaveCount; j++) {
@@ -210,6 +267,10 @@
         canvas->setDrawFilter(NULL);
     }
 
+    if (fMegaVizMode) {
+        this->markActiveSaveLayers(index);
+    }
+
     for (; i <= index; i++) {
         if (i == index && fFilter) {
             SkPaint p;
@@ -226,10 +287,35 @@
         }
 
         if (fCommandVector[i]->isVisible()) {
-            fCommandVector[i]->execute(canvas);
-            fCommandVector[i]->trackSaveState(&fOutstandingSaveCount);
+            if (fMegaVizMode && fCommandVector[i]->active()) {
+                // All active saveLayers get replaced with saves so all draws go to the
+                // visible canvas
+                canvas->save();
+                ++fOutstandingSaveCount;
+            } else {
+                fCommandVector[i]->execute(canvas);
+                fCommandVector[i]->trackSaveState(&fOutstandingSaveCount);
+            }
         }
     }
+
+    if (fMegaVizMode) {
+        SkRect r = SkRect::MakeWH(SkIntToScalar(fWidth), SkIntToScalar(fHeight));
+        r.outset(SK_Scalar1, SK_Scalar1);
+
+        canvas->save();
+        // nuke the CTM
+        canvas->setMatrix(SkMatrix::I());
+        // turn off clipping
+        canvas->clipRect(r, SkRegion::kReplace_Op);
+
+        // visualize existing clips
+        SkDebugClipVisitor visitor(canvas);
+
+        canvas->replayClips(&visitor);
+
+        canvas->restore();
+    }
     fMatrix = canvas->getTotalMatrix();
     fClip = canvas->getTotalClip().getBounds();
     fIndex = index;
@@ -281,10 +367,6 @@
     return commandString;
 }
 
-void SkDebugCanvas::toggleFilter(bool toggle) {
-    fFilter = toggle;
-}
-
 void SkDebugCanvas::overrideTexFiltering(bool overrideTexFiltering, SkPaint::FilterLevel level) {
     if (NULL == fTexOverrideFilter) {
         fTexOverrideFilter = new SkTexOverrideFilter;
diff --git a/src/utils/debugger/SkDebugCanvas.h b/src/utils/debugger/SkDebugCanvas.h
index edf7a22..cb4acc8 100644
--- a/src/utils/debugger/SkDebugCanvas.h
+++ b/src/utils/debugger/SkDebugCanvas.h
@@ -23,7 +23,9 @@
     SkDebugCanvas(int width, int height);
     virtual ~SkDebugCanvas();
 
-    void toggleFilter(bool toggle);
+    void toggleFilter(bool toggle) { fFilter = toggle; }
+
+    void setMegaVizMode(bool megaVizMode) { fMegaVizMode = megaVizMode; }
 
     /**
      * Enable or disable overdraw visualization
@@ -252,11 +254,14 @@
     virtual void onClipPath(const SkPath&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
     virtual void onClipRegion(const SkRegion& region, SkRegion::Op) SK_OVERRIDE;
 
+    void markActiveSaveLayers(int index);
+
 private:
     SkTDArray<SkDrawCommand*> fCommandVector;
     int fWidth;
     int fHeight;
     bool fFilter;
+    bool fMegaVizMode;
     int fIndex;
     SkMatrix fUserMatrix;
     SkMatrix fMatrix;
diff --git a/src/utils/debugger/SkDrawCommand.h b/src/utils/debugger/SkDrawCommand.h
index f3f29be..60df688 100644
--- a/src/utils/debugger/SkDrawCommand.h
+++ b/src/utils/debugger/SkDrawCommand.h
@@ -38,8 +38,24 @@
     SkTDArray<SkString*>* Info() {return &fInfo; };
     virtual void execute(SkCanvas* canvas)=0;
     /** Does nothing by default, but used by save() and restore()-type
-        subclassse to track unresolved save() calls. */
+        subclasses to track unresolved save() calls. */
     virtual void trackSaveState(int* state) { };
+
+    // The next "active" system is only used by save, saveLayer and restore.
+    // It is used to determine which saveLayers are currently active (at a 
+    // given point in the rendering).
+    //      save just return a kPush action but don't track active state
+    //      restore just return a kPop action
+    //      saveLayers return kPush but also track the active state
+    enum Action {
+        kNone_Action,
+        kPop_Action,
+        kPush_Action
+    };
+    virtual Action action() const { return kNone_Action; }
+    virtual void setActive(bool active) {}
+    virtual bool active() const { return false; }
+
     DrawType getType() { return fDrawType; };
 
     virtual bool render(SkCanvas* canvas) const { return false; }
@@ -59,6 +75,7 @@
     SkRestoreCommand();
     virtual void execute(SkCanvas* canvas) SK_OVERRIDE;
     virtual void trackSaveState(int* state) SK_OVERRIDE;
+    virtual Action action() const SK_OVERRIDE { return kPop_Action; }
 
 private:
     typedef SkDrawCommand INHERITED;
@@ -496,6 +513,7 @@
     SkSaveCommand(SkCanvas::SaveFlags flags);
     virtual void execute(SkCanvas* canvas) SK_OVERRIDE;
     virtual void trackSaveState(int* state) SK_OVERRIDE;
+    virtual Action action() const SK_OVERRIDE { return kPush_Action; }
 private:
     SkCanvas::SaveFlags fFlags;
 
@@ -508,6 +526,9 @@
                        SkCanvas::SaveFlags flags);
     virtual void execute(SkCanvas* canvas) SK_OVERRIDE;
     virtual void trackSaveState(int* state) SK_OVERRIDE;
+    virtual Action action() const SK_OVERRIDE{ return kPush_Action; }
+    virtual void setActive(bool active) SK_OVERRIDE { fActive = active; }
+    virtual bool active() const SK_OVERRIDE { return fActive; }
 
     const SkPaint* paint() const { return fPaintPtr; }
 
@@ -517,6 +538,8 @@
     SkPaint*            fPaintPtr;
     SkCanvas::SaveFlags fFlags;
 
+    bool                fActive;
+
     typedef SkDrawCommand INHERITED;
 };