• 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/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