Revert[6] "Remove SkDraw from device-draw methods, and enable device-centric clipping.""""""

Previous failure was failure to detect that the clip wasn't wide-open when
optimizing for retain-vs-discard in copy-on-write. gm:copy_on_write_retain
detected this. Now fixed by adding new method to SkBaseDevice.h

This reverts commit 27d07f0acb85eea4062075dfbe9148ce12d92c66.

BUG=skia:6214

Change-Id: I532d16ec075a4525c2a550b1157bcec695dd8efd
Reviewed-on: https://skia-review.googlesource.com/9341
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Mike Reed <reed@google.com>
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 5c7039f..daefeeb 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -75,8 +75,17 @@
 
     const SkISize size = this->getBaseLayerSize();
     const SkRect bounds = SkRect::MakeIWH(size.width(), size.height());
-    if (!this->getClipStack()->quickContains(bounds)) {
-        return false;
+
+    // if we're clipped at all, we can't overwrite the entire surface
+    {
+        SkBaseDevice* base = this->getDevice();
+        SkBaseDevice* top = this->getTopDevice();
+        if (base != top) {
+            return false;   // we're in a saveLayer, so conservatively don't assume we'll overwrite
+        }
+        if (!base->clipIsWideOpen()) {
+            return false;
+        }
     }
 
     if (rect) {
@@ -192,10 +201,8 @@
     SkMatrix            fMatrixStorage;
     SkMatrix            fStashedMatrix; // original CTM; used by imagefilter in saveLayer
 
-    DeviceCM(SkBaseDevice* device, const SkPaint* paint, SkCanvas* canvas,
-             bool conservativeRasterClip, const SkMatrix& stashed)
+    DeviceCM(SkBaseDevice* device, const SkPaint* paint, SkCanvas* canvas, const SkMatrix& stashed)
         : fNext(nullptr)
-        , fClip(conservativeRasterClip)
         , fStashedMatrix(stashed)
     {
         SkSafeRef(device);
@@ -214,48 +221,6 @@
         SkASSERT(fDevice);
         fClip.setRect(bounds);
     }
-
-    void updateMC(const SkMatrix& totalMatrix, const SkRasterClip& totalClip,
-                  SkRasterClip* updateClip) {
-        int x = fDevice->getOrigin().x();
-        int y = fDevice->getOrigin().y();
-        int width = fDevice->width();
-        int height = fDevice->height();
-
-        if ((x | y) == 0) {
-            fMatrix = &totalMatrix;
-            fClip = totalClip;
-        } else {
-            fMatrixStorage = totalMatrix;
-            fMatrixStorage.postTranslate(SkIntToScalar(-x),
-                                         SkIntToScalar(-y));
-            fMatrix = &fMatrixStorage;
-            totalClip.translate(-x, -y, &fClip);
-        }
-
-        fClip.op(SkIRect::MakeWH(width, height), SkRegion::kIntersect_Op);
-
-#ifdef SK_USE_DEVICE_CLIPPING
-        SkASSERT(*fMatrix == fDevice->ctm());
-        // TODO: debug tiles-rt-8888 so we can enable this all the time
-//        fDevice->validateDevBounds(fClip.getBounds());
-#endif
-
-        // intersect clip, but don't translate it (yet)
-
-        if (updateClip) {
-            updateClip->op(SkIRect::MakeXYWH(x, y, width, height),
-                           SkRegion::kDifference_Op);
-        }
-
-#ifdef SK_DEBUG
-        if (!fClip.isEmpty()) {
-            SkIRect deviceR;
-            deviceR.set(0, 0, width, height);
-            SkASSERT(deviceR.contains(fClip.getBounds()));
-        }
-#endif
-    }
 };
 
 /*  This is the record we keep for each save/restore level in the stack.
@@ -275,15 +240,15 @@
         reference counted, since the real owner is either our fLayer field,
         or a previous one in a lower level.)
     */
-    DeviceCM*       fTopLayer;
-    SkRasterClip    fRasterClip;
-    SkMatrix        fMatrix;
-    int             fDeferredSaveCount;
+    DeviceCM*           fTopLayer;
+    SkConservativeClip  fRasterClip;
+    SkMatrix            fMatrix;
+    int                 fDeferredSaveCount;
 
     // This is the current cumulative depth (aggregate of all done translateZ calls)
     SkScalar        fCurDrawDepth;
 
-    MCRec(bool conservativeRasterClip) : fRasterClip(conservativeRasterClip) {
+    MCRec() {
         fFilter     = nullptr;
         fLayer      = nullptr;
         fTopLayer   = nullptr;
@@ -320,70 +285,26 @@
     }
 };
 
-static SkIRect compute_device_bounds(SkBaseDevice* device) {
-    return SkIRect::MakeXYWH(device->getOrigin().x(), device->getOrigin().y(),
-                             device->width(), device->height());
-}
-
-class SkDrawIter : public SkDraw {
+class SkDrawIter {
 public:
-    SkDrawIter(SkCanvas* canvas) : fDevice(nullptr) {
-        canvas->updateDeviceCMCache();
-
-        fClipStack = canvas->getClipStack();
-        fCurrLayer = canvas->fMCRec->fTopLayer;
-
-        fMultiDeviceCS = nullptr;
-        if (fCurrLayer->fNext) {
-            fMultiDeviceCS = canvas->fClipStack.get();
-            fMultiDeviceCS->save();
-        }
-#ifdef SK_USE_DEVICE_CLIPPING
-        fClipStack = nullptr;   // for testing
-#endif
-    }
-
-    ~SkDrawIter() {
-        if (fMultiDeviceCS) {
-            fMultiDeviceCS->restore();
-        }
-    }
+    SkDrawIter(SkCanvas* canvas)
+        : fDevice(nullptr), fCurrLayer(canvas->fMCRec->fTopLayer), fPaint(nullptr)
+    {}
 
     bool next() {
-        if (fMultiDeviceCS && fDevice) {
-            // remove the previous device's bounds
-            fMultiDeviceCS->clipDevRect(compute_device_bounds(fDevice), kDifference_SkClipOp);
-        }
-
-        // skip over recs with empty clips
-        while (fCurrLayer && fCurrLayer->fClip.isEmpty()) {
-            fCurrLayer = fCurrLayer->fNext;
-        }
-
         const DeviceCM* rec = fCurrLayer;
         if (rec && rec->fDevice) {
-
-            fMatrix = rec->fMatrix;
-            fRC     = &rec->fClip;
             fDevice = rec->fDevice;
-            if (!fDevice->accessPixels(&fDst)) {
-                fDst.reset(fDevice->imageInfo(), nullptr, 0);
-            }
             fPaint  = rec->fPaint;
-            SkDEBUGCODE(this->validate();)
-
             fCurrLayer = rec->fNext;
             // fCurrLayer may be nullptr now
-
             return true;
         }
         return false;
     }
 
-    const SkRasterClip& getClip() const { return *fRC; }
     int getX() const { return fDevice->getOrigin().x(); }
     int getY() const { return fDevice->getOrigin().y(); }
-    const SkMatrix& getMatrix() const { return *fMatrix; }
     const SkPaint* getPaint() const { return fPaint; }
 
     SkBaseDevice*   fDevice;
@@ -391,9 +312,6 @@
 private:
     const DeviceCM* fCurrLayer;
     const SkPaint*  fPaint;     // May be null.
-    SkClipStack*    fMultiDeviceCS;
-
-    typedef SkDraw INHERITED;
 };
 
 #define FOR_EACH_TOP_DEVICE( code )                 \
@@ -657,7 +575,6 @@
 
 void SkCanvas::resetForNextPicture(const SkIRect& bounds) {
     this->restoreToCount(1);
-    fClipStack->reset();
     fMCRec->reset(bounds);
 
     // We're peering through a lot of structs here.  Only at this scope do we
@@ -671,29 +588,22 @@
     if (device && device->forceConservativeRasterClip()) {
         flags = InitFlags(flags | kConservativeRasterClip_InitFlag);
     }
-    // Since init() is only called once by our constructors, it is safe to perform this
-    // const-cast.
-    *const_cast<bool*>(&fConservativeRasterClip) = SkToBool(flags & kConservativeRasterClip_InitFlag);
 
     fAllowSimplifyClip = false;
-    fDeviceCMDirty = true;
     fSaveCount = 1;
     fMetaData = nullptr;
 #ifdef SK_EXPERIMENTAL_SHADOWING
     fLights = nullptr;
 #endif
 
-    fClipStack.reset(new SkClipStack);
-
     fMCRec = (MCRec*)fMCStack.push_back();
-    new (fMCRec) MCRec(fConservativeRasterClip);
+    new (fMCRec) MCRec;
     fMCRec->fRasterClip.setDeviceClipRestriction(&fClipRestrictionRect);
     fIsScaleTranslate = true;
 
     SkASSERT(sizeof(DeviceCM) <= sizeof(fDeviceCMStorage));
     fMCRec->fLayer = (DeviceCM*)fDeviceCMStorage;
-    new (fDeviceCMStorage) DeviceCM(nullptr, nullptr, nullptr, fConservativeRasterClip,
-                                    fMCRec->fMatrix);
+    new (fDeviceCMStorage) DeviceCM(nullptr, nullptr, nullptr, fMCRec->fMatrix);
 
     fMCRec->fTopLayer = fMCRec->fLayer;
 
@@ -706,9 +616,7 @@
         fMCRec->fRasterClip.setRect(device->getGlobalBounds());
         fDeviceClipBounds = qr_clip_bounds(device->getGlobalBounds());
 
-#ifdef SK_USE_DEVICE_CLIPPING
         device->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect);
-#endif
     }
 
     return device;
@@ -717,7 +625,6 @@
 SkCanvas::SkCanvas()
     : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
     , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
-    , fConservativeRasterClip(false)
 {
     inc_canvas();
 
@@ -746,7 +653,6 @@
 SkCanvas::SkCanvas(int width, int height, const SkSurfaceProps* props)
     : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
     , fProps(SkSurfacePropsCopyOrDefault(props))
-    , fConservativeRasterClip(false)
 {
     inc_canvas();
 
@@ -757,7 +663,6 @@
 SkCanvas::SkCanvas(const SkIRect& bounds, InitFlags flags)
     : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
     , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
-    , fConservativeRasterClip(false)
 {
     inc_canvas();
 
@@ -767,7 +672,6 @@
 SkCanvas::SkCanvas(SkBaseDevice* device)
     : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
     , fProps(device->surfaceProps())
-    , fConservativeRasterClip(false)
 {
     inc_canvas();
 
@@ -777,7 +681,6 @@
 SkCanvas::SkCanvas(SkBaseDevice* device, InitFlags flags)
     : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
     , fProps(device->surfaceProps())
-    , fConservativeRasterClip(false)
 {
     inc_canvas();
 
@@ -787,7 +690,6 @@
 SkCanvas::SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props)
     : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
     , fProps(props)
-    , fConservativeRasterClip(false)
 {
     inc_canvas();
 
@@ -800,7 +702,6 @@
     : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
     , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
     , fAllocator(std::move(alloc))
-    , fConservativeRasterClip(false)
 {
     inc_canvas();
 
@@ -967,26 +868,6 @@
 
 //////////////////////////////////////////////////////////////////////////////
 
-void SkCanvas::updateDeviceCMCache() {
-    if (fDeviceCMDirty) {
-        const SkMatrix& totalMatrix = this->getTotalMatrix();
-        const SkRasterClip& totalClip = fMCRec->fRasterClip;
-        DeviceCM*       layer = fMCRec->fTopLayer;
-
-        if (nullptr == layer->fNext) {   // only one layer
-            layer->updateMC(totalMatrix, totalClip, nullptr);
-        } else {
-            SkRasterClip clip(totalClip);
-            do {
-                layer->updateMC(totalMatrix, clip, &clip);
-            } while ((layer = layer->fNext) != nullptr);
-        }
-        fDeviceCMDirty = false;
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
 void SkCanvas::checkForDeferredSave() {
     if (fMCRec->fDeferredSaveCount > 0) {
         this->doSave();
@@ -1057,10 +938,7 @@
     new (newTop) MCRec(*fMCRec);    // balanced in restore()
     fMCRec = newTop;
 
-    fClipStack->save();
-#ifdef SK_USE_DEVICE_CLIPPING
     FOR_EACH_TOP_DEVICE(device->save());
-#endif
 }
 
 bool SkCanvas::BoundsAffectsClip(SaveLayerFlags saveLayerFlags) {
@@ -1091,6 +969,7 @@
         // early exit if the layer's bounds are clipped out
         if (!ir.intersect(clipBounds)) {
             if (BoundsAffectsClip(saveLayerFlags)) {
+                fMCRec->fTopLayer->fDevice->clipRegion(SkRegion(), SkClipOp::kIntersect); // empty
                 fMCRec->fRasterClip.setEmpty();
                 fDeviceClipBounds.setEmpty();
             }
@@ -1103,7 +982,6 @@
 
     if (BoundsAffectsClip(saveLayerFlags)) {
         // Simplify the current clips since they will be applied properly during restore()
-        fClipStack->clipDevRect(ir, kReplace_SkClipOp);
         fMCRec->fRasterClip.setRect(ir);
         fDeviceClipBounds = qr_clip_bounds(ir);
     }
@@ -1136,7 +1014,7 @@
 
 void SkCanvas::DrawDeviceWithFilter(SkBaseDevice* src, const SkImageFilter* filter,
                                     SkBaseDevice* dst, const SkIPoint& dstOrigin,
-                                    const SkMatrix& ctm, const SkClipStack* clipStack) {
+                                    const SkMatrix& ctm) {
     SkDraw draw;
     SkRasterClip rc;
     rc.setRect(SkIRect::MakeWH(dst->width(), dst->height()));
@@ -1145,7 +1023,6 @@
     }
     draw.fMatrix = &SkMatrix::I();
     draw.fRC = &rc;
-    draw.fClipStack = clipStack;
 
     SkPaint p;
     if (filter) {
@@ -1156,7 +1033,7 @@
     int y = src->getOrigin().y() - dstOrigin.y();
     auto special = src->snapSpecial();
     if (special) {
-        dst->drawSpecial(draw, special.get(), x, y, p);
+        dst->drawSpecial(special.get(), x, y, p);
     }
 }
 
@@ -1220,8 +1097,6 @@
     // that would invoke a possibly overridden virtual
     this->internalSave();
 
-    fDeviceCMDirty = true;
-
     SkIRect ir;
     if (!this->clipRectBounds(bounds, saveLayerFlags, &ir, imageFilter)) {
         return;
@@ -1265,12 +1140,8 @@
             return;
         }
     }
-#ifndef SK_USE_DEVICE_CLIPPING
-    newDevice->setOrigin(fMCRec->fMatrix, ir.fLeft, ir.fTop);
-#endif
-
     DeviceCM* layer =
-            new DeviceCM(newDevice.get(), paint, this, fConservativeRasterClip, stashedMatrix);
+            new DeviceCM(newDevice.get(), paint, this, stashedMatrix);
 
     // only have a "next" if this new layer doesn't affect the clip (rare)
     layer->fNext = BoundsAffectsClip(saveLayerFlags) ? nullptr : fMCRec->fTopLayer;
@@ -1279,10 +1150,9 @@
 
     if ((rec.fSaveLayerFlags & kInitWithPrevious_SaveLayerFlag) || rec.fBackdrop) {
         DrawDeviceWithFilter(priorDevice, rec.fBackdrop, newDevice.get(), { ir.fLeft, ir.fTop },
-                             fMCRec->fMatrix, this->getClipStack());
+                             fMCRec->fMatrix);
     }
 
-#ifdef SK_USE_DEVICE_CLIPPING
     newDevice->setOrigin(fMCRec->fMatrix, ir.fLeft, ir.fTop);
 
     newDevice->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect);
@@ -1295,7 +1165,6 @@
             layer->fDevice->clipRegion(hole, SkClipOp::kDifference);
         } while (layer->fNext);
     }
-#endif
 }
 
 int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
@@ -1311,10 +1180,6 @@
 void SkCanvas::internalRestore() {
     SkASSERT(fMCStack.count() != 0);
 
-    fDeviceCMDirty = true;
-
-    fClipStack->restore();
-
     // reserve our layer (if any)
     DeviceCM* layer = fMCRec->fLayer;   // may be null
     // now detach it from fMCRec so we can pop(). Gets freed after its drawn
@@ -1325,11 +1190,9 @@
     fMCStack.pop_back();
     fMCRec = (MCRec*)fMCStack.back();
 
-#ifdef SK_USE_DEVICE_CLIPPING
     if (fMCRec) {
         FOR_EACH_TOP_DEVICE(device->restore(fMCRec->fMatrix));
     }
-#endif
 
     /*  Time to draw the layer's offscreen. We can't call the public drawSprite,
         since if we're being recorded, we don't want to record this (the
@@ -1342,7 +1205,6 @@
             // restore what we smashed in internalSaveLayer
             fMCRec->fMatrix = layer->fStashedMatrix;
             // reset this, since internalDrawDevice will have set it to true
-            fDeviceCMDirty = true;
             delete layer;
         } else {
             // we're at the root
@@ -1448,10 +1310,10 @@
         if (filter) {
             sk_sp<SkSpecialImage> specialImage = srcDev->snapSpecial();
             if (specialImage) {
-                dstDev->drawSpecial(iter, specialImage.get(), pos.x(), pos.y(), *paint);
+                dstDev->drawSpecial(specialImage.get(), pos.x(), pos.y(), *paint);
             }
         } else {
-            dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint);
+            dstDev->drawDevice(srcDev, pos.x(), pos.y(), *paint);
         }
     }
 
@@ -1463,15 +1325,12 @@
 void SkCanvas::translate(SkScalar dx, SkScalar dy) {
     if (dx || dy) {
         this->checkForDeferredSave();
-        fDeviceCMDirty = true;
         fMCRec->fMatrix.preTranslate(dx,dy);
 
         // Translate shouldn't affect the is-scale-translateness of the matrix.
         SkASSERT(fIsScaleTranslate == fMCRec->fMatrix.isScaleTranslate());
 
-#ifdef SK_USE_DEVICE_CLIPPING
         FOR_EACH_TOP_DEVICE(device->setGlobalCTM(fMCRec->fMatrix));
-#endif
 
         this->didTranslate(dx,dy);
     }
@@ -1507,25 +1366,19 @@
     }
 
     this->checkForDeferredSave();
-    fDeviceCMDirty = true;
     fMCRec->fMatrix.preConcat(matrix);
     fIsScaleTranslate = fMCRec->fMatrix.isScaleTranslate();
 
-#ifdef SK_USE_DEVICE_CLIPPING
     FOR_EACH_TOP_DEVICE(device->setGlobalCTM(fMCRec->fMatrix));
-#endif
 
     this->didConcat(matrix);
 }
 
 void SkCanvas::internalSetMatrix(const SkMatrix& matrix) {
-    fDeviceCMDirty = true;
     fMCRec->fMatrix = matrix;
     fIsScaleTranslate = matrix.isScaleTranslate();
 
-#ifdef SK_USE_DEVICE_CLIPPING
     FOR_EACH_TOP_DEVICE(device->setGlobalCTM(fMCRec->fMatrix));
-#endif
 }
 
 void SkCanvas::setMatrix(const SkMatrix& matrix) {
@@ -1569,36 +1422,25 @@
 void SkCanvas::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle) {
     const bool isAA = kSoft_ClipEdgeStyle == edgeStyle;
 
-#ifdef SK_USE_DEVICE_CLIPPING
     FOR_EACH_TOP_DEVICE(device->clipRect(rect, op, isAA));
-#endif
 
     AutoValidateClip avc(this);
-    fClipStack->clipRect(rect, fMCRec->fMatrix, op, isAA);
     fMCRec->fRasterClip.op(rect, fMCRec->fMatrix, this->getTopLayerBounds(), (SkRegion::Op)op,
                            isAA);
-    fDeviceCMDirty = true;
     fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
 }
 
 void SkCanvas::androidFramework_setDeviceClipRestriction(const SkIRect& rect) {
     fClipRestrictionRect = rect;
-    fClipStack->setDeviceClipRestriction(fClipRestrictionRect);
     if (fClipRestrictionRect.isEmpty()) {
         // we notify the device, but we *dont* resolve deferred saves (since we're just
         // removing the restriction if the rect is empty. how I hate this api.
-#ifdef SK_USE_DEVICE_CLIPPING
         FOR_EACH_TOP_DEVICE(device->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect));
-#endif
     } else {
         this->checkForDeferredSave();
-#ifdef SK_USE_DEVICE_CLIPPING
         FOR_EACH_TOP_DEVICE(device->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect));
-#endif
         AutoValidateClip avc(this);
-        fClipStack->clipDevRect(fClipRestrictionRect, kIntersect_SkClipOp);
         fMCRec->fRasterClip.op(fClipRestrictionRect, SkRegion::kIntersect_Op);
-        fDeviceCMDirty = true;
         fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
     }
 }
@@ -1616,19 +1458,13 @@
 void SkCanvas::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle) {
     AutoValidateClip avc(this);
 
-    fDeviceCMDirty = true;
-
     bool isAA = kSoft_ClipEdgeStyle == edgeStyle;
     
-#ifdef SK_USE_DEVICE_CLIPPING
     FOR_EACH_TOP_DEVICE(device->clipRRect(rrect, op, isAA));
-#endif
-    
-    fClipStack->clipRRect(rrect, fMCRec->fMatrix, op, isAA);
+
     fMCRec->fRasterClip.op(rrect, fMCRec->fMatrix, this->getTopLayerBounds(), (SkRegion::Op)op,
                            isAA);
     fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
-    return;
 }
 
 void SkCanvas::clipPath(const SkPath& path, SkClipOp op, bool doAA) {
@@ -1659,24 +1495,12 @@
 void SkCanvas::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle) {
     AutoValidateClip avc(this);
 
-    fDeviceCMDirty = true;
     bool isAA = kSoft_ClipEdgeStyle == edgeStyle;
     
-#ifdef SK_USE_DEVICE_CLIPPING
     FOR_EACH_TOP_DEVICE(device->clipPath(path, op, isAA));
-#endif
-    
-    fClipStack->clipPath(path, fMCRec->fMatrix, op, isAA);
 
     const SkPath* rasterClipPath = &path;
     const SkMatrix* matrix = &fMCRec->fMatrix;
-    SkPath tempPath;
-    if (fAllowSimplifyClip) {
-        isAA = getClipStack()->asPath(&tempPath);
-        rasterClipPath = &tempPath;
-        matrix = &SkMatrix::I();
-        op = kReplace_SkClipOp;
-    }
     fMCRec->fRasterClip.op(*rasterClipPath, *matrix, this->getTopLayerBounds(), (SkRegion::Op)op,
                            isAA);
     fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
@@ -1688,18 +1512,10 @@
 }
 
 void SkCanvas::onClipRegion(const SkRegion& rgn, SkClipOp op) {
-#ifdef SK_USE_DEVICE_CLIPPING
     FOR_EACH_TOP_DEVICE(device->clipRegion(rgn, op));
-#endif
-    
+
     AutoValidateClip avc(this);
 
-    fDeviceCMDirty = true;
-
-    // todo: signal fClipStack that we have a region, and therefore (I guess)
-    // we have to ignore it, and use the region directly?
-    fClipStack->clipDevRect(rgn.getBounds(), op);
-
     fMCRec->fRasterClip.op(rgn, (SkRegion::Op)op);
     fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
 }
@@ -1712,51 +1528,61 @@
         SkASSERT(this->isClipEmpty());
         return;
     }
-
-    SkIRect ir;
-    ir.set(0, 0, device->width(), device->height());
-    SkRasterClip tmpClip(ir, fConservativeRasterClip);
-
-    SkClipStack::B2TIter                iter(*fClipStack);
-    const SkClipStack::Element* element;
-    while ((element = iter.next()) != nullptr) {
-        switch (element->getType()) {
-            case SkClipStack::Element::kRect_Type:
-                element->getRect().round(&ir);
-                tmpClip.op(ir, (SkRegion::Op)element->getOp());
-                break;
-            case SkClipStack::Element::kEmpty_Type:
-                tmpClip.setEmpty();
-                break;
-            default: {
-                SkPath path;
-                element->asPath(&path);
-                tmpClip.op(path, SkMatrix::I(), this->getTopLayerBounds(),
-                           (SkRegion::Op)element->getOp(), element->isAA());
-                break;
-            }
-        }
-    }
 }
 #endif
 
 void SkCanvas::replayClips(ClipVisitor* visitor) const {
+#if 0
     SkClipStack::B2TIter                iter(*fClipStack);
     const SkClipStack::Element*         element;
 
     while ((element = iter.next()) != nullptr) {
         element->replay(visitor);
     }
+#endif
+}
+
+bool SkCanvas::androidFramework_isClipAA() const {
+    bool containsAA = false;
+
+    FOR_EACH_TOP_DEVICE(containsAA |= device->onClipIsAA());
+
+    return containsAA;
+}
+
+class RgnAccumulator {
+    SkRegion* fRgn;
+public:
+    RgnAccumulator(SkRegion* total) : fRgn(total) {}
+    void accumulate(SkBaseDevice* device, SkRegion* rgn) {
+        SkIPoint origin = device->getOrigin();
+        if (origin.x() | origin.y()) {
+            rgn->translate(origin.x(), origin.y());
+        }
+        fRgn->op(*rgn, SkRegion::kUnion_Op);
+    }
+};
+
+void SkCanvas::temporary_internal_getRgnClip(SkRegion* rgn) {
+    RgnAccumulator accum(rgn);
+    SkRegion tmp;
+
+    rgn->setEmpty();
+    FOR_EACH_TOP_DEVICE(device->onAsRgnClip(&tmp); accum.accumulate(device, &tmp));
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 
 bool SkCanvas::isClipEmpty() const {
-    return fMCRec->fRasterClip.isEmpty();
+    SkBaseDevice* dev = this->getTopDevice();
+    // if no device we return true
+    return !dev || dev->onGetClipType() == SkBaseDevice::kEmpty_ClipType;
 }
 
 bool SkCanvas::isClipRect() const {
-    return fMCRec->fRasterClip.isRect();
+    SkBaseDevice* dev = this->getTopDevice();
+    // if no device we return false
+    return dev && dev->onGetClipType() == SkBaseDevice::kRect_ClipType;
 }
 
 static inline bool is_nan_or_clipped(const Sk4f& devRect, const Sk4f& devClip) {
@@ -1857,38 +1683,13 @@
 }
 
 SkIRect SkCanvas::onGetDeviceClipBounds() const {
-    const SkRasterClip& clip = fMCRec->fRasterClip;
-    if (clip.isEmpty()) {
-        return SkIRect::MakeEmpty();
-    }
-    return clip.getBounds();
+    return fMCRec->fRasterClip.getBounds();
 }
 
 const SkMatrix& SkCanvas::getTotalMatrix() const {
     return fMCRec->fMatrix;
 }
 
-void SkCanvas::temporary_internal_getRgnClip(SkRegion* rgn) {
-    // we know that ganesh doesn't track the rgn, so ask for its clipstack
-    if (this->getGrContext()) {
-        const SkClipStack* cs = this->getClipStack();
-        SkClipStack::BoundsType boundType;
-        bool isIntersectionOfRects;
-        SkRect bounds;
-        cs->getBounds(&bounds, &boundType, &isIntersectionOfRects);
-        if (isIntersectionOfRects && SkClipStack::kNormal_BoundsType == boundType) {
-            rgn->setRect(bounds.round());
-            return;
-        }
-        SkPath path;
-        cs->asPath(&path);
-        SkISize size = this->getBaseLayerSize();
-        rgn->setPath(path, SkRegion(SkIRect::MakeWH(size.width(), size.height())));
-    } else {
-        *rgn = fMCRec->fRasterClip.forceGetBW();
-    }
-}
-
 GrRenderTargetContext* SkCanvas::internal_private_accessTopLayerRenderTargetContext() {
     SkBaseDevice* dev = this->getTopDevice();
     return dev ? dev->accessRenderTargetContext() : nullptr;
@@ -2158,7 +1959,7 @@
     LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kPaint_Type, nullptr, false)
 
     while (iter.next()) {
-        iter.fDevice->drawPaint(iter, looper.paint());
+        iter.fDevice->drawPaint(looper.paint());
     }
 
     LOOPER_END
@@ -2192,7 +1993,7 @@
     LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds)
 
     while (iter.next()) {
-        iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint());
+        iter.fDevice->drawPoints(mode, count, pts, looper.paint());
     }
 
     LOOPER_END
@@ -2224,7 +2025,7 @@
         LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kRect_Type, &r, false)
 
         while (iter.next()) {
-            iter.fDevice->drawRect(iter, r, looper.paint());
+            iter.fDevice->drawRect(r, looper.paint());
         }
 
         LOOPER_END
@@ -2232,7 +2033,7 @@
         this->predrawNotify(&r, &paint, false);
         SkDrawIter iter(this);
         while (iter.next()) {
-            iter.fDevice->drawRect(iter, r, paint);
+            iter.fDevice->drawRect(r, paint);
         }
     }
 }
@@ -2249,7 +2050,7 @@
     LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, &regionRect)
 
     while (iter.next()) {
-        iter.fDevice->drawRegion(iter, region, looper.paint());
+        iter.fDevice->drawRegion(region, looper.paint());
     }
 
     LOOPER_END
@@ -2267,7 +2068,7 @@
     LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, &oval)
 
     while (iter.next()) {
-        iter.fDevice->drawOval(iter, oval, looper.paint());
+        iter.fDevice->drawOval(oval, looper.paint());
     }
 
     LOOPER_END
@@ -2288,7 +2089,7 @@
     LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, &oval)
 
     while (iter.next()) {
-        iter.fDevice->drawArc(iter, oval, startAngle, sweepAngle, useCenter, looper.paint());
+        iter.fDevice->drawArc(oval, startAngle, sweepAngle, useCenter, looper.paint());
     }
 
     LOOPER_END
@@ -2316,7 +2117,7 @@
     LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, &rrect.getBounds())
 
     while (iter.next()) {
-        iter.fDevice->drawRRect(iter, rrect, looper.paint());
+        iter.fDevice->drawRRect(rrect, looper.paint());
     }
 
     LOOPER_END
@@ -2333,7 +2134,7 @@
     LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, &outer.getBounds())
 
     while (iter.next()) {
-        iter.fDevice->drawDRRect(iter, outer, inner, looper.paint());
+        iter.fDevice->drawDRRect(outer, inner, looper.paint());
     }
 
     LOOPER_END
@@ -2363,7 +2164,7 @@
     LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, &pathBounds)
 
     while (iter.next()) {
-        iter.fDevice->drawPath(iter, path, looper.paint());
+        iter.fDevice->drawPath(path, looper.paint());
     }
 
     LOOPER_END
@@ -2425,12 +2226,12 @@
         const SkPaint& pnt = looper.paint();
         if (special) {
             SkPoint pt;
-            iter.fMatrix->mapXY(x, y, &pt);
-            iter.fDevice->drawSpecial(iter, special.get(),
+            iter.fDevice->ctm().mapXY(x, y, &pt);
+            iter.fDevice->drawSpecial(special.get(),
                                       SkScalarRoundToInt(pt.fX),
                                       SkScalarRoundToInt(pt.fY), pnt);
         } else {
-            iter.fDevice->drawImage(iter, image, x, y, pnt);
+            iter.fDevice->drawImage(image, x, y, pnt);
         }
     }
 
@@ -2458,7 +2259,7 @@
                                           image->isOpaque())
 
     while (iter.next()) {
-        iter.fDevice->drawImageRect(iter, image, src, dst, looper.paint(), constraint);
+        iter.fDevice->drawImageRect(image, src, dst, looper.paint(), constraint);
     }
 
     LOOPER_END
@@ -2506,12 +2307,12 @@
         const SkPaint& pnt = looper.paint();
         if (special) {
             SkPoint pt;
-            iter.fMatrix->mapXY(x, y, &pt);
-            iter.fDevice->drawSpecial(iter, special.get(),
+            iter.fDevice->ctm().mapXY(x, y, &pt);
+            iter.fDevice->drawSpecial(special.get(),
                                       SkScalarRoundToInt(pt.fX),
                                       SkScalarRoundToInt(pt.fY), pnt);
         } else {
-            iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint());
+            iter.fDevice->drawBitmap(bitmap, matrix, looper.paint());
         }
     }
 
@@ -2542,7 +2343,7 @@
                                           bitmap.isOpaque())
 
     while (iter.next()) {
-        iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), constraint);
+        iter.fDevice->drawBitmapRect(bitmap, src, dst, looper.paint(), constraint);
     }
 
     LOOPER_END
@@ -2574,7 +2375,7 @@
     LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
 
     while (iter.next()) {
-        iter.fDevice->drawImageNine(iter, image, center, dst, looper.paint());
+        iter.fDevice->drawImageNine(image, center, dst, looper.paint());
     }
 
     LOOPER_END
@@ -2600,7 +2401,7 @@
     LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
 
     while (iter.next()) {
-        iter.fDevice->drawBitmapNine(iter, bitmap, center, dst, looper.paint());
+        iter.fDevice->drawBitmapNine(bitmap, center, dst, looper.paint());
     }
 
     LOOPER_END
@@ -2623,7 +2424,7 @@
     LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
 
     while (iter.next()) {
-        iter.fDevice->drawImageLattice(iter, image, lattice, dst, looper.paint());
+        iter.fDevice->drawImageLattice(image, lattice, dst, looper.paint());
     }
 
     LOOPER_END
@@ -2646,7 +2447,7 @@
     LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
 
     while (iter.next()) {
-        iter.fDevice->drawBitmapLattice(iter, bitmap, lattice, dst, looper.paint());
+        iter.fDevice->drawBitmapLattice(bitmap, lattice, dst, looper.paint());
     }
 
     LOOPER_END
@@ -2678,7 +2479,7 @@
 
     while (iter.next()) {
         SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
-        iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint());
+        iter.fDevice->drawText(text, byteLength, x, y, dfp.paint());
     }
 
     LOOPER_END
@@ -2692,7 +2493,7 @@
 
     while (iter.next()) {
         SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
-        iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 2, textOffset,
+        iter.fDevice->drawPosText(text, byteLength, &pos->fX, 2, textOffset,
                                   dfp.paint());
     }
 
@@ -2708,7 +2509,7 @@
 
     while (iter.next()) {
         SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
-        iter.fDevice->drawPosText(iter, text, byteLength, xpos, 1, textOffset,
+        iter.fDevice->drawPosText(text, byteLength, xpos, 1, textOffset,
                                   dfp.paint());
     }
 
@@ -2720,7 +2521,7 @@
     LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
 
     while (iter.next()) {
-        iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
+        iter.fDevice->drawTextOnPath(text, byteLength, path,
                                      matrix, looper.paint());
     }
 
@@ -2736,7 +2537,7 @@
     LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
 
     while (iter.next()) {
-        iter.fDevice->drawTextRSXform(iter, text, byteLength, xform, looper.paint());
+        iter.fDevice->drawTextRSXform(text, byteLength, xform, looper.paint());
     }
 
     LOOPER_END
@@ -2765,7 +2566,7 @@
 
     while (iter.next()) {
         SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
-        iter.fDevice->drawTextBlob(iter, blob, x, y, dfp.paint(), drawFilter);
+        iter.fDevice->drawTextBlob(blob, x, y, dfp.paint(), drawFilter);
     }
 
     LOOPER_END
@@ -2825,7 +2626,7 @@
     LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr)
 
     while (iter.next()) {
-        iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
+        iter.fDevice->drawVertices(vmode, vertexCount, verts, texs,
                                    colors, bmode, indices, indexCount,
                                    looper.paint());
     }
@@ -2840,7 +2641,7 @@
 
     while (iter.next()) {
         // In the common case of one iteration we could std::move vertices here.
-        iter.fDevice->drawVerticesObject(iter, vertices, bmode, looper.paint(), flags);
+        iter.fDevice->drawVerticesObject(vertices, bmode, looper.paint(), flags);
     }
 
     LOOPER_END
@@ -2880,7 +2681,7 @@
     LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr)
 
     while (iter.next()) {
-        iter.fDevice->drawPatch(iter, cubics, colors, texCoords, bmode, paint);
+        iter.fDevice->drawPatch(cubics, colors, texCoords, bmode, paint);
     }
 
     LOOPER_END
@@ -2924,7 +2725,7 @@
 
     LOOPER_BEGIN(pnt, SkDrawFilter::kPath_Type, nullptr)
     while (iter.next()) {
-        iter.fDevice->drawAtlas(iter, atlas, xform, tex, colors, count, bmode, pnt);
+        iter.fDevice->drawAtlas(atlas, xform, tex, colors, count, bmode, pnt);
     }
     LOOPER_END
 }
@@ -2935,7 +2736,7 @@
     SkPaint paint;
     LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, nullptr)
     while (iter.next()) {
-        iter.fDevice->drawAnnotation(iter, rect, key, value);
+        iter.fDevice->drawAnnotation(rect, key, value);
     }
     LOOPER_END
 }
@@ -3310,7 +3111,7 @@
 }
 
 const SkMatrix& SkCanvas::LayerIter::matrix() const {
-    return fImpl->getMatrix();
+    return fImpl->fDevice->ctm();
 }
 
 const SkPaint& SkCanvas::LayerIter::paint() const {
@@ -3321,7 +3122,10 @@
     return *paint;
 }
 
-const SkRasterClip& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
+void SkCanvas::LayerIter::clip(SkRegion* rgn) const {
+    return fImpl->fDevice->onAsRgnClip(rgn);
+}
+
 int SkCanvas::LayerIter::x() const { return fImpl->getX(); }
 int SkCanvas::LayerIter::y() const { return fImpl->getY(); }