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) 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 | /** |
102 | * Given a thing to draw into the stencil clip, a fill type, and a set op |
103 | * this function determines: |
104 | * 1. Whether the thing can be draw directly to the stencil clip or |
105 | * needs to be drawn to the client portion of the stencil first. |
106 | * 2. How many passes are needed. |
107 | * 3. What those passes are. |
108 | * |
109 | * @param op the set op to combine this element with the existing clip |
110 | * @param canBeDirect can the caller draw this element directly (without using stencil)? |
111 | * @param invertedFill is this path inverted |
112 | * @param drawDirectToClip out: true if caller should draw the element directly, false if it |
113 | * should draw it into the user stencil bits first. |
114 | * |
115 | * @return a null-terminated array of settings for stencil passes. |
116 | * |
117 | * If drawDirectToClip is false, the caller must first draw the element into the user |
118 | * stencil bits, and then cover the clip area with multiple passes using the returned |
119 | * stencil settings. |
120 | * |
121 | * If drawDirectToClip is true, the returned array will only have one pass and the |
122 | * caller should use those stencil settings while drawing the element directly. |
123 | */ |
124 | static GrUserStencilSettings const* const* GetClipPasses(SkRegion::Op op, |
125 | bool canBeDirect, |
126 | bool invertedFill, |
127 | bool* drawDirectToClip); |
128 | |
129 | /** Gets the user stencil settings to directly set the clip bit. */ |
130 | static const GrUserStencilSettings* SetClipBitSettings(bool setToInside); |
131 | |
132 | private: |
133 | // Internal flag for backends to optionally mark their tracked stencil state as invalid. |
134 | // NOTE: This value is outside the declared range of GrStencilFlags, but since that type is |
135 | // explicitly backed by 'int', it can still represent this constant. clang 11 complains about |
136 | // mixing enum types in bit operations, so this works around that. |
137 | static constexpr GrStencilFlags kInvalid_PrivateFlag = |
138 | static_cast<GrStencilFlags>(kLast_StencilFlag << 1); |
139 | |
140 | uint32_t fFlags; |
141 | Face fCWFace; |
142 | Face fCCWFace; |
143 | }; |
144 | |
145 | #endif |
146 | |