From 6f09709519b79a1159f3826645f1c5fbc101ee11 Mon Sep 17 00:00:00 2001 From: reed Date: Tue, 9 Sep 2014 12:51:10 -0700 Subject: Revert of allow canvas to force conservative clips (for speed) (patchset #7 id:120001 of https://codereview.chromium.org/541593005/) Reason for revert: multipicturedraw failed on nvprmsaa -- don't know why yet Original issue's description: > Allow SkCanvas to be initialized to force conservative rasterclips. This has the following effects: > > 1. Queries to the current clip will be conservatively large. This can mean the quickReject may return false more often. > > 2. The conservative clips mean less work is done. > > 3. Enabled by default for Gpu, Record, and NoSaveLayer canvases. > > 4. API is private for now. > > Committed: https://skia.googlesource.com/skia/+/27a5e656c3d6ef22f9cb34de18e1b960da3aa241 R=robertphillips@google.com, bsalomon@google.com, mtklein@google.com, junov@google.com TBR=bsalomon@google.com, junov@google.com, mtklein@google.com, robertphillips@google.com NOTREECHECKS=true NOTRY=true Author: reed@google.com Review URL: https://codereview.chromium.org/554033003 --- src/core/SkCanvas.cpp | 183 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 112 insertions(+), 71 deletions(-) (limited to 'src/core/SkCanvas.cpp') diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index 62d60da178..99786151ab 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -81,12 +81,9 @@ struct DeviceCM { const SkMatrix* fMatrix; SkPaint* fPaint; // may be null (in the future) - DeviceCM(SkBaseDevice* device, int x, int y, const SkPaint* paint, SkCanvas* canvas, - bool conservativeRasterClip) - : fNext(NULL) - , fClip(conservativeRasterClip) - { - if (NULL != device) { + DeviceCM(SkBaseDevice* device, int x, int y, const SkPaint* paint, SkCanvas* canvas) + : fNext(NULL) { + if (device) { device->ref(); device->onAttachToCanvas(canvas); } @@ -154,10 +151,11 @@ private: */ class SkCanvas::MCRec { public: - SkRasterClip fRasterClip; SkMatrix fMatrix; + SkRasterClip fRasterClip; SkDrawFilter* fFilter; // the current filter (or null) - DeviceCM* fLayer; + + DeviceCM* fLayer; /* If there are any layers in the stack, this points to the top-most one that is at or below this level in the stack (so we know what bitmap/device to draw into from this level. This value is NOT @@ -166,21 +164,22 @@ public: */ DeviceCM* fTopLayer; - MCRec(bool conservativeRasterClip) : fRasterClip(conservativeRasterClip) { - fMatrix.reset(); - fFilter = NULL; - fLayer = NULL; - fTopLayer = NULL; - - // don't bother initializing fNext - inc_rec(); - } - MCRec(const MCRec& prev) : fRasterClip(prev.fRasterClip) { - fMatrix = prev.fMatrix; - fFilter = SkSafeRef(prev.fFilter); + MCRec(const MCRec* prev) { + if (prev) { + fMatrix = prev->fMatrix; + fRasterClip = prev->fRasterClip; + + fFilter = prev->fFilter; + SkSafeRef(fFilter); + + fTopLayer = prev->fTopLayer; + } else { // no prev + fMatrix.reset(); + fFilter = NULL; + fTopLayer = NULL; + } fLayer = NULL; - fTopLayer = prev.fTopLayer; - + // don't bother initializing fNext inc_rec(); } @@ -382,8 +381,7 @@ bool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) { //////////////////////////////////////////////////////////////////////////// -SkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) { - fConservativeRasterClip = SkToBool(flags & kConservativeRasterClip_InitFlag); +SkBaseDevice* SkCanvas::init(SkBaseDevice* device) { fCachedLocalClipBounds.setEmpty(); fCachedLocalClipBoundsDirty = true; fAllowSoftClip = true; @@ -393,14 +391,10 @@ SkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) { fCullCount = 0; fMetaData = NULL; - if (device && device->forceConservativeRasterClip()) { - fConservativeRasterClip = true; - } - fMCRec = (MCRec*)fMCStack.push_back(); - new (fMCRec) MCRec(fConservativeRasterClip); + new (fMCRec) MCRec(NULL); - fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL, NULL, fConservativeRasterClip)); + fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL, NULL)); fMCRec->fTopLayer = fMCRec->fLayer; fSurfaceBase = NULL; @@ -418,54 +412,25 @@ SkCanvas::SkCanvas() { inc_canvas(); - this->init(NULL, kDefault_InitFlags); + this->init(NULL); } -static SkBitmap make_nopixels(int width, int height) { - SkBitmap bitmap; - bitmap.setInfo(SkImageInfo::MakeUnknown(width, height)); - return bitmap; -} - -class SkNoPixelsBitmapDevice : public SkBitmapDevice { -public: - SkNoPixelsBitmapDevice(int width, int height) : INHERITED(make_nopixels(width, height)) {} - -private: - - typedef SkBitmapDevice INHERITED; -}; - SkCanvas::SkCanvas(int width, int height) : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) { inc_canvas(); - - this->init(SkNEW_ARGS(SkNoPixelsBitmapDevice, (width, height)), kDefault_InitFlags)->unref(); -} - -SkCanvas::SkCanvas(int width, int height, InitFlags flags) - : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) -{ - inc_canvas(); - - this->init(SkNEW_ARGS(SkNoPixelsBitmapDevice, (width, height)), flags)->unref(); -} -SkCanvas::SkCanvas(SkBaseDevice* device, InitFlags flags) - : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) -{ - inc_canvas(); - - this->init(device, flags); + SkBitmap bitmap; + bitmap.setInfo(SkImageInfo::MakeUnknown(width, height)); + this->init(SkNEW_ARGS(SkBitmapDevice, (bitmap)))->unref(); } SkCanvas::SkCanvas(SkBaseDevice* device) : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) { inc_canvas(); - - this->init(device, kDefault_InitFlags); + + this->init(device); } SkCanvas::SkCanvas(const SkBitmap& bitmap) @@ -473,7 +438,7 @@ SkCanvas::SkCanvas(const SkBitmap& bitmap) { inc_canvas(); - this->init(SkNEW_ARGS(SkBitmapDevice, (bitmap)), kDefault_InitFlags)->unref(); + this->init(SkNEW_ARGS(SkBitmapDevice, (bitmap)))->unref(); } SkCanvas::~SkCanvas() { @@ -769,7 +734,7 @@ int SkCanvas::internalSave() { int saveCount = this->getSaveCount(); // record this before the actual save MCRec* newTop = (MCRec*)fMCStack.push_back(); - new (newTop) MCRec(*fMCRec); // balanced in restore() + new (newTop) MCRec(fMCRec); // balanced in restore() fMCRec = newTop; fClipStack.save(); @@ -901,8 +866,7 @@ int SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, Save } device->setOrigin(ir.fLeft, ir.fTop); - DeviceCM* layer = SkNEW_ARGS(DeviceCM, - (device, ir.fLeft, ir.fTop, paint, this, fConservativeRasterClip)); + DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, ir.fLeft, ir.fTop, paint, this)); device->unref(); layer->fNext = fMCRec->fTopLayer; @@ -1322,7 +1286,7 @@ void SkCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edg fMCRec->fMatrix.mapRect(&r, rect); fClipStack.clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle); - fMCRec->fRasterClip.op(r, this->getBaseLayerSize(), op, kSoft_ClipEdgeStyle == edgeStyle); + fMCRec->fRasterClip.op(r, op, kSoft_ClipEdgeStyle == edgeStyle); } else { // since we're rotated or some such thing, we convert the rect to a path // and clip against that, since it can handle any matrix. However, to @@ -1457,6 +1421,82 @@ void SkCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edg rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, edgeStyle); } +void SkCanvas::updateClipConservativelyUsingBounds(const SkRect& bounds, SkRegion::Op op, + bool inverseFilled) { + // This is for updating the clip conservatively using only bounds + // information. + // Contract: + // The current clip must contain the true clip. The true + // clip is the clip that would have normally been computed + // by calls to clipPath and clipRRect + // Objective: + // Keep the current clip as small as possible without + // breaking the contract, using only clip bounding rectangles + // (for performance). + + // N.B.: This *never* calls back through a virtual on canvas, so subclasses + // don't have to worry about getting caught in a loop. Thus anywhere + // we call a virtual method, we explicitly prefix it with + // SkCanvas:: to be sure to call the base-class. + + if (inverseFilled) { + switch (op) { + case SkRegion::kIntersect_Op: + case SkRegion::kDifference_Op: + // These ops can only shrink the current clip. So leaving + // the clip unchanged conservatively respects the contract. + break; + case SkRegion::kUnion_Op: + case SkRegion::kReplace_Op: + case SkRegion::kReverseDifference_Op: + case SkRegion::kXOR_Op: { + // These ops can grow the current clip up to the extents of + // the input clip, which is inverse filled, so we just set + // the current clip to the device bounds. + SkRect deviceBounds; + SkIRect deviceIBounds; + this->getDevice()->getGlobalBounds(&deviceIBounds); + deviceBounds = SkRect::Make(deviceIBounds); + + // set the clip in device space + SkMatrix savedMatrix = this->getTotalMatrix(); + this->SkCanvas::setMatrix(SkMatrix::I()); + this->SkCanvas::onClipRect(deviceBounds, SkRegion::kReplace_Op, + kHard_ClipEdgeStyle); + this->setMatrix(savedMatrix); + break; + } + default: + SkASSERT(0); // unhandled op? + } + } else { + // Not inverse filled + switch (op) { + case SkRegion::kIntersect_Op: + case SkRegion::kUnion_Op: + case SkRegion::kReplace_Op: + this->SkCanvas::onClipRect(bounds, op, kHard_ClipEdgeStyle); + break; + case SkRegion::kDifference_Op: + // Difference can only shrink the current clip. + // Leaving clip unchanged conservatively fullfills the contract. + break; + case SkRegion::kReverseDifference_Op: + // To reverse, we swap in the bounds with a replace op. + // As with difference, leave it unchanged. + this->SkCanvas::onClipRect(bounds, SkRegion::kReplace_Op, kHard_ClipEdgeStyle); + break; + case SkRegion::kXOR_Op: + // Be conservative, based on (A XOR B) always included in (A union B), + // which is always included in (bounds(A) union bounds(B)) + this->SkCanvas::onClipRect(bounds, SkRegion::kUnion_Op, kHard_ClipEdgeStyle); + break; + default: + SkASSERT(0); // unhandled op? + } + } +} + void SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) { this->onClipRegion(rgn, op); } @@ -1485,7 +1525,7 @@ void SkCanvas::validateClip() const { SkIRect ir; ir.set(0, 0, device->width(), device->height()); - SkRasterClip tmpClip(ir, fConservativeRasterClip); + SkRasterClip tmpClip(ir); SkClipStack::B2TIter iter(fClipStack); const SkClipStack::Element* element; @@ -1529,6 +1569,7 @@ bool SkCanvas::isClipRect() const { } bool SkCanvas::quickReject(const SkRect& rect) const { + if (!rect.isFinite()) return true; -- cgit v1.2.3