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: GrStencilSettings()50 GrStencilSettings() { this->setDisabled(); } GrStencilSettings(const GrUserStencilSettings & user,bool hasStencilClip,int numStencilBits)51 GrStencilSettings(const GrUserStencilSettings& user, bool hasStencilClip, int numStencilBits) { 52 this->reset(user, hasStencilClip, numStencilBits); 53 } GrStencilSettings(const GrStencilSettings & that)54 GrStencilSettings(const GrStencilSettings& that) { this->reset(that); } 55 GrStencilSettings& operator=(const GrStencilSettings& that) { this->reset(that); return *this; } 56 invalidate()57 void invalidate() { fFlags |= kInvalid_PrivateFlag; } setDisabled()58 void setDisabled() { fFlags = kAll_StencilFlags; } 59 void reset(const GrUserStencilSettings&, bool hasStencilClip, int numStencilBits); 60 void reset(const GrStencilSettings&); 61 isValid()62 bool isValid() const { return !(fFlags & kInvalid_PrivateFlag); } isDisabled()63 bool isDisabled() const { SkASSERT(this->isValid()); return fFlags & kDisabled_StencilFlag; } doesWrite()64 bool doesWrite() const { SkASSERT(this->isValid()); 65 return !(fFlags & kNoModifyStencil_StencilFlag); } isTwoSided()66 bool isTwoSided() const { SkASSERT(this->isValid()); 67 return !(fFlags & kSingleSided_StencilFlag); } usesWrapOp()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 singleSidedFace()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.) postOriginCWFace(GrSurfaceOrigin origin)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.) postOriginCCWFace(GrSurfaceOrigin origin)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