Flutter Engine
The Flutter Engine
GrStencilSettings.cpp
Go to the documentation of this file.
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 */
8
10#include "src/gpu/KeyBuilder.h"
11
12#include <algorithm>
13#include <cstddef>
14#include <cstring>
15
18 0x0000,
20 0xffff,
23 0x0000>()
24);
25
26static_assert(kAll_StencilFlags == (gUnused.fCWFlags[0] & gUnused.fCCWFlags[0]));
27
29
30void 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
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
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
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.
123};
124
125static_assert(0 == (int)GrUserStencilTest::kAlwaysIfInClip);
126static_assert(1 == (int)GrUserStencilTest::kEqualIfInClip);
127static_assert(2 == (int)GrUserStencilTest::kLessIfInClip);
128static_assert(3 == (int)GrUserStencilTest::kLEqualIfInClip);
129static_assert(4 == (int)GrUserStencilTest::kAlways);
130static_assert(5 == (int)GrUserStencilTest::kNever);
131static_assert(6 == (int)GrUserStencilTest::kGreater);
132static_assert(7 == (int)GrUserStencilTest::kGEqual);
133static_assert(8 == (int)GrUserStencilTest::kLess);
134static_assert(9 == (int)GrUserStencilTest::kLEqual);
135static_assert(10 == (int)GrUserStencilTest::kEqual);
136static_assert(11 == (int)GrUserStencilTest::kNotEqual);
137
140
141 // Ops that only modify user bits.
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
160static_assert(0 == (int)GrUserStencilOp::kKeep);
161static_assert(1 == (int)GrUserStencilOp::kZero);
162static_assert(2 == (int)GrUserStencilOp::kReplace);
163static_assert(3 == (int)GrUserStencilOp::kInvert);
164static_assert(4 == (int)GrUserStencilOp::kIncWrap);
165static_assert(5 == (int)GrUserStencilOp::kDecWrap);
166static_assert(6 == (int)GrUserStencilOp::kIncMaybeClamp);
167static_assert(7 == (int)GrUserStencilOp::kDecMaybeClamp);
168static_assert(8 == (int)GrUserStencilOp::kZeroClipBit);
169static_assert(9 == (int)GrUserStencilOp::kSetClipBit);
170static_assert(10 == (int)GrUserStencilOp::kInvertClipBit);
172static_assert(12 == (int)GrUserStencilOp::kZeroClipAndUserBits);
173
175 int numStencilBits) {
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;
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);
198 }
199
202
203 if (!hasStencilClip || user.fTest > kLastClippedStencilTest) {
204 // Ignore the clip.
205 fTestMask = user.fTestMask & userMask;
207 } else if (GrUserStencilTest::kAlwaysIfInClip != user.fTest) {
208 // Respect the clip.
209 fTestMask = clipBit | (user.fTestMask & userMask);
211 } else {
212 // Test only for clip.
213 fTestMask = clipBit;
215 }
216
217 fRef = (clipBit | user.fRef) & (fTestMask | fWriteMask);
218}
219
221 memset(this, 0, sizeof(*this));
222 static_assert(0 == (int)GrStencilTest::kAlways);
223 static_assert(0 == (int)GrStencilOp::kKeep);
224}
225
228 0x0000,
230 0xffff,
233 0x0000>()
234);
237 0x0000,
239 0xffff,
242 0x0000>()
243);
244
246 return setToInside ? &gSetStencilClipBit : &gZeroStencilClipBit;
247}
248
249void 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}
static constexpr GrUserStencilSettings gSetStencilClipBit(GrUserStencilSettings::StaticInit< 0x0000, GrUserStencilTest::kAlways, 0xffff, GrUserStencilOp::kSetClipBit, GrUserStencilOp::kSetClipBit, 0x0000 >())
static constexpr GrUserStencilSettings gZeroStencilClipBit(GrUserStencilSettings::StaticInit< 0x0000, GrUserStencilTest::kAlways, 0xffff, GrUserStencilOp::kZeroClipBit, GrUserStencilOp::kZeroClipBit, 0x0000 >())
static constexpr GrStencilOp gUserStencilOpToRaw[kGrUserStencilOpCount]
static constexpr GrStencilTest gUserStencilTestToRaw[kGrUserStencilTestCount]
constexpr const GrUserStencilSettings gUnused(GrUserStencilSettings::StaticInit< 0x0000, GrUserStencilTest::kAlwaysIfInClip, 0xffff, GrUserStencilOp::kKeep, GrUserStencilOp::kKeep, 0x0000 >())
GrStencilTest
GrStencilOp
static constexpr GrUserStencilOp kLastUserOnlyStencilOp
@ kAll_StencilFlags
@ kSingleSided_StencilFlag
@ kDisabled_StencilFlag
GrUserStencilTest
static constexpr GrUserStencilOp kLastClipOnlyStencilOp
static constexpr GrUserStencilTest kLastClippedStencilTest
static constexpr int kGrUserStencilOpCount
static constexpr int kGrUserStencilTestCount
#define SkASSERT(cond)
Definition: SkAssert.h:116
SkDEBUGCODE(SK_SPI) SkThreadID SkGetThreadID()
void genKey(skgpu::KeyBuilder *b, bool includeRefsAndMasks) const
void reset(const GrUserStencilSettings &, bool hasStencilClip, int numStencilBits)
static const GrUserStencilSettings * SetClipBitSettings(bool setToInside)
bool isTwoSided() const
bool operator==(const GrStencilSettings &) const
bool isDisabled() const
static bool b
static float max(float r, float g, float b)
Definition: hsl.cpp:49
static float min(float r, float g, float b)
Definition: hsl.cpp:48
void reset(const GrUserStencilSettings::Face &, bool useStencilClip, int numStencilBits)
static constexpr Init< Ref, Test, TestMask, PassOp, FailOp, WriteMask > StaticInit()
static const GrUserStencilSettings & kUnused