blob: 731385885509237e331c5e657930cf1c44c09f8e [file] [log] [blame]
cdalton93a379b2016-05-11 13:58:08 -07001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05009#include "src/gpu/GrStencilSettings.h"
cdalton93a379b2016-05-11 13:58:08 -070010
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "src/gpu/GrProcessor.h"
cdalton93a379b2016-05-11 13:58:08 -070012
13constexpr const GrUserStencilSettings gUnused(
14 GrUserStencilSettings::StaticInit<
15 0x0000,
16 GrUserStencilTest::kAlwaysIfInClip,
17 0xffff,
18 GrUserStencilOp::kKeep,
19 GrUserStencilOp::kKeep,
20 0x0000>()
21);
22
Brian Salomon4dea72a2019-12-18 10:43:10 -050023static_assert(kAll_StencilFlags == (gUnused.fCWFlags[0] & gUnused.fCCWFlags[0]));
cdalton93a379b2016-05-11 13:58:08 -070024
25const GrUserStencilSettings& GrUserStencilSettings::kUnused = gUnused;
26
27void GrStencilSettings::reset(const GrUserStencilSettings& user, bool hasStencilClip,
28 int numStencilBits) {
Chris Dalton67d43fe2019-11-05 23:01:21 -070029 uint16_t cwFlags = user.fCWFlags[hasStencilClip];
30 if (cwFlags & kSingleSided_StencilFlag) {
31 SkASSERT(cwFlags == user.fCCWFlags[hasStencilClip]);
32 fFlags = cwFlags;
cdalton93a379b2016-05-11 13:58:08 -070033 if (!this->isDisabled()) {
Chris Dalton67d43fe2019-11-05 23:01:21 -070034 fCWFace.reset(user.fCWFace, hasStencilClip, numStencilBits);
cdalton93a379b2016-05-11 13:58:08 -070035 }
36 return;
37 }
38
Chris Dalton67d43fe2019-11-05 23:01:21 -070039 uint16_t ccwFlags = user.fCCWFlags[hasStencilClip];
40 fFlags = cwFlags & ccwFlags;
cdalton93a379b2016-05-11 13:58:08 -070041 if (this->isDisabled()) {
42 return;
43 }
Chris Dalton67d43fe2019-11-05 23:01:21 -070044 if (!(cwFlags & kDisabled_StencilFlag)) {
45 fCWFace.reset(user.fCWFace, hasStencilClip, numStencilBits);
cdalton93a379b2016-05-11 13:58:08 -070046 } else {
Chris Dalton67d43fe2019-11-05 23:01:21 -070047 fCWFace.setDisabled();
cdalton93a379b2016-05-11 13:58:08 -070048 }
Chris Dalton67d43fe2019-11-05 23:01:21 -070049 if (!(ccwFlags & kDisabled_StencilFlag)) {
50 fCCWFace.reset(user.fCCWFace, hasStencilClip, numStencilBits);
cdalton93a379b2016-05-11 13:58:08 -070051 } else {
Chris Dalton67d43fe2019-11-05 23:01:21 -070052 fCCWFace.setDisabled();
cdalton93a379b2016-05-11 13:58:08 -070053 }
54}
55
56void GrStencilSettings::reset(const GrStencilSettings& that) {
57 fFlags = that.fFlags;
58 if ((kInvalid_PrivateFlag | kDisabled_StencilFlag) & fFlags) {
59 return;
60 }
61 if (!this->isTwoSided()) {
Chris Dalton67d43fe2019-11-05 23:01:21 -070062 memcpy(&fCWFace, &that.fCWFace, sizeof(Face));
cdalton93a379b2016-05-11 13:58:08 -070063 } else {
Chris Dalton67d43fe2019-11-05 23:01:21 -070064 memcpy(&fCWFace, &that.fCWFace, 2 * sizeof(Face));
Brian Salomon4dea72a2019-12-18 10:43:10 -050065 static_assert(sizeof(Face) ==
66 offsetof(GrStencilSettings, fCCWFace) - offsetof(GrStencilSettings, fCWFace));
cdalton93a379b2016-05-11 13:58:08 -070067 }
68}
69
70bool GrStencilSettings::operator==(const GrStencilSettings& that) const {
71 if ((kInvalid_PrivateFlag | kDisabled_StencilFlag) & (fFlags | that.fFlags)) {
72 // At least one is invalid and/or disabled.
73 if (kInvalid_PrivateFlag & (fFlags | that.fFlags)) {
74 return false; // We never allow invalid stencils to be equal.
75 }
76 // They're only equal if both are disabled.
77 return kDisabled_StencilFlag & (fFlags & that.fFlags);
78 }
79 if (kSingleSided_StencilFlag & (fFlags & that.fFlags)) {
Chris Dalton67d43fe2019-11-05 23:01:21 -070080 return 0 == memcmp(&fCWFace, &that.fCWFace, sizeof(Face)); // Both are single sided.
Brian Salomone01187e2017-03-22 17:50:08 -040081 } else if (kSingleSided_StencilFlag & (fFlags | that.fFlags)) {
82 return false;
cdalton93a379b2016-05-11 13:58:08 -070083 } else {
Chris Dalton67d43fe2019-11-05 23:01:21 -070084 return 0 == memcmp(&fCWFace, &that.fCWFace, 2 * sizeof(Face));
Brian Salomon4dea72a2019-12-18 10:43:10 -050085 static_assert(sizeof(Face) ==
86 offsetof(GrStencilSettings, fCCWFace) - offsetof(GrStencilSettings, fCWFace));
cdalton93a379b2016-05-11 13:58:08 -070087 }
88 // memcmp relies on GrStencilSettings::Face being tightly packed.
Brian Salomon4dea72a2019-12-18 10:43:10 -050089 static_assert(0 == offsetof(Face, fRef));
90 static_assert(2 == sizeof(Face::fRef));
91 static_assert(2 == offsetof(Face, fTest));
92 static_assert(2 == sizeof(Face::fTest));
93 static_assert(4 == offsetof(Face, fTestMask));
94 static_assert(2 == sizeof(Face::fTestMask));
95 static_assert(6 == offsetof(Face, fPassOp));
96 static_assert(1 == sizeof(Face::fPassOp));
97 static_assert(7 == offsetof(Face, fFailOp));
98 static_assert(1 == sizeof(Face::fFailOp));
99 static_assert(8 == offsetof(Face, fWriteMask));
100 static_assert(2 == sizeof(Face::fWriteMask));
101 static_assert(10 == sizeof(Face));
cdalton93a379b2016-05-11 13:58:08 -0700102}
103
104static constexpr GrStencilTest gUserStencilTestToRaw[kGrUserStencilTestCount] = {
105 // Tests that respect the clip.
106 GrStencilTest::kAlways, // kAlwaysIfInClip (This is only for when there is not a stencil clip).
107 GrStencilTest::kEqual, // kEqualIfInClip.
108 GrStencilTest::kLess, // kLessIfInClip.
109 GrStencilTest::kLEqual, // kLEqualIfInClip.
110
111 // Tests that ignore the clip.
112 GrStencilTest::kAlways,
113 GrStencilTest::kNever,
114 GrStencilTest::kGreater,
115 GrStencilTest::kGEqual,
116 GrStencilTest::kLess,
117 GrStencilTest::kLEqual,
118 GrStencilTest::kEqual,
119 GrStencilTest::kNotEqual
120};
121
Brian Salomon4dea72a2019-12-18 10:43:10 -0500122static_assert(0 == (int)GrUserStencilTest::kAlwaysIfInClip);
123static_assert(1 == (int)GrUserStencilTest::kEqualIfInClip);
124static_assert(2 == (int)GrUserStencilTest::kLessIfInClip);
125static_assert(3 == (int)GrUserStencilTest::kLEqualIfInClip);
126static_assert(4 == (int)GrUserStencilTest::kAlways);
127static_assert(5 == (int)GrUserStencilTest::kNever);
128static_assert(6 == (int)GrUserStencilTest::kGreater);
129static_assert(7 == (int)GrUserStencilTest::kGEqual);
130static_assert(8 == (int)GrUserStencilTest::kLess);
131static_assert(9 == (int)GrUserStencilTest::kLEqual);
132static_assert(10 == (int)GrUserStencilTest::kEqual);
133static_assert(11 == (int)GrUserStencilTest::kNotEqual);
cdalton93a379b2016-05-11 13:58:08 -0700134
135static constexpr GrStencilOp gUserStencilOpToRaw[kGrUserStencilOpCount] = {
136 GrStencilOp::kKeep,
137
138 // Ops that only modify user bits.
139 GrStencilOp::kZero,
140 GrStencilOp::kReplace,
141 GrStencilOp::kInvert,
142 GrStencilOp::kIncWrap,
143 GrStencilOp::kDecWrap,
144 GrStencilOp::kIncClamp, // kIncMaybeClamp.
145 GrStencilOp::kDecClamp, // kDecMaybeClamp.
146
147 // Ops that only modify the clip bit.
148 GrStencilOp::kZero, // kZeroClipBit.
149 GrStencilOp::kReplace, // kSetClipBit.
150 GrStencilOp::kInvert, // kInvertClipBit.
151
152 // Ops that modify clip and user bits.
153 GrStencilOp::kReplace, // kSetClipAndReplaceUserBits.
154 GrStencilOp::kZero // kZeroClipAndUserBits.
155};
156
Brian Salomon4dea72a2019-12-18 10:43:10 -0500157static_assert(0 == (int)GrUserStencilOp::kKeep);
158static_assert(1 == (int)GrUserStencilOp::kZero);
159static_assert(2 == (int)GrUserStencilOp::kReplace);
160static_assert(3 == (int)GrUserStencilOp::kInvert);
161static_assert(4 == (int)GrUserStencilOp::kIncWrap);
162static_assert(5 == (int)GrUserStencilOp::kDecWrap);
163static_assert(6 == (int)GrUserStencilOp::kIncMaybeClamp);
164static_assert(7 == (int)GrUserStencilOp::kDecMaybeClamp);
165static_assert(8 == (int)GrUserStencilOp::kZeroClipBit);
166static_assert(9 == (int)GrUserStencilOp::kSetClipBit);
167static_assert(10 == (int)GrUserStencilOp::kInvertClipBit);
168static_assert(11 == (int)GrUserStencilOp::kSetClipAndReplaceUserBits);
169static_assert(12 == (int)GrUserStencilOp::kZeroClipAndUserBits);
cdalton93a379b2016-05-11 13:58:08 -0700170
171void GrStencilSettings::Face::reset(const GrUserStencilSettings::Face& user, bool hasStencilClip,
172 int numStencilBits) {
173 SkASSERT(user.fTest < (GrUserStencilTest)kGrUserStencilTestCount);
174 SkASSERT(user.fPassOp < (GrUserStencilOp)kGrUserStencilOpCount);
175 SkASSERT(user.fFailOp < (GrUserStencilOp)kGrUserStencilOpCount);
cdalton193d9cf2016-05-12 11:52:02 -0700176 SkASSERT(numStencilBits > 0 && numStencilBits <= 16);
cdalton93a379b2016-05-11 13:58:08 -0700177 int clipBit = 1 << (numStencilBits - 1);
178 int userMask = clipBit - 1;
179
Brian Osman788b9162020-02-07 10:36:46 -0500180 GrUserStencilOp maxOp = std::max(user.fPassOp, user.fFailOp);
181 SkDEBUGCODE(GrUserStencilOp otherOp = std::min(user.fPassOp, user.fFailOp);)
cdalton93a379b2016-05-11 13:58:08 -0700182 if (maxOp <= kLastUserOnlyStencilOp) {
183 // Ops that only modify user bits.
184 fWriteMask = user.fWriteMask & userMask;
185 SkASSERT(otherOp <= kLastUserOnlyStencilOp);
186 } else if (maxOp <= kLastClipOnlyStencilOp) {
187 // Ops that only modify the clip bit.
188 fWriteMask = clipBit;
189 SkASSERT(GrUserStencilOp::kKeep == otherOp ||
190 (otherOp > kLastUserOnlyStencilOp && otherOp <= kLastClipOnlyStencilOp));
191 } else {
192 // Ops that modify both clip and user bits.
193 fWriteMask = clipBit | (user.fWriteMask & userMask);
194 SkASSERT(GrUserStencilOp::kKeep == otherOp || otherOp > kLastClipOnlyStencilOp);
195 }
196
197 fFailOp = gUserStencilOpToRaw[(int)user.fFailOp];
198 fPassOp = gUserStencilOpToRaw[(int)user.fPassOp];
199
200 if (!hasStencilClip || user.fTest > kLastClippedStencilTest) {
201 // Ignore the clip.
202 fTestMask = user.fTestMask & userMask;
203 fTest = gUserStencilTestToRaw[(int)user.fTest];
204 } else if (GrUserStencilTest::kAlwaysIfInClip != user.fTest) {
205 // Respect the clip.
206 fTestMask = clipBit | (user.fTestMask & userMask);
207 fTest = gUserStencilTestToRaw[(int)user.fTest];
208 } else {
209 // Test only for clip.
210 fTestMask = clipBit;
211 fTest = GrStencilTest::kEqual;
212 }
213
214 fRef = (clipBit | user.fRef) & (fTestMask | fWriteMask);
215}
216
217void GrStencilSettings::Face::setDisabled() {
218 memset(this, 0, sizeof(*this));
Brian Salomon4dea72a2019-12-18 10:43:10 -0500219 static_assert(0 == (int)GrStencilTest::kAlways);
220 static_assert(0 == (int)GrStencilOp::kKeep);
cdalton93a379b2016-05-11 13:58:08 -0700221}
222
Michael Ludwigde228e52020-05-12 16:17:20 +0000223static constexpr GrUserStencilSettings gZeroStencilClipBit(
224 GrUserStencilSettings::StaticInit<
225 0x0000,
226 GrUserStencilTest::kAlways,
227 0xffff,
228 GrUserStencilOp::kZeroClipBit,
229 GrUserStencilOp::kZeroClipBit,
230 0x0000>()
231);
Michael Ludwig828d3412020-05-12 13:15:35 -0400232static constexpr GrUserStencilSettings gSetStencilClipBit(
233 GrUserStencilSettings::StaticInit<
234 0x0000,
235 GrUserStencilTest::kAlways,
236 0xffff,
237 GrUserStencilOp::kSetClipBit,
238 GrUserStencilOp::kSetClipBit,
239 0x0000>()
240);
Michael Ludwigde228e52020-05-12 16:17:20 +0000241
Mike Klein31550db2017-06-06 23:29:53 +0000242const GrUserStencilSettings* GrStencilSettings::SetClipBitSettings(bool setToInside) {
Michael Ludwig828d3412020-05-12 13:15:35 -0400243 return setToInside ? &gSetStencilClipBit : &gZeroStencilClipBit;
Mike Klein31550db2017-06-06 23:29:53 +0000244}
245
Greg Danielcba4ee22020-05-01 12:49:54 -0400246void GrStencilSettings::genKey(GrProcessorKeyBuilder* b, bool includeRefs) const {
Brian Osmanf0de96f2021-02-26 13:54:11 -0500247 b->addBits(6, fFlags, "stencilFlags");
cdalton93a379b2016-05-11 13:58:08 -0700248 if (this->isDisabled()) {
249 return;
250 }
251 if (!this->isTwoSided()) {
Greg Danielcba4ee22020-05-01 12:49:54 -0400252 if (includeRefs) {
Brian Osmanf0de96f2021-02-26 13:54:11 -0500253 b->addBytes(sizeof(Face), &fCWFace, "stencilCWFace");
Greg Danielcba4ee22020-05-01 12:49:54 -0400254 } else {
255 Face tempFace = fCWFace;
256 tempFace.fRef = 0;
Brian Osmanf0de96f2021-02-26 13:54:11 -0500257 b->addBytes(sizeof(Face), &tempFace, "stencilCWFace");
Greg Danielcba4ee22020-05-01 12:49:54 -0400258 }
cdalton93a379b2016-05-11 13:58:08 -0700259 } else {
Greg Danielcba4ee22020-05-01 12:49:54 -0400260 if (includeRefs) {
Brian Osmanf0de96f2021-02-26 13:54:11 -0500261 b->addBytes(sizeof(Face), &fCWFace, "stencilCWFace");
262 b->addBytes(sizeof(Face), &fCCWFace, "stencilCCWFace");
Greg Danielcba4ee22020-05-01 12:49:54 -0400263 } else {
264 Face tempFaces[2];
265 tempFaces[0] = fCWFace;
266 tempFaces[0].fRef = 0;
267 tempFaces[1] = fCCWFace;
268 tempFaces[1].fRef = 0;
Brian Osmanf0de96f2021-02-26 13:54:11 -0500269 b->addBytes(sizeof(Face), &tempFaces[0], "stencilCWFace");
270 b->addBytes(sizeof(Face), &tempFaces[1], "stencilCCWFace");
Greg Danielcba4ee22020-05-01 12:49:54 -0400271 }
cdalton93a379b2016-05-11 13:58:08 -0700272 }
273 // We rely on GrStencilSettings::Face being tightly packed for the key to be reliable.
Brian Salomon4dea72a2019-12-18 10:43:10 -0500274 static_assert(0 == offsetof(Face, fRef));
275 static_assert(2 == sizeof(Face::fRef));
276 static_assert(2 == offsetof(Face, fTest));
277 static_assert(2 == sizeof(Face::fTest));
278 static_assert(4 == offsetof(Face, fTestMask));
279 static_assert(2 == sizeof(Face::fTestMask));
280 static_assert(6 == offsetof(Face, fPassOp));
281 static_assert(1 == sizeof(Face::fPassOp));
282 static_assert(7 == offsetof(Face, fFailOp));
283 static_assert(1 == sizeof(Face::fFailOp));
284 static_assert(8 == offsetof(Face, fWriteMask));
285 static_assert(2 == sizeof(Face::fWriteMask));
286 static_assert(10 == sizeof(Face));
cdalton93a379b2016-05-11 13:58:08 -0700287}