Revert "Change clear() to respect the clip"

This reverts commit 3729469d6a12266037b697c2192768545e097ab0.

BUG=skia:
TBR=

Review URL: https://codereview.chromium.org/778563002
diff --git a/include/core/SkBitmapDevice.h b/include/core/SkBitmapDevice.h
index 03fd014..dff5e65 100644
--- a/include/core/SkBitmapDevice.h
+++ b/include/core/SkBitmapDevice.h
@@ -40,6 +40,11 @@
 protected:
     bool onShouldDisableLCD(const SkPaint&) const SK_OVERRIDE;
 
+    /** Clears the entire device to the specified color (including alpha).
+     *  Ignores the clip.
+     */
+    virtual void clear(SkColor color) SK_OVERRIDE;
+
     /** These are called inside the per-device-layer loop for each draw call.
      When these are called, we have already applied any saveLayer operations,
      and are handling any looping from the paint, and any effects from the
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h
index ee539c4..0685b6a 100644
--- a/include/core/SkCanvas.h
+++ b/include/core/SkCanvas.h
@@ -619,12 +619,24 @@
         @param color    the color to draw with
         @param mode the mode to apply the color in (defaults to SrcOver)
     */
-    void drawColor(SkColor color, SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode);
+    void drawColor(SkColor color,
+                   SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode);
 
-    // TODO: remove virtual when chrome subclass stop overriding this.
-    virtual void clear(SkColor color) {
-        this->drawColor(color, SkXfermode::kSrc_Mode);
-    }
+    /**
+     *  This erases the entire drawing surface to the specified color,
+     *  irrespective of the clip. It does not blend with the previous pixels,
+     *  but always overwrites them.
+     *
+     *  It is roughly equivalent to the following:
+     *      canvas.save();
+     *      canvas.clipRect(hugeRect, kReplace_Op);
+     *      paint.setColor(color);
+     *      paint.setXfermodeMode(kSrc_Mode);
+     *      canvas.drawPaint(paint);
+     *      canvas.restore();
+     *  though it is almost always much more efficient.
+     */
+    virtual void clear(SkColor);
 
     /**
      * This makes the contents of the canvas undefined. Subsequent calls that
diff --git a/include/core/SkDevice.h b/include/core/SkDevice.h
index f20ebf7..3c26bac 100644
--- a/include/core/SkDevice.h
+++ b/include/core/SkDevice.h
@@ -163,9 +163,8 @@
 
     /** Clears the entire device to the specified color (including alpha).
      *  Ignores the clip.
-     *  DEPRECATED : will go away when chrome subclasses have been updated
      */
-    virtual void clear(SkColor color);
+    virtual void clear(SkColor color) = 0;
 
     SK_ATTR_DEPRECATED("use clear() instead")
     void eraseColor(SkColor eraseColor) { this->clear(eraseColor); }
diff --git a/include/core/SkPicture.h b/include/core/SkPicture.h
index f764d34..2c377b8 100644
--- a/include/core/SkPicture.h
+++ b/include/core/SkPicture.h
@@ -245,8 +245,8 @@
     // V34: Add SkTextBlob serialization.
     // V35: Store SkRect (rather then width & height) in header
     // V36: Remove (obsolete) alphatype from SkColorTable
-    // V37: Added shadow only option to SkDropShadowImageFilter (last version to record CLEAR)
-    // V37: Added PictureResolution and FilterLevel options to SkPictureImageFilter
+    // V37: Added shadow only option to SkDropShadowImageFilter
+    //      Added PictureResolution and FilterLevel options to SkPictureImageFilter
 
     // Note: If the picture version needs to be increased then please follow the
     // steps to generate new SKPs in (only accessible to Googlers): http://goo.gl/qATVcw
diff --git a/include/pdf/SkPDFDevice.h b/include/pdf/SkPDFDevice.h
index fa0e512..1e09b72 100644
--- a/include/pdf/SkPDFDevice.h
+++ b/include/pdf/SkPDFDevice.h
@@ -70,6 +70,8 @@
                        const SkMatrix& initialTransform);
     SK_API virtual ~SkPDFDevice();
 
+    virtual void clear(SkColor color) SK_OVERRIDE;
+
     /** These are called inside the per-device-layer loop for each draw call.
      When these are called, we have already applied any saveLayer operations,
      and are handling any looping from the paint, and any effects from the
diff --git a/include/utils/SkDeferredCanvas.h b/include/utils/SkDeferredCanvas.h
index ec5ea13..69c8c3e 100644
--- a/include/utils/SkDeferredCanvas.h
+++ b/include/utils/SkDeferredCanvas.h
@@ -145,6 +145,7 @@
 
     // Overrides of the SkCanvas interface
     virtual bool isDrawingToLayer() const SK_OVERRIDE;
+    virtual void clear(SkColor) SK_OVERRIDE;
     virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE;
     virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
                             const SkPaint& paint) SK_OVERRIDE;
diff --git a/include/utils/SkNWayCanvas.h b/include/utils/SkNWayCanvas.h
index ec5d49a..a90f7d3 100644
--- a/include/utils/SkNWayCanvas.h
+++ b/include/utils/SkNWayCanvas.h
@@ -23,6 +23,7 @@
     ///////////////////////////////////////////////////////////////////////////
     // These are forwarded to the N canvases we're referencing
 
+    virtual void clear(SkColor) SK_OVERRIDE;
     virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE;
     virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
                             const SkPaint&) SK_OVERRIDE;
diff --git a/src/core/SkBitmapDevice.cpp b/src/core/SkBitmapDevice.cpp
index 020f1da..9df7c9b 100644
--- a/src/core/SkBitmapDevice.cpp
+++ b/src/core/SkBitmapDevice.cpp
@@ -127,6 +127,10 @@
     }
 }
 
+void SkBitmapDevice::clear(SkColor color) {
+    fBitmap.eraseColor(color);
+}
+
 const SkBitmap& SkBitmapDevice::onAccessBitmap() {
     return fBitmap;
 }
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index a6f263f..25d15b4 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -1706,6 +1706,14 @@
 //  These are the virtual drawing methods
 //////////////////////////////////////////////////////////////////////////////
 
+void SkCanvas::clear(SkColor color) {
+    SkDrawIter  iter(this);
+    this->predrawNotify();
+    while (iter.next()) {
+        iter.fDevice->clear(color);
+    }
+}
+
 void SkCanvas::onDiscard() {
     if (fSurfaceBase) {
         fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode);
diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp
index 570cea4..bc6c892 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -90,11 +90,6 @@
 
 const void* SkBaseDevice::peekPixels(SkImageInfo*, size_t*) { return NULL; }
 
-// DEPRECATED : remove when chrome subclass have been updated to not override clear()
-void SkBaseDevice::clear(SkColor color) {
-    SkFAIL("SkDevice::clear() should not be called");
-}
-
 void SkBaseDevice::drawDRRect(const SkDraw& draw, const SkRRect& outer,
                               const SkRRect& inner, const SkPaint& paint) {
     SkPath path;
diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp
index ac05e84..0003658 100644
--- a/src/core/SkPictureRecord.cpp
+++ b/src/core/SkPictureRecord.cpp
@@ -460,6 +460,14 @@
     return offset;
 }
 
+void SkPictureRecord::clear(SkColor color) {
+    // op + color
+    size_t size = 2 * kUInt32Size;
+    size_t initialOffset = this->addDraw(DRAW_CLEAR, &size);
+    this->addInt(color);
+    this->validate(initialOffset, size);
+}
+
 void SkPictureRecord::drawPaint(const SkPaint& paint) {
     // op + paint index
     size_t size = 2 * kUInt32Size;
diff --git a/src/core/SkPictureRecord.h b/src/core/SkPictureRecord.h
index 2a3e4e1..8aee0a8 100644
--- a/src/core/SkPictureRecord.h
+++ b/src/core/SkPictureRecord.h
@@ -29,6 +29,7 @@
     SkPictureRecord(const SkISize& dimensions, uint32_t recordFlags);
     virtual ~SkPictureRecord();
 
+    virtual void clear(SkColor) SK_OVERRIDE;
     virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE;
     virtual void drawPoints(PointMode, size_t count, const SkPoint pts[],
                             const SkPaint&) SK_OVERRIDE;
diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp
index c1fa0e8..4801f66 100644
--- a/src/core/SkRecordDraw.cpp
+++ b/src/core/SkRecordDraw.cpp
@@ -61,12 +61,13 @@
 
 void SkRecordPartialDraw(const SkRecord& record, SkCanvas* canvas,
                          SkPicture const* const drawablePicts[], int drawableCount,
+                         const SkRect& clearRect,
                          unsigned start, unsigned stop,
                          const SkMatrix& initialCTM) {
     SkAutoCanvasRestore saveRestore(canvas, true /*save now, restore at exit*/);
 
     stop = SkTMin(stop, record.count());
-    SkRecords::Draw draw(canvas, drawablePicts, NULL, drawableCount, &initialCTM);
+    SkRecords::PartialDraw draw(canvas, NULL, 0, clearRect, initialCTM);
     for (unsigned i = start; i < stop; i++) {
         record.visit<void>(i, draw);
     }
diff --git a/src/core/SkRecordDraw.h b/src/core/SkRecordDraw.h
index 509f5a6..e95123b 100644
--- a/src/core/SkRecordDraw.h
+++ b/src/core/SkRecordDraw.h
@@ -29,14 +29,15 @@
                   SkCanvasDrawable* const drawables[], int drawableCount,
                   const SkBBoxHierarchy*, SkDrawPictureCallback*);
 
-// Draw a portion of an SkRecord into an SkCanvas.
+// Draw a portion of an SkRecord into an SkCanvas while replacing clears with drawRects.
 // When drawing a portion of an SkRecord the CTM on the passed in canvas must be
 // the composition of the replay matrix with the record-time CTM (for the portion
 // of the record that is being replayed). For setMatrix calls to behave correctly
 // the initialCTM parameter must set to just the replay matrix.
 void SkRecordPartialDraw(const SkRecord&, SkCanvas*,
                          SkPicture const* const drawablePicts[], int drawableCount,
-                         unsigned start, unsigned stop, const SkMatrix& initialCTM);
+                         const SkRect&, unsigned start, unsigned stop,
+                         const SkMatrix& initialCTM);
 
 namespace SkRecords {
 
@@ -75,6 +76,30 @@
     int fDrawableCount;
 };
 
+// Used by SkRecordPartialDraw.
+class PartialDraw : public Draw {
+public:
+    PartialDraw(SkCanvas* canvas, SkPicture const* const drawablePicts[], int drawableCount,
+                const SkRect& clearRect, const SkMatrix& initialCTM)
+        : INHERITED(canvas, drawablePicts, NULL, drawableCount, &initialCTM), fClearRect(clearRect)
+    {}
+
+    // Same as Draw for all ops except Clear.
+    template <typename T> void operator()(const T& r) {
+        this->INHERITED::operator()(r);
+    }
+    void operator()(const Clear& c) {
+        SkPaint p;
+        p.setColor(c.color);
+        DrawRect drawRect(p, fClearRect);
+        this->INHERITED::operator()(drawRect);
+    }
+
+private:
+    const SkRect fClearRect;
+    typedef Draw INHERITED;
+};
+
 }  // namespace SkRecords
 
 #endif//SkRecordDraw_DEFINED
diff --git a/src/core/SkRecorder.cpp b/src/core/SkRecorder.cpp
index 04da7c4..5ba4309 100644
--- a/src/core/SkRecorder.cpp
+++ b/src/core/SkRecorder.cpp
@@ -118,6 +118,10 @@
 }
 
 
+void SkRecorder::clear(SkColor color) {
+    APPEND(Clear, color);
+}
+
 void SkRecorder::drawPaint(const SkPaint& paint) {
     APPEND(DrawPaint, delay_copy(paint));
 }
diff --git a/src/core/SkRecorder.h b/src/core/SkRecorder.h
index ff5c9ed..be67ddd 100644
--- a/src/core/SkRecorder.h
+++ b/src/core/SkRecorder.h
@@ -45,6 +45,7 @@
     // Make SkRecorder forget entirely about its SkRecord*; all calls to SkRecorder will fail.
     void forgetRecord();
 
+    void clear(SkColor) SK_OVERRIDE;
     void drawPaint(const SkPaint& paint) SK_OVERRIDE;
     void drawPoints(PointMode mode,
                     size_t count,
diff --git a/src/core/SkRecords.h b/src/core/SkRecords.h
index 046626a..00332c3 100644
--- a/src/core/SkRecords.h
+++ b/src/core/SkRecords.h
@@ -234,7 +234,6 @@
 RECORD3(ClipRect,   SkIRect, devBounds, SkRect,      rect, RegionOpAndAA, opAA);
 RECORD3(ClipRegion, SkIRect, devBounds, SkRegion,  region, SkRegion::Op,    op);
 
-// Picture version 37 was last to record this op-code; clear is now non-virtual
 RECORD1(Clear, SkColor, color);
 
 RECORD1(BeginCommentGroup, PODArray<char>, description);
diff --git a/src/gpu/GrLayerHoister.cpp b/src/gpu/GrLayerHoister.cpp
index e29e57e..4e78368 100644
--- a/src/gpu/GrLayerHoister.cpp
+++ b/src/gpu/GrLayerHoister.cpp
@@ -234,6 +234,10 @@
 
         SkCanvas* atlasCanvas = surface->getCanvas();
 
+        SkPaint clearPaint;
+        clearPaint.setColor(SK_ColorTRANSPARENT);
+        clearPaint.setXfermode(SkXfermode::Create(SkXfermode::kSrc_Mode))->unref();
+
         for (int i = 0; i < atlased.count(); ++i) {
             const GrCachedLayer* layer = atlased[i].fLayer;
             const SkPicture* pict = atlased[i].fPicture;
@@ -251,7 +255,9 @@
                                             SkIntToScalar(layer->rect().width()),
                                             SkIntToScalar(layer->rect().height()));
             atlasCanvas->clipRect(bound);
-            atlasCanvas->clear(0);
+
+            // Since 'clear' doesn't respect the clip we need to draw a rect
+            atlasCanvas->drawRect(bound, clearPaint);
 
             // '-offset' maps the layer's top/left to the origin.
             // Since this layer is atlased, the top/left corner needs
@@ -266,7 +272,7 @@
 
             SkRecordPartialDraw(*pict->fRecord.get(), atlasCanvas,
                                 pict->drawablePicts(), pict->drawableCount(),
-                                layer->start() + 1, layer->stop(), initialCTM);
+                                bound, layer->start() + 1, layer->stop(), initialCTM);
 
             atlasCanvas->restore();
         }
@@ -297,6 +303,7 @@
                                         SkIntToScalar(layer->rect().height()));
 
         layerCanvas->clipRect(bound);
+
         layerCanvas->clear(SK_ColorTRANSPARENT);
 
         SkMatrix initialCTM;
@@ -308,7 +315,7 @@
 
         SkRecordPartialDraw(*pict->fRecord.get(), layerCanvas,
                             pict->drawablePicts(), pict->drawableCount(),
-                            layer->start()+1, layer->stop(), initialCTM);
+                            bound, layer->start()+1, layer->stop(), initialCTM);
 
         layerCanvas->flush();
     }
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 3a0d6f4..3f08aa4 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -68,7 +68,7 @@
 #define DO_DEFERRED_CLEAR()             \
     do {                                \
         if (fFlags & kNeedClear_Flag) {  \
-            this->clearAll(); \
+            this->clear(SK_ColorTRANSPARENT); \
         }                               \
     } while (false)                     \
 
@@ -294,14 +294,6 @@
     return fRenderTarget;
 }
 
-void SkGpuDevice::clearAll() {
-    GrColor color = 0;
-    GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::clearAll", fContext);
-    SkIRect rect = SkIRect::MakeWH(this->width(), this->height());
-    fContext->clear(&rect, color, true, fRenderTarget);
-    fFlags &= ~kNeedClear_Flag;
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 
 SK_COMPILE_ASSERT(SkShader::kNone_BitmapType == 0, shader_type_mismatch);
@@ -317,6 +309,13 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
+void SkGpuDevice::clear(SkColor color) {
+    GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::clear", fContext);
+    SkIRect rect = SkIRect::MakeWH(this->width(), this->height());
+    fContext->clear(&rect, SkColor2GrColor(color), true, fRenderTarget);
+    fFlags &= ~kNeedClear_Flag;
+}
+
 void SkGpuDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) {
     CHECK_SHOULD_DRAW(draw, false);
     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawPaint", fContext);
@@ -1515,7 +1514,7 @@
     SkGpuDevice* dev = static_cast<SkGpuDevice*>(device);
     if (dev->fFlags & kNeedClear_Flag) {
         // TODO: could check here whether we really need to draw at all
-        dev->clearAll();
+        dev->clear(0x0);
     }
 
     // drawDevice is defined to be in device coords.
diff --git a/src/gpu/SkGpuDevice.h b/src/gpu/SkGpuDevice.h
index 2fb6de7..f7088e3 100644
--- a/src/gpu/SkGpuDevice.h
+++ b/src/gpu/SkGpuDevice.h
@@ -65,15 +65,13 @@
 
     GrContext* context() const { return fContext; }
 
-    // set all pixels to 0
-    void clearAll();
-
     virtual GrRenderTarget* accessRenderTarget() SK_OVERRIDE;
 
     virtual SkImageInfo imageInfo() const SK_OVERRIDE {
         return fRenderTarget ? fRenderTarget->surfacePriv().info() : SkImageInfo::MakeUnknown();
     }
 
+    virtual void clear(SkColor color) SK_OVERRIDE;
     virtual void drawPaint(const SkDraw&, const SkPaint& paint) SK_OVERRIDE;
     virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode, size_t count,
                             const SkPoint[], const SkPaint& paint) SK_OVERRIDE;
diff --git a/src/image/SkSurface_Gpu.cpp b/src/image/SkSurface_Gpu.cpp
index 8487094..9ac6d55 100644
--- a/src/image/SkSurface_Gpu.cpp
+++ b/src/image/SkSurface_Gpu.cpp
@@ -44,7 +44,7 @@
     fDevice = SkGpuDevice::Create(renderTarget, this->props(), deviceFlags);
 
     if (kRGB_565_GrPixelConfig != renderTarget->config() && doClear) {
-        fDevice->clearAll();
+        fDevice->clear(0x0);
     }
 }
 
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp
index 6592ba0..fb8df83 100644
--- a/src/pdf/SkPDFDevice.cpp
+++ b/src/pdf/SkPDFDevice.cpp
@@ -801,6 +801,20 @@
     }
 }
 
+void SkPDFDevice::clear(SkColor color) {
+    this->cleanUp(true);
+    this->init();
+
+    SkPaint paint;
+    paint.setColor(color);
+    paint.setStyle(SkPaint::kFill_Style);
+    SkMatrix identity;
+    identity.reset();
+    ScopedContentEntry content(this, &fExistingClipStack, fExistingClipRegion,
+                               identity, paint);
+    internalDrawPaint(paint, content.entry());
+}
+
 void SkPDFDevice::drawPaint(const SkDraw& d, const SkPaint& paint) {
     SkPaint newPaint = paint;
     newPaint.setStyle(SkPaint::kFill_Style);
diff --git a/src/pipe/SkGPipeWrite.cpp b/src/pipe/SkGPipeWrite.cpp
index a5af6c7..41b0234 100644
--- a/src/pipe/SkGPipeWrite.cpp
+++ b/src/pipe/SkGPipeWrite.cpp
@@ -233,6 +233,7 @@
 
     // overrides from SkCanvas
     virtual bool isDrawingToLayer() const SK_OVERRIDE;
+    virtual void clear(SkColor) SK_OVERRIDE;
     virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE;
     virtual void drawPoints(PointMode, size_t count, const SkPoint pts[],
                             const SkPaint&) SK_OVERRIDE;
@@ -689,6 +690,20 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
+void SkGPipeCanvas::clear(SkColor color) {
+    NOTIFY_SETUP(this);
+    unsigned flags = 0;
+    if (color) {
+        flags |= kClear_HasColor_DrawOpFlag;
+    }
+    if (this->needOpBytes(sizeof(SkColor))) {
+        this->writeOp(kDrawClear_DrawOp, flags, 0);
+        if (color) {
+            fWriter.write32(color);
+        }
+    }
+}
+
 void SkGPipeCanvas::drawPaint(const SkPaint& paint) {
     NOTIFY_SETUP(this);
     this->writePaint(paint);
diff --git a/src/utils/SkDeferredCanvas.cpp b/src/utils/SkDeferredCanvas.cpp
index 34b9146..3c845b1 100644
--- a/src/utils/SkDeferredCanvas.cpp
+++ b/src/utils/SkDeferredCanvas.cpp
@@ -170,6 +170,8 @@
 
     // None of the following drawing methods should ever get called on the
     // deferred device
+    virtual void clear(SkColor color) SK_OVERRIDE
+        {SkASSERT(0);}
     virtual void drawPaint(const SkDraw&, const SkPaint& paint) SK_OVERRIDE
         {SkASSERT(0);}
     virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode,
@@ -739,6 +741,16 @@
     this->recordedDrawCommand();
 }
 
+void SkDeferredCanvas::clear(SkColor color) {
+    // purge pending commands
+    if (fDeferredDrawing) {
+        this->getDeferredDevice()->skipPendingCommands();
+    }
+
+    this->drawingCanvas()->clear(color);
+    this->recordedDrawCommand();
+}
+
 void SkDeferredCanvas::drawPaint(const SkPaint& paint) {
     if (fDeferredDrawing && this->isFullFrame(NULL, &paint) &&
         isPaintOpaque(&paint)) {
diff --git a/src/utils/SkGatherPixelRefsAndRects.h b/src/utils/SkGatherPixelRefsAndRects.h
index 6e11fbe..4eeb56c 100644
--- a/src/utils/SkGatherPixelRefsAndRects.h
+++ b/src/utils/SkGatherPixelRefsAndRects.h
@@ -40,6 +40,9 @@
     }
 
 protected:
+    virtual void clear(SkColor color) SK_OVERRIDE {
+        NothingToDo();
+    }
     virtual void drawPaint(const SkDraw& draw, const SkPaint& paint) SK_OVERRIDE {
         SkBitmap bm;
 
diff --git a/src/utils/SkNWayCanvas.cpp b/src/utils/SkNWayCanvas.cpp
index ddd9b92..a6722d8 100644
--- a/src/utils/SkNWayCanvas.cpp
+++ b/src/utils/SkNWayCanvas.cpp
@@ -134,6 +134,13 @@
     this->INHERITED::onClipRegion(deviceRgn, op);
 }
 
+void SkNWayCanvas::clear(SkColor color) {
+    Iter iter(fList);
+    while (iter.next()) {
+        iter->clear(color);
+    }
+}
+
 void SkNWayCanvas::drawPaint(const SkPaint& paint) {
     Iter iter(fList);
     while (iter.next()) {
diff --git a/src/utils/SkPictureUtils.cpp b/src/utils/SkPictureUtils.cpp
index 2c6b8f5..7f9409a 100644
--- a/src/utils/SkPictureUtils.cpp
+++ b/src/utils/SkPictureUtils.cpp
@@ -77,6 +77,10 @@
         return false;
     }
 
+    virtual void clear(SkColor color) SK_OVERRIDE {
+        nothing_to_do();
+    }
+
     virtual void drawPaint(const SkDraw&, const SkPaint& paint) SK_OVERRIDE {
         this->addBitmapFromPaint(paint);
     }
diff --git a/src/utils/debugger/SkDebugCanvas.cpp b/src/utils/debugger/SkDebugCanvas.cpp
index 787cf89..95256e7 100644
--- a/src/utils/debugger/SkDebugCanvas.cpp
+++ b/src/utils/debugger/SkDebugCanvas.cpp
@@ -426,6 +426,10 @@
     fTexOverrideFilter->setFilterLevel(level);
 }
 
+void SkDebugCanvas::clear(SkColor color) {
+    this->addDrawCommand(new SkClearCommand(color));
+}
+
 void SkDebugCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
     this->addDrawCommand(new SkClipPathCommand(path, op, kSoft_ClipEdgeStyle == edgeStyle));
 }
diff --git a/src/utils/debugger/SkDebugCanvas.h b/src/utils/debugger/SkDebugCanvas.h
index 2c079bd..bdd04aa 100644
--- a/src/utils/debugger/SkDebugCanvas.h
+++ b/src/utils/debugger/SkDebugCanvas.h
@@ -158,6 +158,8 @@
 // Inherited from SkCanvas
 ////////////////////////////////////////////////////////////////////////////////
 
+    virtual void clear(SkColor) SK_OVERRIDE;
+
     virtual void drawBitmap(const SkBitmap&, SkScalar left, SkScalar top,
                             const SkPaint*) SK_OVERRIDE;
 
diff --git a/tests/DeferredCanvasTest.cpp b/tests/DeferredCanvasTest.cpp
index 043fe33..da2d6b9 100644
--- a/tests/DeferredCanvasTest.cpp
+++ b/tests/DeferredCanvasTest.cpp
@@ -284,6 +284,14 @@
     canvas->restore();
     REPORTER_ASSERT(reporter, !canvas->isFreshFrame());
 
+    // Verify that a clear with clipping triggers a fresh frame
+    // (clear is not affected by clipping)
+    canvas->save();
+    canvas->clipRect(partialRect, SkRegion::kIntersect_Op, false);
+    canvas->clear(0x00000000);
+    canvas->restore();
+    REPORTER_ASSERT(reporter, canvas->isFreshFrame());
+
     // Verify that full frame rects with different forms of opaque paint
     // trigger frames to be marked as fresh
     {
diff --git a/tests/RecordDrawTest.cpp b/tests/RecordDrawTest.cpp
index 30be24c..48981ef 100644
--- a/tests/RecordDrawTest.cpp
+++ b/tests/RecordDrawTest.cpp
@@ -191,7 +191,7 @@
 
     SkRecord rerecord;
     SkRecorder canvas(&rerecord, kWidth, kHeight);
-    SkRecordPartialDraw(record, &canvas, NULL, 0, 1, 2, SkMatrix::I()); // replay just drawRect of r2
+    SkRecordPartialDraw(record, &canvas, NULL, 0, r1, 1, 2, SkMatrix::I()); // replay just drawRect of r2
 
     REPORTER_ASSERT(r, 3 == rerecord.count());
     assert_type<SkRecords::Save>     (r, rerecord, 0);
@@ -202,6 +202,30 @@
     REPORTER_ASSERT(r, drawRect->rect == r2);
 }
 
+// Check that clears are converted to drawRects
+DEF_TEST(RecordDraw_PartialClear, r) {
+    static const int kWidth = 10, kHeight = 10;
+
+    SkRect rect = { 0, 0, kWidth, kHeight };
+
+    SkRecord record;
+    SkRecorder recorder(&record, kWidth, kHeight);
+    recorder.clear(SK_ColorRED);
+
+    SkRecord rerecord;
+    SkRecorder canvas(&rerecord, kWidth, kHeight);
+    SkRecordPartialDraw(record, &canvas, NULL, 0, rect, 0, 1, SkMatrix::I()); // replay just the clear
+
+    REPORTER_ASSERT(r, 3 == rerecord.count());
+    assert_type<SkRecords::Save>    (r, rerecord, 0);
+    assert_type<SkRecords::DrawRect>(r, rerecord, 1);
+    assert_type<SkRecords::Restore> (r, rerecord, 2);
+
+    const SkRecords::DrawRect* drawRect = assert_type<SkRecords::DrawRect>(r, rerecord, 1);
+    REPORTER_ASSERT(r, drawRect->rect == rect);
+    REPORTER_ASSERT(r, drawRect->paint.getColor() == SK_ColorRED);
+}
+
 // A regression test for crbug.com/415468 and skbug.com/2957.
 //
 // This also now serves as a regression test for crbug.com/418417.  We used to adjust the