xref: /aosp_15_r20/external/skia/src/gpu/ganesh/GrStencilSettings.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2011 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 #include "src/gpu/ganesh/GrStencilSettings.h"
8 
9 #include "include/private/base/SkDebug.h"
10 #include "src/gpu/KeyBuilder.h"
11 
12 #include <algorithm>
13 #include <cstddef>
14 #include <cstring>
15 
16 constexpr const GrUserStencilSettings gUnused(
17     GrUserStencilSettings::StaticInit<
18         0x0000,
19         GrUserStencilTest::kAlwaysIfInClip,
20         0xffff,
21         GrUserStencilOp::kKeep,
22         GrUserStencilOp::kKeep,
23         0x0000>()
24 );
25 
26 static_assert(kAll_StencilFlags == (gUnused.fCWFlags[0] & gUnused.fCCWFlags[0]));
27 
28 const GrUserStencilSettings& GrUserStencilSettings::kUnused = gUnused;
29 
reset(const GrUserStencilSettings & user,bool hasStencilClip,int numStencilBits)30 void GrStencilSettings::reset(const GrUserStencilSettings& user, bool hasStencilClip,
31                               int numStencilBits) {
32     uint16_t cwFlags = user.fCWFlags[hasStencilClip];
33     if (cwFlags & kSingleSided_StencilFlag) {
34         SkASSERT(cwFlags == user.fCCWFlags[hasStencilClip]);
35         fFlags = cwFlags;
36         if (!this->isDisabled()) {
37             fCWFace.reset(user.fCWFace, hasStencilClip, numStencilBits);
38         }
39         return;
40     }
41 
42     uint16_t ccwFlags = user.fCCWFlags[hasStencilClip];
43     fFlags = cwFlags & ccwFlags;
44     if (this->isDisabled()) {
45         return;
46     }
47     if (!(cwFlags & kDisabled_StencilFlag)) {
48         fCWFace.reset(user.fCWFace, hasStencilClip, numStencilBits);
49     } else {
50         fCWFace.setDisabled();
51     }
52     if (!(ccwFlags & kDisabled_StencilFlag)) {
53         fCCWFace.reset(user.fCCWFace, hasStencilClip, numStencilBits);
54     } else {
55         fCCWFace.setDisabled();
56     }
57 }
58 
reset(const GrStencilSettings & that)59 void GrStencilSettings::reset(const GrStencilSettings& that) {
60     fFlags = that.fFlags;
61     if ((kInvalid_PrivateFlag | kDisabled_StencilFlag) & fFlags) {
62         return;
63     }
64     if (!this->isTwoSided()) {
65         memcpy(&fCWFace, &that.fCWFace, sizeof(Face));
66     } else {
67         memcpy(&fCWFace, &that.fCWFace, 2 * sizeof(Face));
68         static_assert(sizeof(Face) ==
69                       offsetof(GrStencilSettings, fCCWFace) - offsetof(GrStencilSettings, fCWFace));
70     }
71 }
72 
operator ==(const GrStencilSettings & that) const73 bool GrStencilSettings::operator==(const GrStencilSettings& that) const {
74     if ((kInvalid_PrivateFlag | kDisabled_StencilFlag) & (fFlags | that.fFlags)) {
75         // At least one is invalid and/or disabled.
76         if (kInvalid_PrivateFlag & (fFlags | that.fFlags)) {
77             return false; // We never allow invalid stencils to be equal.
78         }
79         // They're only equal if both are disabled.
80         return kDisabled_StencilFlag & (fFlags & that.fFlags);
81     }
82     if (kSingleSided_StencilFlag & (fFlags & that.fFlags)) {
83         return 0 == memcmp(&fCWFace, &that.fCWFace, sizeof(Face)); // Both are single sided.
84     } else if (kSingleSided_StencilFlag & (fFlags | that.fFlags)) {
85         return false;
86     } else {
87         return 0 == memcmp(&fCWFace, &that.fCWFace, 2 * sizeof(Face));
88         static_assert(sizeof(Face) ==
89                       offsetof(GrStencilSettings, fCCWFace) - offsetof(GrStencilSettings, fCWFace));
90     }
91     // memcmp relies on GrStencilSettings::Face being tightly packed.
92     static_assert(0 == offsetof(Face, fRef));
93     static_assert(2 == sizeof(Face::fRef));
94     static_assert(2 == offsetof(Face, fTest));
95     static_assert(2 == sizeof(Face::fTest));
96     static_assert(4 == offsetof(Face, fTestMask));
97     static_assert(2 == sizeof(Face::fTestMask));
98     static_assert(6 == offsetof(Face, fPassOp));
99     static_assert(1 == sizeof(Face::fPassOp));
100     static_assert(7 == offsetof(Face, fFailOp));
101     static_assert(1 == sizeof(Face::fFailOp));
102     static_assert(8 == offsetof(Face, fWriteMask));
103     static_assert(2 == sizeof(Face::fWriteMask));
104     static_assert(10 == sizeof(Face));
105 }
106 
107 static constexpr GrStencilTest gUserStencilTestToRaw[kGrUserStencilTestCount] = {
108     // Tests that respect the clip.
109     GrStencilTest::kAlways,  // kAlwaysIfInClip (This is only for when there is not a stencil clip).
110     GrStencilTest::kEqual,   // kEqualIfInClip.
111     GrStencilTest::kLess,    // kLessIfInClip.
112     GrStencilTest::kLEqual,  // kLEqualIfInClip.
113 
114     // Tests that ignore the clip.
115     GrStencilTest::kAlways,
116     GrStencilTest::kNever,
117     GrStencilTest::kGreater,
118     GrStencilTest::kGEqual,
119     GrStencilTest::kLess,
120     GrStencilTest::kLEqual,
121     GrStencilTest::kEqual,
122     GrStencilTest::kNotEqual
123 };
124 
125 static_assert(0 == (int)GrUserStencilTest::kAlwaysIfInClip);
126 static_assert(1 == (int)GrUserStencilTest::kEqualIfInClip);
127 static_assert(2 == (int)GrUserStencilTest::kLessIfInClip);
128 static_assert(3 == (int)GrUserStencilTest::kLEqualIfInClip);
129 static_assert(4 == (int)GrUserStencilTest::kAlways);
130 static_assert(5 == (int)GrUserStencilTest::kNever);
131 static_assert(6 == (int)GrUserStencilTest::kGreater);
132 static_assert(7 == (int)GrUserStencilTest::kGEqual);
133 static_assert(8 == (int)GrUserStencilTest::kLess);
134 static_assert(9 == (int)GrUserStencilTest::kLEqual);
135 static_assert(10 == (int)GrUserStencilTest::kEqual);
136 static_assert(11 == (int)GrUserStencilTest::kNotEqual);
137 
138 static constexpr GrStencilOp gUserStencilOpToRaw[kGrUserStencilOpCount] = {
139     GrStencilOp::kKeep,
140 
141     // Ops that only modify user bits.
142     GrStencilOp::kZero,
143     GrStencilOp::kReplace,
144     GrStencilOp::kInvert,
145     GrStencilOp::kIncWrap,
146     GrStencilOp::kDecWrap,
147     GrStencilOp::kIncClamp,  // kIncMaybeClamp.
148     GrStencilOp::kDecClamp,  // kDecMaybeClamp.
149 
150     // Ops that only modify the clip bit.
151     GrStencilOp::kZero,      // kZeroClipBit.
152     GrStencilOp::kReplace,   // kSetClipBit.
153     GrStencilOp::kInvert,    // kInvertClipBit.
154 
155     // Ops that modify clip and user bits.
156     GrStencilOp::kReplace,   // kSetClipAndReplaceUserBits.
157     GrStencilOp::kZero       // kZeroClipAndUserBits.
158 };
159 
160 static_assert(0 == (int)GrUserStencilOp::kKeep);
161 static_assert(1 == (int)GrUserStencilOp::kZero);
162 static_assert(2 == (int)GrUserStencilOp::kReplace);
163 static_assert(3 == (int)GrUserStencilOp::kInvert);
164 static_assert(4 == (int)GrUserStencilOp::kIncWrap);
165 static_assert(5 == (int)GrUserStencilOp::kDecWrap);
166 static_assert(6 == (int)GrUserStencilOp::kIncMaybeClamp);
167 static_assert(7 == (int)GrUserStencilOp::kDecMaybeClamp);
168 static_assert(8 == (int)GrUserStencilOp::kZeroClipBit);
169 static_assert(9 == (int)GrUserStencilOp::kSetClipBit);
170 static_assert(10 == (int)GrUserStencilOp::kInvertClipBit);
171 static_assert(11 == (int)GrUserStencilOp::kSetClipAndReplaceUserBits);
172 static_assert(12 == (int)GrUserStencilOp::kZeroClipAndUserBits);
173 
reset(const GrUserStencilSettings::Face & user,bool hasStencilClip,int numStencilBits)174 void GrStencilSettings::Face::reset(const GrUserStencilSettings::Face& user, bool hasStencilClip,
175                                     int numStencilBits) {
176     SkASSERT(user.fTest < (GrUserStencilTest)kGrUserStencilTestCount);
177     SkASSERT(user.fPassOp < (GrUserStencilOp)kGrUserStencilOpCount);
178     SkASSERT(user.fFailOp < (GrUserStencilOp)kGrUserStencilOpCount);
179     SkASSERT(numStencilBits > 0 && numStencilBits <= 16);
180     int clipBit = 1 << (numStencilBits - 1);
181     int userMask = clipBit - 1;
182 
183     GrUserStencilOp maxOp = std::max(user.fPassOp, user.fFailOp);
184     SkDEBUGCODE(GrUserStencilOp otherOp = std::min(user.fPassOp, user.fFailOp);)
185     if (maxOp <= kLastUserOnlyStencilOp) {
186         // Ops that only modify user bits.
187         fWriteMask = user.fWriteMask & userMask;
188         SkASSERT(otherOp <= kLastUserOnlyStencilOp);
189     } else if (maxOp <= kLastClipOnlyStencilOp) {
190         // Ops that only modify the clip bit.
191         fWriteMask = clipBit;
192         SkASSERT(GrUserStencilOp::kKeep == otherOp ||
193                  (otherOp > kLastUserOnlyStencilOp && otherOp <= kLastClipOnlyStencilOp));
194     } else {
195         // Ops that modify both clip and user bits.
196         fWriteMask = clipBit | (user.fWriteMask & userMask);
197         SkASSERT(GrUserStencilOp::kKeep == otherOp || otherOp > kLastClipOnlyStencilOp);
198     }
199 
200     fFailOp = gUserStencilOpToRaw[(int)user.fFailOp];
201     fPassOp = gUserStencilOpToRaw[(int)user.fPassOp];
202 
203     if (!hasStencilClip || user.fTest > kLastClippedStencilTest) {
204         // Ignore the clip.
205         fTestMask = user.fTestMask & userMask;
206         fTest = gUserStencilTestToRaw[(int)user.fTest];
207     } else if (GrUserStencilTest::kAlwaysIfInClip != user.fTest) {
208         // Respect the clip.
209         fTestMask = clipBit | (user.fTestMask & userMask);
210         fTest = gUserStencilTestToRaw[(int)user.fTest];
211     } else {
212         // Test only for clip.
213         fTestMask = clipBit;
214         fTest = GrStencilTest::kEqual;
215     }
216 
217     fRef = (clipBit | user.fRef) & (fTestMask | fWriteMask);
218 }
219 
setDisabled()220 void GrStencilSettings::Face::setDisabled() {
221     memset(this, 0, sizeof(*this));
222     static_assert(0 == (int)GrStencilTest::kAlways);
223     static_assert(0 == (int)GrStencilOp::kKeep);
224 }
225 
226 static constexpr GrUserStencilSettings gZeroStencilClipBit(
227     GrUserStencilSettings::StaticInit<
228         0x0000,
229         GrUserStencilTest::kAlways,
230         0xffff,
231         GrUserStencilOp::kZeroClipBit,
232         GrUserStencilOp::kZeroClipBit,
233         0x0000>()
234 );
235 static constexpr GrUserStencilSettings gSetStencilClipBit(
236     GrUserStencilSettings::StaticInit<
237         0x0000,
238         GrUserStencilTest::kAlways,
239         0xffff,
240         GrUserStencilOp::kSetClipBit,
241         GrUserStencilOp::kSetClipBit,
242         0x0000>()
243 );
244 
SetClipBitSettings(bool setToInside)245 const GrUserStencilSettings* GrStencilSettings::SetClipBitSettings(bool setToInside) {
246     return setToInside ? &gSetStencilClipBit : &gZeroStencilClipBit;
247 }
248 
genKey(skgpu::KeyBuilder * b,bool includeRefs) const249 void GrStencilSettings::genKey(skgpu::KeyBuilder* b, bool includeRefs) const {
250     b->addBits(6, fFlags, "stencilFlags");
251     if (this->isDisabled()) {
252         return;
253     }
254     if (!this->isTwoSided()) {
255         if (includeRefs) {
256             b->addBytes(sizeof(Face), &fCWFace, "stencilCWFace");
257         } else {
258             Face tempFace = fCWFace;
259             tempFace.fRef = 0;
260             b->addBytes(sizeof(Face), &tempFace, "stencilCWFace");
261         }
262     } else {
263         if (includeRefs) {
264             b->addBytes(sizeof(Face), &fCWFace, "stencilCWFace");
265             b->addBytes(sizeof(Face), &fCCWFace, "stencilCCWFace");
266         } else {
267             Face tempFaces[2];
268             tempFaces[0] = fCWFace;
269             tempFaces[0].fRef = 0;
270             tempFaces[1] = fCCWFace;
271             tempFaces[1].fRef = 0;
272             b->addBytes(sizeof(Face), &tempFaces[0], "stencilCWFace");
273             b->addBytes(sizeof(Face), &tempFaces[1], "stencilCCWFace");
274         }
275     }
276     // We rely on GrStencilSettings::Face being tightly packed for the key to be reliable.
277     static_assert(0 == offsetof(Face, fRef));
278     static_assert(2 == sizeof(Face::fRef));
279     static_assert(2 == offsetof(Face, fTest));
280     static_assert(2 == sizeof(Face::fTest));
281     static_assert(4 == offsetof(Face, fTestMask));
282     static_assert(2 == sizeof(Face::fTestMask));
283     static_assert(6 == offsetof(Face, fPassOp));
284     static_assert(1 == sizeof(Face::fPassOp));
285     static_assert(7 == offsetof(Face, fFailOp));
286     static_assert(1 == sizeof(Face::fFailOp));
287     static_assert(8 == offsetof(Face, fWriteMask));
288     static_assert(2 == sizeof(Face::fWriteMask));
289     static_assert(10 == sizeof(Face));
290 }
291