aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Chris Dalton <csmartdalton@google.com>2017-10-27 01:50:57 -0600
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-10-27 19:16:44 +0000
commit7947193c319bced2ef557971550e196adbe60966 (patch)
tree82f94198c9ce7a0c74363bbc478a3920c0fc50c0
parent75e98c14e91cd94a2ac5751c39ff9b7e1dff1c20 (diff)
Merge clip rects in GrReducedClip
Merges the intersection of all rect clips into a single clip rect element. This is also the first step toward better handling of the subtractive elements. Bug: skia: Change-Id: I36bd9c256874917adb68f43e8faddc609e65f37a Reviewed-on: https://skia-review.googlesource.com/64380 Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Chris Dalton <csmartdalton@google.com>
-rw-r--r--src/gpu/GrClipStackClip.cpp60
-rw-r--r--src/gpu/GrReducedClip.cpp273
-rw-r--r--src/gpu/GrReducedClip.h77
-rw-r--r--tests/ClipStackTest.cpp84
4 files changed, 272 insertions, 222 deletions
diff --git a/src/gpu/GrClipStackClip.cpp b/src/gpu/GrClipStackClip.cpp
index 09f5bef323..6a71e00a1c 100644
--- a/src/gpu/GrClipStackClip.cpp
+++ b/src/gpu/GrClipStackClip.cpp
@@ -160,7 +160,7 @@ bool GrClipStackClip::UseSWOnlyPath(GrContext* context,
SkMatrix translate;
translate.setTranslate(SkIntToScalar(-reducedClip.left()), SkIntToScalar(-reducedClip.top()));
- for (ElementList::Iter iter(reducedClip.elements()); iter.get(); iter.next()) {
+ for (ElementList::Iter iter(reducedClip.maskElements()); iter.get(); iter.next()) {
const Element* element = iter.get();
SkClipOp op = element->getOp();
@@ -168,7 +168,7 @@ bool GrClipStackClip::UseSWOnlyPath(GrContext* context,
bool needsStencil = invert ||
kIntersect_SkClipOp == op || kReverseDifference_SkClipOp == op;
- if (PathNeedsSWRenderer(context, reducedClip.ibounds(), hasUserStencilSettings,
+ if (PathNeedsSWRenderer(context, reducedClip.scissor(), hasUserStencilSettings,
renderTargetContext, translate, element, nullptr, needsStencil)) {
return true;
}
@@ -268,8 +268,8 @@ bool GrClipStackClip::apply(GrContext* context, GrRenderTargetContext* renderTar
const GrReducedClip reducedClip(*fStack, devBounds,
renderTargetContext->priv().maxWindowRectangles());
- if (reducedClip.hasIBounds() && !GrClip::IsInsideClip(reducedClip.ibounds(), devBounds)) {
- out->addScissor(reducedClip.ibounds(), bounds);
+ if (reducedClip.hasScissor() && !GrClip::IsInsideClip(reducedClip.scissor(), devBounds)) {
+ out->addScissor(reducedClip.scissor(), bounds);
}
if (!reducedClip.windowRectangles().empty()) {
@@ -277,16 +277,16 @@ bool GrClipStackClip::apply(GrContext* context, GrRenderTargetContext* renderTar
GrWindowRectsState::Mode::kExclusive);
}
- if (reducedClip.elements().isEmpty()) {
+ if (reducedClip.maskElements().isEmpty()) {
return InitialState::kAllIn == reducedClip.initialState();
}
#ifdef SK_DEBUG
- SkASSERT(reducedClip.hasIBounds());
+ SkASSERT(reducedClip.hasScissor());
SkIRect rtIBounds = SkIRect::MakeWH(renderTargetContext->width(),
renderTargetContext->height());
- const SkIRect& clipIBounds = reducedClip.ibounds();
- SkASSERT(rtIBounds.contains(clipIBounds)); // Mask shouldn't be larger than the RT.
+ const SkIRect& scissor = reducedClip.scissor();
+ SkASSERT(rtIBounds.contains(scissor)); // Mask shouldn't be larger than the RT.
#endif
bool avoidStencilBuffers = context->caps()->avoidStencilBuffers();
@@ -299,7 +299,7 @@ bool GrClipStackClip::apply(GrContext* context, GrRenderTargetContext* renderTar
// when drawing rounded div borders. This could probably be tuned based on a
// configuration's relative costs of switching RTs to generate a mask vs
// longer shaders.
- if (reducedClip.elements().count() <= kMaxAnalyticElements) {
+ if (reducedClip.maskElements().count() <= kMaxAnalyticElements) {
// When there are multiple samples we want to do per-sample clipping, not compute a
// fractional pixel coverage.
bool disallowAnalyticAA =
@@ -311,8 +311,8 @@ bool GrClipStackClip::apply(GrContext* context, GrRenderTargetContext* renderTar
disallowAnalyticAA = useHWAA || hasUserStencilSettings;
}
std::unique_ptr<GrFragmentProcessor> clipFP;
- if ((reducedClip.requiresAA() || avoidStencilBuffers) &&
- get_analytic_clip_processor(reducedClip.elements(), disallowAnalyticAA, devBounds,
+ if ((reducedClip.maskRequiresAA() || avoidStencilBuffers) &&
+ get_analytic_clip_processor(reducedClip.maskElements(), disallowAnalyticAA, devBounds,
&clipFP)) {
out->addCoverageFP(std::move(clipFP));
return true;
@@ -320,7 +320,7 @@ bool GrClipStackClip::apply(GrContext* context, GrRenderTargetContext* renderTar
}
// If the stencil buffer is multisampled we can use it to do everything.
- if ((GrFSAAType::kNone == renderTargetContext->fsaaType() && reducedClip.requiresAA()) ||
+ if ((GrFSAAType::kNone == renderTargetContext->fsaaType() && reducedClip.maskRequiresAA()) ||
avoidStencilBuffers) {
sk_sp<GrTextureProxy> result;
if (UseSWOnlyPath(context, hasUserStencilSettings, renderTargetContext, reducedClip)) {
@@ -334,7 +334,7 @@ bool GrClipStackClip::apply(GrContext* context, GrRenderTargetContext* renderTar
if (result) {
// The mask's top left coord should be pinned to the rounded-out top left corner of
// the clip's device space bounds.
- out->addCoverageFP(create_fp_for_mask(std::move(result), reducedClip.ibounds()));
+ out->addCoverageFP(create_fp_for_mask(std::move(result), reducedClip.scissor()));
return true;
}
@@ -351,12 +351,12 @@ bool GrClipStackClip::apply(GrContext* context, GrRenderTargetContext* renderTar
// This relies on the property that a reduced sub-rect of the last clip will contain all the
// relevant window rectangles that were in the last clip. This subtle requirement will go away
// after clipping is overhauled.
- if (renderTargetContext->priv().mustRenderClip(reducedClip.elementsGenID(),
- reducedClip.ibounds())) {
+ if (renderTargetContext->priv().mustRenderClip(reducedClip.maskGenID(),
+ reducedClip.scissor())) {
reducedClip.drawStencilClipMask(context, renderTargetContext);
- renderTargetContext->priv().setLastClip(reducedClip.elementsGenID(), reducedClip.ibounds());
+ renderTargetContext->priv().setLastClip(reducedClip.maskGenID(), reducedClip.scissor());
}
- out->addStencilClip(reducedClip.elementsGenID());
+ out->addStencilClip(reducedClip.maskGenID());
return true;
}
@@ -391,7 +391,7 @@ sk_sp<GrTextureProxy> GrClipStackClip::createAlphaClipMask(GrContext* context,
const GrReducedClip& reducedClip) const {
GrResourceProvider* resourceProvider = context->resourceProvider();
GrUniqueKey key;
- create_clip_mask_key(reducedClip.elementsGenID(), reducedClip.ibounds(), &key);
+ create_clip_mask_key(reducedClip.maskGenID(), reducedClip.scissor(), &key);
sk_sp<GrTextureProxy> proxy(resourceProvider->findOrCreateProxyByUniqueKey(
key, kBottomLeft_GrSurfaceOrigin));
@@ -420,7 +420,7 @@ sk_sp<GrTextureProxy> GrClipStackClip::createAlphaClipMask(GrContext* context,
SkASSERT(result->origin() == kBottomLeft_GrSurfaceOrigin);
resourceProvider->assignUniqueKeyToProxy(key, result.get());
- add_invalidate_on_pop_message(*fStack, reducedClip.elementsGenID(), key);
+ add_invalidate_on_pop_message(*fStack, reducedClip.maskGenID(), key);
return result;
}
@@ -436,19 +436,19 @@ namespace {
class ClipMaskData {
public:
ClipMaskData(const GrReducedClip& reducedClip)
- : fMaskBounds(reducedClip.ibounds())
+ : fScissor(reducedClip.scissor())
, fInitialState(reducedClip.initialState()) {
- for (ElementList::Iter iter(reducedClip.elements()); iter.get(); iter.next()) {
+ for (ElementList::Iter iter(reducedClip.maskElements()); iter.get(); iter.next()) {
fElements.addToTail(*iter.get());
}
}
- const SkIRect& ibounds() const { return fMaskBounds; }
+ const SkIRect& scissor() const { return fScissor; }
InitialState initialState() const { return fInitialState; }
const ElementList& elements() const { return fElements; }
private:
- SkIRect fMaskBounds;
+ SkIRect fScissor;
InitialState fInitialState;
ElementList fElements;
};
@@ -456,10 +456,10 @@ private:
}
static void draw_clip_elements_to_mask_helper(GrSWMaskHelper& helper, const ElementList& elements,
- const SkIRect& ibounds, InitialState initialState) {
+ const SkIRect& scissor, InitialState initialState) {
// Set the matrix so that rendered clip elements are transformed to mask space from clip space.
SkMatrix translate;
- translate.setTranslate(SkIntToScalar(-ibounds.left()), SkIntToScalar(-ibounds.top()));
+ translate.setTranslate(SkIntToScalar(-scissor.left()), SkIntToScalar(-scissor.top()));
helper.clear(InitialState::kAllIn == initialState ? 0xFF : 0x00);
@@ -474,7 +474,7 @@ static void draw_clip_elements_to_mask_helper(GrSWMaskHelper& helper, const Elem
// 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) {
- SkRect temp = SkRect::Make(ibounds);
+ SkRect temp = SkRect::Make(scissor);
// invert the entire scene
helper.drawRect(temp, translate, SkRegion::kXOR_Op, GrAA::kNo, 0xFF);
}
@@ -503,7 +503,7 @@ sk_sp<GrTextureProxy> GrClipStackClip::createSoftwareClipMask(
GrContext* context, const GrReducedClip& reducedClip,
GrRenderTargetContext* renderTargetContext) const {
GrUniqueKey key;
- create_clip_mask_key(reducedClip.elementsGenID(), reducedClip.ibounds(), &key);
+ create_clip_mask_key(reducedClip.maskGenID(), reducedClip.scissor(), &key);
sk_sp<GrTextureProxy> proxy(context->resourceProvider()->findOrCreateProxyByUniqueKey(
key, kTopLeft_GrSurfaceOrigin));
@@ -536,7 +536,7 @@ sk_sp<GrTextureProxy> GrClipStackClip::createSoftwareClipMask(
GrSWMaskHelper helper(uploaderRaw->getPixels());
if (helper.init(maskSpaceIBounds)) {
draw_clip_elements_to_mask_helper(helper, uploaderRaw->data().elements(),
- uploaderRaw->data().ibounds(),
+ uploaderRaw->data().scissor(),
uploaderRaw->data().initialState());
} else {
SkDEBUGFAIL("Unable to allocate SW clip mask.");
@@ -552,7 +552,7 @@ sk_sp<GrTextureProxy> GrClipStackClip::createSoftwareClipMask(
return nullptr;
}
- draw_clip_elements_to_mask_helper(helper, reducedClip.elements(), reducedClip.ibounds(),
+ draw_clip_elements_to_mask_helper(helper, reducedClip.maskElements(), reducedClip.scissor(),
reducedClip.initialState());
proxy = helper.toTextureProxy(context, SkBackingFit::kApprox);
@@ -560,6 +560,6 @@ sk_sp<GrTextureProxy> GrClipStackClip::createSoftwareClipMask(
SkASSERT(proxy->origin() == kTopLeft_GrSurfaceOrigin);
context->resourceProvider()->assignUniqueKeyToProxy(key, proxy.get());
- add_invalidate_on_pop_message(*fStack, reducedClip.elementsGenID(), key);
+ add_invalidate_on_pop_message(*fStack, reducedClip.maskGenID(), key);
return proxy;
}
diff --git a/src/gpu/GrReducedClip.cpp b/src/gpu/GrReducedClip.cpp
index 22316c5c0a..29f483022b 100644
--- a/src/gpu/GrReducedClip.cpp
+++ b/src/gpu/GrReducedClip.cpp
@@ -21,8 +21,6 @@
#include "GrUserStencilSettings.h"
#include "SkClipOpPriv.h"
-typedef SkClipStack::Element Element;
-
/**
* There are plenty of optimizations that could be added here. Maybe flips could be folded into
* earlier operations. Or would inserting flips and reversing earlier ops ever be a win? Perhaps
@@ -33,7 +31,8 @@ typedef SkClipStack::Element Element;
GrReducedClip::GrReducedClip(const SkClipStack& stack, const SkRect& queryBounds,
int maxWindowRectangles) {
SkASSERT(!queryBounds.isEmpty());
- fHasIBounds = false;
+ fHasScissor = false;
+ fAAClipRectGenID = SK_InvalidGenID;
if (stack.isWideOpen()) {
fInitialState = InitialState::kAllIn;
@@ -57,11 +56,10 @@ GrReducedClip::GrReducedClip(const SkClipStack& stack, const SkRect& queryBounds
SkASSERT(SkClipStack::kNormal_BoundsType == stackBoundsType);
SkClipStack::Iter iter(stack, SkClipStack::Iter::kTop_IterStart);
if (!iter.prev()->isAA() || GrClip::IsPixelAligned(stackBounds)) {
- // The clip is a non-aa rect. This is the one spot where we can actually implement the
- // clip (using fIBounds) rather than just telling the caller what it should be.
- stackBounds.round(&fIBounds);
- fHasIBounds = true;
- fInitialState = fIBounds.isEmpty() ? InitialState::kAllOut : InitialState::kAllIn;
+ // The clip is a non-aa rect. Here we just implement the entire thing using fScissor.
+ stackBounds.round(&fScissor);
+ fHasScissor = true;
+ fInitialState = fScissor.isEmpty() ? InitialState::kAllOut : InitialState::kAllIn;
return;
}
if (GrClip::IsInsideClip(stackBounds, queryBounds)) {
@@ -71,42 +69,49 @@ GrReducedClip::GrReducedClip(const SkClipStack& stack, const SkRect& queryBounds
SkRect tightBounds;
SkAssertResult(tightBounds.intersect(stackBounds, queryBounds));
- fIBounds = GrClip::GetPixelIBounds(tightBounds);
- if (fIBounds.isEmpty()) {
+ fScissor = GrClip::GetPixelIBounds(tightBounds);
+ if (fScissor.isEmpty()) {
fInitialState = InitialState::kAllOut;
return;
}
- fHasIBounds = true;
+ fHasScissor = true;
- // Implement the clip with an AA rect element.
- fElements.addToHead(stackBounds, SkMatrix::I(), kReplace_SkClipOp, true /*doAA*/);
- fElementsGenID = stack.getTopmostGenID();
- fRequiresAA = true;
+ fAAClipRect = stackBounds;
+ fAAClipRectGenID = stack.getTopmostGenID();
+ SkASSERT(SK_InvalidGenID != fAAClipRectGenID);
- fInitialState = InitialState::kAllOut;
- return;
- }
+ fInitialState = InitialState::kAllIn;
+ } else {
+ SkRect tighterQuery = queryBounds;
+ if (SkClipStack::kNormal_BoundsType == stackBoundsType) {
+ // Tighten the query by introducing a new clip at the stack's pixel boundaries. (This
+ // new clip will be enforced by the scissor.)
+ SkAssertResult(tighterQuery.intersect(GrClip::GetPixelBounds(stackBounds)));
+ }
- SkRect tighterQuery = queryBounds;
- if (SkClipStack::kNormal_BoundsType == stackBoundsType) {
- // Tighten the query by introducing a new clip at the stack's pixel boundaries. (This new
- // clip will be enforced by the scissor through fIBounds.)
- SkAssertResult(tighterQuery.intersect(GrClip::GetPixelBounds(stackBounds)));
- }
+ fScissor = GrClip::GetPixelIBounds(tighterQuery);
+ if (fScissor.isEmpty()) {
+ fInitialState = InitialState::kAllOut;
+ return;
+ }
+ fHasScissor = true;
- fIBounds = GrClip::GetPixelIBounds(tighterQuery);
- if (fIBounds.isEmpty()) {
- fInitialState = InitialState::kAllOut;
- return;
+ // Now that we have determined the bounds to use and filtered out the trivial cases, call the
+ // helper that actually walks the stack.
+ this->walkStack(stack, tighterQuery, maxWindowRectangles);
}
- fHasIBounds = true;
- // Now that we have determined the bounds to use and filtered out the trivial cases, call the
- // helper that actually walks the stack.
- this->walkStack(stack, tighterQuery, maxWindowRectangles);
-
- if (fWindowRects.count() < maxWindowRectangles) {
- this->addInteriorWindowRectangles(maxWindowRectangles);
+ if (SK_InvalidGenID != fAAClipRectGenID) { // Is there an AA clip rect?
+ if (fMaskElements.isEmpty()) {
+ // Use a replace since it is faster than intersect.
+ fMaskElements.addToHead(fAAClipRect, SkMatrix::I(), kReplace_SkClipOp, true /*doAA*/);
+ fInitialState = InitialState::kAllOut;
+ } else {
+ fMaskElements.addToTail(fAAClipRect, SkMatrix::I(), kIntersect_SkClipOp, true /*doAA*/);
+ }
+ fMaskRequiresAA = true;
+ fMaskGenID = fAAClipRectGenID;
+ fAAClipRectGenID = SK_InvalidGenID;
}
}
@@ -170,11 +175,12 @@ void GrReducedClip::walkStack(const SkClipStack& stack, const SkRect& queryBound
skippable = true;
} else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
skippable = true;
- } else if (fWindowRects.count() < maxWindowRectangles && !embiggens &&
- !element->isAA() &&
- Element::DeviceSpaceType::kRect == element->getDeviceSpaceType()) {
- this->addWindowRectangle(element->getDeviceSpaceRect(), false);
- skippable = true;
+ } else if (!embiggens) {
+ ClipResult result = this->clipOutsideElement(element, maxWindowRectangles);
+ if (ClipResult::kMadeEmpty == result) {
+ return;
+ }
+ skippable = (ClipResult::kClipped == result);
}
}
if (!skippable) {
@@ -198,16 +204,12 @@ void GrReducedClip::walkStack(const SkClipStack& stack, const SkRect& queryBound
} else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
initialTriState = InitialTriState::kAllOut;
skippable = true;
- } else if (!embiggens && !element->isAA() &&
- Element::DeviceSpaceType::kRect == element->getDeviceSpaceType()) {
- // fIBounds and queryBounds have already acccounted for this element via
- // clip stack bounds; here we just apply the non-aa rounding effect.
- SkIRect nonaaRect;
- element->getDeviceSpaceRect().round(&nonaaRect);
- if (!this->intersectIBounds(nonaaRect)) {
+ } else if (!embiggens) {
+ ClipResult result = this->clipInsideElement(element);
+ if (ClipResult::kMadeEmpty == result) {
return;
}
- skippable = true;
+ skippable = (ClipResult::kClipped == result);
}
}
if (!skippable) {
@@ -304,17 +306,15 @@ void GrReducedClip::walkStack(const SkClipStack& stack, const SkRect& queryBound
} else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
initialTriState = InitialTriState::kAllOut;
skippable = true;
- } else if (!embiggens && !element->isAA() &&
- Element::DeviceSpaceType::kRect == element->getDeviceSpaceType()) {
- // fIBounds and queryBounds have already acccounted for this element via
- // clip stack bounds; here we just apply the non-aa rounding effect.
- SkIRect nonaaRect;
- element->getDeviceSpaceRect().round(&nonaaRect);
- if (!this->intersectIBounds(nonaaRect)) {
+ } else if (!embiggens) {
+ ClipResult result = this->clipInsideElement(element);
+ if (ClipResult::kMadeEmpty == result) {
return;
}
- initialTriState = InitialTriState::kAllIn;
- skippable = true;
+ if (ClipResult::kClipped == result) {
+ initialTriState = InitialTriState::kAllIn;
+ skippable = true;
+ }
}
}
if (!skippable) {
@@ -327,19 +327,19 @@ void GrReducedClip::walkStack(const SkClipStack& stack, const SkRect& queryBound
break;
}
if (!skippable) {
- if (0 == fElements.count()) {
+ if (fMaskElements.isEmpty()) {
// This will be the last element. Record the stricter genID.
- fElementsGenID = element->getGenID();
+ fMaskGenID = element->getGenID();
}
// if it is a flip, change it to a bounds-filling rect
if (isFlip) {
SkASSERT(kXOR_SkClipOp == element->getOp() ||
kReverseDifference_SkClipOp == element->getOp());
- fElements.addToHead(SkRect::Make(fIBounds), SkMatrix::I(),
- kReverseDifference_SkClipOp, false);
+ fMaskElements.addToHead(SkRect::Make(fScissor), SkMatrix::I(),
+ kReverseDifference_SkClipOp, false);
} else {
- Element* newElement = fElements.addToHead(*element);
+ Element* newElement = fMaskElements.addToHead(*element);
if (newElement->isAA()) {
++numAAElements;
}
@@ -362,10 +362,10 @@ void GrReducedClip::walkStack(const SkClipStack& stack, const SkRect& queryBound
if ((InitialTriState::kAllOut == initialTriState && !embiggens) ||
(InitialTriState::kAllIn == initialTriState && !emsmallens)) {
- fElements.reset();
+ fMaskElements.reset();
numAAElements = 0;
} else {
- Element* element = fElements.headIter().get();
+ Element* element = fMaskElements.headIter().get();
while (element) {
bool skippable = false;
switch (element->getOp()) {
@@ -429,47 +429,80 @@ void GrReducedClip::walkStack(const SkClipStack& stack, const SkRect& queryBound
if (element->isAA()) {
--numAAElements;
}
- fElements.popHead();
- element = fElements.headIter().get();
+ fMaskElements.popHead();
+ element = fMaskElements.headIter().get();
}
}
}
- fRequiresAA = numAAElements > 0;
+ fMaskRequiresAA = numAAElements > 0;
SkASSERT(InitialTriState::kUnknown != initialTriState);
fInitialState = static_cast<GrReducedClip::InitialState>(initialTriState);
}
-static bool element_is_pure_subtract(SkClipOp op) {
- SkASSERT(static_cast<int>(op) >= 0);
- return static_cast<int>(op) <= static_cast<int>(kIntersect_SkClipOp);
+GrReducedClip::ClipResult GrReducedClip::clipInsideElement(const Element* element) {
+ SkIRect elementIBounds;
+ if (!element->isAA()) {
+ element->getBounds().round(&elementIBounds);
+ } else {
+ elementIBounds = GrClip::GetPixelIBounds(element->getBounds());
+ }
+ SkASSERT(fHasScissor);
+ if (!fScissor.intersect(elementIBounds)) {
+ this->makeEmpty();
+ return ClipResult::kMadeEmpty;
+ }
+
+ switch (element->getDeviceSpaceType()) {
+ case Element::DeviceSpaceType::kEmpty:
+ return ClipResult::kMadeEmpty;
+
+ case Element::DeviceSpaceType::kRect:
+ SkASSERT(element->getBounds() == element->getDeviceSpaceRect());
+ if (element->isAA()) {
+ if (SK_InvalidGenID == fAAClipRectGenID) { // No AA clip rect yet?
+ fAAClipRect = element->getDeviceSpaceRect();
+ // fAAClipRectGenID is the value we should use for fMaskGenID if we end up
+ // moving the AA clip rect into the mask. The mask GenID is simply the topmost
+ // element's GenID. And since we walk the stack backwards, this means it's just
+ // the first element we don't skip during our walk.
+ fAAClipRectGenID = fMaskElements.isEmpty() ? element->getGenID() : fMaskGenID;
+ SkASSERT(SK_InvalidGenID != fAAClipRectGenID);
+ } else if (!fAAClipRect.intersect(element->getDeviceSpaceRect())) {
+ this->makeEmpty();
+ return ClipResult::kMadeEmpty;
+ }
+ }
+ return ClipResult::kClipped;
+
+ case Element::DeviceSpaceType::kRRect:
+ case Element::DeviceSpaceType::kPath:
+ return ClipResult::kNotClipped;
+ }
- GR_STATIC_ASSERT(0 == static_cast<int>(kDifference_SkClipOp));
- GR_STATIC_ASSERT(1 == static_cast<int>(kIntersect_SkClipOp));
+ SK_ABORT("Unexpected DeviceSpaceType");
+ return ClipResult::kNotClipped;
}
-void GrReducedClip::addInteriorWindowRectangles(int maxWindowRectangles) {
- SkASSERT(fWindowRects.count() < maxWindowRectangles);
- // Walk backwards through the element list and add window rectangles to the interiors of
- // "difference" elements. Quit if we encounter an element that may grow the clip.
- ElementList::Iter iter(fElements, ElementList::Iter::kTail_IterStart);
- for (; iter.get() && element_is_pure_subtract(iter.get()->getOp()); iter.prev()) {
- const Element* element = iter.get();
- if (kDifference_SkClipOp != element->getOp()) {
- continue;
- }
+GrReducedClip::ClipResult GrReducedClip::clipOutsideElement(const Element* element,
+ int maxWindowRectangles) {
+ if (fWindowRects.count() >= maxWindowRectangles) {
+ return ClipResult::kNotClipped;
+ }
- if (Element::DeviceSpaceType::kRect == element->getDeviceSpaceType()) {
- SkASSERT(element->isAA());
- this->addWindowRectangle(element->getDeviceSpaceRect(), true);
- if (fWindowRects.count() >= maxWindowRectangles) {
- return;
- }
- continue;
- }
+ switch (element->getDeviceSpaceType()) {
+ case Element::DeviceSpaceType::kEmpty:
+ return ClipResult::kMadeEmpty;
- if (Element::DeviceSpaceType::kRRect == element->getDeviceSpaceType()) {
- // For round rects we add two overlapping windows in the shape of a plus.
+ case Element::DeviceSpaceType::kRect:
+ // Clip out the inside of every rect. We won't be able to entirely skip the AA ones, but
+ // it saves processing time.
+ this->addWindowRectangle(element->getDeviceSpaceRect(), element->isAA());
+ return !element->isAA() ? ClipResult::kClipped : ClipResult::kNotClipped;
+
+ case Element::DeviceSpaceType::kRRect: {
+ // Clip out the interiors of round rects with two window rectangles in the shape of a
+ // plus. It doesn't allow us to skip the clip element, but still saves processing time.
const SkRRect& clipRRect = element->getDeviceSpaceRRect();
SkVector insetTL = clipRRect.radii(SkRRect::kUpperLeft_Corner);
SkVector insetBR = clipRRect.radii(SkRRect::kLowerRight_Corner);
@@ -484,25 +517,28 @@ void GrReducedClip::addInteriorWindowRectangles(int maxWindowRectangles) {
const SkRect& bounds = clipRRect.getBounds();
if (insetTL.x() + insetBR.x() >= bounds.width() ||
insetTL.y() + insetBR.y() >= bounds.height()) {
- continue; // The interior "plus" is empty.
+ return ClipResult::kNotClipped; // The interior "plus" is empty.
}
SkRect horzRect = SkRect::MakeLTRB(bounds.left(), bounds.top() + insetTL.y(),
bounds.right(), bounds.bottom() - insetBR.y());
this->addWindowRectangle(horzRect, element->isAA());
if (fWindowRects.count() >= maxWindowRectangles) {
- return;
+ return ClipResult::kNotClipped;
}
SkRect vertRect = SkRect::MakeLTRB(bounds.left() + insetTL.x(), bounds.top(),
bounds.right() - insetBR.x(), bounds.bottom());
this->addWindowRectangle(vertRect, element->isAA());
- if (fWindowRects.count() >= maxWindowRectangles) {
- return;
- }
- continue;
+ return ClipResult::kNotClipped;
}
+
+ case Element::DeviceSpaceType::kPath:
+ return ClipResult::kNotClipped;
}
+
+ SK_ABORT("Unexpected DeviceSpaceType");
+ return ClipResult::kNotClipped;
}
inline void GrReducedClip::addWindowRectangle(const SkRect& elementInteriorRect, bool elementIsAA) {
@@ -517,17 +553,12 @@ inline void GrReducedClip::addWindowRectangle(const SkRect& elementInteriorRect,
}
}
-inline bool GrReducedClip::intersectIBounds(const SkIRect& irect) {
- SkASSERT(fHasIBounds);
- if (!fIBounds.intersect(irect)) {
- fHasIBounds = false;
- fWindowRects.reset();
- fElements.reset();
- fRequiresAA = false;
- fInitialState = InitialState::kAllOut;
- return false;
- }
- return true;
+void GrReducedClip::makeEmpty() {
+ fHasScissor = false;
+ fAAClipRectGenID = SK_InvalidGenID;
+ fWindowRects.reset();
+ fMaskElements.reset();
+ fInitialState = InitialState::kAllOut;
}
////////////////////////////////////////////////////////////////////////////////
@@ -540,10 +571,10 @@ static bool stencil_element(GrRenderTargetContext* rtc,
const SkClipStack::Element* element) {
GrAA aa = GrBoolToAA(element->isAA());
switch (element->getDeviceSpaceType()) {
- case Element::DeviceSpaceType::kEmpty:
+ case SkClipStack::Element::DeviceSpaceType::kEmpty:
SkDEBUGFAIL("Should never get here with an empty element.");
break;
- case Element::DeviceSpaceType::kRect:
+ case SkClipStack::Element::DeviceSpaceType::kRect:
return rtc->priv().drawAndStencilRect(clip, ss, (SkRegion::Op)element->getOp(),
element->isInverseFilled(), aa, viewMatrix,
element->getDeviceSpaceRect());
@@ -572,10 +603,10 @@ static void draw_element(GrRenderTargetContext* rtc,
const SkClipStack::Element* element) {
// TODO: Draw rrects directly here.
switch (element->getDeviceSpaceType()) {
- case Element::DeviceSpaceType::kEmpty:
+ case SkClipStack::Element::DeviceSpaceType::kEmpty:
SkDEBUGFAIL("Should never get here with an empty element.");
break;
- case Element::DeviceSpaceType::kRect:
+ case SkClipStack::Element::DeviceSpaceType::kRect:
rtc->drawRect(clip, std::move(paint), aa, viewMatrix, element->getDeviceSpaceRect());
break;
default: {
@@ -594,10 +625,10 @@ static void draw_element(GrRenderTargetContext* rtc,
bool GrReducedClip::drawAlphaClipMask(GrRenderTargetContext* rtc) const {
// The texture may be larger than necessary, this rect represents the part of the texture
// we populate with a rasterization of the clip.
- GrFixedClip clip(SkIRect::MakeWH(fIBounds.width(), fIBounds.height()));
+ GrFixedClip clip(SkIRect::MakeWH(fScissor.width(), fScissor.height()));
if (!fWindowRects.empty()) {
- clip.setWindowRectangles(fWindowRects.makeOffset(-fIBounds.left(), -fIBounds.top()),
+ clip.setWindowRectangles(fWindowRects.makeOffset(-fScissor.left(), -fScissor.top()),
GrWindowRectsState::Mode::kExclusive);
}
@@ -608,10 +639,10 @@ bool GrReducedClip::drawAlphaClipMask(GrRenderTargetContext* rtc) const {
// Set the matrix so that rendered clip elements are transformed to mask space from clip space.
SkMatrix translate;
- translate.setTranslate(SkIntToScalar(-fIBounds.left()), SkIntToScalar(-fIBounds.top()));
+ translate.setTranslate(SkIntToScalar(-fScissor.left()), SkIntToScalar(-fScissor.top()));
// walk through each clip element and perform its set op
- for (ElementList::Iter iter(fElements); iter.get(); iter.next()) {
+ for (ElementList::Iter iter(fMaskElements); iter.get(); iter.next()) {
const Element* element = iter.get();
SkRegion::Op op = (SkRegion::Op)element->getOp();
GrAA aa = GrBoolToAA(element->isAA());
@@ -643,7 +674,7 @@ bool GrReducedClip::drawAlphaClipMask(GrRenderTargetContext* rtc) const {
0xffff>()
);
if (!rtc->priv().drawAndStencilRect(clip, &kDrawOutsideElement, op, !invert, GrAA::kNo,
- translate, SkRect::Make(fIBounds))) {
+ translate, SkRect::Make(fScissor))) {
return false;
}
} else {
@@ -703,7 +734,7 @@ private:
bool GrReducedClip::drawStencilClipMask(GrContext* context,
GrRenderTargetContext* renderTargetContext) const {
// We set the current clip to the bounds so that our recursive draws are scissored to them.
- StencilClip stencilClip(fIBounds, this->elementsGenID());
+ StencilClip stencilClip(fScissor, this->maskGenID());
if (!fWindowRects.empty()) {
stencilClip.setWindowRectangles(fWindowRects, GrWindowRectsState::Mode::kExclusive);
@@ -713,7 +744,7 @@ bool GrReducedClip::drawStencilClipMask(GrContext* context,
renderTargetContext->priv().clearStencilClip(stencilClip.fixedClip(), initialState);
// walk through each clip element and perform its set op with the existing clip.
- for (ElementList::Iter iter(fElements); iter.get(); iter.next()) {
+ for (ElementList::Iter iter(fMaskElements); iter.get(); iter.next()) {
const Element* element = iter.get();
GrAAType aaType = GrAAType::kNone;
if (element->isAA() && GrFSAAType::kNone != renderTargetContext->fsaaType()) {
@@ -843,7 +874,7 @@ bool GrReducedClip::drawStencilClipMask(GrContext* context,
// The view matrix is setup to do clip space -> stencil space translation, so
// draw rect in clip space.
renderTargetContext->priv().stencilRect(stencilClip, *pass, aaType, SkMatrix::I(),
- SkRect::Make(fIBounds));
+ SkRect::Make(fScissor));
}
}
}
diff --git a/src/gpu/GrReducedClip.h b/src/gpu/GrReducedClip.h
index c9cce361ec..0746439ba3 100644
--- a/src/gpu/GrReducedClip.h
+++ b/src/gpu/GrReducedClip.h
@@ -21,47 +21,54 @@ class GrRenderTargetContext;
*/
class SK_API GrReducedClip {
public:
+ using Element = SkClipStack::Element;
+ using ElementList = SkTLList<SkClipStack::Element, 16>;
+
GrReducedClip(const SkClipStack&, const SkRect& queryBounds, int maxWindowRectangles = 0);
/**
- * If hasIBounds() is true, this is the bounding box within which the clip elements are valid.
- * The caller must not modify any pixels outside this box. Undefined if hasIBounds() is false.
+ * If hasScissor() is true, the clip mask is not valid outside this rect and the caller must
+ * enforce this scissor during draw.
*/
- const SkIRect& ibounds() const { SkASSERT(fHasIBounds); return fIBounds; }
- int left() const { return this->ibounds().left(); }
- int top() const { return this->ibounds().top(); }
- int width() const { return this->ibounds().width(); }
- int height() const { return this->ibounds().height(); }
+ const SkIRect& scissor() const { SkASSERT(fHasScissor); return fScissor; }
+ int left() const { return this->scissor().left(); }
+ int top() const { return this->scissor().top(); }
+ int width() const { return this->scissor().width(); }
+ int height() const { return this->scissor().height(); }
/**
- * Indicates whether ibounds() are defined. They will always be defined if the elements() are
+ * Indicates whether scissor() is defined. It will always be defined if the maskElements() are
* nonempty.
*/
- bool hasIBounds() const { return fHasIBounds; }
+ bool hasScissor() const { return fHasScissor; }
/**
- * If nonempty, this is a set of "exclusive" windows within which the clip elements are NOT
- * valid. The caller must not modify any pixels inside these windows.
+ * If nonempty, the clip mask is not valid inside these windows and the caller must clip them
+ * out using the window rectangles GPU extension.
*/
const GrWindowRectangles& windowRectangles() const { return fWindowRects; }
- typedef SkTLList<SkClipStack::Element, 16> ElementList;
-
/**
- * Populated with a minimal list of elements required to fully implement the clip.
+ * An ordered list of clip elements that could not be skipped or implemented by other means. If
+ * nonempty, the caller must create an alpha and/or stencil mask for these elements and apply it
+ * during draw.
*/
- const ElementList& elements() const { return fElements; }
+ const ElementList& maskElements() const { return fMaskElements; }
/**
- * If elements() are nonempty, uniquely identifies the list of elements within ibounds().
- * Otherwise undefined.
+ * If maskElements() are nonempty, uniquely identifies the region of the clip mask that falls
+ * inside of scissor().
+ * NOTE: since clip elements might fall outside the query bounds, different regions of the same
+ * clip stack might have more or less restrictive IDs.
+ * FIXME: this prevents us from reusing a sub-rect of a perfectly good mask when that rect has
+ * been assigned a less restrictive ID.
*/
- uint32_t elementsGenID() const { SkASSERT(!fElements.isEmpty()); return fElementsGenID; }
+ uint32_t maskGenID() const { SkASSERT(!fMaskElements.isEmpty()); return fMaskGenID; }
/**
- * Indicates whether antialiasing is required to process any of the clip elements.
+ * Indicates whether antialiasing is required to process any of the mask elements.
*/
- bool requiresAA() const { return fRequiresAA; }
+ bool maskRequiresAA() const { SkASSERT(!fMaskElements.isEmpty()); return fMaskRequiresAA; }
enum class InitialState : bool {
kAllIn,
@@ -75,16 +82,32 @@ public:
private:
void walkStack(const SkClipStack&, const SkRect& queryBounds, int maxWindowRectangles);
- void addInteriorWindowRectangles(int maxWindowRectangles);
+
+ enum class ClipResult {
+ kNotClipped,
+ kClipped,
+ kMadeEmpty
+ };
+
+ // Clips the the given element's interior out of the final clip.
+ // NOTE: do not call for elements followed by ops that can grow the clip.
+ ClipResult clipInsideElement(const Element* element);
+
+ // Clips the the given element's exterior out of the final clip.
+ // NOTE: do not call for elements followed by ops that can grow the clip.
+ ClipResult clipOutsideElement(const Element* element, int maxWindowRectangles);
+
void addWindowRectangle(const SkRect& elementInteriorRect, bool elementIsAA);
- bool intersectIBounds(const SkIRect&);
+ void makeEmpty();
- SkIRect fIBounds;
- bool fHasIBounds;
+ SkIRect fScissor;
+ bool fHasScissor;
+ SkRect fAAClipRect;
+ uint32_t fAAClipRectGenID; // GenID the mask will have if includes the AA clip rect.
GrWindowRectangles fWindowRects;
- ElementList fElements;
- uint32_t fElementsGenID;
- bool fRequiresAA;
+ ElementList fMaskElements;
+ uint32_t fMaskGenID;
+ bool fMaskRequiresAA;
InitialState fInitialState;
};
diff --git a/tests/ClipStackTest.cpp b/tests/ClipStackTest.cpp
index 8984027664..554362372d 100644
--- a/tests/ClipStackTest.cpp
+++ b/tests/ClipStackTest.cpp
@@ -1031,23 +1031,16 @@ static void test_reduced_clip_stack(skiatest::Reporter* reporter) {
const GrReducedClip* reduced = new (storage.get()) GrReducedClip(stack, queryBounds);
REPORTER_ASSERT_MESSAGE(reporter,
- reduced->elements().isEmpty() ||
- SkClipStack::kInvalidGenID != reduced->elementsGenID(),
+ reduced->maskElements().isEmpty() ||
+ SkClipStack::kInvalidGenID != reduced->maskGenID(),
testCase.c_str());
- if (!reduced->elements().isEmpty()) {
- REPORTER_ASSERT_MESSAGE(reporter, reduced->hasIBounds(), testCase.c_str());
+ if (!reduced->maskElements().isEmpty()) {
+ REPORTER_ASSERT_MESSAGE(reporter, reduced->hasScissor(), testCase.c_str());
SkRect stackBounds;
SkClipStack::BoundsType stackBoundsType;
stack.getBounds(&stackBounds, &stackBoundsType);
- if (SkClipStack::kNormal_BoundsType == stackBoundsType) {
- // Unless GrReducedClip starts doing some heroic tightening of the clip bounds, this
- // will be true since the stack bounds are completely contained inside the query.
- REPORTER_ASSERT_MESSAGE(reporter,
- GrClip::IsInsideClip(reduced->ibounds(), stackBounds),
- testCase.c_str());
- }
- REPORTER_ASSERT_MESSAGE(reporter, reduced->requiresAA() == doAA, testCase.c_str());
+ REPORTER_ASSERT_MESSAGE(reporter, reduced->maskRequiresAA() == doAA, testCase.c_str());
}
// Build a new clip stack based on the reduced clip elements
@@ -1056,22 +1049,22 @@ static void test_reduced_clip_stack(skiatest::Reporter* reporter) {
// whether the result is bounded or not, the whole plane should start outside the clip.
reducedStack.clipEmpty();
}
- for (ElementList::Iter iter(reduced->elements()); iter.get(); iter.next()) {
+ for (ElementList::Iter iter(reduced->maskElements()); iter.get(); iter.next()) {
add_elem_to_stack(*iter.get(), &reducedStack);
}
- SkIRect ibounds = reduced->hasIBounds() ? reduced->ibounds() : kIBounds;
+ SkIRect scissor = reduced->hasScissor() ? reduced->scissor() : kIBounds;
// GrReducedClipStack assumes that the final result is clipped to the returned bounds
- reducedStack.clipDevRect(ibounds, kIntersect_SkClipOp);
- stack.clipDevRect(ibounds, kIntersect_SkClipOp);
+ reducedStack.clipDevRect(scissor, kIntersect_SkClipOp);
+ stack.clipDevRect(scissor, kIntersect_SkClipOp);
// convert both the original stack and reduced stack to SkRegions and see if they're equal
SkRegion region;
- set_region_to_stack(stack, ibounds, &region);
+ set_region_to_stack(stack, scissor, &region);
SkRegion reducedRegion;
- set_region_to_stack(reducedStack, ibounds, &reducedRegion);
+ set_region_to_stack(reducedStack, scissor, &reducedRegion);
REPORTER_ASSERT_MESSAGE(reporter, region == reducedRegion, testCase.c_str());
@@ -1099,9 +1092,9 @@ static void test_reduced_clip_stack_genid(skiatest::Reporter* reporter) {
GR_STATIC_ASSERT(0 == SkClipStack::kInvalidGenID);
const GrReducedClip* reduced = new (storage.get()) GrReducedClip(stack, bounds);
- REPORTER_ASSERT(reporter, reduced->elements().count() == 1);
+ REPORTER_ASSERT(reporter, reduced->maskElements().count() == 1);
// Clips will be cached based on the generation id. Make sure the gen id is valid.
- REPORTER_ASSERT(reporter, SkClipStack::kInvalidGenID != reduced->elementsGenID());
+ REPORTER_ASSERT(reporter, SkClipStack::kInvalidGenID != reduced->maskGenID());
reduced->~GrReducedClip();
}
@@ -1151,7 +1144,7 @@ static void test_reduced_clip_stack_genid(skiatest::Reporter* reporter) {
// Rect A.
{ XYWH(0, 0, 25, 25), 0, SkClipStack::kInvalidGenID, GrReducedClip::InitialState::kAllIn, IXYWH(0, 0, 25, 25) },
{ XYWH(0.1f, 0.1f, 25.1f, 25.1f), 0, SkClipStack::kInvalidGenID, GrReducedClip::InitialState::kAllIn, IXYWH(0, 0, 26, 26) },
- { XYWH(0, 0, 27, 27), 1, genIDA, GrReducedClip::InitialState::kAllOut, IXYWH(0, 0, 27, 27)},
+ { XYWH(0, 0, 27, 27), 1, genIDA, GrReducedClip::InitialState::kAllOut, IXYWH(0, 0, 26, 26)},
// Rect B.
{ XYWH(50, 0, 25, 25), 0, SkClipStack::kInvalidGenID, GrReducedClip::InitialState::kAllIn, IXYWH(50, 0, 25, 25) },
@@ -1183,18 +1176,19 @@ static void test_reduced_clip_stack_genid(skiatest::Reporter* reporter) {
for (size_t i = 0; i < SK_ARRAY_COUNT(testCases); ++i) {
const GrReducedClip reduced(stack, testCases[i].testBounds);
- REPORTER_ASSERT(reporter, reduced.elements().count() == testCases[i].reducedClipCount);
- SkASSERT(reduced.elements().count() == testCases[i].reducedClipCount);
- if (reduced.elements().count()) {
- REPORTER_ASSERT(reporter, reduced.elementsGenID() == testCases[i].reducedGenID);
- SkASSERT(reduced.elementsGenID() == testCases[i].reducedGenID);
+ REPORTER_ASSERT(reporter, reduced.maskElements().count() ==
+ testCases[i].reducedClipCount);
+ SkASSERT(reduced.maskElements().count() == testCases[i].reducedClipCount);
+ if (reduced.maskElements().count()) {
+ REPORTER_ASSERT(reporter, reduced.maskGenID() == testCases[i].reducedGenID);
+ SkASSERT(reduced.maskGenID() == testCases[i].reducedGenID);
}
REPORTER_ASSERT(reporter, reduced.initialState() == testCases[i].initialState);
SkASSERT(reduced.initialState() == testCases[i].initialState);
- REPORTER_ASSERT(reporter, reduced.hasIBounds());
- SkASSERT(reduced.hasIBounds());
- REPORTER_ASSERT(reporter, reduced.ibounds() == testCases[i].clipIRect);
- SkASSERT(reduced.ibounds() == testCases[i].clipIRect);
+ REPORTER_ASSERT(reporter, reduced.hasScissor());
+ SkASSERT(reduced.hasScissor());
+ REPORTER_ASSERT(reporter, reduced.scissor() == testCases[i].clipIRect);
+ SkASSERT(reduced.scissor() == testCases[i].clipIRect);
}
}
}
@@ -1207,7 +1201,7 @@ static void test_reduced_clip_stack_no_aa_crash(skiatest::Reporter* reporter) {
// At the time, this would crash.
const GrReducedClip reduced(stack, bounds);
- REPORTER_ASSERT(reporter, reduced.elements().isEmpty());
+ REPORTER_ASSERT(reporter, reduced.maskElements().isEmpty());
}
enum class ClipMethod {
@@ -1232,7 +1226,8 @@ static void test_aa_query(skiatest::Reporter* reporter, const SkString& testName
switch (expectedMethod) {
case ClipMethod::kSkipDraw:
SkASSERT(0 == numExpectedElems);
- REPORTER_ASSERT_MESSAGE(reporter, reduced.elements().isEmpty(), testName.c_str());
+ REPORTER_ASSERT_MESSAGE(reporter,
+ reduced.maskElements().isEmpty(), testName.c_str());
REPORTER_ASSERT_MESSAGE(reporter,
GrReducedClip::InitialState::kAllOut == reduced.initialState(),
testName.c_str());
@@ -1240,10 +1235,10 @@ static void test_aa_query(skiatest::Reporter* reporter, const SkString& testName
case ClipMethod::kIgnoreClip:
SkASSERT(0 == numExpectedElems);
REPORTER_ASSERT_MESSAGE(reporter,
- !reduced.hasIBounds() ||
- GrClip::IsInsideClip(reduced.ibounds(), queryBounds),
+ !reduced.hasScissor() ||
+ GrClip::IsInsideClip(reduced.scissor(), queryBounds),
testName.c_str());
- REPORTER_ASSERT_MESSAGE(reporter, reduced.elements().isEmpty(), testName.c_str());
+ REPORTER_ASSERT_MESSAGE(reporter, reduced.maskElements().isEmpty(), testName.c_str());
REPORTER_ASSERT_MESSAGE(reporter,
GrReducedClip::InitialState::kAllIn == reduced.initialState(),
testName.c_str());
@@ -1253,9 +1248,9 @@ static void test_aa_query(skiatest::Reporter* reporter, const SkString& testName
SkASSERT(0 == numExpectedElems);
SkIRect expectedScissor;
stackBounds.round(&expectedScissor);
- REPORTER_ASSERT_MESSAGE(reporter, reduced.elements().isEmpty(), testName.c_str());
- REPORTER_ASSERT_MESSAGE(reporter, reduced.hasIBounds(), testName.c_str());
- REPORTER_ASSERT_MESSAGE(reporter, expectedScissor == reduced.ibounds(),
+ REPORTER_ASSERT_MESSAGE(reporter, reduced.maskElements().isEmpty(), testName.c_str());
+ REPORTER_ASSERT_MESSAGE(reporter, reduced.hasScissor(), testName.c_str());
+ REPORTER_ASSERT_MESSAGE(reporter, expectedScissor == reduced.scissor(),
testName.c_str());
REPORTER_ASSERT_MESSAGE(reporter,
GrReducedClip::InitialState::kAllIn == reduced.initialState(),
@@ -1267,12 +1262,13 @@ static void test_aa_query(skiatest::Reporter* reporter, const SkString& testName
if (SkClipStack::kNormal_BoundsType == stackBoundsType) {
SkAssertResult(expectedClipIBounds.intersect(GrClip::GetPixelIBounds(stackBounds)));
}
- REPORTER_ASSERT_MESSAGE(reporter, numExpectedElems == reduced.elements().count(),
+ REPORTER_ASSERT_MESSAGE(reporter, numExpectedElems == reduced.maskElements().count(),
testName.c_str());
- REPORTER_ASSERT_MESSAGE(reporter, reduced.hasIBounds(), testName.c_str());
- REPORTER_ASSERT_MESSAGE(reporter, expectedClipIBounds == reduced.ibounds(),
+ REPORTER_ASSERT_MESSAGE(reporter, reduced.hasScissor(), testName.c_str());
+ REPORTER_ASSERT_MESSAGE(reporter, expectedClipIBounds == reduced.scissor(),
testName.c_str());
- REPORTER_ASSERT_MESSAGE(reporter, reduced.requiresAA() == !reduced.elements().isEmpty(),
+ REPORTER_ASSERT_MESSAGE(reporter,
+ reduced.maskElements().isEmpty() || reduced.maskRequiresAA(),
testName.c_str());
break;
}
@@ -1387,8 +1383,8 @@ static void test_tiny_query_bounds_assertion_bug(skiatest::Reporter* reporter) {
SkRect::MakeXYWH(53, 160, 1000, GrClip::kBoundsTolerance),
SkRect::MakeXYWH(53, 160, 1000, GrClip::kBoundsTolerance/2)}) {
const GrReducedClip reduced(stack, queryBounds);
- REPORTER_ASSERT(reporter, !reduced.hasIBounds());
- REPORTER_ASSERT(reporter, reduced.elements().isEmpty());
+ REPORTER_ASSERT(reporter, !reduced.hasScissor());
+ REPORTER_ASSERT(reporter, reduced.maskElements().isEmpty());
REPORTER_ASSERT(reporter,
GrReducedClip::InitialState::kAllOut == reduced.initialState());
}