xref: /aosp_15_r20/external/skia/src/gpu/ganesh/StencilMaskHelper.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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