| 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 |  | 
|---|