add virtuals in prep for device-clipping
authorMike Reed <reed@google.com>
Wed, 8 Feb 2017 15:07:53 +0000 (10:07 -0500)
committerSkia Commit-Bot <skia-commit-bot@chromium.org>
Wed, 8 Feb 2017 15:42:46 +0000 (15:42 +0000)
Build flag available for backends to begin testing their impl.

Need to formalize save/restore, and how to forward these to device but not on picture canvases.

BUG=skia:6214

Change-Id: Ic5c0afba3e8c84fcf124567e63fe2f5880b623e7
Reviewed-on: https://skia-review.googlesource.com/8183
Commit-Queue: Mike Reed <reed@google.com>
Reviewed-by: Florin Malita <fmalita@chromium.org>
Reviewed-by: Brian Salomon <bsalomon@google.com>
src/core/SkBitmapDevice.cpp
src/core/SkBitmapDevice.h
src/core/SkCanvas.cpp
src/core/SkDevice.h

index fe43ba2..2b5c37f 100644 (file)
@@ -74,6 +74,8 @@ SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap)
 {
     SkASSERT(valid_for_bitmap_device(bitmap.info(), nullptr));
     fBitmap.lockPixels();
+
+    fRCStack.push_back().setRect(SkIRect::MakeWH(bitmap.width(), bitmap.height()));
 }
 
 SkBitmapDevice* SkBitmapDevice::Create(const SkImageInfo& info) {
@@ -88,6 +90,8 @@ SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap, const SkSurfaceProps& sur
 {
     SkASSERT(valid_for_bitmap_device(bitmap.info(), nullptr));
     fBitmap.lockPixels();
+
+    fRCStack.push_back().setRect(SkIRect::MakeWH(bitmap.width(), bitmap.height()));
 }
 
 SkBitmapDevice* SkBitmapDevice::Create(const SkImageInfo& origInfo,
@@ -439,7 +443,7 @@ SkImageFilterCache* SkBitmapDevice::getImageFilterCache() {
     return cache;
 }
 
-///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////
 
 bool SkBitmapDevice::onShouldDisableLCD(const SkPaint& paint) const {
     if (kN32_SkColorType != fBitmap.colorType() ||
@@ -453,3 +457,32 @@ bool SkBitmapDevice::onShouldDisableLCD(const SkPaint& paint) const {
     }
     return false;
 }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+void SkBitmapDevice::onSave() {
+    fRCStack.push_back(fRCStack.back());
+}
+
+void SkBitmapDevice::onRestore() {
+    fRCStack.pop_back();
+}
+
+void SkBitmapDevice::onClipRect(const SkRect& rect, SkClipOp op, bool aa) {
+    fRCStack.back().op(rect, this->ctm(), SkIRect::MakeWH(this->width(), this->height()),
+                       (SkRegion::Op)op, aa);
+}
+
+void SkBitmapDevice::onClipRRect(const SkRRect& rrect, SkClipOp op, bool aa) {
+    fRCStack.back().op(rrect, this->ctm(), SkIRect::MakeWH(this->width(), this->height()),
+                       (SkRegion::Op)op, aa);
+}
+
+void SkBitmapDevice::onClipPath(const SkPath& path, SkClipOp op, bool aa) {
+    fRCStack.back().op(path, this->ctm(), SkIRect::MakeWH(this->width(), this->height()),
+                       (SkRegion::Op)op, aa);
+}
+
+void SkBitmapDevice::onClipRegion(const SkRegion& rgn, SkClipOp op) {
+    fRCStack.back().op(rgn, (SkRegion::Op)op);
+}
index 1f72d8d..0a64710 100644 (file)
@@ -14,6 +14,7 @@
 #include "SkDevice.h"
 #include "SkImageInfo.h"
 #include "SkPixelRef.h"
+#include "SkRasterClip.h"
 #include "SkRect.h"
 #include "SkScalar.h"
 #include "SkSize.h"
@@ -125,6 +126,13 @@ protected:
     bool onPeekPixels(SkPixmap*) override;
     bool onAccessPixels(SkPixmap*) override;
 
+    void onSave() override;
+    void onRestore() override;
+    void onClipRect(const SkRect& rect, SkClipOp, bool aa) override;
+    void onClipRRect(const SkRRect& rrect, SkClipOp, bool aa) override;
+    void onClipPath(const SkPath& path, SkClipOp, bool aa) override;
+    void onClipRegion(const SkRegion& deviceRgn, SkClipOp) override;
+
 private:
     friend class SkCanvas;
     friend struct DeviceCM; //for setMatrixClip
@@ -147,6 +155,7 @@ private:
 
     SkBitmap    fBitmap;
     void*       fRasterHandle = nullptr;
+    SkTArray<SkRasterClip>  fRCStack;
 
     void setNewSize(const SkISize&);  // Used by SkCanvas for resetForNextPicture().
 
index eb81bd7..64ef348 100644 (file)
@@ -387,6 +387,16 @@ private:
     typedef SkDraw INHERITED;
 };
 
+#define FOR_EACH_TOP_DEVICE( code )                 \
+    do {                                            \
+        DeviceCM* layer = fMCRec->fTopLayer;        \
+        while (layer) {                             \
+            SkBaseDevice* device = layer->fDevice;  \
+            code;                                   \
+            layer = layer->fNext;                   \
+        }                                           \
+    } while (0)
+
 /////////////////////////////////////////////////////////////////////////////
 
 static SkPaint* set_if_needed(SkLazyPaint* lazy, const SkPaint& orig) {
@@ -999,6 +1009,9 @@ void SkCanvas::doSave() {
     SkASSERT(fMCRec->fDeferredSaveCount > 0);
     fMCRec->fDeferredSaveCount -= 1;
     this->internalSave();
+#ifdef SK_USE_DEVICE_CLIPPING
+    FOR_EACH_TOP_DEVICE(device->save());
+#endif
 }
 
 void SkCanvas::restore() {
@@ -1014,6 +1027,9 @@ void SkCanvas::restore() {
             fSaveCount -= 1;
             this->internalRestore();
             this->didRestore();
+#ifdef SK_USE_DEVICE_CLIPPING
+            FOR_EACH_TOP_DEVICE(device->restore(fMCRec->fMatrix));
+#endif
         }
     }
 }
@@ -1456,6 +1472,11 @@ void SkCanvas::concat(const SkMatrix& matrix) {
     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);
 }
 
@@ -1505,6 +1526,11 @@ void SkCanvas::clipRect(const SkRect& rect, SkClipOp op, bool doAA) {
 
 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,
@@ -1542,6 +1568,11 @@ void SkCanvas::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edge
     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);
@@ -1579,7 +1610,11 @@ void SkCanvas::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeSty
 
     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;
@@ -1602,6 +1637,10 @@ void SkCanvas::clipRegion(const SkRegion& rgn, SkClipOp op) {
 }
 
 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;
index 9239672..3c0b778 100644 (file)
@@ -13,6 +13,9 @@
 #include "SkColor.h"
 #include "SkSurfaceProps.h"
 
+// enable to test new device-base clipping
+//#define SK_USE_DEVICE_CLIPPING
+
 class SkBitmap;
 class SkDraw;
 class SkDrawFilter;
@@ -101,6 +104,35 @@ public:
 
     virtual void* getRasterHandle() const { return nullptr; }
 
+    void save() { this->onSave(); }
+    void restore(const SkMatrix& ctm) {
+        this->onRestore();
+        this->setGlobalCTM(ctm);
+    }
+    void clipRect(const SkRect& rect, SkClipOp op, bool aa) {
+        this->onClipRect(rect, op, aa);
+    }
+    void clipRRect(const SkRRect& rrect, SkClipOp op, bool aa) {
+        this->onClipRRect(rrect, op, aa);
+    }
+    void clipPath(const SkPath& path, SkClipOp op, bool aa) {
+        this->onClipPath(path, op, aa);
+    }
+    void clipRegion(const SkRegion& region, SkClipOp op) {
+        this->onClipRegion(region, op);
+    }
+
+    const SkMatrix& ctm() const { return fCTM; }
+    void setCTM(const SkMatrix& ctm) {
+        fCTM = ctm;
+    }
+    void setGlobalCTM(const SkMatrix& ctm) {
+        fCTM = ctm;
+        if (fOrigin.fX | fOrigin.fY) {
+            fCTM.postTranslate(-SkIntToScalar(fOrigin.fX), -SkIntToScalar(fOrigin.fY));
+        }
+    }
+    
 protected:
     enum TileUsage {
         kPossible_TileUsage,    //!< the created device may be drawn tiled
@@ -119,6 +151,13 @@ protected:
 
     virtual bool onShouldDisableLCD(const SkPaint&) const { return false; }
 
+    virtual void onSave() {}
+    virtual void onRestore() {}
+    virtual void onClipRect(const SkRect& rect, SkClipOp, bool aa) {}
+    virtual void onClipRRect(const SkRRect& rrect, SkClipOp, bool aa) {}
+    virtual void onClipPath(const SkPath& path, SkClipOp, bool aa) {}
+    virtual void onClipRegion(const SkRegion& deviceRgn, SkClipOp) {}
+
     /** 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
@@ -348,6 +387,7 @@ private:
     SkIPoint             fOrigin;
     const SkImageInfo    fInfo;
     const SkSurfaceProps fSurfaceProps;
+    SkMatrix             fCTM;
 
     typedef SkRefCnt INHERITED;
 };