diff options
author | Brian Salomon <bsalomon@google.com> | 2017-12-05 10:35:15 -0500 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-12-05 15:56:01 +0000 |
commit | 1447177005fcbac83acd501766a46c751a49ae73 (patch) | |
tree | ed20f7b0984a3a0f01e0d46465c4fda98bb49802 | |
parent | bb4b20a265a78b561c005aaf80920d4bc9c2e7d0 (diff) |
Avoid GrEllipseEffect for small radii on devices without 32 bit float.
Also limit small radius bail in GrCircleEffect to clip out cases.
Change-Id: I14ce736969b05203219d68f30283c36c84f78f3a
Reviewed-on: https://skia-review.googlesource.com/80621
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
-rw-r--r-- | gm/bigrrectaaeffect.cpp | 3 | ||||
-rw-r--r-- | gm/rrects.cpp | 3 | ||||
-rw-r--r-- | gm/windowrectangles.cpp | 3 | ||||
-rw-r--r-- | src/gpu/GrClipStackClip.cpp | 5 | ||||
-rw-r--r-- | src/gpu/GrReducedClip.cpp | 18 | ||||
-rw-r--r-- | src/gpu/GrReducedClip.h | 3 | ||||
-rw-r--r-- | src/gpu/GrRenderTargetContext.cpp | 5 | ||||
-rw-r--r-- | src/gpu/effects/GrCircleEffect.fp | 2 | ||||
-rw-r--r-- | src/gpu/effects/GrCircleEffect.h | 2 | ||||
-rw-r--r-- | src/gpu/effects/GrEllipseEffect.cpp | 3 | ||||
-rw-r--r-- | src/gpu/effects/GrEllipseEffect.fp | 18 | ||||
-rw-r--r-- | src/gpu/effects/GrEllipseEffect.h | 9 | ||||
-rw-r--r-- | src/gpu/effects/GrOvalEffect.cpp | 6 | ||||
-rw-r--r-- | src/gpu/effects/GrOvalEffect.h | 4 | ||||
-rw-r--r-- | src/gpu/effects/GrRRectEffect.cpp | 9 | ||||
-rw-r--r-- | src/gpu/effects/GrRRectEffect.h | 4 | ||||
-rw-r--r-- | tests/ClipStackTest.cpp | 29 |
17 files changed, 88 insertions, 38 deletions
diff --git a/gm/bigrrectaaeffect.cpp b/gm/bigrrectaaeffect.cpp index 62c9da8b30..a5d77fc248 100644 --- a/gm/bigrrectaaeffect.cpp +++ b/gm/bigrrectaaeffect.cpp @@ -77,7 +77,8 @@ protected: SkRRect rrect = fRRect; rrect.offset(SkIntToScalar(x + kGap), SkIntToScalar(y + kGap)); - std::unique_ptr<GrFragmentProcessor> fp(GrRRectEffect::Make(edgeType, rrect)); + const auto& caps = *renderTargetContext->caps()->shaderCaps(); + auto fp = GrRRectEffect::Make(edgeType, rrect, caps); SkASSERT(fp); if (fp) { GrPaint grPaint; diff --git a/gm/rrects.cpp b/gm/rrects.cpp index 217e528e2b..dfeebf3dd8 100644 --- a/gm/rrects.cpp +++ b/gm/rrects.cpp @@ -106,7 +106,8 @@ protected: SkRRect rrect = fRRects[curRRect]; rrect.offset(SkIntToScalar(x), SkIntToScalar(y)); GrClipEdgeType edgeType = (GrClipEdgeType) et; - auto fp = GrRRectEffect::Make(edgeType, rrect); + const auto& caps = *renderTargetContext->caps()->shaderCaps(); + auto fp = GrRRectEffect::Make(edgeType, rrect, caps); if (fp) { GrPaint grPaint; grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc)); diff --git a/gm/windowrectangles.cpp b/gm/windowrectangles.cpp index 6a3f2a1eb0..a2c8f0bc10 100644 --- a/gm/windowrectangles.cpp +++ b/gm/windowrectangles.cpp @@ -181,7 +181,8 @@ void WindowRectanglesMaskGM::onCoverClipStack(const SkClipStack& stack, SkCanvas return; } - const GrReducedClip reducedClip(stack, SkRect::Make(kCoverRect), kNumWindows); + const GrReducedClip reducedClip(stack, SkRect::Make(kCoverRect), rtc->caps()->shaderCaps(), + kNumWindows); GrPaint paint; if (GrFSAAType::kNone == rtc->fsaaType()) { diff --git a/src/gpu/GrClipStackClip.cpp b/src/gpu/GrClipStackClip.cpp index 684a52d216..bd6ed9afed 100644 --- a/src/gpu/GrClipStackClip.cpp +++ b/src/gpu/GrClipStackClip.cpp @@ -201,8 +201,9 @@ bool GrClipStackClip::apply(GrContext* context, GrRenderTargetContext* renderTar SkASSERT(!context->caps()->avoidStencilBuffers()); // We disable MSAA when avoiding stencil. } - GrReducedClip reducedClip(*fStack, devBounds, renderTargetContext->priv().maxWindowRectangles(), - maxAnalyticFPs); + const auto* caps = context->caps()->shaderCaps(); + GrReducedClip reducedClip(*fStack, devBounds, caps, + renderTargetContext->priv().maxWindowRectangles(), maxAnalyticFPs); if (reducedClip.hasScissor() && !GrClip::IsInsideClip(reducedClip.scissor(), devBounds)) { out->hardClip().addScissor(reducedClip.scissor(), bounds); diff --git a/src/gpu/GrReducedClip.cpp b/src/gpu/GrReducedClip.cpp index 883ed5d956..f481a10b1c 100644 --- a/src/gpu/GrReducedClip.cpp +++ b/src/gpu/GrReducedClip.cpp @@ -32,9 +32,8 @@ * take a rect in case the caller knows a bound on what is to be drawn through this clip. */ GrReducedClip::GrReducedClip(const SkClipStack& stack, const SkRect& queryBounds, - int maxWindowRectangles, int maxAnalyticFPs) - : fMaxWindowRectangles(maxWindowRectangles) - , fMaxAnalyticFPs(maxAnalyticFPs) { + const GrShaderCaps* caps, int maxWindowRectangles, int maxAnalyticFPs) + : fCaps(caps), fMaxWindowRectangles(maxWindowRectangles), fMaxAnalyticFPs(maxAnalyticFPs) { SkASSERT(!queryBounds.isEmpty()); SkASSERT(fMaxWindowRectangles <= GrWindowRectangles::kMaxWindows); fHasScissor = false; @@ -588,7 +587,7 @@ inline GrReducedClip::ClipResult GrReducedClip::addAnalyticFP(const T& deviceSpa : GrClipEdgeType::kInverseFillBW; } - if (auto fp = make_analytic_clip_fp(edgeType, deviceSpaceShape)) { + if (auto fp = make_analytic_clip_fp(edgeType, deviceSpaceShape, *fCaps)) { fAnalyticFPs.push_back(std::move(fp)); return ClipResult::kClipped; } @@ -597,17 +596,20 @@ inline GrReducedClip::ClipResult GrReducedClip::addAnalyticFP(const T& deviceSpa } std::unique_ptr<GrFragmentProcessor> make_analytic_clip_fp(GrClipEdgeType edgeType, - const SkRect& deviceSpaceRect) { + const SkRect& deviceSpaceRect, + const GrShaderCaps&) { return GrConvexPolyEffect::Make(edgeType, deviceSpaceRect); } std::unique_ptr<GrFragmentProcessor> make_analytic_clip_fp(GrClipEdgeType edgeType, - const SkRRect& deviceSpaceRRect) { - return GrRRectEffect::Make(edgeType, deviceSpaceRRect); + const SkRRect& deviceSpaceRRect, + const GrShaderCaps& caps) { + return GrRRectEffect::Make(edgeType, deviceSpaceRRect, caps); } std::unique_ptr<GrFragmentProcessor> make_analytic_clip_fp(GrClipEdgeType edgeType, - const SkPath& deviceSpacePath) { + const SkPath& deviceSpacePath, + const GrShaderCaps&) { return GrConvexPolyEffect::Make(edgeType, deviceSpacePath); } diff --git a/src/gpu/GrReducedClip.h b/src/gpu/GrReducedClip.h index 22387d7962..0922d9126f 100644 --- a/src/gpu/GrReducedClip.h +++ b/src/gpu/GrReducedClip.h @@ -25,7 +25,7 @@ public: using Element = SkClipStack::Element; using ElementList = SkTLList<SkClipStack::Element, 16>; - GrReducedClip(const SkClipStack&, const SkRect& queryBounds, + GrReducedClip(const SkClipStack&, const SkRect& queryBounds, const GrShaderCaps* caps, int maxWindowRectangles = 0, int maxAnalyticFPs = 0); /** @@ -117,6 +117,7 @@ private: void makeEmpty(); + const GrShaderCaps* fCaps; const int fMaxWindowRectangles; const int fMaxAnalyticFPs; SkIRect fScissor; diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp index c9cc3957a4..1f7f6458ae 100644 --- a/src/gpu/GrRenderTargetContext.cpp +++ b/src/gpu/GrRenderTargetContext.cpp @@ -1276,13 +1276,14 @@ bool GrRenderTargetContext::drawFilledDRRect(const GrClip& clip, inverseVM.reset(); } + const auto& caps = *this->caps()->shaderCaps(); // TODO these need to be a geometry processors - std::unique_ptr<GrFragmentProcessor> innerEffect(GrRRectEffect::Make(innerEdgeType, *inner)); + auto innerEffect = GrRRectEffect::Make(innerEdgeType, *inner, caps); if (!innerEffect) { return false; } - std::unique_ptr<GrFragmentProcessor> outerEffect(GrRRectEffect::Make(outerEdgeType, *outer)); + auto outerEffect = GrRRectEffect::Make(outerEdgeType, *outer, caps); if (!outerEffect) { return false; } diff --git a/src/gpu/effects/GrCircleEffect.fp b/src/gpu/effects/GrCircleEffect.fp index 352e824b54..0faf7d74bc 100644 --- a/src/gpu/effects/GrCircleEffect.fp +++ b/src/gpu/effects/GrCircleEffect.fp @@ -20,7 +20,7 @@ uniform half4 circle; float radius) { // A radius below half causes the implicit insetting done by this processor to become // inverted. We could handle this case by making the processor code more complicated. - if (radius < .5f) { + if (radius < .5f && GrProcessorEdgeTypeIsInverseFill(edgeType)) { return nullptr; } return std::unique_ptr<GrFragmentProcessor>(new GrCircleEffect(edgeType, center, radius)); diff --git a/src/gpu/effects/GrCircleEffect.h b/src/gpu/effects/GrCircleEffect.h index d721a78241..cfc5aaf411 100644 --- a/src/gpu/effects/GrCircleEffect.h +++ b/src/gpu/effects/GrCircleEffect.h @@ -24,7 +24,7 @@ public: float radius) { // A radius below half causes the implicit insetting done by this processor to become // inverted. We could handle this case by making the processor code more complicated. - if (radius < .5f) { + if (radius < .5f && GrProcessorEdgeTypeIsInverseFill(edgeType)) { return nullptr; } return std::unique_ptr<GrFragmentProcessor>(new GrCircleEffect(edgeType, center, radius)); diff --git a/src/gpu/effects/GrEllipseEffect.cpp b/src/gpu/effects/GrEllipseEffect.cpp index b41af395d4..88a07f9bed 100644 --- a/src/gpu/effects/GrEllipseEffect.cpp +++ b/src/gpu/effects/GrEllipseEffect.cpp @@ -139,7 +139,8 @@ std::unique_ptr<GrFragmentProcessor> GrEllipseEffect::TestCreate(GrProcessorTest do { et = (GrClipEdgeType)testData->fRandom->nextULessThan(kGrClipEdgeTypeCnt); } while (GrClipEdgeType::kHairlineAA == et); - return GrEllipseEffect::Make(et, center, SkPoint::Make(rx, ry)); + return GrEllipseEffect::Make(et, center, SkPoint::Make(rx, ry), + *testData->caps()->shaderCaps()); } #endif #endif diff --git a/src/gpu/effects/GrEllipseEffect.fp b/src/gpu/effects/GrEllipseEffect.fp index 27beb85d2f..24cbec2c72 100644 --- a/src/gpu/effects/GrEllipseEffect.fp +++ b/src/gpu/effects/GrEllipseEffect.fp @@ -5,6 +5,10 @@ * found in the LICENSE file. */ +@header { + #include "GrShaderCaps.h" +} + layout(key) in GrClipEdgeType edgeType; in float2 center; in float2 radii; @@ -18,6 +22,17 @@ uniform float4 ellipse; bool useScale = !sk_Caps.floatIs32Bits; layout(when=useScale) uniform float2 scale; +@make { + static std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType edgeType, SkPoint center, + SkPoint radii, const GrShaderCaps& caps) { + // Small radii produce bad results on devices without full float. + if (!caps.floatIs32Bits() && (radii.fX < 0.5f || radii.fY < 0.5f)) { + return nullptr; + } + return std::unique_ptr<GrFragmentProcessor>(new GrEllipseEffect(edgeType, center, radii)); + } +} + @optimizationFlags { kCompatibleWithCoverageAsAlpha_OptimizationFlag } @setData(pdman) { @@ -101,5 +116,6 @@ void main() { do { et = (GrClipEdgeType) testData->fRandom->nextULessThan(kGrClipEdgeTypeCnt); } while (GrClipEdgeType::kHairlineAA == et); - return GrEllipseEffect::Make(et, center, SkPoint::Make(rx, ry)); + return GrEllipseEffect::Make(et, center, SkPoint::Make(rx, ry), + *testData->caps()->shaderCaps()); } diff --git a/src/gpu/effects/GrEllipseEffect.h b/src/gpu/effects/GrEllipseEffect.h index 8769295ef0..b892f98a56 100644 --- a/src/gpu/effects/GrEllipseEffect.h +++ b/src/gpu/effects/GrEllipseEffect.h @@ -12,6 +12,8 @@ #define GrEllipseEffect_DEFINED #include "SkTypes.h" #if SK_SUPPORT_GPU + +#include "GrShaderCaps.h" #include "GrFragmentProcessor.h" #include "GrCoordTransform.h" class GrEllipseEffect : public GrFragmentProcessor { @@ -19,8 +21,13 @@ public: GrClipEdgeType edgeType() const { return fEdgeType; } SkPoint center() const { return fCenter; } SkPoint radii() const { return fRadii; } + static std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType edgeType, SkPoint center, - SkPoint radii) { + SkPoint radii, const GrShaderCaps& caps) { + // Small radii produce bad results on devices without full float. + if (!caps.floatIs32Bits() && (radii.fX < 0.5f || radii.fY < 0.5f)) { + return nullptr; + } return std::unique_ptr<GrFragmentProcessor>(new GrEllipseEffect(edgeType, center, radii)); } GrEllipseEffect(const GrEllipseEffect& src); diff --git a/src/gpu/effects/GrOvalEffect.cpp b/src/gpu/effects/GrOvalEffect.cpp index 0c0f3bde5c..a475ec02df 100644 --- a/src/gpu/effects/GrOvalEffect.cpp +++ b/src/gpu/effects/GrOvalEffect.cpp @@ -11,8 +11,8 @@ #include "GrEllipseEffect.h" #include "SkRect.h" -std::unique_ptr<GrFragmentProcessor> GrOvalEffect::Make(GrClipEdgeType edgeType, - const SkRect& oval) { +std::unique_ptr<GrFragmentProcessor> GrOvalEffect::Make(GrClipEdgeType edgeType, const SkRect& oval, + const GrShaderCaps& caps) { if (GrClipEdgeType::kHairlineAA == edgeType) { return nullptr; } @@ -26,7 +26,7 @@ std::unique_ptr<GrFragmentProcessor> GrOvalEffect::Make(GrClipEdgeType edgeType, w /= 2; h /= 2; return GrEllipseEffect::Make(edgeType, SkPoint::Make(oval.fLeft + w, oval.fTop + h), - SkPoint::Make(w, h)); + SkPoint::Make(w, h), caps); } return nullptr; diff --git a/src/gpu/effects/GrOvalEffect.h b/src/gpu/effects/GrOvalEffect.h index f85df89459..c102a0bca2 100644 --- a/src/gpu/effects/GrOvalEffect.h +++ b/src/gpu/effects/GrOvalEffect.h @@ -13,6 +13,7 @@ #include "SkRefCnt.h" class GrFragmentProcessor; +class GrShaderCaps; struct SkRect; namespace GrOvalEffect { @@ -20,8 +21,7 @@ namespace GrOvalEffect { /** * Creates an effect that performs clipping against an oval. */ -std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType, const SkRect&); - +std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType, const SkRect&, const GrShaderCaps&); }; #endif diff --git a/src/gpu/effects/GrRRectEffect.cpp b/src/gpu/effects/GrRRectEffect.cpp index 510a26b425..871578f924 100644 --- a/src/gpu/effects/GrRRectEffect.cpp +++ b/src/gpu/effects/GrRRectEffect.cpp @@ -122,7 +122,7 @@ std::unique_ptr<GrFragmentProcessor> CircularRRectEffect::TestCreate(GrProcessor do { GrClipEdgeType et = (GrClipEdgeType)d->fRandom->nextULessThan(kGrClipEdgeTypeCnt); - fp = GrRRectEffect::Make(et, rrect); + fp = GrRRectEffect::Make(et, rrect, *d->caps()->shaderCaps()); } while (nullptr == fp); return fp; } @@ -473,7 +473,7 @@ std::unique_ptr<GrFragmentProcessor> EllipticalRRectEffect::TestCreate(GrProcess std::unique_ptr<GrFragmentProcessor> fp; do { GrClipEdgeType et = (GrClipEdgeType)d->fRandom->nextULessThan(kGrClipEdgeTypeCnt); - fp = GrRRectEffect::Make(et, rrect); + fp = GrRRectEffect::Make(et, rrect, *d->caps()->shaderCaps()); } while (nullptr == fp); return fp; } @@ -673,13 +673,14 @@ GrGLSLFragmentProcessor* EllipticalRRectEffect::onCreateGLSLInstance() const { ////////////////////////////////////////////////////////////////////////////// std::unique_ptr<GrFragmentProcessor> GrRRectEffect::Make(GrClipEdgeType edgeType, - const SkRRect& rrect) { + const SkRRect& rrect, + const GrShaderCaps& caps) { if (rrect.isRect()) { return GrConvexPolyEffect::Make(edgeType, rrect.getBounds()); } if (rrect.isOval()) { - return GrOvalEffect::Make(edgeType, rrect.getBounds()); + return GrOvalEffect::Make(edgeType, rrect.getBounds(), caps); } if (rrect.isSimple()) { diff --git a/src/gpu/effects/GrRRectEffect.h b/src/gpu/effects/GrRRectEffect.h index e9c593c53e..55ef5353b4 100644 --- a/src/gpu/effects/GrRRectEffect.h +++ b/src/gpu/effects/GrRRectEffect.h @@ -13,6 +13,7 @@ #include "SkRefCnt.h" class GrFragmentProcessor; +class GrShaderCaps; class GrProcessor; class SkRRect; @@ -22,8 +23,7 @@ namespace GrRRectEffect { * Creates an effect that performs anti-aliased clipping against a SkRRect. It doesn't support * all varieties of SkRRect so the caller must check for a nullptr return. */ -std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType, const SkRRect&); - +std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType, const SkRRect&, const GrShaderCaps&); }; #endif diff --git a/tests/ClipStackTest.cpp b/tests/ClipStackTest.cpp index 554362372d..fe24bc14e6 100644 --- a/tests/ClipStackTest.cpp +++ b/tests/ClipStackTest.cpp @@ -1019,6 +1019,9 @@ static void test_reduced_clip_stack(skiatest::Reporter* reporter) { } } + auto context = GrContext::MakeMock(nullptr); + const auto* caps = context->caps()->shaderCaps(); + // Zero the memory we will new the GrReducedClip into. This ensures the elements gen ID // will be kInvalidGenID if left uninitialized. SkAlignedSTStorage<1, GrReducedClip> storage; @@ -1028,7 +1031,7 @@ static void test_reduced_clip_stack(skiatest::Reporter* reporter) { // Get the reduced version of the stack. SkRect queryBounds = kBounds; queryBounds.outset(kBounds.width() / 2, kBounds.height() / 2); - const GrReducedClip* reduced = new (storage.get()) GrReducedClip(stack, queryBounds); + const GrReducedClip* reduced = new (storage.get()) GrReducedClip(stack, queryBounds, caps); REPORTER_ASSERT_MESSAGE(reporter, reduced->maskElements().isEmpty() || @@ -1087,10 +1090,13 @@ static void test_reduced_clip_stack_genid(skiatest::Reporter* reporter) { kReplace_SkClipOp, true); SkRect bounds = SkRect::MakeXYWH(0, 0, 100, 100); + auto context = GrContext::MakeMock(nullptr); + const auto* caps = context->caps()->shaderCaps(); + SkAlignedSTStorage<1, GrReducedClip> storage; memset(storage.get(), 0, sizeof(GrReducedClip)); GR_STATIC_ASSERT(0 == SkClipStack::kInvalidGenID); - const GrReducedClip* reduced = new (storage.get()) GrReducedClip(stack, bounds); + const GrReducedClip* reduced = new (storage.get()) GrReducedClip(stack, bounds, caps); REPORTER_ASSERT(reporter, reduced->maskElements().count() == 1); // Clips will be cached based on the generation id. Make sure the gen id is valid. @@ -1173,9 +1179,11 @@ static void test_reduced_clip_stack_genid(skiatest::Reporter* reporter) { #undef XYWH #undef IXYWH + auto context = GrContext::MakeMock(nullptr); + const auto* caps = context->caps()->shaderCaps(); for (size_t i = 0; i < SK_ARRAY_COUNT(testCases); ++i) { - const GrReducedClip reduced(stack, testCases[i].testBounds); + const GrReducedClip reduced(stack, testCases[i].testBounds, caps); REPORTER_ASSERT(reporter, reduced.maskElements().count() == testCases[i].reducedClipCount); SkASSERT(reduced.maskElements().count() == testCases[i].reducedClipCount); @@ -1199,8 +1207,11 @@ static void test_reduced_clip_stack_no_aa_crash(skiatest::Reporter* reporter) { stack.clipDevRect(SkIRect::MakeXYWH(0, 0, 50, 50), kReplace_SkClipOp); SkRect bounds = SkRect::MakeXYWH(0, 0, 100, 100); + auto context = GrContext::MakeMock(nullptr); + const auto* caps = context->caps()->shaderCaps(); + // At the time, this would crash. - const GrReducedClip reduced(stack, bounds); + const GrReducedClip reduced(stack, bounds, caps); REPORTER_ASSERT(reporter, reduced.maskElements().isEmpty()); } @@ -1215,9 +1226,12 @@ static void test_aa_query(skiatest::Reporter* reporter, const SkString& testName const SkClipStack& stack, const SkMatrix& queryXform, const SkRect& preXformQuery, ClipMethod expectedMethod, int numExpectedElems = 0) { + auto context = GrContext::MakeMock(nullptr); + const auto* caps = context->caps()->shaderCaps(); + SkRect queryBounds; queryXform.mapRect(&queryBounds, preXformQuery); - const GrReducedClip reduced(stack, queryBounds); + const GrReducedClip reduced(stack, queryBounds, caps); SkClipStack::BoundsType stackBoundsType; SkRect stackBounds; @@ -1377,12 +1391,15 @@ static void test_tiny_query_bounds_assertion_bug(skiatest::Reporter* reporter) { SkClipStack pathStack; pathStack.clipPath(clipPath, SkMatrix::I(), kIntersect_SkClipOp, true); + auto context = GrContext::MakeMock(nullptr); + const auto* caps = context->caps()->shaderCaps(); + for (const SkClipStack& stack : {rectStack, pathStack}) { for (SkRect queryBounds : {SkRect::MakeXYWH(53, 60, GrClip::kBoundsTolerance, 1000), SkRect::MakeXYWH(53, 60, GrClip::kBoundsTolerance/2, 1000), SkRect::MakeXYWH(53, 160, 1000, GrClip::kBoundsTolerance), SkRect::MakeXYWH(53, 160, 1000, GrClip::kBoundsTolerance/2)}) { - const GrReducedClip reduced(stack, queryBounds); + const GrReducedClip reduced(stack, queryBounds, caps); REPORTER_ASSERT(reporter, !reduced.hasScissor()); REPORTER_ASSERT(reporter, reduced.maskElements().isEmpty()); REPORTER_ASSERT(reporter, |