Add overdraw visualization to the debugger

https://codereview.appspot.com/7267043/



git-svn-id: http://skia.googlecode.com/svn/trunk@7627 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/debugger/QT/SkDebuggerGUI.cpp b/debugger/QT/SkDebuggerGUI.cpp
index 6005944..890c607 100644
--- a/debugger/QT/SkDebuggerGUI.cpp
+++ b/debugger/QT/SkDebuggerGUI.cpp
@@ -89,6 +89,7 @@
     connect(fSettingsWidget.getVisibilityButton(), SIGNAL(toggled(bool)), this, SLOT(actionCommandFilter()));
     connect(fSettingsWidget.getGLCheckBox(), SIGNAL(toggled(bool)), this, SLOT(actionGLWidget(bool)));
     connect(fSettingsWidget.getRasterCheckBox(), SIGNAL(toggled(bool)), this, SLOT(actionRasterWidget(bool)));
+    connect(fSettingsWidget.getOverdrawVizCheckBox(), SIGNAL(toggled(bool)), this, SLOT(actionOverdrawVizWidget(bool)));
     connect(&fActionPause, SIGNAL(toggled(bool)), this, SLOT(pauseDrawing(bool)));
     connect(&fActionCreateBreakpoint, SIGNAL(activated()), this, SLOT(toggleBreakpoint()));
     connect(&fActionShowDeletes, SIGNAL(triggered()), this, SLOT(showDeletes()));
@@ -516,6 +517,11 @@
     fCanvasWidget.setWidgetVisibility(SkCanvasWidget::kRaster_8888_WidgetType, !isToggled);
 }
 
+void SkDebuggerGUI::actionOverdrawVizWidget(bool isToggled) {
+    fDebugger.setOverdrawViz(isToggled);
+    fCanvasWidget.update();
+}
+
 void SkDebuggerGUI::actionRewind() {
     fListWidget.setCurrentRow(0);
 }
diff --git a/debugger/QT/SkDebuggerGUI.h b/debugger/QT/SkDebuggerGUI.h
index 6d57a8a..4130e96 100644
--- a/debugger/QT/SkDebuggerGUI.h
+++ b/debugger/QT/SkDebuggerGUI.h
@@ -134,6 +134,11 @@
     void actionRasterWidget(bool isToggled);
 
     /**
+        Toggles the the overdraw visualization on and off
+     */
+    void actionOverdrawVizWidget(bool isToggled);
+
+    /**
         Rewinds from the current step back to the start of the commands.
      */
     void actionRewind();
diff --git a/debugger/QT/SkRasterWidget.cpp b/debugger/QT/SkRasterWidget.cpp
index a8a36a8..db3d00f 100644
--- a/debugger/QT/SkRasterWidget.cpp
+++ b/debugger/QT/SkRasterWidget.cpp
@@ -27,6 +27,7 @@
 void SkRasterWidget::resizeEvent(QResizeEvent* event) {
     fBitmap.setConfig(SkBitmap::kARGB_8888_Config, event->size().width(), event->size().height());
     fBitmap.allocPixels();
+    fBitmap.eraseColor(SK_ColorTRANSPARENT);
     SkSafeUnref(fCanvas);
     SkSafeUnref(fDevice);
     fDevice = new SkDevice(fBitmap);
diff --git a/debugger/QT/SkSettingsWidget.cpp b/debugger/QT/SkSettingsWidget.cpp
index c74be40..09196fb 100644
--- a/debugger/QT/SkSettingsWidget.cpp
+++ b/debugger/QT/SkSettingsWidget.cpp
@@ -59,6 +59,10 @@
 
     fRasterCheckBox.setChecked(true);
 
+    fOverdrawVizLabel.setText("     Overdraw Viz: ");
+    fOverdrawVizLabel.setMinimumWidth(178);
+    fOverdrawVizLabel.setMaximumWidth(178);
+
     fGLLabel.setText("OpenGL: ");
     fGLLabel.setMinimumWidth(178);
     fGLLabel.setMaximumWidth(178);
@@ -66,12 +70,16 @@
     fRasterLayout.addWidget(&fRasterLabel);
     fRasterLayout.addWidget(&fRasterCheckBox);
 
+    fOverdrawVizLayout.addWidget(&fOverdrawVizLabel);
+    fOverdrawVizLayout.addWidget(&fOverdrawVizCheckBox);
+
     fGLLayout.addWidget(&fGLLabel);
     fGLLayout.addWidget(&fGLCheckBox);
 
     fCanvasLayout.setSpacing(6);
     fCanvasLayout.setContentsMargins(11,11,11,11);
     fCanvasLayout.addLayout(&fRasterLayout);
+    fCanvasLayout.addLayout(&fOverdrawVizLayout);
     fCanvasLayout.addLayout(&fGLLayout);
 
     // Command Toggle
diff --git a/debugger/QT/SkSettingsWidget.h b/debugger/QT/SkSettingsWidget.h
index 1f75527..73cd6e1 100644
--- a/debugger/QT/SkSettingsWidget.h
+++ b/debugger/QT/SkSettingsWidget.h
@@ -47,6 +47,10 @@
         return &fRasterCheckBox;
     }
 
+    QCheckBox* getOverdrawVizCheckBox() {
+        return &fOverdrawVizCheckBox;
+    }
+
 private slots:
     void updateCommand(int newCommand);
     void updateHit(int newHit);
@@ -87,6 +91,10 @@
     QLabel fRasterLabel;
     QCheckBox fRasterCheckBox;
 
+    QHBoxLayout fOverdrawVizLayout;
+    QLabel fOverdrawVizLabel;
+    QCheckBox fOverdrawVizCheckBox;
+
     QHBoxLayout fGLLayout;
     QLabel fGLLabel;
     QCheckBox fGLCheckBox;
diff --git a/debugger/SkDebugCanvas.cpp b/debugger/SkDebugCanvas.cpp
index 27b58da..23f3d34 100644
--- a/debugger/SkDebugCanvas.cpp
+++ b/debugger/SkDebugCanvas.cpp
@@ -7,9 +7,12 @@
  */
 
 
+#include "SkColorPriv.h"
 #include "SkDebugCanvas.h"
 #include "SkDrawCommand.h"
+#include "SkDrawFilter.h"
 #include "SkDevice.h"
+#include "SkXfermode.h"
 
 #ifdef SK_BUILD_FOR_WIN
     // iostream includes xlocale which generates warning 4530 because we're compiling without
@@ -30,7 +33,9 @@
 
 SkDebugCanvas::SkDebugCanvas(int width, int height)
         : INHERITED(make_noconfig_bm(width, height))
-        , fOutstandingSaveCount(0) {
+        , fOutstandingSaveCount(0)
+        , fOverdrawViz(false)
+        , fOverdrawFilter(NULL) {
     // TODO(chudy): Free up memory from all draw commands in destructor.
     fWidth = width;
     fHeight = height;
@@ -43,6 +48,7 @@
 
 SkDebugCanvas::~SkDebugCanvas() {
     fCommandVector.deleteAll();
+    SkSafeUnref(fOverdrawFilter);
 }
 
 void SkDebugCanvas::addDrawCommand(SkDrawCommand* command) {
@@ -87,6 +93,55 @@
     return layer;
 }
 
+SkPMColor OverdrawXferModeProc(SkPMColor src, SkPMColor dst) {
+    // This table encodes the color progression of the overdraw visualization
+    static const SkPMColor gTable[] = {
+        SkPackARGB32(0x00, 0x00, 0x00, 0x00),
+        SkPackARGB32(0xFF, 128, 158, 255),
+        SkPackARGB32(0xFF, 170, 185, 212),
+        SkPackARGB32(0xFF, 213, 195, 170),
+        SkPackARGB32(0xFF, 255, 192, 127),
+        SkPackARGB32(0xFF, 255, 185, 85),
+        SkPackARGB32(0xFF, 255, 165, 42),
+        SkPackARGB32(0xFF, 255, 135, 0),
+        SkPackARGB32(0xFF, 255,  95, 0),
+        SkPackARGB32(0xFF, 255,  50, 0),
+        SkPackARGB32(0xFF, 255,  0, 0)
+    };
+
+    for (int i = 0; i < SK_ARRAY_COUNT(gTable)-1; ++i) {
+        if (gTable[i] == dst) {
+            return gTable[i+1];
+        }
+    }
+
+    return gTable[SK_ARRAY_COUNT(gTable)-1];
+}
+
+// The OverdrawFilter modifies every paint to use an SkProcXfermode which
+// in turn invokes OverdrawXferModeProc
+class OverdrawFilter : public SkDrawFilter {
+public:
+    OverdrawFilter() {
+        fXferMode = new SkProcXfermode(OverdrawXferModeProc);
+    }
+
+    virtual ~OverdrawFilter() {
+        delete fXferMode;
+    }
+
+    virtual bool filter(SkPaint* p, Type) SK_OVERRIDE {
+        p->setXfermode(fXferMode);
+        return true;
+    }
+
+protected:
+    SkXfermode* fXferMode;
+
+private:
+    typedef SkDrawFilter INHERITED;
+};
+
 void SkDebugCanvas::drawTo(SkCanvas* canvas, int index) {
     SkASSERT(!fCommandVector.isEmpty());
     SkASSERT(index < fCommandVector.count());
@@ -109,6 +164,22 @@
         canvas->clipRect(rect, SkRegion::kReplace_Op );
         applyUserTransform(canvas);
         fOutstandingSaveCount = 0;
+
+        // The setting of the draw filter has to go here (rather than in
+        // SkRasterWidget) due to the canvas restores this class performs.
+        // Since the draw filter is stored in the layer stack if we
+        // call setDrawFilter on anything but the root layer odd things happen
+        if (fOverdrawViz) {
+            if (NULL == fOverdrawFilter) {
+                fOverdrawFilter = new OverdrawFilter;
+            }
+
+            if (fOverdrawFilter != canvas->getDrawFilter()) {
+                canvas->setDrawFilter(fOverdrawFilter);
+            }
+        } else {
+            canvas->setDrawFilter(NULL);
+        }
     }
 
     for (; i <= index; i++) {
diff --git a/debugger/SkDebugCanvas.h b/debugger/SkDebugCanvas.h
index 238c5c0..a29fe6a 100644
--- a/debugger/SkDebugCanvas.h
+++ b/debugger/SkDebugCanvas.h
@@ -19,11 +19,16 @@
 class SkDebugCanvas : public SkCanvas {
 public:
     SkDebugCanvas(int width, int height);
-    ~SkDebugCanvas();
+    virtual ~SkDebugCanvas();
 
     void toggleFilter(bool toggle);
 
     /**
+     * Enable or disable overdraw visualization
+     */
+    void setOverdrawViz(bool overdrawViz) { fOverdrawViz = overdrawViz; }
+
+    /**
         Executes all draw calls to the canvas.
         @param canvas  The canvas being drawn to
      */
@@ -213,6 +218,8 @@
     SkMatrix fUserMatrix;
     SkMatrix fMatrix;
     SkIRect fClip;
+    bool fOverdrawViz;
+    SkDrawFilter* fOverdrawFilter;
 
     /**
         Number of unmatched save() calls at any point during a draw.
diff --git a/debugger/SkDebugger.h b/debugger/SkDebugger.h
index 6b85de3..6749ff7 100644
--- a/debugger/SkDebugger.h
+++ b/debugger/SkDebugger.h
@@ -99,6 +99,13 @@
         return fIndex;
     }
 
+    void setOverdrawViz(bool overDrawViz) {
+        if (NULL != fDebugCanvas) {
+            fDebugCanvas->setOverdrawViz(overDrawViz);
+        }
+    }
+
+
 private:
     SkDebugCanvas* fDebugCanvas;
     SkPicture* fPicture;