1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2020 Google LLC
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/StencilMaskHelper.h"
9*c8dee2aaSAndroid Build Coastguard Worker
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkMatrix.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPath.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRegion.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrRecordingContext.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkAssert.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/gpu/ganesh/GrTypesPriv.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkTLazy.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrClip.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrDrawingManager.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrFixedClip.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrPaint.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrRecordingContextPriv.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrStencilSettings.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrStyle.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrUserStencilSettings.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrWindowRectangles.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrWindowRectsState.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/PathRenderer.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/PathRendererChain.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/SurfaceDrawContext.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/effects/GrDisableColorXP.h"
32*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/geometry/GrShape.h"
33*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/geometry/GrStyledShape.h"
34*c8dee2aaSAndroid Build Coastguard Worker
35*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
36*c8dee2aaSAndroid Build Coastguard Worker
37*c8dee2aaSAndroid Build Coastguard Worker namespace {
38*c8dee2aaSAndroid Build Coastguard Worker
39*c8dee2aaSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
40*c8dee2aaSAndroid Build Coastguard Worker // Stencil Rules for Merging user stencil space into clip
41*c8dee2aaSAndroid Build Coastguard Worker //
42*c8dee2aaSAndroid Build Coastguard Worker
43*c8dee2aaSAndroid Build Coastguard Worker ///////
44*c8dee2aaSAndroid Build Coastguard Worker // Replace
45*c8dee2aaSAndroid Build Coastguard Worker static constexpr GrUserStencilSettings gUserToClipReplace(
46*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilSettings::StaticInit<
47*c8dee2aaSAndroid Build Coastguard Worker 0x0000,
48*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilTest::kNotEqual,
49*c8dee2aaSAndroid Build Coastguard Worker 0xffff,
50*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp::kSetClipAndReplaceUserBits,
51*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp::kZeroClipAndUserBits,
52*c8dee2aaSAndroid Build Coastguard Worker 0xffff>()
53*c8dee2aaSAndroid Build Coastguard Worker );
54*c8dee2aaSAndroid Build Coastguard Worker
55*c8dee2aaSAndroid Build Coastguard Worker static constexpr GrUserStencilSettings gInvUserToClipReplace(
56*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilSettings::StaticInit<
57*c8dee2aaSAndroid Build Coastguard Worker 0x0000,
58*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilTest::kEqual,
59*c8dee2aaSAndroid Build Coastguard Worker 0xffff,
60*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp::kSetClipAndReplaceUserBits,
61*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp::kZeroClipAndUserBits,
62*c8dee2aaSAndroid Build Coastguard Worker 0xffff>()
63*c8dee2aaSAndroid Build Coastguard Worker );
64*c8dee2aaSAndroid Build Coastguard Worker
65*c8dee2aaSAndroid Build Coastguard Worker ///////
66*c8dee2aaSAndroid Build Coastguard Worker // Intersect
67*c8dee2aaSAndroid Build Coastguard Worker static constexpr GrUserStencilSettings gUserToClipIsect(
68*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilSettings::StaticInit<
69*c8dee2aaSAndroid Build Coastguard Worker 0x0000,
70*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilTest::kLessIfInClip, // "0 < userBits" is equivalent to "0 != userBits".
71*c8dee2aaSAndroid Build Coastguard Worker 0xffff,
72*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp::kSetClipAndReplaceUserBits,
73*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp::kZeroClipAndUserBits,
74*c8dee2aaSAndroid Build Coastguard Worker 0xffff>()
75*c8dee2aaSAndroid Build Coastguard Worker );
76*c8dee2aaSAndroid Build Coastguard Worker
77*c8dee2aaSAndroid Build Coastguard Worker ///////
78*c8dee2aaSAndroid Build Coastguard Worker // Difference
79*c8dee2aaSAndroid Build Coastguard Worker static constexpr GrUserStencilSettings gUserToClipDiff(
80*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilSettings::StaticInit<
81*c8dee2aaSAndroid Build Coastguard Worker 0x0000,
82*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilTest::kEqualIfInClip,
83*c8dee2aaSAndroid Build Coastguard Worker 0xffff,
84*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp::kSetClipAndReplaceUserBits,
85*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp::kZeroClipAndUserBits,
86*c8dee2aaSAndroid Build Coastguard Worker 0xffff>()
87*c8dee2aaSAndroid Build Coastguard Worker );
88*c8dee2aaSAndroid Build Coastguard Worker
89*c8dee2aaSAndroid Build Coastguard Worker ///////
90*c8dee2aaSAndroid Build Coastguard Worker // Union
91*c8dee2aaSAndroid Build Coastguard Worker static constexpr GrUserStencilSettings gUserToClipUnion(
92*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilSettings::StaticInit<
93*c8dee2aaSAndroid Build Coastguard Worker 0x0000,
94*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilTest::kNotEqual,
95*c8dee2aaSAndroid Build Coastguard Worker 0xffff,
96*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp::kSetClipAndReplaceUserBits,
97*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp::kKeep,
98*c8dee2aaSAndroid Build Coastguard Worker 0xffff>()
99*c8dee2aaSAndroid Build Coastguard Worker );
100*c8dee2aaSAndroid Build Coastguard Worker
101*c8dee2aaSAndroid Build Coastguard Worker static constexpr GrUserStencilSettings gInvUserToClipUnionPass0( // Does not zero user bits.
102*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilSettings::StaticInit<
103*c8dee2aaSAndroid Build Coastguard Worker 0x0000,
104*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilTest::kEqual,
105*c8dee2aaSAndroid Build Coastguard Worker 0xffff,
106*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp::kSetClipBit,
107*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp::kKeep,
108*c8dee2aaSAndroid Build Coastguard Worker 0x0000>()
109*c8dee2aaSAndroid Build Coastguard Worker );
110*c8dee2aaSAndroid Build Coastguard Worker
111*c8dee2aaSAndroid Build Coastguard Worker ///////
112*c8dee2aaSAndroid Build Coastguard Worker // Xor
113*c8dee2aaSAndroid Build Coastguard Worker static constexpr GrUserStencilSettings gUserToClipXorPass0( // Does not zero user bits.
114*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilSettings::StaticInit<
115*c8dee2aaSAndroid Build Coastguard Worker 0x0000,
116*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilTest::kNotEqual,
117*c8dee2aaSAndroid Build Coastguard Worker 0xffff,
118*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp::kInvertClipBit,
119*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp::kKeep,
120*c8dee2aaSAndroid Build Coastguard Worker 0x0000>()
121*c8dee2aaSAndroid Build Coastguard Worker );
122*c8dee2aaSAndroid Build Coastguard Worker
123*c8dee2aaSAndroid Build Coastguard Worker static constexpr GrUserStencilSettings gInvUserToClipXorPass0( // Does not zero user bits.
124*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilSettings::StaticInit<
125*c8dee2aaSAndroid Build Coastguard Worker 0x0000,
126*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilTest::kEqual,
127*c8dee2aaSAndroid Build Coastguard Worker 0xffff,
128*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp::kInvertClipBit,
129*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp::kKeep,
130*c8dee2aaSAndroid Build Coastguard Worker 0x0000>()
131*c8dee2aaSAndroid Build Coastguard Worker );
132*c8dee2aaSAndroid Build Coastguard Worker
133*c8dee2aaSAndroid Build Coastguard Worker ///////
134*c8dee2aaSAndroid Build Coastguard Worker // Reverse Diff
135*c8dee2aaSAndroid Build Coastguard Worker static constexpr GrUserStencilSettings gUserToClipRDiffPass0( // Does not zero user bits.
136*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilSettings::StaticInit<
137*c8dee2aaSAndroid Build Coastguard Worker 0x0000,
138*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilTest::kNotEqual,
139*c8dee2aaSAndroid Build Coastguard Worker 0xffff,
140*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp::kInvertClipBit,
141*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp::kZeroClipBit,
142*c8dee2aaSAndroid Build Coastguard Worker 0x0000>()
143*c8dee2aaSAndroid Build Coastguard Worker );
144*c8dee2aaSAndroid Build Coastguard Worker
145*c8dee2aaSAndroid Build Coastguard Worker static constexpr GrUserStencilSettings gInvUserToClipRDiffPass0( // Does not zero user bits.
146*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilSettings::StaticInit<
147*c8dee2aaSAndroid Build Coastguard Worker 0x0000,
148*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilTest::kEqual,
149*c8dee2aaSAndroid Build Coastguard Worker 0xffff,
150*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp::kInvertClipBit,
151*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp::kZeroClipBit,
152*c8dee2aaSAndroid Build Coastguard Worker 0x0000>()
153*c8dee2aaSAndroid Build Coastguard Worker );
154*c8dee2aaSAndroid Build Coastguard Worker
155*c8dee2aaSAndroid Build Coastguard Worker ///////
156*c8dee2aaSAndroid Build Coastguard Worker // Second pass to clear user bits (only needed sometimes)
157*c8dee2aaSAndroid Build Coastguard Worker static constexpr GrUserStencilSettings gZeroUserBits(
158*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilSettings::StaticInit<
159*c8dee2aaSAndroid Build Coastguard Worker 0x0000,
160*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilTest::kNotEqual,
161*c8dee2aaSAndroid Build Coastguard Worker 0xffff,
162*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp::kZero,
163*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp::kKeep,
164*c8dee2aaSAndroid Build Coastguard Worker 0xffff>()
165*c8dee2aaSAndroid Build Coastguard Worker );
166*c8dee2aaSAndroid Build Coastguard Worker
167*c8dee2aaSAndroid Build Coastguard Worker static constexpr const GrUserStencilSettings* gUserToClipTable[2][1 + SkRegion::kLastOp][3] = {
168*c8dee2aaSAndroid Build Coastguard Worker { /* Normal fill. */
169*c8dee2aaSAndroid Build Coastguard Worker {&gUserToClipDiff, nullptr, nullptr}, // kDifference_Op.
170*c8dee2aaSAndroid Build Coastguard Worker {&gUserToClipIsect, nullptr, nullptr}, // kIntersect_Op.
171*c8dee2aaSAndroid Build Coastguard Worker {&gUserToClipUnion, nullptr, nullptr}, // kUnion_Op.
172*c8dee2aaSAndroid Build Coastguard Worker {&gUserToClipXorPass0, &gZeroUserBits, nullptr}, // kXOR_Op.
173*c8dee2aaSAndroid Build Coastguard Worker {&gUserToClipRDiffPass0, &gZeroUserBits, nullptr}, // kReverseDifference_Op.
174*c8dee2aaSAndroid Build Coastguard Worker {&gUserToClipReplace, nullptr, nullptr} // kReplace_Op.
175*c8dee2aaSAndroid Build Coastguard Worker
176*c8dee2aaSAndroid Build Coastguard Worker }, /* Inverse fill. */ {
177*c8dee2aaSAndroid Build Coastguard Worker {&gUserToClipIsect, nullptr, nullptr}, // ~diff (aka isect).
178*c8dee2aaSAndroid Build Coastguard Worker {&gUserToClipDiff, nullptr, nullptr}, // ~isect (aka diff).
179*c8dee2aaSAndroid Build Coastguard Worker {&gInvUserToClipUnionPass0, &gZeroUserBits, nullptr}, // ~union.
180*c8dee2aaSAndroid Build Coastguard Worker {&gInvUserToClipXorPass0, &gZeroUserBits, nullptr}, // ~xor.
181*c8dee2aaSAndroid Build Coastguard Worker {&gInvUserToClipRDiffPass0, &gZeroUserBits, nullptr}, // ~reverse diff.
182*c8dee2aaSAndroid Build Coastguard Worker {&gInvUserToClipReplace, nullptr, nullptr} // ~replace.
183*c8dee2aaSAndroid Build Coastguard Worker }
184*c8dee2aaSAndroid Build Coastguard Worker };
185*c8dee2aaSAndroid Build Coastguard Worker
186*c8dee2aaSAndroid Build Coastguard Worker ///////
187*c8dee2aaSAndroid Build Coastguard Worker // Direct to Stencil
188*c8dee2aaSAndroid Build Coastguard Worker
189*c8dee2aaSAndroid Build Coastguard Worker // We can render a clip element directly without first writing to the client
190*c8dee2aaSAndroid Build Coastguard Worker // portion of the clip when the fill is not inverse and the set operation will
191*c8dee2aaSAndroid Build Coastguard Worker // only modify the in/out status of samples covered by the clip element.
192*c8dee2aaSAndroid Build Coastguard Worker
193*c8dee2aaSAndroid Build Coastguard Worker // this one only works if used right after stencil clip was cleared.
194*c8dee2aaSAndroid Build Coastguard Worker // Our clip mask creation code doesn't allow midstream replace ops.
195*c8dee2aaSAndroid Build Coastguard Worker static constexpr GrUserStencilSettings gReplaceClip(
196*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilSettings::StaticInit<
197*c8dee2aaSAndroid Build Coastguard Worker 0x0000,
198*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilTest::kAlways,
199*c8dee2aaSAndroid Build Coastguard Worker 0xffff,
200*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp::kSetClipBit,
201*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp::kSetClipBit,
202*c8dee2aaSAndroid Build Coastguard Worker 0x0000>()
203*c8dee2aaSAndroid Build Coastguard Worker );
204*c8dee2aaSAndroid Build Coastguard Worker
205*c8dee2aaSAndroid Build Coastguard Worker static constexpr GrUserStencilSettings gUnionClip(
206*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilSettings::StaticInit<
207*c8dee2aaSAndroid Build Coastguard Worker 0x0000,
208*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilTest::kAlwaysIfInClip,
209*c8dee2aaSAndroid Build Coastguard Worker 0xffff,
210*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp::kKeep,
211*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp::kSetClipBit,
212*c8dee2aaSAndroid Build Coastguard Worker 0x0000>()
213*c8dee2aaSAndroid Build Coastguard Worker );
214*c8dee2aaSAndroid Build Coastguard Worker
215*c8dee2aaSAndroid Build Coastguard Worker static constexpr GrUserStencilSettings gXorClip(
216*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilSettings::StaticInit<
217*c8dee2aaSAndroid Build Coastguard Worker 0x0000,
218*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilTest::kAlways,
219*c8dee2aaSAndroid Build Coastguard Worker 0xffff,
220*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp::kInvertClipBit,
221*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp::kInvertClipBit,
222*c8dee2aaSAndroid Build Coastguard Worker 0x0000>()
223*c8dee2aaSAndroid Build Coastguard Worker );
224*c8dee2aaSAndroid Build Coastguard Worker
225*c8dee2aaSAndroid Build Coastguard Worker static constexpr GrUserStencilSettings gDiffClip(
226*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilSettings::StaticInit<
227*c8dee2aaSAndroid Build Coastguard Worker 0x0000,
228*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilTest::kAlwaysIfInClip,
229*c8dee2aaSAndroid Build Coastguard Worker 0xffff,
230*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp::kZeroClipBit,
231*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp::kKeep,
232*c8dee2aaSAndroid Build Coastguard Worker 0x0000>()
233*c8dee2aaSAndroid Build Coastguard Worker );
234*c8dee2aaSAndroid Build Coastguard Worker
235*c8dee2aaSAndroid Build Coastguard Worker static constexpr const GrUserStencilSettings* gDirectDrawTable[1 + SkRegion::kLastOp][2] = {
236*c8dee2aaSAndroid Build Coastguard Worker {&gDiffClip, nullptr}, // kDifference_Op.
237*c8dee2aaSAndroid Build Coastguard Worker {nullptr, nullptr}, // kIntersect_Op.
238*c8dee2aaSAndroid Build Coastguard Worker {&gUnionClip, nullptr}, // kUnion_Op.
239*c8dee2aaSAndroid Build Coastguard Worker {&gXorClip, nullptr}, // kXOR_Op.
240*c8dee2aaSAndroid Build Coastguard Worker {nullptr, nullptr}, // kReverseDifference_Op.
241*c8dee2aaSAndroid Build Coastguard Worker {&gReplaceClip, nullptr} // kReplace_Op.
242*c8dee2aaSAndroid Build Coastguard Worker };
243*c8dee2aaSAndroid Build Coastguard Worker
244*c8dee2aaSAndroid Build Coastguard Worker static_assert(0 == SkRegion::kDifference_Op);
245*c8dee2aaSAndroid Build Coastguard Worker static_assert(1 == SkRegion::kIntersect_Op);
246*c8dee2aaSAndroid Build Coastguard Worker static_assert(2 == SkRegion::kUnion_Op);
247*c8dee2aaSAndroid Build Coastguard Worker static_assert(3 == SkRegion::kXOR_Op);
248*c8dee2aaSAndroid Build Coastguard Worker static_assert(4 == SkRegion::kReverseDifference_Op);
249*c8dee2aaSAndroid Build Coastguard Worker static_assert(5 == SkRegion::kReplace_Op);
250*c8dee2aaSAndroid Build Coastguard Worker
251*c8dee2aaSAndroid Build Coastguard Worker // Settings used to when not allowed to draw directly to the clip to fill the user stencil bits
252*c8dee2aaSAndroid Build Coastguard Worker // before applying the covering clip stencil passes.
253*c8dee2aaSAndroid Build Coastguard Worker static constexpr GrUserStencilSettings gDrawToStencil(
254*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilSettings::StaticInit<
255*c8dee2aaSAndroid Build Coastguard Worker 0x0000,
256*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilTest::kAlways,
257*c8dee2aaSAndroid Build Coastguard Worker 0xffff,
258*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp::kIncMaybeClamp,
259*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp::kIncMaybeClamp,
260*c8dee2aaSAndroid Build Coastguard Worker 0xffff>()
261*c8dee2aaSAndroid Build Coastguard Worker );
262*c8dee2aaSAndroid Build Coastguard Worker
263*c8dee2aaSAndroid Build Coastguard Worker // Get the stencil settings per-pass to achieve the given fill+region op effect on the
264*c8dee2aaSAndroid Build Coastguard Worker // stencil buffer.
265*c8dee2aaSAndroid Build Coastguard Worker //
266*c8dee2aaSAndroid Build Coastguard Worker // If drawDirectToClip comes back false, the caller must first draw the element into the user
267*c8dee2aaSAndroid Build Coastguard Worker // stencil bits, and then cover the clip area with multiple passes using the returned
268*c8dee2aaSAndroid Build Coastguard Worker // stencil settings.
269*c8dee2aaSAndroid Build Coastguard Worker
270*c8dee2aaSAndroid Build Coastguard Worker // If drawDirectToClip is true, the returned array will only have one pass and the
271*c8dee2aaSAndroid Build Coastguard Worker // caller should use those stencil settings while drawing the element directly.
272*c8dee2aaSAndroid Build Coastguard Worker //
273*c8dee2aaSAndroid Build Coastguard Worker // This returns a null-terminated list of const GrUserStencilSettings*
get_stencil_passes(SkRegion::Op op,skgpu::ganesh::PathRenderer::StencilSupport stencilSupport,bool fillInverted,bool * drawDirectToClip)274*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilSettings const* const* get_stencil_passes(
275*c8dee2aaSAndroid Build Coastguard Worker SkRegion::Op op,
276*c8dee2aaSAndroid Build Coastguard Worker skgpu::ganesh::PathRenderer::StencilSupport stencilSupport,
277*c8dee2aaSAndroid Build Coastguard Worker bool fillInverted,
278*c8dee2aaSAndroid Build Coastguard Worker bool* drawDirectToClip) {
279*c8dee2aaSAndroid Build Coastguard Worker bool canRenderDirectToStencil =
280*c8dee2aaSAndroid Build Coastguard Worker skgpu::ganesh::PathRenderer::kNoRestriction_StencilSupport == stencilSupport;
281*c8dee2aaSAndroid Build Coastguard Worker
282*c8dee2aaSAndroid Build Coastguard Worker // TODO: inverse fill + intersect op can be direct.
283*c8dee2aaSAndroid Build Coastguard Worker // TODO: this can be greatly simplified when we only need intersect and difference ops and
284*c8dee2aaSAndroid Build Coastguard Worker // none of the paths will be inverse-filled (just toggle the op instead).
285*c8dee2aaSAndroid Build Coastguard Worker SkASSERT((unsigned)op <= SkRegion::kLastOp);
286*c8dee2aaSAndroid Build Coastguard Worker if (canRenderDirectToStencil && !fillInverted) {
287*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilSettings const* const* directPass = gDirectDrawTable[op];
288*c8dee2aaSAndroid Build Coastguard Worker if (directPass[0]) {
289*c8dee2aaSAndroid Build Coastguard Worker *drawDirectToClip = true;
290*c8dee2aaSAndroid Build Coastguard Worker return directPass;
291*c8dee2aaSAndroid Build Coastguard Worker }
292*c8dee2aaSAndroid Build Coastguard Worker }
293*c8dee2aaSAndroid Build Coastguard Worker *drawDirectToClip = false;
294*c8dee2aaSAndroid Build Coastguard Worker return gUserToClipTable[fillInverted][op];
295*c8dee2aaSAndroid Build Coastguard Worker }
296*c8dee2aaSAndroid Build Coastguard Worker
draw_stencil_rect(skgpu::ganesh::SurfaceDrawContext * sdc,const GrHardClip & clip,const GrUserStencilSettings * ss,const SkMatrix & matrix,const SkRect & rect,GrAA aa)297*c8dee2aaSAndroid Build Coastguard Worker void draw_stencil_rect(skgpu::ganesh::SurfaceDrawContext* sdc,
298*c8dee2aaSAndroid Build Coastguard Worker const GrHardClip& clip,
299*c8dee2aaSAndroid Build Coastguard Worker const GrUserStencilSettings* ss,
300*c8dee2aaSAndroid Build Coastguard Worker const SkMatrix& matrix,
301*c8dee2aaSAndroid Build Coastguard Worker const SkRect& rect,
302*c8dee2aaSAndroid Build Coastguard Worker GrAA aa) {
303*c8dee2aaSAndroid Build Coastguard Worker GrPaint paint;
304*c8dee2aaSAndroid Build Coastguard Worker paint.setXPFactory(GrDisableColorXPFactory::Get());
305*c8dee2aaSAndroid Build Coastguard Worker sdc->stencilRect(&clip, ss, std::move(paint), aa, matrix, rect);
306*c8dee2aaSAndroid Build Coastguard Worker }
307*c8dee2aaSAndroid Build Coastguard Worker
draw_path(GrRecordingContext * rContext,skgpu::ganesh::SurfaceDrawContext * sdc,skgpu::ganesh::PathRenderer * pr,const GrHardClip & clip,const SkIRect & bounds,const GrUserStencilSettings * ss,const SkMatrix & matrix,const GrStyledShape & shape,GrAA aa)308*c8dee2aaSAndroid Build Coastguard Worker void draw_path(GrRecordingContext* rContext,
309*c8dee2aaSAndroid Build Coastguard Worker skgpu::ganesh::SurfaceDrawContext* sdc,
310*c8dee2aaSAndroid Build Coastguard Worker skgpu::ganesh::PathRenderer* pr,
311*c8dee2aaSAndroid Build Coastguard Worker const GrHardClip& clip,
312*c8dee2aaSAndroid Build Coastguard Worker const SkIRect& bounds,
313*c8dee2aaSAndroid Build Coastguard Worker const GrUserStencilSettings* ss,
314*c8dee2aaSAndroid Build Coastguard Worker const SkMatrix& matrix,
315*c8dee2aaSAndroid Build Coastguard Worker const GrStyledShape& shape,
316*c8dee2aaSAndroid Build Coastguard Worker GrAA aa) {
317*c8dee2aaSAndroid Build Coastguard Worker GrPaint paint;
318*c8dee2aaSAndroid Build Coastguard Worker paint.setXPFactory(GrDisableColorXPFactory::Get());
319*c8dee2aaSAndroid Build Coastguard Worker
320*c8dee2aaSAndroid Build Coastguard Worker // kMSAA is the only type of AA that's possible on a stencil buffer.
321*c8dee2aaSAndroid Build Coastguard Worker GrAAType pathAAType = aa == GrAA::kYes ? GrAAType::kMSAA : GrAAType::kNone;
322*c8dee2aaSAndroid Build Coastguard Worker
323*c8dee2aaSAndroid Build Coastguard Worker skgpu::ganesh::PathRenderer::DrawPathArgs args{rContext,
324*c8dee2aaSAndroid Build Coastguard Worker std::move(paint),
325*c8dee2aaSAndroid Build Coastguard Worker ss,
326*c8dee2aaSAndroid Build Coastguard Worker sdc,
327*c8dee2aaSAndroid Build Coastguard Worker &clip,
328*c8dee2aaSAndroid Build Coastguard Worker &bounds,
329*c8dee2aaSAndroid Build Coastguard Worker &matrix,
330*c8dee2aaSAndroid Build Coastguard Worker &shape,
331*c8dee2aaSAndroid Build Coastguard Worker pathAAType,
332*c8dee2aaSAndroid Build Coastguard Worker false};
333*c8dee2aaSAndroid Build Coastguard Worker pr->drawPath(args);
334*c8dee2aaSAndroid Build Coastguard Worker }
335*c8dee2aaSAndroid Build Coastguard Worker
stencil_path(GrRecordingContext * rContext,skgpu::ganesh::SurfaceDrawContext * sdc,skgpu::ganesh::PathRenderer * pr,const GrFixedClip & clip,const SkMatrix & matrix,const GrStyledShape & shape,GrAA aa)336*c8dee2aaSAndroid Build Coastguard Worker void stencil_path(GrRecordingContext* rContext,
337*c8dee2aaSAndroid Build Coastguard Worker skgpu::ganesh::SurfaceDrawContext* sdc,
338*c8dee2aaSAndroid Build Coastguard Worker skgpu::ganesh::PathRenderer* pr,
339*c8dee2aaSAndroid Build Coastguard Worker const GrFixedClip& clip,
340*c8dee2aaSAndroid Build Coastguard Worker const SkMatrix& matrix,
341*c8dee2aaSAndroid Build Coastguard Worker const GrStyledShape& shape,
342*c8dee2aaSAndroid Build Coastguard Worker GrAA aa) {
343*c8dee2aaSAndroid Build Coastguard Worker skgpu::ganesh::PathRenderer::StencilPathArgs args;
344*c8dee2aaSAndroid Build Coastguard Worker args.fContext = rContext;
345*c8dee2aaSAndroid Build Coastguard Worker args.fSurfaceDrawContext = sdc;
346*c8dee2aaSAndroid Build Coastguard Worker args.fClip = &clip;
347*c8dee2aaSAndroid Build Coastguard Worker args.fClipConservativeBounds = &clip.scissorRect();
348*c8dee2aaSAndroid Build Coastguard Worker args.fViewMatrix = &matrix;
349*c8dee2aaSAndroid Build Coastguard Worker args.fShape = &shape;
350*c8dee2aaSAndroid Build Coastguard Worker args.fDoStencilMSAA = aa;
351*c8dee2aaSAndroid Build Coastguard Worker
352*c8dee2aaSAndroid Build Coastguard Worker pr->stencilPath(args);
353*c8dee2aaSAndroid Build Coastguard Worker }
354*c8dee2aaSAndroid Build Coastguard Worker
supported_aa(skgpu::ganesh::SurfaceDrawContext * sdc,GrAA aa)355*c8dee2aaSAndroid Build Coastguard Worker GrAA supported_aa(skgpu::ganesh::SurfaceDrawContext* sdc, GrAA aa) {
356*c8dee2aaSAndroid Build Coastguard Worker return GrAA(sdc->numSamples() > 1 || sdc->canUseDynamicMSAA());
357*c8dee2aaSAndroid Build Coastguard Worker }
358*c8dee2aaSAndroid Build Coastguard Worker
359*c8dee2aaSAndroid Build Coastguard Worker } // namespace
360*c8dee2aaSAndroid Build Coastguard Worker
361*c8dee2aaSAndroid Build Coastguard Worker namespace skgpu::ganesh {
362*c8dee2aaSAndroid Build Coastguard Worker
StencilMaskHelper(GrRecordingContext * rContext,SurfaceDrawContext * sdc)363*c8dee2aaSAndroid Build Coastguard Worker StencilMaskHelper::StencilMaskHelper(GrRecordingContext* rContext,
364*c8dee2aaSAndroid Build Coastguard Worker SurfaceDrawContext* sdc)
365*c8dee2aaSAndroid Build Coastguard Worker : fContext(rContext)
366*c8dee2aaSAndroid Build Coastguard Worker , fSDC(sdc)
367*c8dee2aaSAndroid Build Coastguard Worker , fClip(sdc->dimensions()) {
368*c8dee2aaSAndroid Build Coastguard Worker }
369*c8dee2aaSAndroid Build Coastguard Worker
init(const SkIRect & bounds,uint32_t genID,const GrWindowRectangles & windowRects,int numFPs)370*c8dee2aaSAndroid Build Coastguard Worker bool StencilMaskHelper::init(const SkIRect& bounds, uint32_t genID,
371*c8dee2aaSAndroid Build Coastguard Worker const GrWindowRectangles& windowRects, int numFPs) {
372*c8dee2aaSAndroid Build Coastguard Worker if (!fSDC->mustRenderClip(genID, bounds, numFPs)) {
373*c8dee2aaSAndroid Build Coastguard Worker return false;
374*c8dee2aaSAndroid Build Coastguard Worker }
375*c8dee2aaSAndroid Build Coastguard Worker
376*c8dee2aaSAndroid Build Coastguard Worker fClip.setStencilClip(genID);
377*c8dee2aaSAndroid Build Coastguard Worker // Should have caught bounds not intersecting the render target much earlier in clip application
378*c8dee2aaSAndroid Build Coastguard Worker SkAssertResult(fClip.fixedClip().setScissor(bounds));
379*c8dee2aaSAndroid Build Coastguard Worker if (!windowRects.empty()) {
380*c8dee2aaSAndroid Build Coastguard Worker fClip.fixedClip().setWindowRectangles(
381*c8dee2aaSAndroid Build Coastguard Worker windowRects, GrWindowRectsState::Mode::kExclusive);
382*c8dee2aaSAndroid Build Coastguard Worker }
383*c8dee2aaSAndroid Build Coastguard Worker fNumFPs = numFPs;
384*c8dee2aaSAndroid Build Coastguard Worker return true;
385*c8dee2aaSAndroid Build Coastguard Worker }
386*c8dee2aaSAndroid Build Coastguard Worker
drawRect(const SkRect & rect,const SkMatrix & matrix,SkRegion::Op op,GrAA aa)387*c8dee2aaSAndroid Build Coastguard Worker void StencilMaskHelper::drawRect(const SkRect& rect,
388*c8dee2aaSAndroid Build Coastguard Worker const SkMatrix& matrix,
389*c8dee2aaSAndroid Build Coastguard Worker SkRegion::Op op,
390*c8dee2aaSAndroid Build Coastguard Worker GrAA aa) {
391*c8dee2aaSAndroid Build Coastguard Worker if (rect.isEmpty()) {
392*c8dee2aaSAndroid Build Coastguard Worker return;
393*c8dee2aaSAndroid Build Coastguard Worker }
394*c8dee2aaSAndroid Build Coastguard Worker
395*c8dee2aaSAndroid Build Coastguard Worker bool drawDirectToClip;
396*c8dee2aaSAndroid Build Coastguard Worker auto passes = get_stencil_passes(op, PathRenderer::kNoRestriction_StencilSupport,
397*c8dee2aaSAndroid Build Coastguard Worker false, &drawDirectToClip);
398*c8dee2aaSAndroid Build Coastguard Worker aa = supported_aa(fSDC, aa);
399*c8dee2aaSAndroid Build Coastguard Worker
400*c8dee2aaSAndroid Build Coastguard Worker if (!drawDirectToClip) {
401*c8dee2aaSAndroid Build Coastguard Worker // Draw to client stencil bits first
402*c8dee2aaSAndroid Build Coastguard Worker draw_stencil_rect(fSDC, fClip.fixedClip(), &gDrawToStencil, matrix, rect, aa);
403*c8dee2aaSAndroid Build Coastguard Worker }
404*c8dee2aaSAndroid Build Coastguard Worker
405*c8dee2aaSAndroid Build Coastguard Worker // Now modify the clip bit (either by rendering directly), or by covering the bounding box
406*c8dee2aaSAndroid Build Coastguard Worker // of the clip
407*c8dee2aaSAndroid Build Coastguard Worker for (GrUserStencilSettings const* const* pass = passes; *pass; ++pass) {
408*c8dee2aaSAndroid Build Coastguard Worker if (drawDirectToClip) {
409*c8dee2aaSAndroid Build Coastguard Worker draw_stencil_rect(fSDC, fClip, *pass, matrix, rect, aa);
410*c8dee2aaSAndroid Build Coastguard Worker } else {
411*c8dee2aaSAndroid Build Coastguard Worker draw_stencil_rect(fSDC, fClip, *pass, SkMatrix::I(),
412*c8dee2aaSAndroid Build Coastguard Worker SkRect::Make(fClip.fixedClip().scissorRect()), aa);
413*c8dee2aaSAndroid Build Coastguard Worker }
414*c8dee2aaSAndroid Build Coastguard Worker }
415*c8dee2aaSAndroid Build Coastguard Worker }
416*c8dee2aaSAndroid Build Coastguard Worker
drawPath(const SkPath & path,const SkMatrix & matrix,SkRegion::Op op,GrAA aa)417*c8dee2aaSAndroid Build Coastguard Worker bool StencilMaskHelper::drawPath(const SkPath& path,
418*c8dee2aaSAndroid Build Coastguard Worker const SkMatrix& matrix,
419*c8dee2aaSAndroid Build Coastguard Worker SkRegion::Op op,
420*c8dee2aaSAndroid Build Coastguard Worker GrAA aa) {
421*c8dee2aaSAndroid Build Coastguard Worker if (path.isEmpty()) {
422*c8dee2aaSAndroid Build Coastguard Worker return true;
423*c8dee2aaSAndroid Build Coastguard Worker }
424*c8dee2aaSAndroid Build Coastguard Worker
425*c8dee2aaSAndroid Build Coastguard Worker // drawPath follows a similar approach to drawRect(), where we either draw directly to the clip
426*c8dee2aaSAndroid Build Coastguard Worker // bit or first draw to client bits and then apply a cover pass. The complicating factor is that
427*c8dee2aaSAndroid Build Coastguard Worker // we rely on path rendering and how the chosen path renderer uses the stencil buffer.
428*c8dee2aaSAndroid Build Coastguard Worker aa = supported_aa(fSDC, aa);
429*c8dee2aaSAndroid Build Coastguard Worker
430*c8dee2aaSAndroid Build Coastguard Worker GrAAType pathAAType = aa == GrAA::kYes ? GrAAType::kMSAA : GrAAType::kNone;
431*c8dee2aaSAndroid Build Coastguard Worker
432*c8dee2aaSAndroid Build Coastguard Worker // This will be used to determine whether the clip shape can be rendered into the
433*c8dee2aaSAndroid Build Coastguard Worker // stencil with arbitrary stencil settings.
434*c8dee2aaSAndroid Build Coastguard Worker PathRenderer::StencilSupport stencilSupport;
435*c8dee2aaSAndroid Build Coastguard Worker
436*c8dee2aaSAndroid Build Coastguard Worker // Make path canonical with regards to fill type (inverse handled by stencil settings).
437*c8dee2aaSAndroid Build Coastguard Worker bool fillInverted = path.isInverseFillType();
438*c8dee2aaSAndroid Build Coastguard Worker SkTCopyOnFirstWrite<SkPath> clipPath(path);
439*c8dee2aaSAndroid Build Coastguard Worker if (fillInverted) {
440*c8dee2aaSAndroid Build Coastguard Worker clipPath.writable()->toggleInverseFillType();
441*c8dee2aaSAndroid Build Coastguard Worker }
442*c8dee2aaSAndroid Build Coastguard Worker
443*c8dee2aaSAndroid Build Coastguard Worker GrStyledShape shape(*clipPath, GrStyle::SimpleFill());
444*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!shape.inverseFilled());
445*c8dee2aaSAndroid Build Coastguard Worker
446*c8dee2aaSAndroid Build Coastguard Worker PathRenderer::CanDrawPathArgs canDrawArgs;
447*c8dee2aaSAndroid Build Coastguard Worker canDrawArgs.fCaps = fContext->priv().caps();
448*c8dee2aaSAndroid Build Coastguard Worker canDrawArgs.fProxy = fSDC->asRenderTargetProxy();
449*c8dee2aaSAndroid Build Coastguard Worker canDrawArgs.fClipConservativeBounds = &fClip.fixedClip().scissorRect();
450*c8dee2aaSAndroid Build Coastguard Worker canDrawArgs.fViewMatrix = &matrix;
451*c8dee2aaSAndroid Build Coastguard Worker canDrawArgs.fShape = &shape;
452*c8dee2aaSAndroid Build Coastguard Worker canDrawArgs.fPaint = nullptr;
453*c8dee2aaSAndroid Build Coastguard Worker canDrawArgs.fSurfaceProps = &fSDC->surfaceProps();
454*c8dee2aaSAndroid Build Coastguard Worker canDrawArgs.fAAType = pathAAType;
455*c8dee2aaSAndroid Build Coastguard Worker canDrawArgs.fHasUserStencilSettings = false;
456*c8dee2aaSAndroid Build Coastguard Worker
457*c8dee2aaSAndroid Build Coastguard Worker auto pr = fContext->priv().drawingManager()->getPathRenderer(
458*c8dee2aaSAndroid Build Coastguard Worker canDrawArgs, false, PathRendererChain::DrawType::kStencil, &stencilSupport);
459*c8dee2aaSAndroid Build Coastguard Worker if (!pr) {
460*c8dee2aaSAndroid Build Coastguard Worker return false;
461*c8dee2aaSAndroid Build Coastguard Worker }
462*c8dee2aaSAndroid Build Coastguard Worker
463*c8dee2aaSAndroid Build Coastguard Worker bool drawDirectToClip;
464*c8dee2aaSAndroid Build Coastguard Worker auto passes = get_stencil_passes(op, stencilSupport, fillInverted, &drawDirectToClip);
465*c8dee2aaSAndroid Build Coastguard Worker
466*c8dee2aaSAndroid Build Coastguard Worker // Write to client bits if necessary
467*c8dee2aaSAndroid Build Coastguard Worker if (!drawDirectToClip) {
468*c8dee2aaSAndroid Build Coastguard Worker if (stencilSupport == PathRenderer::kNoRestriction_StencilSupport) {
469*c8dee2aaSAndroid Build Coastguard Worker draw_path(fContext, fSDC, pr, fClip.fixedClip(), fClip.fixedClip().scissorRect(),
470*c8dee2aaSAndroid Build Coastguard Worker &gDrawToStencil, matrix, shape, aa);
471*c8dee2aaSAndroid Build Coastguard Worker } else {
472*c8dee2aaSAndroid Build Coastguard Worker stencil_path(fContext, fSDC, pr, fClip.fixedClip(), matrix, shape, aa);
473*c8dee2aaSAndroid Build Coastguard Worker }
474*c8dee2aaSAndroid Build Coastguard Worker }
475*c8dee2aaSAndroid Build Coastguard Worker
476*c8dee2aaSAndroid Build Coastguard Worker // Now modify the clip bit (either by rendering directly), or by covering the bounding box
477*c8dee2aaSAndroid Build Coastguard Worker // of the clip
478*c8dee2aaSAndroid Build Coastguard Worker for (GrUserStencilSettings const* const* pass = passes; *pass; ++pass) {
479*c8dee2aaSAndroid Build Coastguard Worker if (drawDirectToClip) {
480*c8dee2aaSAndroid Build Coastguard Worker draw_path(fContext, fSDC, pr, fClip, fClip.fixedClip().scissorRect(),
481*c8dee2aaSAndroid Build Coastguard Worker *pass, matrix, shape, aa);
482*c8dee2aaSAndroid Build Coastguard Worker } else {
483*c8dee2aaSAndroid Build Coastguard Worker draw_stencil_rect(fSDC, fClip, *pass, SkMatrix::I(),
484*c8dee2aaSAndroid Build Coastguard Worker SkRect::Make(fClip.fixedClip().scissorRect()), aa);
485*c8dee2aaSAndroid Build Coastguard Worker }
486*c8dee2aaSAndroid Build Coastguard Worker }
487*c8dee2aaSAndroid Build Coastguard Worker
488*c8dee2aaSAndroid Build Coastguard Worker return true;
489*c8dee2aaSAndroid Build Coastguard Worker }
490*c8dee2aaSAndroid Build Coastguard Worker
drawShape(const GrShape & shape,const SkMatrix & matrix,SkRegion::Op op,GrAA aa)491*c8dee2aaSAndroid Build Coastguard Worker bool StencilMaskHelper::drawShape(const GrShape& shape,
492*c8dee2aaSAndroid Build Coastguard Worker const SkMatrix& matrix,
493*c8dee2aaSAndroid Build Coastguard Worker SkRegion::Op op,
494*c8dee2aaSAndroid Build Coastguard Worker GrAA aa) {
495*c8dee2aaSAndroid Build Coastguard Worker if (shape.isRect() && !shape.inverted()) {
496*c8dee2aaSAndroid Build Coastguard Worker this->drawRect(shape.rect(), matrix, op, aa);
497*c8dee2aaSAndroid Build Coastguard Worker return true;
498*c8dee2aaSAndroid Build Coastguard Worker } else {
499*c8dee2aaSAndroid Build Coastguard Worker SkPath p;
500*c8dee2aaSAndroid Build Coastguard Worker shape.asPath(&p);
501*c8dee2aaSAndroid Build Coastguard Worker return this->drawPath(p, matrix, op, aa);
502*c8dee2aaSAndroid Build Coastguard Worker }
503*c8dee2aaSAndroid Build Coastguard Worker }
504*c8dee2aaSAndroid Build Coastguard Worker
clear(bool insideStencil)505*c8dee2aaSAndroid Build Coastguard Worker void StencilMaskHelper::clear(bool insideStencil) {
506*c8dee2aaSAndroid Build Coastguard Worker if (fClip.fixedClip().hasWindowRectangles()) {
507*c8dee2aaSAndroid Build Coastguard Worker // Use a draw to benefit from window rectangles when resetting the stencil buffer; for
508*c8dee2aaSAndroid Build Coastguard Worker // large buffers with MSAA this can be significant.
509*c8dee2aaSAndroid Build Coastguard Worker draw_stencil_rect(fSDC, fClip.fixedClip(),
510*c8dee2aaSAndroid Build Coastguard Worker GrStencilSettings::SetClipBitSettings(insideStencil), SkMatrix::I(),
511*c8dee2aaSAndroid Build Coastguard Worker SkRect::Make(fClip.fixedClip().scissorRect()), GrAA::kNo);
512*c8dee2aaSAndroid Build Coastguard Worker } else {
513*c8dee2aaSAndroid Build Coastguard Worker fSDC->clearStencilClip(fClip.fixedClip().scissorRect(), insideStencil);
514*c8dee2aaSAndroid Build Coastguard Worker }
515*c8dee2aaSAndroid Build Coastguard Worker }
516*c8dee2aaSAndroid Build Coastguard Worker
finish()517*c8dee2aaSAndroid Build Coastguard Worker void StencilMaskHelper::finish() {
518*c8dee2aaSAndroid Build Coastguard Worker fSDC->setLastClip(fClip.stencilStackID(), fClip.fixedClip().scissorRect(), fNumFPs);
519*c8dee2aaSAndroid Build Coastguard Worker }
520*c8dee2aaSAndroid Build Coastguard Worker
521*c8dee2aaSAndroid Build Coastguard Worker } // namespace skgpu::ganesh
522