From 27d07f0acb85eea4062075dfbe9148ce12d92c66 Mon Sep 17 00:00:00 2001 From: Mike Reed Date: Sat, 4 Mar 2017 21:47:47 +0000 Subject: Revert "Revert "Revert "Revert[2] "Remove SkDraw from device-draw methods, and enable device-centric clipping.""""" This reverts commit 025e2444c1f5a0c3cdc0bf60d1fa59941a0b5db4. Reason for revert: layouttest failures -- need to rebase these (tiny diffs in gradients) https://storage.googleapis.com/chromium-layout-test-archives/linux_trusty_blink_rel/6018/layout-test-results/results.html Original change's description: > Revert "Revert "Revert[2] "Remove SkDraw from device-draw methods, and enable device-centric clipping."""" > > This reverts commit baf06bc89a0ee2ac4033281e7310f6c727faab79. > > Reason for revert: reland to diagnose possible g3 failure > > Original change's description: > > Revert "Revert[2] "Remove SkDraw from device-draw methods, and enable device-centric clipping.""" > > > > This reverts commit cfaa63237b152ae216f1351207bce3ea9808814c. > > > > Reason for revert: speculative revert to fix Google3 > > > > Original change's description: > > > Revert[2] "Remove SkDraw from device-draw methods, and enable device-centric clipping."" > > > > > > passes new (augmented) CanvasClipType unittest > > > fixed rasterclipstack::setnewsize > > > > > > This reverts commit ea5e676a7b75600edcde3912886486004ccd7626. > > > > > > BUG=skia: > > > > > > Change-Id: I004653e0f4d01454662f8516fccab0046486f273 > > > Reviewed-on: https://skia-review.googlesource.com/9185 > > > Reviewed-by: Brian Salomon > > > Commit-Queue: Mike Reed > > > > > > > TBR=bsalomon@google.com,reed@google.com,reviews@skia.org > > NOPRESUBMIT=true > > NOTREECHECKS=true > > NOTRY=true > > BUG=skia: > > > > Change-Id: Ibd7ee6383999f008eb6ee59c1c3f1c06a86044ea > > Reviewed-on: https://skia-review.googlesource.com/9230 > > Reviewed-by: Cary Clark > > Commit-Queue: Cary Clark > > > > TBR=bsalomon@google.com,reviews@skia.org,caryclark@google.com,reed@google.com,mtklein@chromium.org > NOPRESUBMIT=true > NOTREECHECKS=true > NOTRY=true > BUG=skia: > > Change-Id: I093fa8788056be39af01191bbf3a9e5de9f73954 > Reviewed-on: https://skia-review.googlesource.com/9244 > Reviewed-by: Mike Reed > Commit-Queue: Mike Reed > TBR=mtklein@chromium.org,bsalomon@google.com,reviews@skia.org,caryclark@google.com,reed@google.com NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=skia: Change-Id: I58f810a8ff241dbaf3133e2fe844548fcd0fa67a Reviewed-on: https://skia-review.googlesource.com/9245 Reviewed-by: Mike Reed Commit-Queue: Mike Reed --- src/core/SkCanvas.cpp | 403 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 302 insertions(+), 101 deletions(-) (limited to 'src/core/SkCanvas.cpp') diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index 0e8e7e5644..5c7039fc50 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -75,13 +75,9 @@ bool SkCanvas::wouldOverwriteEntireSurface(const SkRect* rect, const SkPaint* pa const SkISize size = this->getBaseLayerSize(); const SkRect bounds = SkRect::MakeIWH(size.width(), size.height()); - -#if 0 - // Replace with device method? if (!this->getClipStack()->quickContains(bounds)) { return false; } -#endif if (rect) { if (!this->getTotalMatrix().isScaleTranslate()) { @@ -196,8 +192,10 @@ struct DeviceCM { SkMatrix fMatrixStorage; SkMatrix fStashedMatrix; // original CTM; used by imagefilter in saveLayer - DeviceCM(SkBaseDevice* device, const SkPaint* paint, SkCanvas* canvas, const SkMatrix& stashed) + DeviceCM(SkBaseDevice* device, const SkPaint* paint, SkCanvas* canvas, + bool conservativeRasterClip, const SkMatrix& stashed) : fNext(nullptr) + , fClip(conservativeRasterClip) , fStashedMatrix(stashed) { SkSafeRef(device); @@ -216,6 +214,48 @@ struct DeviceCM { 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. @@ -235,15 +275,15 @@ public: reference counted, since the real owner is either our fLayer field, or a previous one in a lower level.) */ - DeviceCM* fTopLayer; - SkConservativeClip fRasterClip; - SkMatrix fMatrix; - int fDeferredSaveCount; + DeviceCM* fTopLayer; + SkRasterClip fRasterClip; + SkMatrix fMatrix; + int fDeferredSaveCount; // This is the current cumulative depth (aggregate of all done translateZ calls) SkScalar fCurDrawDepth; - MCRec() { + MCRec(bool conservativeRasterClip) : fRasterClip(conservativeRasterClip) { fFilter = nullptr; fLayer = nullptr; fTopLayer = nullptr; @@ -280,26 +320,70 @@ public: } }; -class SkDrawIter { +static SkIRect compute_device_bounds(SkBaseDevice* device) { + return SkIRect::MakeXYWH(device->getOrigin().x(), device->getOrigin().y(), + device->width(), device->height()); +} + +class SkDrawIter : public SkDraw { public: - SkDrawIter(SkCanvas* canvas) - : fDevice(nullptr), fCurrLayer(canvas->fMCRec->fTopLayer), fPaint(nullptr) - {} + 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(); + } + } 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; @@ -307,6 +391,9 @@ public: private: const DeviceCM* fCurrLayer; const SkPaint* fPaint; // May be null. + SkClipStack* fMultiDeviceCS; + + typedef SkDraw INHERITED; }; #define FOR_EACH_TOP_DEVICE( code ) \ @@ -570,6 +657,7 @@ static inline SkRect qr_clip_bounds(const SkIRect& bounds) { 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 @@ -583,22 +671,29 @@ SkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) { 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(&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; + new (fMCRec) MCRec(fConservativeRasterClip); fMCRec->fRasterClip.setDeviceClipRestriction(&fClipRestrictionRect); fIsScaleTranslate = true; SkASSERT(sizeof(DeviceCM) <= sizeof(fDeviceCMStorage)); fMCRec->fLayer = (DeviceCM*)fDeviceCMStorage; - new (fDeviceCMStorage) DeviceCM(nullptr, nullptr, nullptr, fMCRec->fMatrix); + new (fDeviceCMStorage) DeviceCM(nullptr, nullptr, nullptr, fConservativeRasterClip, + fMCRec->fMatrix); fMCRec->fTopLayer = fMCRec->fLayer; @@ -611,7 +706,9 @@ SkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) { fMCRec->fRasterClip.setRect(device->getGlobalBounds()); fDeviceClipBounds = qr_clip_bounds(device->getGlobalBounds()); +#ifdef SK_USE_DEVICE_CLIPPING device->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect); +#endif } return device; @@ -620,6 +717,7 @@ SkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) { SkCanvas::SkCanvas() : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) , fProps(SkSurfaceProps::kLegacyFontHost_InitType) + , fConservativeRasterClip(false) { inc_canvas(); @@ -648,6 +746,7 @@ private: SkCanvas::SkCanvas(int width, int height, const SkSurfaceProps* props) : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) , fProps(SkSurfacePropsCopyOrDefault(props)) + , fConservativeRasterClip(false) { inc_canvas(); @@ -658,6 +757,7 @@ SkCanvas::SkCanvas(int width, int height, const SkSurfaceProps* props) SkCanvas::SkCanvas(const SkIRect& bounds, InitFlags flags) : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) , fProps(SkSurfaceProps::kLegacyFontHost_InitType) + , fConservativeRasterClip(false) { inc_canvas(); @@ -667,6 +767,7 @@ SkCanvas::SkCanvas(const SkIRect& bounds, InitFlags flags) SkCanvas::SkCanvas(SkBaseDevice* device) : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) , fProps(device->surfaceProps()) + , fConservativeRasterClip(false) { inc_canvas(); @@ -676,6 +777,7 @@ SkCanvas::SkCanvas(SkBaseDevice* device) SkCanvas::SkCanvas(SkBaseDevice* device, InitFlags flags) : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) , fProps(device->surfaceProps()) + , fConservativeRasterClip(false) { inc_canvas(); @@ -685,6 +787,7 @@ SkCanvas::SkCanvas(SkBaseDevice* device, InitFlags flags) SkCanvas::SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props) : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) , fProps(props) + , fConservativeRasterClip(false) { inc_canvas(); @@ -697,6 +800,7 @@ SkCanvas::SkCanvas(const SkBitmap& bitmap, std::unique_ptrgetTotalMatrix(); + 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(); @@ -933,7 +1057,10 @@ void SkCanvas::internalSave() { 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) { @@ -964,7 +1091,6 @@ bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveLayerFlags saveLayerFlag // 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(); } @@ -977,6 +1103,7 @@ bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveLayerFlags saveLayerFlag 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); } @@ -1009,7 +1136,7 @@ int SkCanvas::saveLayer(const SaveLayerRec& origRec) { void SkCanvas::DrawDeviceWithFilter(SkBaseDevice* src, const SkImageFilter* filter, SkBaseDevice* dst, const SkIPoint& dstOrigin, - const SkMatrix& ctm) { + const SkMatrix& ctm, const SkClipStack* clipStack) { SkDraw draw; SkRasterClip rc; rc.setRect(SkIRect::MakeWH(dst->width(), dst->height())); @@ -1018,6 +1145,7 @@ void SkCanvas::DrawDeviceWithFilter(SkBaseDevice* src, const SkImageFilter* filt } draw.fMatrix = &SkMatrix::I(); draw.fRC = &rc; + draw.fClipStack = clipStack; SkPaint p; if (filter) { @@ -1028,7 +1156,7 @@ void SkCanvas::DrawDeviceWithFilter(SkBaseDevice* src, const SkImageFilter* filt int y = src->getOrigin().y() - dstOrigin.y(); auto special = src->snapSpecial(); if (special) { - dst->drawSpecial(special.get(), x, y, p); + dst->drawSpecial(draw, special.get(), x, y, p); } } @@ -1092,6 +1220,8 @@ void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy stra // that would invoke a possibly overridden virtual this->internalSave(); + fDeviceCMDirty = true; + SkIRect ir; if (!this->clipRectBounds(bounds, saveLayerFlags, &ir, imageFilter)) { return; @@ -1135,8 +1265,12 @@ void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy stra return; } } +#ifndef SK_USE_DEVICE_CLIPPING + newDevice->setOrigin(fMCRec->fMatrix, ir.fLeft, ir.fTop); +#endif + DeviceCM* layer = - new DeviceCM(newDevice.get(), paint, this, stashedMatrix); + new DeviceCM(newDevice.get(), paint, this, fConservativeRasterClip, stashedMatrix); // only have a "next" if this new layer doesn't affect the clip (rare) layer->fNext = BoundsAffectsClip(saveLayerFlags) ? nullptr : fMCRec->fTopLayer; @@ -1145,9 +1279,10 @@ void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy stra if ((rec.fSaveLayerFlags & kInitWithPrevious_SaveLayerFlag) || rec.fBackdrop) { DrawDeviceWithFilter(priorDevice, rec.fBackdrop, newDevice.get(), { ir.fLeft, ir.fTop }, - fMCRec->fMatrix); + fMCRec->fMatrix, this->getClipStack()); } +#ifdef SK_USE_DEVICE_CLIPPING newDevice->setOrigin(fMCRec->fMatrix, ir.fLeft, ir.fTop); newDevice->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect); @@ -1160,6 +1295,7 @@ void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy stra layer->fDevice->clipRegion(hole, SkClipOp::kDifference); } while (layer->fNext); } +#endif } int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) { @@ -1175,6 +1311,10 @@ int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) { 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 @@ -1185,9 +1325,11 @@ void SkCanvas::internalRestore() { 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 @@ -1200,6 +1342,7 @@ void SkCanvas::internalRestore() { // 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 @@ -1305,10 +1448,10 @@ void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y, const SkPa if (filter) { sk_sp specialImage = srcDev->snapSpecial(); if (specialImage) { - dstDev->drawSpecial(specialImage.get(), pos.x(), pos.y(), *paint); + dstDev->drawSpecial(iter, specialImage.get(), pos.x(), pos.y(), *paint); } } else { - dstDev->drawDevice(srcDev, pos.x(), pos.y(), *paint); + dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint); } } @@ -1320,12 +1463,15 @@ void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y, const SkPa 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); } @@ -1361,19 +1507,25 @@ void SkCanvas::concat(const SkMatrix& matrix) { } 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) { @@ -1417,25 +1569,36 @@ 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, 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()); } } @@ -1453,13 +1616,19 @@ void SkCanvas::clipRRect(const SkRRect& rrect, SkClipOp op, bool doAA) { 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) { @@ -1490,12 +1659,24 @@ void SkCanvas::clipPath(const SkPath& path, SkClipOp op, bool doAA) { 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()); @@ -1507,10 +1688,18 @@ 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; + + // 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()); } @@ -1523,61 +1712,51 @@ void SkCanvas::validateClip() const { 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 { - SkBaseDevice* dev = this->getTopDevice(); - // if no device we return true - return !dev || dev->onGetClipType() == SkBaseDevice::kEmpty_ClipType; + return fMCRec->fRasterClip.isEmpty(); } bool SkCanvas::isClipRect() const { - SkBaseDevice* dev = this->getTopDevice(); - // if no device we return false - return dev && dev->onGetClipType() == SkBaseDevice::kRect_ClipType; + return fMCRec->fRasterClip.isRect(); } static inline bool is_nan_or_clipped(const Sk4f& devRect, const Sk4f& devClip) { @@ -1678,13 +1857,38 @@ SkRect SkCanvas::onGetLocalClipBounds() const { } SkIRect SkCanvas::onGetDeviceClipBounds() const { - return fMCRec->fRasterClip.getBounds(); + const SkRasterClip& clip = fMCRec->fRasterClip; + if (clip.isEmpty()) { + return SkIRect::MakeEmpty(); + } + return clip.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; @@ -1954,7 +2158,7 @@ void SkCanvas::internalDrawPaint(const SkPaint& paint) { LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kPaint_Type, nullptr, false) while (iter.next()) { - iter.fDevice->drawPaint(looper.paint()); + iter.fDevice->drawPaint(iter, looper.paint()); } LOOPER_END @@ -1988,7 +2192,7 @@ void SkCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[], LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds) while (iter.next()) { - iter.fDevice->drawPoints(mode, count, pts, looper.paint()); + iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint()); } LOOPER_END @@ -2020,7 +2224,7 @@ void SkCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) { LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kRect_Type, &r, false) while (iter.next()) { - iter.fDevice->drawRect(r, looper.paint()); + iter.fDevice->drawRect(iter, r, looper.paint()); } LOOPER_END @@ -2028,7 +2232,7 @@ void SkCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) { this->predrawNotify(&r, &paint, false); SkDrawIter iter(this); while (iter.next()) { - iter.fDevice->drawRect(r, paint); + iter.fDevice->drawRect(iter, r, paint); } } } @@ -2045,7 +2249,7 @@ void SkCanvas::onDrawRegion(const SkRegion& region, const SkPaint& paint) { LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, ®ionRect) while (iter.next()) { - iter.fDevice->drawRegion(region, looper.paint()); + iter.fDevice->drawRegion(iter, region, looper.paint()); } LOOPER_END @@ -2063,7 +2267,7 @@ void SkCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) { LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, &oval) while (iter.next()) { - iter.fDevice->drawOval(oval, looper.paint()); + iter.fDevice->drawOval(iter, oval, looper.paint()); } LOOPER_END @@ -2084,7 +2288,7 @@ void SkCanvas::onDrawArc(const SkRect& oval, SkScalar startAngle, LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, &oval) while (iter.next()) { - iter.fDevice->drawArc(oval, startAngle, sweepAngle, useCenter, looper.paint()); + iter.fDevice->drawArc(iter, oval, startAngle, sweepAngle, useCenter, looper.paint()); } LOOPER_END @@ -2112,7 +2316,7 @@ void SkCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) { LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, &rrect.getBounds()) while (iter.next()) { - iter.fDevice->drawRRect(rrect, looper.paint()); + iter.fDevice->drawRRect(iter, rrect, looper.paint()); } LOOPER_END @@ -2129,7 +2333,7 @@ void SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const Sk LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, &outer.getBounds()) while (iter.next()) { - iter.fDevice->drawDRRect(outer, inner, looper.paint()); + iter.fDevice->drawDRRect(iter, outer, inner, looper.paint()); } LOOPER_END @@ -2159,7 +2363,7 @@ void SkCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) { LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, &pathBounds) while (iter.next()) { - iter.fDevice->drawPath(path, looper.paint()); + iter.fDevice->drawPath(iter, path, looper.paint()); } LOOPER_END @@ -2221,12 +2425,12 @@ void SkCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const S const SkPaint& pnt = looper.paint(); if (special) { SkPoint pt; - iter.fDevice->ctm().mapXY(x, y, &pt); - iter.fDevice->drawSpecial(special.get(), + iter.fMatrix->mapXY(x, y, &pt); + iter.fDevice->drawSpecial(iter, special.get(), SkScalarRoundToInt(pt.fX), SkScalarRoundToInt(pt.fY), pnt); } else { - iter.fDevice->drawImage(image, x, y, pnt); + iter.fDevice->drawImage(iter, image, x, y, pnt); } } @@ -2254,7 +2458,7 @@ void SkCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const Sk image->isOpaque()) while (iter.next()) { - iter.fDevice->drawImageRect(image, src, dst, looper.paint(), constraint); + iter.fDevice->drawImageRect(iter, image, src, dst, looper.paint(), constraint); } LOOPER_END @@ -2302,12 +2506,12 @@ void SkCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, cons const SkPaint& pnt = looper.paint(); if (special) { SkPoint pt; - iter.fDevice->ctm().mapXY(x, y, &pt); - iter.fDevice->drawSpecial(special.get(), + iter.fMatrix->mapXY(x, y, &pt); + iter.fDevice->drawSpecial(iter, special.get(), SkScalarRoundToInt(pt.fX), SkScalarRoundToInt(pt.fY), pnt); } else { - iter.fDevice->drawBitmap(bitmap, matrix, looper.paint()); + iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint()); } } @@ -2338,7 +2542,7 @@ void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, bitmap.isOpaque()) while (iter.next()) { - iter.fDevice->drawBitmapRect(bitmap, src, dst, looper.paint(), constraint); + iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), constraint); } LOOPER_END @@ -2370,7 +2574,7 @@ void SkCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center, cons LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst) while (iter.next()) { - iter.fDevice->drawImageNine(image, center, dst, looper.paint()); + iter.fDevice->drawImageNine(iter, image, center, dst, looper.paint()); } LOOPER_END @@ -2396,7 +2600,7 @@ void SkCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, c LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst) while (iter.next()) { - iter.fDevice->drawBitmapNine(bitmap, center, dst, looper.paint()); + iter.fDevice->drawBitmapNine(iter, bitmap, center, dst, looper.paint()); } LOOPER_END @@ -2419,7 +2623,7 @@ void SkCanvas::onDrawImageLattice(const SkImage* image, const Lattice& lattice, LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst) while (iter.next()) { - iter.fDevice->drawImageLattice(image, lattice, dst, looper.paint()); + iter.fDevice->drawImageLattice(iter, image, lattice, dst, looper.paint()); } LOOPER_END @@ -2442,7 +2646,7 @@ void SkCanvas::onDrawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattic LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst) while (iter.next()) { - iter.fDevice->drawBitmapLattice(bitmap, lattice, dst, looper.paint()); + iter.fDevice->drawBitmapLattice(iter, bitmap, lattice, dst, looper.paint()); } LOOPER_END @@ -2474,7 +2678,7 @@ void SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkSca while (iter.next()) { SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); - iter.fDevice->drawText(text, byteLength, x, y, dfp.paint()); + iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint()); } LOOPER_END @@ -2488,7 +2692,7 @@ void SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint while (iter.next()) { SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); - iter.fDevice->drawPosText(text, byteLength, &pos->fX, 2, textOffset, + iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 2, textOffset, dfp.paint()); } @@ -2504,7 +2708,7 @@ void SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScala while (iter.next()) { SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); - iter.fDevice->drawPosText(text, byteLength, xpos, 1, textOffset, + iter.fDevice->drawPosText(iter, text, byteLength, xpos, 1, textOffset, dfp.paint()); } @@ -2516,7 +2720,7 @@ void SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPat LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr) while (iter.next()) { - iter.fDevice->drawTextOnPath(text, byteLength, path, + iter.fDevice->drawTextOnPath(iter, text, byteLength, path, matrix, looper.paint()); } @@ -2532,7 +2736,7 @@ void SkCanvas::onDrawTextRSXform(const void* text, size_t byteLength, const SkRS LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr) while (iter.next()) { - iter.fDevice->drawTextRSXform(text, byteLength, xform, looper.paint()); + iter.fDevice->drawTextRSXform(iter, text, byteLength, xform, looper.paint()); } LOOPER_END @@ -2561,7 +2765,7 @@ void SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, while (iter.next()) { SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); - iter.fDevice->drawTextBlob(blob, x, y, dfp.paint(), drawFilter); + iter.fDevice->drawTextBlob(iter, blob, x, y, dfp.paint(), drawFilter); } LOOPER_END @@ -2621,7 +2825,7 @@ void SkCanvas::onDrawVertices(VertexMode vmode, int vertexCount, LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr) while (iter.next()) { - iter.fDevice->drawVertices(vmode, vertexCount, verts, texs, + iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs, colors, bmode, indices, indexCount, looper.paint()); } @@ -2636,7 +2840,7 @@ void SkCanvas::onDrawVerticesObject(sk_sp vertices, SkBlendMode bmod while (iter.next()) { // In the common case of one iteration we could std::move vertices here. - iter.fDevice->drawVerticesObject(vertices, bmode, looper.paint(), flags); + iter.fDevice->drawVerticesObject(iter, vertices, bmode, looper.paint(), flags); } LOOPER_END @@ -2676,7 +2880,7 @@ void SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4], LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr) while (iter.next()) { - iter.fDevice->drawPatch(cubics, colors, texCoords, bmode, paint); + iter.fDevice->drawPatch(iter, cubics, colors, texCoords, bmode, paint); } LOOPER_END @@ -2720,7 +2924,7 @@ void SkCanvas::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const LOOPER_BEGIN(pnt, SkDrawFilter::kPath_Type, nullptr) while (iter.next()) { - iter.fDevice->drawAtlas(atlas, xform, tex, colors, count, bmode, pnt); + iter.fDevice->drawAtlas(iter, atlas, xform, tex, colors, count, bmode, pnt); } LOOPER_END } @@ -2731,7 +2935,7 @@ void SkCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* va SkPaint paint; LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, nullptr) while (iter.next()) { - iter.fDevice->drawAnnotation(rect, key, value); + iter.fDevice->drawAnnotation(iter, rect, key, value); } LOOPER_END } @@ -3106,7 +3310,7 @@ SkBaseDevice* SkCanvas::LayerIter::device() const { } const SkMatrix& SkCanvas::LayerIter::matrix() const { - return fImpl->fDevice->ctm(); + return fImpl->getMatrix(); } const SkPaint& SkCanvas::LayerIter::paint() const { @@ -3117,10 +3321,7 @@ const SkPaint& SkCanvas::LayerIter::paint() const { return *paint; } -void SkCanvas::LayerIter::clip(SkRegion* rgn) const { - return fImpl->fDevice->onAsRgnClip(rgn); -} - +const SkRasterClip& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); } int SkCanvas::LayerIter::x() const { return fImpl->getX(); } int SkCanvas::LayerIter::y() const { return fImpl->getY(); } -- cgit v1.2.3