1 | /* |
2 | * Copyright 2016 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 | #ifndef GrStencilSettings_DEFINED |
10 | #define GrStencilSettings_DEFINED |
11 | |
12 | #include "include/core/SkRegion.h" |
13 | #include "src/gpu/GrUserStencilSettings.h" |
14 | |
15 | class GrProcessorKeyBuilder; |
16 | |
17 | enum class GrStencilTest : uint16_t { |
18 | kAlways, |
19 | kNever, |
20 | kGreater, |
21 | kGEqual, |
22 | kLess, |
23 | kLEqual, |
24 | kEqual, |
25 | kNotEqual |
26 | }; |
27 | static constexpr int kGrStencilTestCount = 1 + (int)GrStencilTest::kNotEqual; |
28 | |
29 | enum class GrStencilOp : uint8_t { |
30 | kKeep, |
31 | kZero, |
32 | kReplace, // Replace stencil value with fRef (only the bits enabled in fWriteMask). |
33 | kInvert, |
34 | kIncWrap, |
35 | kDecWrap, |
36 | // NOTE: clamping occurs before the write mask. So if the MSB is zero and masked out, stencil |
37 | // values will still wrap when using clamping ops. |
38 | kIncClamp, |
39 | kDecClamp |
40 | }; |
41 | static constexpr int kGrStencilOpCount = 1 + (int)GrStencilOp::kDecClamp; |
42 | |
43 | /** |
44 | * This class defines concrete stencil settings that map directly to the underlying hardware. It |
45 | * is deduced from user stencil settings, stencil clip status, and the number of bits in the |
46 | * target stencil buffer. |
47 | */ |
48 | class GrStencilSettings { |
49 | public: |
50 | GrStencilSettings() { this->setDisabled(); } |
51 | GrStencilSettings(const GrUserStencilSettings& user, bool hasStencilClip, int numStencilBits) { |
52 | this->reset(user, hasStencilClip, numStencilBits); |
53 | } |
54 | GrStencilSettings(const GrStencilSettings& that) { this->reset(that); } |
55 | GrStencilSettings& operator=(const GrStencilSettings& that) { this->reset(that); return *this; } |
56 | |
57 | void invalidate() { fFlags |= kInvalid_PrivateFlag; } |
58 | void setDisabled() { fFlags = kAll_StencilFlags; } |
59 | void reset(const GrUserStencilSettings&, bool hasStencilClip, int numStencilBits); |
60 | void reset(const GrStencilSettings&); |
61 | |
62 | bool isValid() const { return !(fFlags & kInvalid_PrivateFlag); } |
63 | bool isDisabled() const { SkASSERT(this->isValid()); return fFlags & kDisabled_StencilFlag; } |
64 | bool doesWrite() const { SkASSERT(this->isValid()); |
65 | return !(fFlags & kNoModifyStencil_StencilFlag); } |
66 | bool isTwoSided() const { SkASSERT(this->isValid()); |
67 | return !(fFlags & kSingleSided_StencilFlag); } |
68 | bool usesWrapOp() const { SkASSERT(this->isValid()); |
69 | return !(fFlags & kNoWrapOps_StencilFlag); } |
70 | |
71 | void genKey(GrProcessorKeyBuilder* b, bool includeRefsAndMasks) const; |
72 | |
73 | bool operator!=(const GrStencilSettings& that) const { return !(*this == that); } |
74 | bool operator==(const GrStencilSettings&) const; |
75 | |
76 | struct Face : public GrTStencilFaceSettings<GrStencilTest, GrStencilOp> { |
77 | void reset(const GrUserStencilSettings::Face&, bool useStencilClip, int numStencilBits); |
78 | void setDisabled(); |
79 | }; |
80 | |
81 | const Face& singleSidedFace() const { |
82 | SkASSERT(!this->isDisabled()); |
83 | SkASSERT(!this->isTwoSided()); |
84 | return fCWFace; |
85 | } |
86 | // Returns the stencil settings for triangles that wind clockwise in "post-origin" space. |
87 | // (i.e., the space that results after a potential y-axis flip on device space for bottom-left |
88 | // origins.) |
89 | const Face& postOriginCWFace(GrSurfaceOrigin origin) const { |
90 | SkASSERT(this->isTwoSided()); |
91 | return (kTopLeft_GrSurfaceOrigin == origin) ? fCWFace : fCCWFace; |
92 | } |
93 | // Returns the stencil settings for triangles that wind counter-clockwise in "post-origin" |
94 | // space. (i.e., the space that results after a potential y-axis flip on device space for |
95 | // bottom-left origins.) |
96 | const Face& postOriginCCWFace(GrSurfaceOrigin origin) const { |
97 | SkASSERT(this->isTwoSided()); |
98 | return (kTopLeft_GrSurfaceOrigin == origin) ? fCCWFace : fCWFace; |
99 | } |
100 | |
101 | /** Gets the user stencil settings to directly set the clip bit. */ |
102 | static const GrUserStencilSettings* SetClipBitSettings(bool setToInside); |
103 | |
104 | private: |
105 | // Internal flag for backends to optionally mark their tracked stencil state as invalid. |
106 | // NOTE: This value is outside the declared range of GrStencilFlags, but since that type is |
107 | // explicitly backed by 'int', it can still represent this constant. clang 11 complains about |
108 | // mixing enum types in bit operations, so this works around that. |
109 | static constexpr GrStencilFlags kInvalid_PrivateFlag = |
110 | static_cast<GrStencilFlags>(kLast_StencilFlag << 1); |
111 | |
112 | uint32_t fFlags; |
113 | Face fCWFace; |
114 | Face fCCWFace; |
115 | }; |
116 | |
117 | #endif |
118 | |