• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/GrStencilSettings.h"
10 
11 #include "src/gpu/GrProcessor.h"
12 
13 constexpr const GrUserStencilSettings gUnused(
14     GrUserStencilSettings::StaticInit<
15         0x0000,
16         GrUserStencilTest::kAlwaysIfInClip,
17         0xffff,
18         GrUserStencilOp::kKeep,
19         GrUserStencilOp::kKeep,
20         0x0000>()
21 );
22 
23 static_assert(kAll_StencilFlags == (gUnused.fCWFlags[0] & gUnused.fCCWFlags[0]));
24 
25 const GrUserStencilSettings& GrUserStencilSettings::kUnused = gUnused;
26 
reset(const GrUserStencilSettings & user,bool hasStencilClip,int numStencilBits)27 void GrStencilSettings::reset(const GrUserStencilSettings& user, bool hasStencilClip,
28                               int numStencilBits) {
29     uint16_t cwFlags = user.fCWFlags[hasStencilClip];
30     if (cwFlags & kSingleSided_StencilFlag) {
31         SkASSERT(cwFlags == user.fCCWFlags[hasStencilClip]);
32         fFlags = cwFlags;
33         if (!this->isDisabled()) {
34             fCWFace.reset(user.fCWFace, hasStencilClip, numStencilBits);
35         }
36         return;
37     }
38 
39     uint16_t ccwFlags = user.fCCWFlags[hasStencilClip];
40     fFlags = cwFlags & ccwFlags;
41     if (this->isDisabled()) {
42         return;
43     }
44     if (!(cwFlags & kDisabled_StencilFlag)) {
45         fCWFace.reset(user.fCWFace, hasStencilClip, numStencilBits);
46     } else {
47         fCWFace.setDisabled();
48     }
49     if (!(ccwFlags & kDisabled_StencilFlag)) {
50         fCCWFace.reset(user.fCCWFace, hasStencilClip, numStencilBits);
51     } else {
52         fCCWFace.setDisabled();
53     }
54 }
55 
reset(const GrStencilSettings & that)56 void GrStencilSettings::reset(const GrStencilSettings& that) {
57     fFlags = that.fFlags;
58     if ((kInvalid_PrivateFlag | kDisabled_StencilFlag) & fFlags) {
59         return;
60     }
61     if (!this->isTwoSided()) {
62         memcpy(&fCWFace, &that.fCWFace, sizeof(Face));
63     } else {
64         memcpy(&fCWFace, &that.fCWFace, 2 * sizeof(Face));
65         static_assert(sizeof(Face) ==
66                       offsetof(GrStencilSettings, fCCWFace) - offsetof(GrStencilSettings, fCWFace));
67     }
68 }
69 
operator ==(const GrStencilSettings & that) const70 bool 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)) {
80         return 0 == memcmp(&fCWFace, &that.fCWFace, sizeof(Face)); // Both are single sided.
81     } else if (kSingleSided_StencilFlag & (fFlags | that.fFlags)) {
82         return false;
83     } else {
84         return 0 == memcmp(&fCWFace, &that.fCWFace, 2 * sizeof(Face));
85         static_assert(sizeof(Face) ==
86                       offsetof(GrStencilSettings, fCCWFace) - offsetof(GrStencilSettings, fCWFace));
87     }
88     // memcmp relies on GrStencilSettings::Face being tightly packed.
89     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));
102 }
103 
104 static 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 
122 static_assert(0 == (int)GrUserStencilTest::kAlwaysIfInClip);
123 static_assert(1 == (int)GrUserStencilTest::kEqualIfInClip);
124 static_assert(2 == (int)GrUserStencilTest::kLessIfInClip);
125 static_assert(3 == (int)GrUserStencilTest::kLEqualIfInClip);
126 static_assert(4 == (int)GrUserStencilTest::kAlways);
127 static_assert(5 == (int)GrUserStencilTest::kNever);
128 static_assert(6 == (int)GrUserStencilTest::kGreater);
129 static_assert(7 == (int)GrUserStencilTest::kGEqual);
130 static_assert(8 == (int)GrUserStencilTest::kLess);
131 static_assert(9 == (int)GrUserStencilTest::kLEqual);
132 static_assert(10 == (int)GrUserStencilTest::kEqual);
133 static_assert(11 == (int)GrUserStencilTest::kNotEqual);
134 
135 static 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 
157 static_assert(0 == (int)GrUserStencilOp::kKeep);
158 static_assert(1 == (int)GrUserStencilOp::kZero);
159 static_assert(2 == (int)GrUserStencilOp::kReplace);
160 static_assert(3 == (int)GrUserStencilOp::kInvert);
161 static_assert(4 == (int)GrUserStencilOp::kIncWrap);
162 static_assert(5 == (int)GrUserStencilOp::kDecWrap);
163 static_assert(6 == (int)GrUserStencilOp::kIncMaybeClamp);
164 static_assert(7 == (int)GrUserStencilOp::kDecMaybeClamp);
165 static_assert(8 == (int)GrUserStencilOp::kZeroClipBit);
166 static_assert(9 == (int)GrUserStencilOp::kSetClipBit);
167 static_assert(10 == (int)GrUserStencilOp::kInvertClipBit);
168 static_assert(11 == (int)GrUserStencilOp::kSetClipAndReplaceUserBits);
169 static_assert(12 == (int)GrUserStencilOp::kZeroClipAndUserBits);
170 
reset(const GrUserStencilSettings::Face & user,bool hasStencilClip,int numStencilBits)171 void 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);
176     SkASSERT(numStencilBits > 0 && numStencilBits <= 16);
177     int clipBit = 1 << (numStencilBits - 1);
178     int userMask = clipBit - 1;
179 
180     GrUserStencilOp maxOp = std::max(user.fPassOp, user.fFailOp);
181     SkDEBUGCODE(GrUserStencilOp otherOp = std::min(user.fPassOp, user.fFailOp);)
182     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 
setDisabled()217 void GrStencilSettings::Face::setDisabled() {
218     memset(this, 0, sizeof(*this));
219     static_assert(0 == (int)GrStencilTest::kAlways);
220     static_assert(0 == (int)GrStencilOp::kKeep);
221 }
222 
223 static constexpr GrUserStencilSettings gZeroStencilClipBit(
224     GrUserStencilSettings::StaticInit<
225         0x0000,
226         GrUserStencilTest::kAlways,
227         0xffff,
228         GrUserStencilOp::kZeroClipBit,
229         GrUserStencilOp::kZeroClipBit,
230         0x0000>()
231 );
232 static constexpr GrUserStencilSettings gSetStencilClipBit(
233     GrUserStencilSettings::StaticInit<
234         0x0000,
235         GrUserStencilTest::kAlways,
236         0xffff,
237         GrUserStencilOp::kSetClipBit,
238         GrUserStencilOp::kSetClipBit,
239         0x0000>()
240 );
241 
SetClipBitSettings(bool setToInside)242 const GrUserStencilSettings* GrStencilSettings::SetClipBitSettings(bool setToInside) {
243     return setToInside ? &gSetStencilClipBit : &gZeroStencilClipBit;
244 }
245 
genKey(GrProcessorKeyBuilder * b,bool includeRefs) const246 void GrStencilSettings::genKey(GrProcessorKeyBuilder* b, bool includeRefs) const {
247     b->addBits(6, fFlags, "stencilFlags");
248     if (this->isDisabled()) {
249         return;
250     }
251     if (!this->isTwoSided()) {
252         if (includeRefs) {
253             b->addBytes(sizeof(Face), &fCWFace, "stencilCWFace");
254         } else {
255             Face tempFace = fCWFace;
256             tempFace.fRef = 0;
257             b->addBytes(sizeof(Face), &tempFace, "stencilCWFace");
258         }
259     } else {
260         if (includeRefs) {
261             b->addBytes(sizeof(Face), &fCWFace, "stencilCWFace");
262             b->addBytes(sizeof(Face), &fCCWFace, "stencilCCWFace");
263         } else {
264             Face tempFaces[2];
265             tempFaces[0] = fCWFace;
266             tempFaces[0].fRef = 0;
267             tempFaces[1] = fCCWFace;
268             tempFaces[1].fRef = 0;
269             b->addBytes(sizeof(Face), &tempFaces[0], "stencilCWFace");
270             b->addBytes(sizeof(Face), &tempFaces[1], "stencilCCWFace");
271         }
272     }
273     // We rely on GrStencilSettings::Face being tightly packed for the key to be reliable.
274     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));
287 }
288