Reland "Add SkClipStack::replaceClip() separate from deprecated clip op"
This reverts commit8ba1e71a1f
. Reason for revert: had missed a few places where GrReducedClip needed to use the equivalent region op, not skClipOp + replace bool. TBR=robertphillips@google.com,brianosman@google.com,csmartdalton@google.com Original change's description: > Revert "Add SkClipStack::replaceClip() separate from deprecated clip op" > > This reverts commit68587ae274
. > > Reason for revert: breaking path clipping tests in Android? > > Original change's description: > > Add SkClipStack::replaceClip() separate from deprecated clip op > > > > The replaceClip functionality was added to allow Android to move off of > > generalized expanding clips. At the time, SkClipStack simply used the > > kReplace_SkClipOp to handle it. In order to remove those expanding ops, > > SkClipStack will need a proper implementation of replaceClip(). > > > > The clip elements have an additional field to mark if > > it's a replace (and it's op will be kIntersect). Adds a temporary > > getRegionOp() function to unify elements that use this field vs. > > elements that use the deprecated clip op (i.e. if they were deserialized > > from an SKP that recorded an expanding op). > > > > Clients of SkClipOp that checked for replace ops use the new function > > instead of referring to the enum value directly. > > > > Bug: skia:10209 > > Change-Id: I1c16c87fadb2becfe181db717c05e240ac87fd34 > > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/436158 > > Commit-Queue: Michael Ludwig <michaelludwig@google.com> > > Reviewed-by: Robert Phillips <robertphillips@google.com> > > Reviewed-by: Chris Dalton <csmartdalton@google.com> > > TBR=robertphillips@google.com,brianosman@google.com,csmartdalton@google.com,michaelludwig@google.com,skcq-be@skia-corp.google.com.iam.gserviceaccount.com > > Change-Id: If3f99a7d2f2df99c2b99d431d494ca28da66b1d8 > No-Presubmit: true > No-Tree-Checks: true > No-Try: true > Bug: skia:10209 > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/436956 > Reviewed-by: Michael Ludwig <michaelludwig@google.com> # Not skipping CQ checks because this is a reland. Bug: skia:10209 Change-Id: I9feb0f3571ec26580bcdf0fe541f43f2ee8cf8d2 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/436959 Reviewed-by: Michael Ludwig <michaelludwig@google.com> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
This commit is contained in:
parent
363c6e298f
commit
d59d3e179d
@ -46,6 +46,7 @@ SkClipStack::Element::Element(const Element& that) {
|
||||
fOp = that.fOp;
|
||||
fDeviceSpaceType = that.fDeviceSpaceType;
|
||||
fDoAA = that.fDoAA;
|
||||
fIsReplace = that.fIsReplace;
|
||||
fFiniteBoundType = that.fFiniteBoundType;
|
||||
fFiniteBound = that.fFiniteBound;
|
||||
fIsIntersectionOfRects = that.fIsIntersectionOfRects;
|
||||
@ -66,7 +67,8 @@ bool SkClipStack::Element::operator== (const Element& element) const {
|
||||
return true;
|
||||
}
|
||||
if (fOp != element.fOp || fDeviceSpaceType != element.fDeviceSpaceType ||
|
||||
fDoAA != element.fDoAA || fSaveCount != element.fSaveCount) {
|
||||
fDoAA != element.fDoAA || fIsReplace != element.fIsReplace ||
|
||||
fSaveCount != element.fSaveCount) {
|
||||
return false;
|
||||
}
|
||||
switch (fDeviceSpaceType) {
|
||||
@ -173,6 +175,7 @@ void SkClipStack::Element::initCommon(int saveCount, SkClipOp op, bool doAA) {
|
||||
fSaveCount = saveCount;
|
||||
fOp = op;
|
||||
fDoAA = doAA;
|
||||
fIsReplace = false;
|
||||
// A default of inside-out and empty bounds means the bounds are effectively void as it
|
||||
// indicates that nothing is known to be outside the clip.
|
||||
fFiniteBoundType = kInsideOut_BoundsType;
|
||||
@ -249,6 +252,13 @@ void SkClipStack::Element::initShader(int saveCount, sk_sp<SkShader> shader) {
|
||||
this->initCommon(saveCount, SkClipOp::kIntersect, false);
|
||||
}
|
||||
|
||||
void SkClipStack::Element::initReplaceRect(int saveCount, const SkRect& rect, bool doAA) {
|
||||
fDeviceSpaceRRect.setRect(rect);
|
||||
fDeviceSpaceType = DeviceSpaceType::kRect;
|
||||
this->initCommon(saveCount, SkClipOp::kIntersect, doAA);
|
||||
fIsReplace = true;
|
||||
}
|
||||
|
||||
void SkClipStack::Element::asDeviceSpacePath(SkPath* path) const {
|
||||
switch (fDeviceSpaceType) {
|
||||
case DeviceSpaceType::kEmpty:
|
||||
@ -297,14 +307,14 @@ void SkClipStack::Element::checkEmpty() const {
|
||||
|
||||
bool SkClipStack::Element::canBeIntersectedInPlace(int saveCount, SkClipOp op) const {
|
||||
if (DeviceSpaceType::kEmpty == fDeviceSpaceType &&
|
||||
(kDifference_SkClipOp == op || kIntersect_SkClipOp == op)) {
|
||||
(SkClipOp::kDifference == op || SkClipOp::kIntersect == op)) {
|
||||
return true;
|
||||
}
|
||||
// Only clips within the same save/restore frame (as captured by
|
||||
// the save count) can be merged
|
||||
return fSaveCount == saveCount &&
|
||||
kIntersect_SkClipOp == op &&
|
||||
(kIntersect_SkClipOp == fOp || kReplace_SkClipOp == fOp);
|
||||
SkClipOp::kIntersect == op &&
|
||||
(SkClipOp::kIntersect == fOp || this->isReplaceOp());
|
||||
}
|
||||
|
||||
bool SkClipStack::Element::rectRectIntersectAllowed(const SkRect& newR, bool newAA) const {
|
||||
@ -518,8 +528,9 @@ void SkClipStack::Element::updateBoundAndGenID(const Element* prior) {
|
||||
fFiniteBound = this->getDeviceSpaceRect();
|
||||
fFiniteBoundType = kNormal_BoundsType;
|
||||
|
||||
if (kReplace_SkClipOp == fOp || (kIntersect_SkClipOp == fOp && nullptr == prior) ||
|
||||
(kIntersect_SkClipOp == fOp && prior->fIsIntersectionOfRects &&
|
||||
if (this->isReplaceOp() ||
|
||||
(SkClipOp::kIntersect == fOp && nullptr == prior) ||
|
||||
(SkClipOp::kIntersect == fOp && prior->fIsIntersectionOfRects &&
|
||||
prior->rectRectIntersectAllowed(this->getDeviceSpaceRect(), fDoAA))) {
|
||||
fIsIntersectionOfRects = true;
|
||||
}
|
||||
@ -578,8 +589,9 @@ void SkClipStack::Element::updateBoundAndGenID(const Element* prior) {
|
||||
kPrev_Cur_FillCombo == combination);
|
||||
|
||||
// Now integrate with clip with the prior clips
|
||||
if (!this->isReplaceOp()) {
|
||||
switch (fOp) {
|
||||
case kDifference_SkClipOp:
|
||||
case SkClipOp::kDifference:
|
||||
this->combineBoundsDiff(combination, prevFinite);
|
||||
break;
|
||||
case kXOR_SkClipOp:
|
||||
@ -588,22 +600,18 @@ void SkClipStack::Element::updateBoundAndGenID(const Element* prior) {
|
||||
case kUnion_SkClipOp:
|
||||
this->combineBoundsUnion(combination, prevFinite);
|
||||
break;
|
||||
case kIntersect_SkClipOp:
|
||||
case SkClipOp::kIntersect:
|
||||
this->combineBoundsIntersection(combination, prevFinite);
|
||||
break;
|
||||
case kReverseDifference_SkClipOp:
|
||||
this->combineBoundsRevDiff(combination, prevFinite);
|
||||
break;
|
||||
case kReplace_SkClipOp:
|
||||
// Replace just ignores everything prior
|
||||
// The current clip's bound information is already filled in
|
||||
// so nothing to do
|
||||
break;
|
||||
default:
|
||||
SkDebugf("SkClipOp error\n");
|
||||
SkASSERT(0);
|
||||
break;
|
||||
}
|
||||
} // else Replace just ignores everything prior and should already have filled in bounds.
|
||||
}
|
||||
|
||||
// This constant determines how many Element's are allocated together as a block in
|
||||
@ -742,12 +750,13 @@ void SkClipStack::getBounds(SkRect* canvFiniteBound,
|
||||
}
|
||||
|
||||
bool SkClipStack::internalQuickContains(const SkRect& rect) const {
|
||||
|
||||
Iter iter(*this, Iter::kTop_IterStart);
|
||||
const Element* element = iter.prev();
|
||||
while (element != nullptr) {
|
||||
if (kIntersect_SkClipOp != element->getOp() && kReplace_SkClipOp != element->getOp())
|
||||
// TODO: Once expanding ops are removed, this condition is equiv. to op == kDifference.
|
||||
if (SkClipOp::kIntersect != element->getOp() && !element->isReplaceOp()) {
|
||||
return false;
|
||||
}
|
||||
if (element->isInverseFilled()) {
|
||||
// Part of 'rect' could be trimmed off by the inverse-filled clip element
|
||||
if (SkRect::Intersects(element->getBounds(), rect)) {
|
||||
@ -758,7 +767,7 @@ bool SkClipStack::internalQuickContains(const SkRect& rect) const {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (kReplace_SkClipOp == element->getOp()) {
|
||||
if (element->isReplaceOp()) {
|
||||
break;
|
||||
}
|
||||
element = iter.prev();
|
||||
@ -767,12 +776,13 @@ bool SkClipStack::internalQuickContains(const SkRect& rect) const {
|
||||
}
|
||||
|
||||
bool SkClipStack::internalQuickContains(const SkRRect& rrect) const {
|
||||
|
||||
Iter iter(*this, Iter::kTop_IterStart);
|
||||
const Element* element = iter.prev();
|
||||
while (element != nullptr) {
|
||||
if (kIntersect_SkClipOp != element->getOp() && kReplace_SkClipOp != element->getOp())
|
||||
// TODO: Once expanding ops are removed, this condition is equiv. to op == kDifference.
|
||||
if (SkClipOp::kIntersect != element->getOp() && !element->isReplaceOp()) {
|
||||
return false;
|
||||
}
|
||||
if (element->isInverseFilled()) {
|
||||
// Part of 'rrect' could be trimmed off by the inverse-filled clip element
|
||||
if (SkRect::Intersects(element->getBounds(), rrect.getBounds())) {
|
||||
@ -783,7 +793,7 @@ bool SkClipStack::internalQuickContains(const SkRRect& rrect) const {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (kReplace_SkClipOp == element->getOp()) {
|
||||
if (element->isReplaceOp()) {
|
||||
break;
|
||||
}
|
||||
element = iter.prev();
|
||||
@ -797,7 +807,10 @@ void SkClipStack::pushElement(const Element& element) {
|
||||
Element* prior = (Element*) iter.prev();
|
||||
|
||||
if (prior) {
|
||||
if (prior->canBeIntersectedInPlace(fSaveCount, element.getOp())) {
|
||||
if (element.isReplaceOp()) {
|
||||
this->restoreTo(fSaveCount - 1);
|
||||
prior = (Element*) fDeque.back();
|
||||
} else if (prior->canBeIntersectedInPlace(fSaveCount, element.getOp())) {
|
||||
switch (prior->fDeviceSpaceType) {
|
||||
case Element::DeviceSpaceType::kEmpty:
|
||||
SkDEBUGCODE(prior->checkEmpty();)
|
||||
@ -838,32 +851,27 @@ void SkClipStack::pushElement(const Element& element) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else if (kReplace_SkClipOp == element.getOp()) {
|
||||
this->restoreTo(fSaveCount - 1);
|
||||
prior = (Element*) fDeque.back();
|
||||
}
|
||||
}
|
||||
Element* newElement = new (fDeque.push_back()) Element(element);
|
||||
newElement->updateBoundAndGenID(prior);
|
||||
}
|
||||
|
||||
void SkClipStack::clipRRect(const SkRRect& rrect, const SkMatrix& matrix, SkClipOp op,
|
||||
bool doAA) {
|
||||
void SkClipStack::clipRRect(const SkRRect& rrect, const SkMatrix& matrix, SkClipOp op, bool doAA) {
|
||||
Element element(fSaveCount, rrect, matrix, op, doAA);
|
||||
this->pushElement(element);
|
||||
if (this->hasClipRestriction(op)) {
|
||||
Element restriction(fSaveCount, fClipRestrictionRect, SkMatrix::I(), kIntersect_SkClipOp,
|
||||
Element restriction(fSaveCount, fClipRestrictionRect, SkMatrix::I(), SkClipOp::kIntersect,
|
||||
false);
|
||||
this->pushElement(restriction);
|
||||
}
|
||||
}
|
||||
|
||||
void SkClipStack::clipRect(const SkRect& rect, const SkMatrix& matrix, SkClipOp op,
|
||||
bool doAA) {
|
||||
void SkClipStack::clipRect(const SkRect& rect, const SkMatrix& matrix, SkClipOp op, bool doAA) {
|
||||
Element element(fSaveCount, rect, matrix, op, doAA);
|
||||
this->pushElement(element);
|
||||
if (this->hasClipRestriction(op)) {
|
||||
Element restriction(fSaveCount, fClipRestrictionRect, SkMatrix::I(), kIntersect_SkClipOp,
|
||||
Element restriction(fSaveCount, fClipRestrictionRect, SkMatrix::I(), SkClipOp::kIntersect,
|
||||
false);
|
||||
this->pushElement(restriction);
|
||||
}
|
||||
@ -874,7 +882,7 @@ void SkClipStack::clipPath(const SkPath& path, const SkMatrix& matrix, SkClipOp
|
||||
Element element(fSaveCount, path, matrix, op, doAA);
|
||||
this->pushElement(element);
|
||||
if (this->hasClipRestriction(op)) {
|
||||
Element restriction(fSaveCount, fClipRestrictionRect, SkMatrix::I(), kIntersect_SkClipOp,
|
||||
Element restriction(fSaveCount, fClipRestrictionRect, SkMatrix::I(), SkClipOp::kIntersect,
|
||||
false);
|
||||
this->pushElement(restriction);
|
||||
}
|
||||
@ -888,10 +896,21 @@ void SkClipStack::clipShader(sk_sp<SkShader> shader) {
|
||||
SkASSERT(fClipRestrictionRect.isEmpty());
|
||||
}
|
||||
|
||||
void SkClipStack::replaceClip(const SkRect& rect, bool doAA) {
|
||||
Element element(fSaveCount, rect, doAA);
|
||||
this->pushElement(element);
|
||||
// A replace is always affected by the clip restriction
|
||||
if (!fClipRestrictionRect.isEmpty()) {
|
||||
Element restriction(fSaveCount, fClipRestrictionRect, SkMatrix::I(), SkClipOp::kIntersect,
|
||||
false);
|
||||
this->pushElement(restriction);
|
||||
}
|
||||
}
|
||||
|
||||
void SkClipStack::clipEmpty() {
|
||||
Element* element = (Element*) fDeque.back();
|
||||
|
||||
if (element && element->canBeIntersectedInPlace(fSaveCount, kIntersect_SkClipOp)) {
|
||||
if (element && element->canBeIntersectedInPlace(fSaveCount, SkClipOp::kIntersect)) {
|
||||
element->setEmpty();
|
||||
}
|
||||
new (fDeque.push_back()) Element(fSaveCount);
|
||||
@ -918,7 +937,6 @@ const SkClipStack::Element* SkClipStack::Iter::prev() {
|
||||
}
|
||||
|
||||
const SkClipStack::Element* SkClipStack::Iter::skipToTopmost(SkClipOp op) {
|
||||
|
||||
if (nullptr == fStack) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -1007,13 +1025,13 @@ bool SkClipStack::isRRect(const SkRect& bounds, SkRRect* rrect, bool* aa) const
|
||||
back->getDeviceSpaceType() != SkClipStack::Element::DeviceSpaceType::kRRect) {
|
||||
return false;
|
||||
}
|
||||
if (back->getOp() == kReplace_SkClipOp) {
|
||||
if (back->isReplaceOp()) {
|
||||
*rrect = back->asDeviceSpaceRRect();
|
||||
*aa = back->isAA();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (back->getOp() == kIntersect_SkClipOp) {
|
||||
if (back->getOp() == SkClipOp::kIntersect) {
|
||||
SkRect backBounds;
|
||||
if (!backBounds.intersect(bounds, back->asDeviceSpaceRRect().rect())) {
|
||||
return false;
|
||||
@ -1028,12 +1046,12 @@ bool SkClipStack::isRRect(const SkRect& bounds, SkRRect* rrect, bool* aa) const
|
||||
SkDeque::Iter iter(fDeque, SkDeque::Iter::kBack_IterStart);
|
||||
SkAssertResult(static_cast<const Element*>(iter.prev()) == back);
|
||||
while (const Element* prior = (const Element*)iter.prev()) {
|
||||
if ((prior->getOp() != kIntersect_SkClipOp &&
|
||||
prior->getOp() != kReplace_SkClipOp) ||
|
||||
// TODO: Once expanding clip ops are removed, this is equiv. to op == kDifference
|
||||
if ((prior->getOp() != SkClipOp::kIntersect && !prior->isReplaceOp()) ||
|
||||
!prior->contains(backBounds)) {
|
||||
return false;
|
||||
}
|
||||
if (prior->getOp() == kReplace_SkClipOp) {
|
||||
if (prior->isReplaceOp()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1103,8 +1121,9 @@ void SkClipStack::Element::dump() const {
|
||||
static_assert(5 == static_cast<int>(kReplace_SkClipOp), "enum mismatch");
|
||||
static_assert(SK_ARRAY_COUNT(kOpStrings) == SkRegion::kOpCnt, "enum mismatch");
|
||||
|
||||
const char* opName = this->isReplaceOp() ? "replace" : kOpStrings[static_cast<int>(fOp)];
|
||||
SkDebugf("Type: %s, Op: %s, AA: %s, Save Count: %d\n", kTypeStrings[(int)fDeviceSpaceType],
|
||||
kOpStrings[static_cast<int>(fOp)], (fDoAA ? "yes" : "no"), fSaveCount);
|
||||
opName, (fDoAA ? "yes" : "no"), fSaveCount);
|
||||
switch (fDeviceSpaceType) {
|
||||
case DeviceSpaceType::kEmpty:
|
||||
SkDebugf("\n");
|
||||
|
@ -68,7 +68,7 @@ public:
|
||||
static const int kTypeCnt = (int)DeviceSpaceType::kLastType + 1;
|
||||
|
||||
Element() {
|
||||
this->initCommon(0, kReplace_SkClipOp, false);
|
||||
this->initCommon(0, SkClipOp::kIntersect, false);
|
||||
this->setEmpty();
|
||||
}
|
||||
|
||||
@ -90,6 +90,10 @@ public:
|
||||
this->initShader(0, std::move(shader));
|
||||
}
|
||||
|
||||
Element(const SkRect& rect, bool doAA) {
|
||||
this->initReplaceRect(0, rect, doAA);
|
||||
}
|
||||
|
||||
~Element();
|
||||
|
||||
bool operator== (const Element& element) const;
|
||||
@ -130,7 +134,13 @@ public:
|
||||
|
||||
//!< Call if getDeviceSpaceType() is not kEmpty to get the set operation used to combine
|
||||
//!< this element.
|
||||
SkClipOp getOp() const { return fOp; }
|
||||
SkClipOp getOp() const { return fOp == kReplace_SkClipOp ? SkClipOp::kIntersect : fOp; }
|
||||
// Augments getOps()'s behavior by requiring a clip reset before the op is applied.
|
||||
bool isReplaceOp() const { return fIsReplace || fOp == kReplace_SkClipOp; }
|
||||
|
||||
SkRegion::Op getRegionOp() const {
|
||||
return this->isReplaceOp() ? SkRegion::kReplace_Op : (SkRegion::Op) fOp;
|
||||
}
|
||||
|
||||
//!< Call to get the element as a path, regardless of its type.
|
||||
void asDeviceSpacePath(SkPath* path) const;
|
||||
@ -149,7 +159,16 @@ public:
|
||||
void invertShapeFillType();
|
||||
|
||||
//!< Sets the set operation represented by the element.
|
||||
void setOp(SkClipOp op) { fOp = op; }
|
||||
void setOp(SkClipOp op) {
|
||||
fOp = op;
|
||||
fIsReplace = false;
|
||||
}
|
||||
// TODO: This is only used by GrReducedClip, which will be deletable soon, so then this
|
||||
// can also be cleaned up.
|
||||
void setReplaceOp() {
|
||||
fOp = SkClipOp::kIntersect;
|
||||
fIsReplace = true;
|
||||
}
|
||||
|
||||
/** The GenID can be used by clip stack clients to cache representations of the clip. The
|
||||
ID corresponds to the set of clip elements up to and including this element within the
|
||||
@ -215,6 +234,7 @@ public:
|
||||
SkClipOp fOp;
|
||||
DeviceSpaceType fDeviceSpaceType;
|
||||
bool fDoAA;
|
||||
bool fIsReplace;
|
||||
|
||||
/* fFiniteBoundType and fFiniteBound are used to incrementally update the clip stack's
|
||||
bound. When fFiniteBoundType is kNormal_BoundsType, fFiniteBound represents the
|
||||
@ -239,7 +259,7 @@ public:
|
||||
mutable SkTArray<GrUniqueKey> fKeysToInvalidate;
|
||||
#endif
|
||||
Element(int saveCount) {
|
||||
this->initCommon(saveCount, kReplace_SkClipOp, false);
|
||||
this->initCommon(saveCount, SkClipOp::kIntersect, false);
|
||||
this->setEmpty();
|
||||
}
|
||||
|
||||
@ -259,12 +279,17 @@ public:
|
||||
this->initShader(saveCount, std::move(shader));
|
||||
}
|
||||
|
||||
Element(int saveCount, const SkRect& rect, bool doAA) {
|
||||
this->initReplaceRect(saveCount, rect, doAA);
|
||||
}
|
||||
|
||||
void initCommon(int saveCount, SkClipOp op, bool doAA);
|
||||
void initRect(int saveCount, const SkRect&, const SkMatrix&, SkClipOp, bool doAA);
|
||||
void initRRect(int saveCount, const SkRRect&, const SkMatrix&, SkClipOp, bool doAA);
|
||||
void initPath(int saveCount, const SkPath&, const SkMatrix&, SkClipOp, bool doAA);
|
||||
void initAsPath(int saveCount, const SkPath&, const SkMatrix&, SkClipOp, bool doAA);
|
||||
void initShader(int saveCount, sk_sp<SkShader>);
|
||||
void initReplaceRect(int saveCount, const SkRect&, bool doAA);
|
||||
|
||||
void setEmpty();
|
||||
|
||||
@ -373,6 +398,8 @@ public:
|
||||
fClipRestrictionRect = SkRect::Make(rect);
|
||||
}
|
||||
|
||||
void replaceClip(const SkRect& devRect, bool doAA);
|
||||
|
||||
/**
|
||||
* isWideOpen returns true if the clip state corresponds to the infinite
|
||||
* plane (i.e., draws are not limited at all)
|
||||
|
@ -53,10 +53,8 @@ void SkClipStackDevice::onClipRegion(const SkRegion& rgn, SkClipOp op) {
|
||||
}
|
||||
|
||||
void SkClipStackDevice::onReplaceClip(const SkIRect& rect) {
|
||||
// FIXME When the deprecated clip ops are completely removed, SkClipStack will need to be
|
||||
// updated to have a better way of tracking replacement.
|
||||
fClipStack.clipRect(SkRect::Make(rect), this->globalToDevice().asM33(),
|
||||
kReplace_SkClipOp, false);
|
||||
SkRect deviceRect = SkMatrixPriv::MapRect(this->globalToDevice(), SkRect::Make(rect));
|
||||
fClipStack.replaceClip(deviceRect, /*doAA=*/false);
|
||||
}
|
||||
|
||||
void SkClipStackDevice::onSetDeviceClipRestriction(SkIRect* clipRestriction) {
|
||||
@ -104,7 +102,7 @@ void SkClipStackDevice::onAsRgnClip(SkRegion* rgn) const {
|
||||
elem->asDeviceSpacePath(&tmpPath);
|
||||
SkRegion tmpRgn;
|
||||
tmpRgn.setPath(tmpPath, boundsRgn);
|
||||
rgn->op(tmpRgn, SkRegion::Op(elem->getOp()));
|
||||
rgn->op(tmpRgn, elem->getRegionOp());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -335,15 +335,15 @@ static void draw_clip_elements_to_mask_helper(GrSWMaskHelper& helper, const Elem
|
||||
|
||||
for (ElementList::Iter iter(elements); iter.get(); iter.next()) {
|
||||
const Element* element = iter.get();
|
||||
SkClipOp op = element->getOp();
|
||||
SkRegion::Op op = element->getRegionOp();
|
||||
GrAA aa = GrAA(element->isAA());
|
||||
|
||||
if (kIntersect_SkClipOp == op || kReverseDifference_SkClipOp == op) {
|
||||
if (SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op) {
|
||||
// Intersect and reverse difference require modifying pixels outside of the geometry
|
||||
// that is being "drawn". In both cases we erase all the pixels outside of the geometry
|
||||
// but leave the pixels inside the geometry alone. For reverse difference we invert all
|
||||
// the pixels before clearing the ones outside the geometry.
|
||||
if (kReverseDifference_SkClipOp == op) {
|
||||
if (SkRegion::kReverseDifference_Op == op) {
|
||||
SkRect temp = SkRect::Make(scissor);
|
||||
// invert the entire scene
|
||||
helper.drawRect(temp, translate, SkRegion::kXOR_Op, GrAA::kNo, 0xFF);
|
||||
@ -358,13 +358,13 @@ static void draw_clip_elements_to_mask_helper(GrSWMaskHelper& helper, const Elem
|
||||
// The other ops (union, xor, diff) only affect pixels inside
|
||||
// the geometry so they can just be drawn normally
|
||||
if (Element::DeviceSpaceType::kRect == element->getDeviceSpaceType()) {
|
||||
helper.drawRect(element->getDeviceSpaceRect(), translate, (SkRegion::Op)op, aa, 0xFF);
|
||||
helper.drawRect(element->getDeviceSpaceRect(), translate, op, aa, 0xFF);
|
||||
} else if (Element::DeviceSpaceType::kRRect == element->getDeviceSpaceType()) {
|
||||
helper.drawRRect(element->getDeviceSpaceRRect(), translate, (SkRegion::Op)op, aa, 0xFF);
|
||||
helper.drawRRect(element->getDeviceSpaceRRect(), translate, op, aa, 0xFF);
|
||||
} else {
|
||||
SkPath path;
|
||||
element->asDeviceSpacePath(&path);
|
||||
helper.drawShape(GrShape(path), translate, (SkRegion::Op)op, aa, 0xFF);
|
||||
helper.drawShape(GrShape(path), translate, op, aa, 0xFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -122,10 +122,11 @@ GrReducedClip::GrReducedClip(const SkClipStack& stack, const SkRect& queryBounds
|
||||
ClipResult::kNotClipped == this->addAnalyticRect(fAAClipRect, Invert::kNo, GrAA::kYes)) {
|
||||
if (fMaskElements.isEmpty()) {
|
||||
// Use a replace since it is faster than intersect.
|
||||
fMaskElements.addToHead(fAAClipRect, SkMatrix::I(), kReplace_SkClipOp, true /*doAA*/);
|
||||
fMaskElements.addToHead(fAAClipRect, true /*doAA*/);
|
||||
fInitialState = InitialState::kAllOut;
|
||||
} else {
|
||||
fMaskElements.addToTail(fAAClipRect, SkMatrix::I(), kIntersect_SkClipOp, true /*doAA*/);
|
||||
fMaskElements.addToTail(fAAClipRect, SkMatrix::I(), SkClipOp::kIntersect,
|
||||
true /*doAA*/);
|
||||
}
|
||||
fMaskRequiresAA = true;
|
||||
fMaskGenID = fAAClipRectGenID;
|
||||
@ -189,8 +190,8 @@ void GrReducedClip::walkStack(const SkClipStack& stack, const SkRect& queryBound
|
||||
bool skippable = false;
|
||||
bool isFlip = false; // does this op just flip the in/out state of every point in the bounds
|
||||
|
||||
switch (element->getOp()) {
|
||||
case kDifference_SkClipOp:
|
||||
switch (element->getRegionOp()) {
|
||||
case SkRegion::kDifference_Op:
|
||||
// check if the shape subtracted either contains the entire bounds (and makes
|
||||
// the clip empty) or is outside the bounds and therefore can be skipped.
|
||||
if (element->isInverseFilled()) {
|
||||
@ -224,7 +225,7 @@ void GrReducedClip::walkStack(const SkClipStack& stack, const SkRect& queryBound
|
||||
emsmallens = true;
|
||||
}
|
||||
break;
|
||||
case kIntersect_SkClipOp:
|
||||
case SkRegion::kIntersect_Op:
|
||||
// check if the shape intersected contains the entire bounds and therefore can
|
||||
// be skipped or it is outside the entire bounds and therefore makes the clip
|
||||
// empty.
|
||||
@ -259,7 +260,7 @@ void GrReducedClip::walkStack(const SkClipStack& stack, const SkRect& queryBound
|
||||
emsmallens = true;
|
||||
}
|
||||
break;
|
||||
case kUnion_SkClipOp:
|
||||
case SkRegion::kUnion_Op:
|
||||
// If the union-ed shape contains the entire bounds then after this element
|
||||
// the bounds is entirely inside the clip. If the union-ed shape is outside the
|
||||
// bounds then this op can be skipped.
|
||||
@ -282,7 +283,7 @@ void GrReducedClip::walkStack(const SkClipStack& stack, const SkRect& queryBound
|
||||
embiggens = true;
|
||||
}
|
||||
break;
|
||||
case kXOR_SkClipOp:
|
||||
case SkRegion::kXOR_Op:
|
||||
// If the bounds is entirely inside the shape being xor-ed then the effect is
|
||||
// to flip the inside/outside state of every point in the bounds. We may be
|
||||
// able to take advantage of this in the forward pass. If the xor-ed shape
|
||||
@ -304,7 +305,7 @@ void GrReducedClip::walkStack(const SkClipStack& stack, const SkRect& queryBound
|
||||
emsmallens = embiggens = true;
|
||||
}
|
||||
break;
|
||||
case kReverseDifference_SkClipOp:
|
||||
case SkRegion::kReverseDifference_Op:
|
||||
// When the bounds is entirely within the rev-diff shape then this behaves like xor
|
||||
// and reverses every point inside the bounds. If the shape is completely outside
|
||||
// the bounds then we know after this element is applied that the bounds will be
|
||||
@ -329,7 +330,7 @@ void GrReducedClip::walkStack(const SkClipStack& stack, const SkRect& queryBound
|
||||
}
|
||||
break;
|
||||
|
||||
case kReplace_SkClipOp:
|
||||
case SkRegion::kReplace_Op:
|
||||
// Replace will always terminate our walk. We will either begin the forward walk
|
||||
// at the replace op or detect here than the shape is either completely inside
|
||||
// or completely outside the bounds. In this latter case it can be skipped by
|
||||
@ -398,11 +399,11 @@ void GrReducedClip::walkStack(const SkClipStack& stack, const SkRect& queryBound
|
||||
// Intersecting an inverse shape is the same as differencing the non-inverse shape.
|
||||
// Replacing with an inverse shape is the same as setting initialState=kAllIn and
|
||||
// differencing the non-inverse shape.
|
||||
bool isReplace = kReplace_SkClipOp == newElement->getOp();
|
||||
bool isReplace = newElement->isReplaceOp();
|
||||
if (newElement->isInverseFilled() &&
|
||||
(kIntersect_SkClipOp == newElement->getOp() || isReplace)) {
|
||||
(SkClipOp::kIntersect == newElement->getOp() || isReplace)) {
|
||||
newElement->invertShapeFillType();
|
||||
newElement->setOp(kDifference_SkClipOp);
|
||||
newElement->setOp(SkClipOp::kDifference);
|
||||
if (isReplace) {
|
||||
SkASSERT(InitialTriState::kAllOut == initialTriState);
|
||||
initialTriState = InitialTriState::kAllIn;
|
||||
@ -420,37 +421,37 @@ void GrReducedClip::walkStack(const SkClipStack& stack, const SkRect& queryBound
|
||||
Element* element = fMaskElements.headIter().get();
|
||||
while (element) {
|
||||
bool skippable = false;
|
||||
switch (element->getOp()) {
|
||||
case kDifference_SkClipOp:
|
||||
switch (element->getRegionOp()) {
|
||||
case SkRegion::kDifference_Op:
|
||||
// subtracting from the empty set yields the empty set.
|
||||
skippable = InitialTriState::kAllOut == initialTriState;
|
||||
break;
|
||||
case kIntersect_SkClipOp:
|
||||
case SkRegion::kIntersect_Op:
|
||||
// intersecting with the empty set yields the empty set
|
||||
if (InitialTriState::kAllOut == initialTriState) {
|
||||
skippable = true;
|
||||
} else {
|
||||
// We can clear to zero and then simply draw the clip element.
|
||||
initialTriState = InitialTriState::kAllOut;
|
||||
element->setOp(kReplace_SkClipOp);
|
||||
element->setReplaceOp();
|
||||
}
|
||||
break;
|
||||
case kUnion_SkClipOp:
|
||||
case SkRegion::kUnion_Op:
|
||||
if (InitialTriState::kAllIn == initialTriState) {
|
||||
// unioning the infinite plane with anything is a no-op.
|
||||
skippable = true;
|
||||
} else {
|
||||
// unioning the empty set with a shape is the shape.
|
||||
element->setOp(kReplace_SkClipOp);
|
||||
element->setReplaceOp();
|
||||
}
|
||||
break;
|
||||
case kXOR_SkClipOp:
|
||||
case SkRegion::kXOR_Op:
|
||||
if (InitialTriState::kAllOut == initialTriState) {
|
||||
// xor could be changed to diff in the kAllIn case, not sure it's a win.
|
||||
element->setOp(kReplace_SkClipOp);
|
||||
element->setReplaceOp();
|
||||
}
|
||||
break;
|
||||
case kReverseDifference_SkClipOp:
|
||||
case SkRegion::kReverseDifference_Op:
|
||||
if (InitialTriState::kAllIn == initialTriState) {
|
||||
// subtracting the whole plane will yield the empty set.
|
||||
skippable = true;
|
||||
@ -463,11 +464,11 @@ void GrReducedClip::walkStack(const SkClipStack& stack, const SkRect& queryBound
|
||||
if (skippable) {
|
||||
initialTriState = InitialTriState::kAllIn;
|
||||
} else {
|
||||
element->setOp(kReplace_SkClipOp);
|
||||
element->setReplaceOp();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case kReplace_SkClipOp:
|
||||
case SkRegion::kReplace_Op:
|
||||
skippable = false; // we would have skipped it in the backwards walk if we
|
||||
// could've.
|
||||
break;
|
||||
@ -720,7 +721,7 @@ static bool stencil_element(skgpu::v1::SurfaceDrawContext* sdc,
|
||||
break;
|
||||
case SkClipStack::Element::DeviceSpaceType::kRect: {
|
||||
GrPaint paint;
|
||||
paint.setCoverageSetOpXPFactory((SkRegion::Op)element->getOp(),
|
||||
paint.setCoverageSetOpXPFactory(element->getRegionOp(),
|
||||
element->isInverseFilled());
|
||||
sdc->stencilRect(&clip, ss, std::move(paint), aa, viewMatrix,
|
||||
element->getDeviceSpaceRect());
|
||||
@ -733,7 +734,7 @@ static bool stencil_element(skgpu::v1::SurfaceDrawContext* sdc,
|
||||
path.toggleInverseFillType();
|
||||
}
|
||||
|
||||
return sdc->drawAndStencilPath(&clip, ss, (SkRegion::Op)element->getOp(),
|
||||
return sdc->drawAndStencilPath(&clip, ss, element->getRegionOp(),
|
||||
element->isInverseFilled(), aa, viewMatrix, path);
|
||||
}
|
||||
}
|
||||
@ -799,7 +800,7 @@ bool GrReducedClip::drawAlphaClipMask(skgpu::v1::SurfaceDrawContext* sdc) const
|
||||
// walk through each clip element and perform its set op
|
||||
for (ElementList::Iter iter(fMaskElements); iter.get(); iter.next()) {
|
||||
const Element* element = iter.get();
|
||||
SkRegion::Op op = (SkRegion::Op)element->getOp();
|
||||
SkRegion::Op op = element->getRegionOp();
|
||||
GrAA aa = GrAA(element->isAA());
|
||||
bool invert = element->isInverseFilled();
|
||||
if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op) {
|
||||
@ -861,7 +862,7 @@ bool GrReducedClip::drawStencilClipMask(GrRecordingContext* rContext,
|
||||
// walk through each clip element and perform its set op with the existing clip.
|
||||
for (ElementList::Iter iter(fMaskElements); iter.get(); iter.next()) {
|
||||
const Element* element = iter.get();
|
||||
SkRegion::Op op = (SkRegion::Op)element->getOp();
|
||||
SkRegion::Op op = element->getRegionOp();
|
||||
GrAA aa = element->isAA() ? GrAA::kYes : GrAA::kNo;
|
||||
|
||||
if (Element::DeviceSpaceType::kRect == element->getDeviceSpaceType()) {
|
||||
|
@ -39,14 +39,11 @@ static bool is_rect(const SkClipStack& clipStack, const SkRect& bounds, SkRect*
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
switch (element->getOp()) {
|
||||
case kReplace_SkClipOp:
|
||||
if (element->isReplaceOp()) {
|
||||
currentClip = rect_intersect(bounds, elementRect);
|
||||
break;
|
||||
case SkClipOp::kIntersect:
|
||||
} else if (element->getOp() == SkClipOp::kIntersect) {
|
||||
currentClip = rect_intersect(currentClip, elementRect);
|
||||
break;
|
||||
default:
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -54,14 +51,13 @@ static bool is_rect(const SkClipStack& clipStack, const SkRect& bounds, SkRect*
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: When there's no expanding clip ops, this function may not be necessary anymore.
|
||||
static bool is_complex_clip(const SkClipStack& stack) {
|
||||
SkClipStack::Iter iter(stack, SkClipStack::Iter::kBottom_IterStart);
|
||||
while (const SkClipStack::Element* element = iter.next()) {
|
||||
switch (element->getOp()) {
|
||||
case SkClipOp::kDifference:
|
||||
case SkClipOp::kIntersect:
|
||||
break;
|
||||
default:
|
||||
if (element->isReplaceOp() ||
|
||||
(element->getOp() != SkClipOp::kDifference &&
|
||||
element->getOp() != SkClipOp::kIntersect)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -242,4 +238,3 @@ void SkPDFGraphicStackState::drainStack() {
|
||||
}
|
||||
SkASSERT(fStackDepth == 0);
|
||||
}
|
||||
|
||||
|
@ -25,8 +25,10 @@ void SkClipStack_AsPath(const SkClipStack& cs, SkPath* path) {
|
||||
}
|
||||
|
||||
SkClipOp elementOp = element->getOp();
|
||||
if (elementOp == kReplace_SkClipOp) {
|
||||
if (element->isReplaceOp()) {
|
||||
*path = operand;
|
||||
// TODO: Once expanding clip ops are removed, we can switch the iterator to be top
|
||||
// to bottom, which allows us to break here on encountering a replace op.
|
||||
} else {
|
||||
Op(*path, operand, (SkPathOp)elementOp, path);
|
||||
}
|
||||
|
@ -12,7 +12,6 @@
|
||||
|
||||
#include "include/core/SkMatrix.h"
|
||||
#include "include/core/SkRect.h"
|
||||
#include "src/core/SkClipOpPriv.h"
|
||||
#include "src/core/SkClipStack.h"
|
||||
#include "src/gpu/GrClipStackClip.h"
|
||||
#include "tests/Test.h"
|
||||
@ -32,7 +31,7 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrClipBounds, reporter, ctxInfo) {
|
||||
// create a clip stack that will (trivially) reduce to a single rect that
|
||||
// is larger than the screen
|
||||
SkClipStack stack;
|
||||
stack.clipRect(clipRect, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
stack.replaceRect(clipRect);
|
||||
|
||||
bool isIntersectionOfRects = true;
|
||||
SkRect devStackBounds;
|
||||
|
@ -58,15 +58,15 @@ static void test_assign_and_comparison(skiatest::Reporter* reporter) {
|
||||
p.lineTo(7, 8);
|
||||
p.lineTo(5, 9);
|
||||
p.close();
|
||||
s.clipPath(p, SkMatrix::I(), kIntersect_SkClipOp, doAA);
|
||||
s.clipPath(p, SkMatrix::I(), SkClipOp::kIntersect, doAA);
|
||||
|
||||
s.save();
|
||||
REPORTER_ASSERT(reporter, 2 == s.getSaveCount());
|
||||
|
||||
SkRect r = SkRect::MakeLTRB(1, 2, 3, 4);
|
||||
s.clipRect(r, SkMatrix::I(), kIntersect_SkClipOp, doAA);
|
||||
s.clipRect(r, SkMatrix::I(), SkClipOp::kIntersect, doAA);
|
||||
r = SkRect::MakeLTRB(10, 11, 12, 13);
|
||||
s.clipRect(r, SkMatrix::I(), kIntersect_SkClipOp, doAA);
|
||||
s.clipRect(r, SkMatrix::I(), SkClipOp::kIntersect, doAA);
|
||||
|
||||
s.save();
|
||||
REPORTER_ASSERT(reporter, 3 == s.getSaveCount());
|
||||
@ -96,7 +96,7 @@ static void test_assign_and_comparison(skiatest::Reporter* reporter) {
|
||||
s.save();
|
||||
REPORTER_ASSERT(reporter, 3 == s.getSaveCount());
|
||||
r = SkRect::MakeLTRB(14, 15, 16, 17);
|
||||
s.clipRect(r, SkMatrix::I(), kIntersect_SkClipOp, doAA);
|
||||
s.clipRect(r, SkMatrix::I(), SkClipOp::kIntersect, doAA);
|
||||
REPORTER_ASSERT(reporter, s != copy);
|
||||
|
||||
// Test that version constructed with rect-path rather than a rect is still considered equal.
|
||||
@ -136,7 +136,7 @@ static void test_assign_and_comparison(skiatest::Reporter* reporter) {
|
||||
REPORTER_ASSERT(reporter, 1 == s.getSaveCount());
|
||||
|
||||
p.addRect(r);
|
||||
s.clipPath(p, SkMatrix::I(), kIntersect_SkClipOp, doAA);
|
||||
s.clipPath(p, SkMatrix::I(), SkClipOp::kIntersect, doAA);
|
||||
REPORTER_ASSERT(reporter, s != copy);
|
||||
}
|
||||
|
||||
@ -249,8 +249,8 @@ static void test_bounds(skiatest::Reporter* reporter,
|
||||
};
|
||||
|
||||
static const SkClipOp gOps[] = {
|
||||
kIntersect_SkClipOp,
|
||||
kDifference_SkClipOp,
|
||||
SkClipOp::kIntersect,
|
||||
SkClipOp::kDifference,
|
||||
kUnion_SkClipOp,
|
||||
kXOR_SkClipOp,
|
||||
kReverseDifference_SkClipOp
|
||||
@ -294,15 +294,15 @@ static void test_bounds(skiatest::Reporter* reporter,
|
||||
SkDEBUGFAIL("Don't call this with kEmpty or kShader.");
|
||||
break;
|
||||
case SkClipStack::Element::DeviceSpaceType::kRect:
|
||||
stack.clipRect(rectA, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.clipRect(rectA, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.clipRect(rectB, SkMatrix::I(), gOps[op], false);
|
||||
break;
|
||||
case SkClipStack::Element::DeviceSpaceType::kRRect:
|
||||
stack.clipRRect(rrectA, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.clipRRect(rrectA, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.clipRRect(rrectB, SkMatrix::I(), gOps[op], false);
|
||||
break;
|
||||
case SkClipStack::Element::DeviceSpaceType::kPath:
|
||||
stack.clipPath(pathA, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.clipPath(pathA, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.clipPath(pathB, SkMatrix::I(), gOps[op], false);
|
||||
break;
|
||||
}
|
||||
@ -315,7 +315,7 @@ static void test_bounds(skiatest::Reporter* reporter,
|
||||
|
||||
if (SkClipStack::Element::DeviceSpaceType::kRect == primType) {
|
||||
REPORTER_ASSERT(reporter, isIntersectionOfRects ==
|
||||
(gOps[op] == kIntersect_SkClipOp));
|
||||
(gOps[op] == SkClipOp::kIntersect));
|
||||
} else {
|
||||
REPORTER_ASSERT(reporter, !isIntersectionOfRects);
|
||||
}
|
||||
@ -363,7 +363,7 @@ static void test_isWideOpen(skiatest::Reporter* reporter) {
|
||||
clipB.addRoundRect(rectB, SkIntToScalar(5), SkIntToScalar(5));
|
||||
clipB.setFillType(SkPathFillType::kInverseEvenOdd);
|
||||
|
||||
stack.clipPath(clipA, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
stack.clipPath(clipA, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.clipPath(clipB, SkMatrix::I(), kUnion_SkClipOp, false);
|
||||
|
||||
REPORTER_ASSERT(reporter, stack.isWideOpen());
|
||||
@ -387,7 +387,7 @@ static void test_isWideOpen(skiatest::Reporter* reporter) {
|
||||
SkRect emptyRect;
|
||||
emptyRect.setEmpty();
|
||||
|
||||
stack.clipRect(emptyRect, SkMatrix::I(), kDifference_SkClipOp, false);
|
||||
stack.clipRect(emptyRect, SkMatrix::I(), SkClipOp::kDifference, false);
|
||||
|
||||
REPORTER_ASSERT(reporter, stack.isWideOpen());
|
||||
REPORTER_ASSERT(reporter, SkClipStack::kWideOpenGenID == stack.getTopmostGenID());
|
||||
@ -399,7 +399,7 @@ static void test_isWideOpen(skiatest::Reporter* reporter) {
|
||||
|
||||
stack.save();
|
||||
|
||||
stack.clipRect(rectA, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
stack.clipRect(rectA, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
|
||||
REPORTER_ASSERT(reporter, !stack.isWideOpen());
|
||||
REPORTER_ASSERT(reporter, SkClipStack::kWideOpenGenID != stack.getTopmostGenID());
|
||||
@ -432,7 +432,7 @@ static void test_rect_inverse_fill(skiatest::Reporter* reporter) {
|
||||
path.addRect(rect);
|
||||
path.toggleInverseFillType();
|
||||
SkClipStack stack;
|
||||
stack.clipPath(path, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.clipPath(path, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
|
||||
SkRect bounds;
|
||||
SkClipStack::BoundsType boundsType;
|
||||
@ -454,9 +454,9 @@ static void test_rect_replace(skiatest::Reporter* reporter) {
|
||||
{
|
||||
SkClipStack stack;
|
||||
REPORTER_ASSERT(reporter, 0 == count(stack));
|
||||
stack.clipRect(rect, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
stack.replaceClip(rect, false);
|
||||
REPORTER_ASSERT(reporter, 1 == count(stack));
|
||||
stack.clipRect(rect, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
stack.replaceClip(rect, false);
|
||||
REPORTER_ASSERT(reporter, 1 == count(stack));
|
||||
}
|
||||
|
||||
@ -465,9 +465,9 @@ static void test_rect_replace(skiatest::Reporter* reporter) {
|
||||
{
|
||||
SkClipStack stack;
|
||||
REPORTER_ASSERT(reporter, 0 == count(stack));
|
||||
stack.clipRect(rect, SkMatrix::I(), kReplace_SkClipOp, true);
|
||||
stack.replaceClip(rect, true);
|
||||
REPORTER_ASSERT(reporter, 1 == count(stack));
|
||||
stack.clipRect(rect, SkMatrix::I(), kReplace_SkClipOp, true);
|
||||
stack.replaceClip(rect, true);
|
||||
REPORTER_ASSERT(reporter, 1 == count(stack));
|
||||
}
|
||||
|
||||
@ -476,23 +476,23 @@ static void test_rect_replace(skiatest::Reporter* reporter) {
|
||||
{
|
||||
SkClipStack stack;
|
||||
REPORTER_ASSERT(reporter, 0 == count(stack));
|
||||
stack.clipRect(rect, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
stack.replaceClip(rect, false);
|
||||
REPORTER_ASSERT(reporter, 1 == count(stack));
|
||||
stack.clipRect(rect, SkMatrix::I(), kReplace_SkClipOp, true);
|
||||
stack.replaceClip(rect, true);
|
||||
REPORTER_ASSERT(reporter, 1 == count(stack));
|
||||
stack.clipRect(rect, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
stack.replaceClip(rect, false);
|
||||
REPORTER_ASSERT(reporter, 1 == count(stack));
|
||||
}
|
||||
|
||||
// Make sure replace clip rects don't collapse too much.
|
||||
{
|
||||
SkClipStack stack;
|
||||
stack.clipRect(rect, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
stack.clipRect(rect2, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.replaceClip(rect, false);
|
||||
stack.clipRect(rect2, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
REPORTER_ASSERT(reporter, 1 == count(stack));
|
||||
|
||||
stack.save();
|
||||
stack.clipRect(rect, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
stack.replaceClip(rect, false);
|
||||
REPORTER_ASSERT(reporter, 2 == count(stack));
|
||||
stack.getBounds(&bound, &type, &isIntersectionOfRects);
|
||||
REPORTER_ASSERT(reporter, bound == rect);
|
||||
@ -500,16 +500,16 @@ static void test_rect_replace(skiatest::Reporter* reporter) {
|
||||
REPORTER_ASSERT(reporter, 1 == count(stack));
|
||||
|
||||
stack.save();
|
||||
stack.clipRect(rect, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
stack.clipRect(rect, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
stack.replaceClip(rect, false);
|
||||
stack.replaceClip(rect, false);
|
||||
REPORTER_ASSERT(reporter, 2 == count(stack));
|
||||
stack.restore();
|
||||
REPORTER_ASSERT(reporter, 1 == count(stack));
|
||||
|
||||
stack.save();
|
||||
stack.clipRect(rect, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
stack.clipRect(rect2, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.clipRect(rect, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
stack.replaceClip(rect, false);
|
||||
stack.clipRect(rect2, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.replaceClip(rect, false);
|
||||
REPORTER_ASSERT(reporter, 2 == count(stack));
|
||||
stack.restore();
|
||||
REPORTER_ASSERT(reporter, 1 == count(stack));
|
||||
@ -518,27 +518,35 @@ static void test_rect_replace(skiatest::Reporter* reporter) {
|
||||
|
||||
// Simplified path-based version of test_rect_replace.
|
||||
static void test_path_replace(skiatest::Reporter* reporter) {
|
||||
auto replacePath = [](SkClipStack* stack, const SkPath& path, bool doAA) {
|
||||
const SkRect wideOpen = SkRect::MakeLTRB(-1000, -1000, 1000, 1000);
|
||||
stack->replaceClip(wideOpen, false);
|
||||
stack->clipPath(path, SkMatrix::I(), SkClipOp::kIntersect, doAA);
|
||||
};
|
||||
SkRect rect = SkRect::MakeWH(100, 100);
|
||||
SkPath path;
|
||||
path.addCircle(50, 50, 50);
|
||||
|
||||
// Replace operation doesn't grow the stack.
|
||||
// Emulating replace operations with more complex geometry is not atomic, it's a replace
|
||||
// with a wide-open rect and then an intersection with the complex geometry. The replace can
|
||||
// combine with prior elements, but the subsequent intersect cannot be combined so the stack
|
||||
// continues to grow.
|
||||
{
|
||||
SkClipStack stack;
|
||||
REPORTER_ASSERT(reporter, 0 == count(stack));
|
||||
stack.clipPath(path, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
REPORTER_ASSERT(reporter, 1 == count(stack));
|
||||
stack.clipPath(path, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
REPORTER_ASSERT(reporter, 1 == count(stack));
|
||||
replacePath(&stack, path, false);
|
||||
REPORTER_ASSERT(reporter, 2 == count(stack));
|
||||
replacePath(&stack, path, false);
|
||||
REPORTER_ASSERT(reporter, 2 == count(stack));
|
||||
}
|
||||
|
||||
// Replacing rect with path.
|
||||
{
|
||||
SkClipStack stack;
|
||||
stack.clipRect(rect, SkMatrix::I(), kReplace_SkClipOp, true);
|
||||
REPORTER_ASSERT(reporter, 1 == count(stack));
|
||||
stack.clipPath(path, SkMatrix::I(), kReplace_SkClipOp, true);
|
||||
stack.replaceClip(rect, true);
|
||||
REPORTER_ASSERT(reporter, 1 == count(stack));
|
||||
replacePath(&stack, path, true);
|
||||
REPORTER_ASSERT(reporter, 2 == count(stack));
|
||||
}
|
||||
}
|
||||
|
||||
@ -559,10 +567,8 @@ static void test_rect_merging(skiatest::Reporter* reporter) {
|
||||
// all bw overlapping - should merge
|
||||
{
|
||||
SkClipStack stack;
|
||||
|
||||
stack.clipRect(overlapLeft, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
|
||||
stack.clipRect(overlapRight, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.clipRect(overlapLeft, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.clipRect(overlapRight, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
|
||||
REPORTER_ASSERT(reporter, 1 == count(stack));
|
||||
|
||||
@ -574,10 +580,8 @@ static void test_rect_merging(skiatest::Reporter* reporter) {
|
||||
// all aa overlapping - should merge
|
||||
{
|
||||
SkClipStack stack;
|
||||
|
||||
stack.clipRect(overlapLeft, SkMatrix::I(), kReplace_SkClipOp, true);
|
||||
|
||||
stack.clipRect(overlapRight, SkMatrix::I(), kIntersect_SkClipOp, true);
|
||||
stack.clipRect(overlapLeft, SkMatrix::I(), SkClipOp::kIntersect, true);
|
||||
stack.clipRect(overlapRight, SkMatrix::I(), SkClipOp::kIntersect, true);
|
||||
|
||||
REPORTER_ASSERT(reporter, 1 == count(stack));
|
||||
|
||||
@ -589,10 +593,8 @@ static void test_rect_merging(skiatest::Reporter* reporter) {
|
||||
// mixed overlapping - should _not_ merge
|
||||
{
|
||||
SkClipStack stack;
|
||||
|
||||
stack.clipRect(overlapLeft, SkMatrix::I(), kReplace_SkClipOp, true);
|
||||
|
||||
stack.clipRect(overlapRight, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.clipRect(overlapLeft, SkMatrix::I(), SkClipOp::kIntersect, true);
|
||||
stack.clipRect(overlapRight, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
|
||||
REPORTER_ASSERT(reporter, 2 == count(stack));
|
||||
|
||||
@ -604,10 +606,8 @@ static void test_rect_merging(skiatest::Reporter* reporter) {
|
||||
// mixed nested (bw inside aa) - should merge
|
||||
{
|
||||
SkClipStack stack;
|
||||
|
||||
stack.clipRect(nestedParent, SkMatrix::I(), kReplace_SkClipOp, true);
|
||||
|
||||
stack.clipRect(nestedChild, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.clipRect(nestedParent, SkMatrix::I(), SkClipOp::kIntersect, true);
|
||||
stack.clipRect(nestedChild, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
|
||||
REPORTER_ASSERT(reporter, 1 == count(stack));
|
||||
|
||||
@ -619,10 +619,8 @@ static void test_rect_merging(skiatest::Reporter* reporter) {
|
||||
// mixed nested (aa inside bw) - should merge
|
||||
{
|
||||
SkClipStack stack;
|
||||
|
||||
stack.clipRect(nestedParent, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
|
||||
stack.clipRect(nestedChild, SkMatrix::I(), kIntersect_SkClipOp, true);
|
||||
stack.clipRect(nestedParent, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.clipRect(nestedChild, SkMatrix::I(), SkClipOp::kIntersect, true);
|
||||
|
||||
REPORTER_ASSERT(reporter, 1 == count(stack));
|
||||
|
||||
@ -634,10 +632,8 @@ static void test_rect_merging(skiatest::Reporter* reporter) {
|
||||
// reverse nested (aa inside bw) - should _not_ merge
|
||||
{
|
||||
SkClipStack stack;
|
||||
|
||||
stack.clipRect(nestedChild, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
|
||||
stack.clipRect(nestedParent, SkMatrix::I(), kIntersect_SkClipOp, true);
|
||||
stack.clipRect(nestedChild, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.clipRect(nestedParent, SkMatrix::I(), SkClipOp::kIntersect, true);
|
||||
|
||||
REPORTER_ASSERT(reporter, 2 == count(stack));
|
||||
|
||||
@ -665,32 +661,32 @@ static void test_quickContains(skiatest::Reporter* reporter) {
|
||||
|
||||
{
|
||||
SkClipStack stack;
|
||||
stack.clipRect(outsideRect, SkMatrix::I(), kDifference_SkClipOp, false);
|
||||
// return false because quickContains currently does not care for kDifference_SkClipOp
|
||||
stack.clipRect(outsideRect, SkMatrix::I(), SkClipOp::kDifference, false);
|
||||
// return false because quickContains currently does not care for kDifference
|
||||
REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
|
||||
}
|
||||
|
||||
// Replace Op tests
|
||||
{
|
||||
SkClipStack stack;
|
||||
stack.clipRect(outsideRect, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
stack.replaceClip(outsideRect, false);
|
||||
REPORTER_ASSERT(reporter, true == stack.quickContains(testRect));
|
||||
}
|
||||
|
||||
{
|
||||
SkClipStack stack;
|
||||
stack.clipRect(insideRect, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.clipRect(insideRect, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.save(); // To prevent in-place substitution by replace OP
|
||||
stack.clipRect(outsideRect, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
stack.replaceClip(outsideRect, false);
|
||||
REPORTER_ASSERT(reporter, true == stack.quickContains(testRect));
|
||||
stack.restore();
|
||||
}
|
||||
|
||||
{
|
||||
SkClipStack stack;
|
||||
stack.clipRect(outsideRect, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.clipRect(outsideRect, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.save(); // To prevent in-place substitution by replace OP
|
||||
stack.clipRect(insideRect, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
stack.replaceClip(insideRect, false);
|
||||
REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
|
||||
stack.restore();
|
||||
}
|
||||
@ -698,59 +694,59 @@ static void test_quickContains(skiatest::Reporter* reporter) {
|
||||
// Verify proper traversal of multi-element clip
|
||||
{
|
||||
SkClipStack stack;
|
||||
stack.clipRect(insideRect, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.clipRect(insideRect, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
// Use a path for second clip to prevent in-place intersection
|
||||
stack.clipPath(outsideCircle, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.clipPath(outsideCircle, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
|
||||
}
|
||||
|
||||
// Intersect Op tests with rectangles
|
||||
{
|
||||
SkClipStack stack;
|
||||
stack.clipRect(outsideRect, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.clipRect(outsideRect, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
REPORTER_ASSERT(reporter, true == stack.quickContains(testRect));
|
||||
}
|
||||
|
||||
{
|
||||
SkClipStack stack;
|
||||
stack.clipRect(insideRect, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.clipRect(insideRect, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
|
||||
}
|
||||
|
||||
{
|
||||
SkClipStack stack;
|
||||
stack.clipRect(intersectingRect, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.clipRect(intersectingRect, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
|
||||
}
|
||||
|
||||
{
|
||||
SkClipStack stack;
|
||||
stack.clipRect(nonIntersectingRect, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.clipRect(nonIntersectingRect, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
|
||||
}
|
||||
|
||||
// Intersect Op tests with circle paths
|
||||
{
|
||||
SkClipStack stack;
|
||||
stack.clipPath(outsideCircle, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.clipPath(outsideCircle, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
REPORTER_ASSERT(reporter, true == stack.quickContains(testRect));
|
||||
}
|
||||
|
||||
{
|
||||
SkClipStack stack;
|
||||
stack.clipPath(insideCircle, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.clipPath(insideCircle, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
|
||||
}
|
||||
|
||||
{
|
||||
SkClipStack stack;
|
||||
stack.clipPath(intersectingCircle, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.clipPath(intersectingCircle, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
|
||||
}
|
||||
|
||||
{
|
||||
SkClipStack stack;
|
||||
stack.clipPath(nonIntersectingCircle, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.clipPath(nonIntersectingCircle, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
|
||||
}
|
||||
|
||||
@ -760,7 +756,7 @@ static void test_quickContains(skiatest::Reporter* reporter) {
|
||||
SkPath path;
|
||||
path.addRect(outsideRect);
|
||||
path.toggleInverseFillType();
|
||||
stack.clipPath(path, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.clipPath(path, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
|
||||
}
|
||||
|
||||
@ -769,7 +765,7 @@ static void test_quickContains(skiatest::Reporter* reporter) {
|
||||
SkPath path;
|
||||
path.addRect(insideRect);
|
||||
path.toggleInverseFillType();
|
||||
stack.clipPath(path, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.clipPath(path, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
|
||||
}
|
||||
|
||||
@ -778,7 +774,7 @@ static void test_quickContains(skiatest::Reporter* reporter) {
|
||||
SkPath path;
|
||||
path.addRect(intersectingRect);
|
||||
path.toggleInverseFillType();
|
||||
stack.clipPath(path, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.clipPath(path, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
|
||||
}
|
||||
|
||||
@ -787,7 +783,7 @@ static void test_quickContains(skiatest::Reporter* reporter) {
|
||||
SkPath path;
|
||||
path.addRect(nonIntersectingRect);
|
||||
path.toggleInverseFillType();
|
||||
stack.clipPath(path, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.clipPath(path, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
REPORTER_ASSERT(reporter, true == stack.quickContains(testRect));
|
||||
}
|
||||
|
||||
@ -796,7 +792,7 @@ static void test_quickContains(skiatest::Reporter* reporter) {
|
||||
SkClipStack stack;
|
||||
SkPath path = outsideCircle;
|
||||
path.toggleInverseFillType();
|
||||
stack.clipPath(path, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.clipPath(path, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
|
||||
}
|
||||
|
||||
@ -804,7 +800,7 @@ static void test_quickContains(skiatest::Reporter* reporter) {
|
||||
SkClipStack stack;
|
||||
SkPath path = insideCircle;
|
||||
path.toggleInverseFillType();
|
||||
stack.clipPath(path, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.clipPath(path, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
|
||||
}
|
||||
|
||||
@ -812,7 +808,7 @@ static void test_quickContains(skiatest::Reporter* reporter) {
|
||||
SkClipStack stack;
|
||||
SkPath path = intersectingCircle;
|
||||
path.toggleInverseFillType();
|
||||
stack.clipPath(path, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.clipPath(path, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
|
||||
}
|
||||
|
||||
@ -820,7 +816,7 @@ static void test_quickContains(skiatest::Reporter* reporter) {
|
||||
SkClipStack stack;
|
||||
SkPath path = nonIntersectingCircle;
|
||||
path.toggleInverseFillType();
|
||||
stack.clipPath(path, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.clipPath(path, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
REPORTER_ASSERT(reporter, true == stack.quickContains(testRect));
|
||||
}
|
||||
}
|
||||
@ -843,18 +839,18 @@ static void set_region_to_stack(const SkClipStack& stack, const SkIRect& bounds,
|
||||
break;
|
||||
}
|
||||
|
||||
region->op(elemRegion, (SkRegion::Op)element->getOp());
|
||||
region->op(elemRegion, element->getRegionOp());
|
||||
}
|
||||
}
|
||||
|
||||
static void test_invfill_diff_bug(skiatest::Reporter* reporter) {
|
||||
SkClipStack stack;
|
||||
stack.clipRect({10, 10, 20, 20}, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.clipRect({10, 10, 20, 20}, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
|
||||
SkPath path;
|
||||
path.addRect({30, 10, 40, 20});
|
||||
path.setFillType(SkPathFillType::kInverseWinding);
|
||||
stack.clipPath(path, SkMatrix::I(), kDifference_SkClipOp, false);
|
||||
stack.clipPath(path, SkMatrix::I(), SkClipOp::kDifference, false);
|
||||
|
||||
REPORTER_ASSERT(reporter, SkClipStack::kEmptyGenID == stack.getTopmostGenID());
|
||||
|
||||
@ -940,6 +936,10 @@ static void add_shader(const SkRect& rect, bool invert, SkClipOp op, SkClipStack
|
||||
}
|
||||
|
||||
static void add_elem_to_stack(const SkClipStack::Element& element, SkClipStack* stack) {
|
||||
if (element.isReplaceOp()) {
|
||||
const SkRect resetBounds = SkRect::MakeLTRB(-10000.f, -10000.f, 10000.f, 10000.f);
|
||||
stack->replaceClip(resetBounds, element.isAA());
|
||||
}
|
||||
switch (element.getDeviceSpaceType()) {
|
||||
case SkClipStack::Element::DeviceSpaceType::kRect:
|
||||
stack->clipRect(element.getDeviceSpaceRect(), SkMatrix::I(), element.getOp(),
|
||||
@ -983,19 +983,13 @@ static void test_reduced_clip_stack(skiatest::Reporter* reporter, bool enableCli
|
||||
static const SkScalar kMaxElemSizeFrac = SK_Scalar1;
|
||||
|
||||
static const SkClipOp kOps[] = {
|
||||
kDifference_SkClipOp,
|
||||
kIntersect_SkClipOp,
|
||||
SkClipOp::kDifference,
|
||||
SkClipOp::kIntersect,
|
||||
kUnion_SkClipOp,
|
||||
kXOR_SkClipOp,
|
||||
kReverseDifference_SkClipOp,
|
||||
kReplace_SkClipOp,
|
||||
};
|
||||
|
||||
// Replace operations short-circuit the optimizer. We want to make sure that we test this code
|
||||
// path a little bit but we don't want it to prevent us from testing many longer traversals in
|
||||
// the optimizer.
|
||||
static const int kReplaceDiv = 4 * kMaxElemsPerTest;
|
||||
|
||||
// We want to test inverse fills. However, they are quite rare in practice so don't over do it.
|
||||
static const SkScalar kFractionInverted = SK_Scalar1 / kMaxElemsPerTest;
|
||||
|
||||
@ -1019,15 +1013,9 @@ static void test_reduced_clip_stack(skiatest::Reporter* reporter, bool enableCli
|
||||
int numElems = r.nextRangeU(kMinElemsPerTest, kMaxElemsPerTest);
|
||||
bool doAA = r.nextBiasedBool(kFractionAntialiased);
|
||||
for (int e = 0; e < numElems; ++e) {
|
||||
size_t opLimit = enableClipShader ? ((size_t) kIntersect_SkClipOp + 1)
|
||||
size_t opLimit = enableClipShader ? ((size_t) SkClipOp::kIntersect + 1)
|
||||
: SK_ARRAY_COUNT(kOps);
|
||||
SkClipOp op = kOps[r.nextULessThan(opLimit)];
|
||||
if (op == kReplace_SkClipOp) {
|
||||
if (r.nextU() % kReplaceDiv) {
|
||||
--e;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// saves can change the clip stack behavior when an element is added.
|
||||
bool doSave = r.nextBool();
|
||||
@ -1110,8 +1098,8 @@ static void test_reduced_clip_stack(skiatest::Reporter* reporter, bool enableCli
|
||||
SkIRect scissor = reduced->hasScissor() ? reduced->scissor() : kIBounds;
|
||||
|
||||
// GrReducedClipStack assumes that the final result is clipped to the returned bounds
|
||||
reducedStack.clipDevRect(scissor, kIntersect_SkClipOp);
|
||||
stack.clipDevRect(scissor, kIntersect_SkClipOp);
|
||||
reducedStack.clipDevRect(scissor, SkClipOp::kIntersect);
|
||||
stack.clipDevRect(scissor, SkClipOp::kIntersect);
|
||||
|
||||
// convert both the original stack and reduced stack to SkRegions and see if they're equal
|
||||
SkRegion region;
|
||||
@ -1135,10 +1123,8 @@ static void test_reduced_clip_stack(skiatest::Reporter* reporter, bool enableCli
|
||||
static void test_reduced_clip_stack_genid(skiatest::Reporter* reporter) {
|
||||
{
|
||||
SkClipStack stack;
|
||||
stack.clipRect(SkRect::MakeXYWH(0, 0, 100, 100), SkMatrix::I(), kReplace_SkClipOp,
|
||||
true);
|
||||
stack.clipRect(SkRect::MakeXYWH(0, 0, SkScalar(50.3), SkScalar(50.3)), SkMatrix::I(),
|
||||
kReplace_SkClipOp, true);
|
||||
stack.replaceClip(SkRect::MakeXYWH(0, 0, 100, 100), true);
|
||||
stack.replaceClip(SkRect::MakeXYWH(0, 0, 50.3f, 50.3f), true);
|
||||
SkRect bounds = SkRect::MakeXYWH(0, 0, 100, 100);
|
||||
|
||||
sk_sp<GrDirectContext> context = GrDirectContext::MakeMock(nullptr);
|
||||
@ -1162,8 +1148,7 @@ static void test_reduced_clip_stack_genid(skiatest::Reporter* reporter) {
|
||||
// A B
|
||||
// C D
|
||||
|
||||
stack.clipRect(SkRect::MakeXYWH(0, 0, SkScalar(25.3), SkScalar(25.3)), SkMatrix::I(),
|
||||
kReplace_SkClipOp, true);
|
||||
stack.replaceClip(SkRect::MakeXYWH(0, 0, 25.3f, 25.3f), true);
|
||||
uint32_t genIDA = stack.getTopmostGenID();
|
||||
stack.clipRect(SkRect::MakeXYWH(50, 0, SkScalar(25.3), SkScalar(25.3)), SkMatrix::I(),
|
||||
kUnion_SkClipOp, true);
|
||||
@ -1250,11 +1235,10 @@ static void test_reduced_clip_stack_genid(skiatest::Reporter* reporter) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void test_reduced_clip_stack_no_aa_crash(skiatest::Reporter* reporter) {
|
||||
SkClipStack stack;
|
||||
stack.clipDevRect(SkIRect::MakeXYWH(0, 0, 100, 100), kReplace_SkClipOp);
|
||||
stack.clipDevRect(SkIRect::MakeXYWH(0, 0, 50, 50), kReplace_SkClipOp);
|
||||
stack.clipDevRect(SkIRect::MakeXYWH(0, 0, 100, 100), SkClipOp::kIntersect);
|
||||
stack.clipDevRect(SkIRect::MakeXYWH(0, 0, 50, 50), SkClipOp::kIntersect);
|
||||
SkRect bounds = SkRect::MakeXYWH(0, 0, 100, 100);
|
||||
|
||||
sk_sp<GrDirectContext> context = GrDirectContext::MakeMock(nullptr);
|
||||
@ -1359,7 +1343,7 @@ static void test_reduced_clip_stack_aa(skiatest::Reporter* reporter) {
|
||||
// Pixel-aligned rect (iior=true).
|
||||
name.printf("Pixel-aligned rect test, iter %i", i);
|
||||
SkClipStack stack;
|
||||
stack.clipRect(alignedRect, SkMatrix::I(), kIntersect_SkClipOp, true);
|
||||
stack.clipRect(alignedRect, SkMatrix::I(), SkClipOp::kIntersect, true);
|
||||
test_aa_query(reporter, name, stack, m, {IL, IT, IR, IB}, ClipMethod::kIgnoreClip);
|
||||
test_aa_query(reporter, name, stack, m, {IL, IT-1, IR, IT}, ClipMethod::kSkipDraw);
|
||||
test_aa_query(reporter, name, stack, m, {IL, IT-2, IR, IB}, ClipMethod::kScissor);
|
||||
@ -1367,7 +1351,7 @@ static void test_reduced_clip_stack_aa(skiatest::Reporter* reporter) {
|
||||
// Rect (iior=true).
|
||||
name.printf("Rect test, iter %i", i);
|
||||
stack.reset();
|
||||
stack.clipRect(rect, SkMatrix::I(), kIntersect_SkClipOp, true);
|
||||
stack.clipRect(rect, SkMatrix::I(), SkClipOp::kIntersect, true);
|
||||
test_aa_query(reporter, name, stack, m, {L, T, R, B}, ClipMethod::kIgnoreClip);
|
||||
test_aa_query(reporter, name, stack, m, {L-.1f, T, L, B}, ClipMethod::kSkipDraw);
|
||||
test_aa_query(reporter, name, stack, m, {L-.1f, T, L+.1f, B}, ClipMethod::kAAElements, 1);
|
||||
@ -1375,7 +1359,7 @@ static void test_reduced_clip_stack_aa(skiatest::Reporter* reporter) {
|
||||
// Difference rect (iior=false, inside-out bounds).
|
||||
name.printf("Difference rect test, iter %i", i);
|
||||
stack.reset();
|
||||
stack.clipRect(rect, SkMatrix::I(), kDifference_SkClipOp, true);
|
||||
stack.clipRect(rect, SkMatrix::I(), SkClipOp::kDifference, true);
|
||||
test_aa_query(reporter, name, stack, m, {L, T, R, B}, ClipMethod::kSkipDraw);
|
||||
test_aa_query(reporter, name, stack, m, {L, T-.1f, R, T}, ClipMethod::kIgnoreClip);
|
||||
test_aa_query(reporter, name, stack, m, {L, T-.1f, R, T+.1f}, ClipMethod::kAAElements, 1);
|
||||
@ -1383,7 +1367,7 @@ static void test_reduced_clip_stack_aa(skiatest::Reporter* reporter) {
|
||||
// Complex clip (iior=false, normal bounds).
|
||||
name.printf("Complex clip test, iter %i", i);
|
||||
stack.reset();
|
||||
stack.clipRect(rect, SkMatrix::I(), kIntersect_SkClipOp, true);
|
||||
stack.clipRect(rect, SkMatrix::I(), SkClipOp::kIntersect, true);
|
||||
stack.clipRect(innerRect, SkMatrix::I(), kXOR_SkClipOp, true);
|
||||
test_aa_query(reporter, name, stack, m, {l, t, r, b}, ClipMethod::kSkipDraw);
|
||||
test_aa_query(reporter, name, stack, m, {r-.1f, t, R, b}, ClipMethod::kAAElements, 1);
|
||||
@ -1395,7 +1379,7 @@ static void test_reduced_clip_stack_aa(skiatest::Reporter* reporter) {
|
||||
// Complex clip where outer rect is pixel aligned (iior=false, normal bounds).
|
||||
name.printf("Aligned Complex clip test, iter %i", i);
|
||||
stack.reset();
|
||||
stack.clipRect(alignedRect, SkMatrix::I(), kIntersect_SkClipOp, true);
|
||||
stack.clipRect(alignedRect, SkMatrix::I(), SkClipOp::kIntersect, true);
|
||||
stack.clipRect(innerRect, SkMatrix::I(), kXOR_SkClipOp, true);
|
||||
test_aa_query(reporter, name, stack, m, {l, t, r, b}, ClipMethod::kSkipDraw);
|
||||
test_aa_query(reporter, name, stack, m, {l, b-.1f, r, IB}, ClipMethod::kAAElements, 1);
|
||||
@ -1427,7 +1411,7 @@ static void test_tiny_query_bounds_assertion_bug(skiatest::Reporter* reporter) {
|
||||
const SkRect clipBounds = SkRect::MakeXYWH(1.5f, 100, 1000, 1000);
|
||||
|
||||
SkClipStack rectStack;
|
||||
rectStack.clipRect(clipBounds, SkMatrix::I(), kIntersect_SkClipOp, true);
|
||||
rectStack.clipRect(clipBounds, SkMatrix::I(), SkClipOp::kIntersect, true);
|
||||
|
||||
SkPath clipPath;
|
||||
clipPath.moveTo(clipBounds.left(), clipBounds.top());
|
||||
@ -1436,7 +1420,7 @@ static void test_tiny_query_bounds_assertion_bug(skiatest::Reporter* reporter) {
|
||||
clipPath.quadTo(clipBounds.left(), clipBounds.bottom(),
|
||||
clipBounds.left(), clipBounds.top());
|
||||
SkClipStack pathStack;
|
||||
pathStack.clipPath(clipPath, SkMatrix::I(), kIntersect_SkClipOp, true);
|
||||
pathStack.clipPath(clipPath, SkMatrix::I(), SkClipOp::kIntersect, true);
|
||||
|
||||
sk_sp<GrDirectContext> context = GrDirectContext::MakeMock(nullptr);
|
||||
const GrCaps* caps = context->priv().caps();
|
||||
@ -1505,7 +1489,7 @@ DEF_TEST(ClipStack, reporter) {
|
||||
{ 0, 0, 75, 75 }
|
||||
};
|
||||
for (size_t i = 0; i < SK_ARRAY_COUNT(gRects); i++) {
|
||||
stack.clipDevRect(gRects[i], kIntersect_SkClipOp);
|
||||
stack.clipDevRect(gRects[i], SkClipOp::kIntersect);
|
||||
}
|
||||
|
||||
// all of the above rects should have been intersected, leaving only 1 rect
|
||||
@ -1517,7 +1501,7 @@ DEF_TEST(ClipStack, reporter) {
|
||||
REPORTER_ASSERT(reporter, element);
|
||||
REPORTER_ASSERT(reporter,
|
||||
SkClipStack::Element::DeviceSpaceType::kRect == element->getDeviceSpaceType());
|
||||
REPORTER_ASSERT(reporter, kIntersect_SkClipOp == element->getOp());
|
||||
REPORTER_ASSERT(reporter, SkClipOp::kIntersect == element->getOp());
|
||||
REPORTER_ASSERT(reporter, element->getDeviceSpaceRect() == answer);
|
||||
// now check that we only had one in our iterator
|
||||
REPORTER_ASSERT(reporter, !iter.next());
|
||||
|
Loading…
Reference in New Issue
Block a user