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