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