Skip to content

Commit 8636e13

Browse files
lhkbobSkia Commit-Bot
authored andcommitted
Revert "Move conservative bounds tracking from SkCanvas to SkNoPixelsDevice"
This reverts commit 11a3947. Reason for revert: assert during google3 tests. Original change's description: > Move conservative bounds tracking from SkCanvas to SkNoPixelsDevice > > Change-Id: I56670b4a4159e21eaa1a58a9a3ee439298d5aa8e > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/335863 > Reviewed-by: Mike Reed <[email protected]> > Commit-Queue: Michael Ludwig <[email protected]> [email protected],[email protected],[email protected],[email protected] Change-Id: I7c3a8797460113d9a8ef18d82bbbd64aba2f439c No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://skia-review.googlesource.com/c/skia/+/338316 Reviewed-by: Michael Ludwig <[email protected]> Commit-Queue: Michael Ludwig <[email protected]>
1 parent ee792d6 commit 8636e13

File tree

4 files changed

+72
-196
lines changed

4 files changed

+72
-196
lines changed

include/core/SkCanvas.h

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2636,9 +2636,9 @@ class SK_API SkCanvas {
26362636
sk_sp<SkMarkerStack> fMarkerStack;
26372637

26382638
// the first N recs that can fit here mean we won't call malloc
2639-
static constexpr int kMCRecSize = 96; // most recent measurement
2640-
static constexpr int kMCRecCount = 32; // common depth for save/restores
2641-
static constexpr int kDeviceCMSize = 64; // most recent measurement
2639+
static constexpr int kMCRecSize = 128; // most recent measurement
2640+
static constexpr int kMCRecCount = 32; // common depth for save/restores
2641+
static constexpr int kDeviceCMSize = 64; // most recent measurement
26422642

26432643
intptr_t fMCRecStorage[kMCRecSize * kMCRecCount / sizeof(intptr_t)];
26442644
intptr_t fDeviceCMStorage[kDeviceCMSize / sizeof(intptr_t)];
@@ -2758,10 +2758,6 @@ class SK_API SkCanvas {
27582758
bool fIsScaleTranslate;
27592759
SkRect fQuickRejectBounds;
27602760

2761-
// Compute the clip's bounds based on all clipped SkDevice's reported device bounds transformed
2762-
// into the canvas' global space.
2763-
SkRect computeDeviceClipBounds() const;
2764-
27652761
class AutoValidateClip;
27662762
void validateClip() const;
27672763

src/core/SkCanvas.cpp

Lines changed: 50 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ class SkCanvas::MCRec {
230230
*/
231231
DeviceCM* fTopLayer;
232232
std::unique_ptr<BackImage> fBackImage;
233+
SkConservativeClip fRasterClip;
233234
SkM44 fMatrix;
234235
int fDeferredSaveCount;
235236

@@ -242,7 +243,7 @@ class SkCanvas::MCRec {
242243
// don't bother initializing fNext
243244
inc_rec();
244245
}
245-
MCRec(const MCRec& prev) : fMatrix(prev.fMatrix) {
246+
MCRec(const MCRec& prev) : fRasterClip(prev.fRasterClip), fMatrix(prev.fMatrix) {
246247
fLayer = nullptr;
247248
fTopLayer = prev.fTopLayer;
248249
fDeferredSaveCount = 0;
@@ -255,12 +256,13 @@ class SkCanvas::MCRec {
255256
dec_rec();
256257
}
257258

258-
void reset() {
259+
void reset(const SkIRect& bounds) {
259260
SkASSERT(fLayer);
260261
SkASSERT(fDeferredSaveCount == 0);
261262
fLayer->validate();
262263

263264
fMatrix.setIdentity();
265+
fRasterClip.setRect(bounds);
264266
}
265267
};
266268

@@ -469,35 +471,37 @@ class AutoLayerForImageFilter {
469471

470472
#define DRAW_END }
471473

472-
#define UPDATE_DEVICE_CLIP(code) \
474+
// TODO: conservativeUpdate is temporary to stage moving bounds tracking into SkNoPixelsDevice
475+
#define UPDATE_DEVICE_CLIP(code, conservativeUpdate) \
473476
do { \
474477
AutoValidateClip avc(this); \
475478
FOR_EACH_TOP_DEVICE(code); \
476-
fQuickRejectBounds = qr_clip_bounds(this->computeDeviceClipBounds()); \
479+
fMCRec->fRasterClip.conservativeUpdate; \
480+
fQuickRejectBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds()); \
477481
} while(0)
478482

479483
////////////////////////////////////////////////////////////////////////////
480484

481-
static inline SkRect qr_clip_bounds(const SkRect& bounds) {
485+
static inline SkRect qr_clip_bounds(const SkIRect& bounds) {
482486
if (bounds.isEmpty()) {
483487
return SkRect::MakeEmpty();
484488
}
485489

486490
// Expand bounds out by 1 in case we are anti-aliasing. We store the
487491
// bounds as floats to enable a faster quick reject implementation.
488492
SkRect dst;
489-
(Sk4f::Load(&bounds.fLeft) + Sk4f(-1.f, -1.f, 1.f, 1.f)).store(&dst.fLeft);
493+
SkNx_cast<float>(Sk4i::Load(&bounds.fLeft) + Sk4i(-1,-1,1,1)).store(&dst.fLeft);
490494
return dst;
491495
}
492496

493497
void SkCanvas::resetForNextPicture(const SkIRect& bounds) {
494498
this->restoreToCount(1);
495-
fMCRec->reset();
499+
fMCRec->reset(bounds);
496500

497501
// We're peering through a lot of structs here. Only at this scope do we
498502
// know that the device is a SkNoPixelsDevice.
499503
static_cast<SkNoPixelsDevice*>(fMCRec->fLayer->fDevice.get())->resetForNextPicture(bounds);
500-
fQuickRejectBounds = qr_clip_bounds(SkRect::Make(bounds));
504+
fQuickRejectBounds = qr_clip_bounds(bounds);
501505
fIsScaleTranslate = true;
502506
}
503507

@@ -515,6 +519,7 @@ void SkCanvas::init(sk_sp<SkBaseDevice> device) {
515519

516520
fMCRec = (MCRec*)fMCStack.push_back();
517521
new (fMCRec) MCRec;
522+
fMCRec->fRasterClip.setDeviceClipRestriction(&fClipRestrictionRect);
518523
fIsScaleTranslate = true;
519524

520525
fMCRec->fLayer = (DeviceCM*)fDeviceCMStorage;
@@ -523,15 +528,19 @@ void SkCanvas::init(sk_sp<SkBaseDevice> device) {
523528
fMCRec->fTopLayer = fMCRec->fLayer;
524529

525530
fSurfaceBase = nullptr;
531+
fQuickRejectBounds = {0, 0, 0, 0};
526532

527533
if (device) {
528534
// The root device and the canvas should always have the same pixel geometry
529535
SkASSERT(fProps.pixelGeometry() == device->surfaceProps().pixelGeometry());
536+
fMCRec->fRasterClip.setRect(device->getGlobalBounds());
537+
fQuickRejectBounds = qr_clip_bounds(device->getGlobalBounds());
538+
530539
device->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect);
540+
531541
device->setMarkerStack(fMarkerStack.get());
532542
}
533543

534-
fQuickRejectBounds = qr_clip_bounds(this->computeDeviceClipBounds());
535544
fScratchGlyphRunBuilder = std::make_unique<SkGlyphRunBuilder>();
536545
}
537546

@@ -1158,13 +1167,15 @@ void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy stra
11581167
// replaceClip() simulates what a new top-level device's canvas would be in
11591168
// the non-recording scenario. This allows the canvas to report the expanding
11601169
// effects of image filters on the temporary clip bounds.
1161-
UPDATE_DEVICE_CLIP(device->replaceClip(ir));
1170+
UPDATE_DEVICE_CLIP(device->replaceClip(ir),
1171+
setRect(ir));
11621172
} else {
11631173
// else the layer device failed to be created, so the saveLayer() effectively
11641174
// becomes just a save(). The clipRegion() explicitly applies the bounds of the
11651175
// failed layer, without resetting the clip of the prior device that all subsequent
11661176
// nested draw calls need to respect.
1167-
UPDATE_DEVICE_CLIP(device->clipRegion(SkRegion(ir), SkClipOp::kIntersect));
1177+
UPDATE_DEVICE_CLIP(device->clipRegion(SkRegion(ir), SkClipOp::kIntersect),
1178+
opRegion(SkRegion(ir), SkRegion::kIntersect_Op));
11681179
}
11691180
}
11701181
return;
@@ -1185,6 +1196,10 @@ void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy stra
11851196

11861197
newDevice->setOrigin(fMCRec->fMatrix, ir.fLeft, ir.fTop);
11871198
newDevice->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect);
1199+
if (boundsAffectsClip) {
1200+
fMCRec->fRasterClip.setRect(ir);
1201+
fQuickRejectBounds = qr_clip_bounds(ir);
1202+
}
11881203

11891204
if (layer->fNext) {
11901205
// need to punch a hole in the previous device, so we don't draw there, given that
@@ -1195,8 +1210,6 @@ void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy stra
11951210
layer->fDevice->clipRegion(hole, SkClipOp::kDifference);
11961211
} while (layer->fNext);
11971212
}
1198-
1199-
fQuickRejectBounds = qr_clip_bounds(this->computeDeviceClipBounds());
12001213
}
12011214

12021215
int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
@@ -1304,10 +1317,7 @@ void SkCanvas::internalRestore() {
13041317

13051318
if (fMCRec) {
13061319
fIsScaleTranslate = SkMatrixPriv::IsScaleTranslateAsM33(fMCRec->fMatrix);
1307-
// Update the quick-reject bounds in case the restore changed the top device or the
1308-
// removed save record had included modifications to the clip stack.
1309-
fQuickRejectBounds = qr_clip_bounds(this->computeDeviceClipBounds());
1310-
this->validateClip();
1320+
fQuickRejectBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
13111321
}
13121322
}
13131323

@@ -1576,7 +1586,8 @@ void SkCanvas::clipRect(const SkRect& rect, SkClipOp op, bool doAA) {
15761586
void SkCanvas::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle) {
15771587
SkASSERT(rect.isSorted());
15781588
const bool isAA = kSoft_ClipEdgeStyle == edgeStyle;
1579-
UPDATE_DEVICE_CLIP(device->clipRect(rect, op, isAA));
1589+
UPDATE_DEVICE_CLIP(device->clipRect(rect, op, isAA), \
1590+
opRect(rect, fMCRec->fMatrix.asM33(), this->getTopLayerBounds(), (SkRegion::Op) op, isAA));
15801591
}
15811592

15821593
void SkCanvas::androidFramework_setDeviceClipRestriction(const SkIRect& rect) {
@@ -1586,12 +1597,14 @@ void SkCanvas::androidFramework_setDeviceClipRestriction(const SkIRect& rect) {
15861597
// removing it (i.e. rect is empty).
15871598
this->checkForDeferredSave();
15881599
}
1589-
UPDATE_DEVICE_CLIP(device->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect));
1600+
UPDATE_DEVICE_CLIP(device->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect),\
1601+
opIRect(fClipRestrictionRect, SkRegion::kIntersect_Op));
15901602
}
15911603

15921604
void SkCanvas::androidFramework_replaceClip(const SkIRect& rect) {
15931605
this->checkForDeferredSave();
1594-
UPDATE_DEVICE_CLIP(device->replaceClip(rect));
1606+
UPDATE_DEVICE_CLIP(device->replaceClip(rect), \
1607+
setRect(rect));
15951608
}
15961609

15971610
void SkCanvas::clipRRect(const SkRRect& rrect, SkClipOp op, bool doAA) {
@@ -1606,7 +1619,8 @@ void SkCanvas::clipRRect(const SkRRect& rrect, SkClipOp op, bool doAA) {
16061619

16071620
void SkCanvas::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle) {
16081621
bool isAA = kSoft_ClipEdgeStyle == edgeStyle;
1609-
UPDATE_DEVICE_CLIP(device->clipRRect(rrect, op, isAA));
1622+
UPDATE_DEVICE_CLIP(device->clipRRect(rrect, op, isAA), \
1623+
opRRect(rrect, fMCRec->fMatrix.asM33(), this->getTopLayerBounds(), (SkRegion::Op)op, isAA));
16101624
}
16111625

16121626
void SkCanvas::clipPath(const SkPath& path, SkClipOp op, bool doAA) {
@@ -1636,7 +1650,8 @@ void SkCanvas::clipPath(const SkPath& path, SkClipOp op, bool doAA) {
16361650

16371651
void SkCanvas::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle) {
16381652
bool isAA = kSoft_ClipEdgeStyle == edgeStyle;
1639-
UPDATE_DEVICE_CLIP(device->clipPath(path, op, isAA));
1653+
UPDATE_DEVICE_CLIP(device->clipPath(path, op, isAA), \
1654+
opPath(path, fMCRec->fMatrix.asM33(), this->getTopLayerBounds(), (SkRegion::Op)op, isAA));
16401655
}
16411656

16421657
void SkCanvas::clipShader(sk_sp<SkShader> sh, SkClipOp op) {
@@ -1657,7 +1672,8 @@ void SkCanvas::clipShader(sk_sp<SkShader> sh, SkClipOp op) {
16571672
}
16581673

16591674
void SkCanvas::onClipShader(sk_sp<SkShader> sh, SkClipOp op) {
1660-
UPDATE_DEVICE_CLIP(device->clipShader(sh, op));
1675+
UPDATE_DEVICE_CLIP(device->clipShader(sh, op),
1676+
opShader(sh));
16611677
}
16621678

16631679
void SkCanvas::clipRegion(const SkRegion& rgn, SkClipOp op) {
@@ -1666,12 +1682,13 @@ void SkCanvas::clipRegion(const SkRegion& rgn, SkClipOp op) {
16661682
}
16671683

16681684
void SkCanvas::onClipRegion(const SkRegion& rgn, SkClipOp op) {
1669-
UPDATE_DEVICE_CLIP(device->clipRegion(rgn, op));
1685+
UPDATE_DEVICE_CLIP(device->clipRegion(rgn, op),
1686+
opRegion(rgn, (SkRegion::Op) op));
16701687
}
16711688

16721689
void SkCanvas::validateClip() const {
16731690
#ifdef SK_DEBUG
1674-
SkRect tmp = qr_clip_bounds(this->computeDeviceClipBounds());
1691+
SkRect tmp = qr_clip_bounds(this->fMCRec->fRasterClip.getBounds());
16751692
if (this->isClipEmpty()) {
16761693
SkASSERT(fQuickRejectBounds.isEmpty());
16771694
} else {
@@ -1718,9 +1735,14 @@ void SkCanvas::temporary_internal_getRgnClip(SkRegion* rgn) {
17181735
///////////////////////////////////////////////////////////////////////////////
17191736

17201737
bool SkCanvas::isClipEmpty() const {
1738+
return fMCRec->fRasterClip.isEmpty();
1739+
1740+
// TODO: should we only use the conservative answer in a recording canvas?
1741+
#if 0
17211742
SkBaseDevice* dev = this->getTopDevice();
17221743
// if no device we return true
1723-
return !dev || dev->onGetClipType() == SkBaseDevice::ClipType::kEmpty;
1744+
return !dev || dev->onGetClipType() == SkBaseDevice::kEmpty_ClipType;
1745+
#endif
17241746
}
17251747

17261748
bool SkCanvas::isClipRect() const {
@@ -1819,28 +1841,7 @@ SkRect SkCanvas::getLocalClipBounds() const {
18191841
}
18201842

18211843
SkIRect SkCanvas::getDeviceClipBounds() const {
1822-
return this->computeDeviceClipBounds().roundOut();
1823-
}
1824-
1825-
SkRect SkCanvas::computeDeviceClipBounds() const {
1826-
if (this->isClipEmpty()) {
1827-
return SkRect::MakeEmpty();
1828-
}
1829-
1830-
// Compute the union of all top devices' device bounds, mapped into the global coordinate system
1831-
DeviceCM* layer = fMCRec->fTopLayer;
1832-
SkRect totalBounds = SkRect::MakeEmpty();
1833-
while (layer) {
1834-
if (layer->fDevice) {
1835-
SkIRect devClipBounds = layer->fDevice->devClipBounds();
1836-
SkRect layerBounds =
1837-
layer->fDevice->deviceToGlobal().mapRect(SkRect::Make(devClipBounds));
1838-
totalBounds.join(layerBounds);
1839-
}
1840-
layer = layer->fNext;
1841-
}
1842-
1843-
return totalBounds;
1844+
return fMCRec->fRasterClip.getBounds();
18441845
}
18451846

18461847
///////////////////////////////////////////////////////////////////////
@@ -2452,10 +2453,7 @@ bool SkCanvas::canDrawBitmapAsSprite(SkScalar x, SkScalar y, int w, int h, const
24522453
SkPoint pt;
24532454
ctm.mapXY(x, y, &pt);
24542455
SkIRect ir = SkIRect::MakeXYWH(SkScalarRoundToInt(pt.x()), SkScalarRoundToInt(pt.y()), w, h);
2455-
// quick bounds have been outset by 1px compared to overall device bounds, so this makes the
2456-
// contains check equivalent to between ir and device bounds
2457-
ir.outset(1, 1);
2458-
return ir.contains(fQuickRejectBounds);
2456+
return ir.contains(fMCRec->fRasterClip.getBounds());
24592457
}
24602458

24612459
// Given storage for a real paint, and an optional paint parameter, clean-up the param (if non-null)

0 commit comments

Comments
 (0)