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
13constexpr const GrUserStencilSettings gUnused(
14    GrUserStencilSettings::StaticInit<
15        0x0000,
16        GrUserStencilTest::kAlwaysIfInClip,
17        0xffff,
18        GrUserStencilOp::kKeep,
19        GrUserStencilOp::kKeep,
20        0x0000>()
21);
22
23static_assert(kAll_StencilFlags == (gUnused.fCWFlags[0] & gUnused.fCCWFlags[0]));
24
25const GrUserStencilSettings& GrUserStencilSettings::kUnused = gUnused;
26
27void 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
56void 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
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)) {
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
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
122static_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);
134
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
157static_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);
170
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);
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
217void 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
223static constexpr GrUserStencilSettings gZeroStencilClipBit(
224    GrUserStencilSettings::StaticInit<
225        0x0000,
226        GrUserStencilTest::kAlways,
227        0xffff,
228        GrUserStencilOp::kZeroClipBit,
229        GrUserStencilOp::kZeroClipBit,
230        0x0000>()
231);
232static constexpr GrUserStencilSettings gSetStencilClipBit(
233    GrUserStencilSettings::StaticInit<
234        0x0000,
235        GrUserStencilTest::kAlways,
236        0xffff,
237        GrUserStencilOp::kSetClipBit,
238        GrUserStencilOp::kSetClipBit,
239        0x0000>()
240);
241
242const GrUserStencilSettings* GrStencilSettings::SetClipBitSettings(bool setToInside) {
243    return setToInside ? &gSetStencilClipBit : &gZeroStencilClipBit;
244}
245
246void 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