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 "GrUserStencilSettings.h" 13 #include "SkRegion.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 front()81 const Face& front() const { SkASSERT(!this->isDisabled()); return fFront; } back()82 const Face& back() const { SkASSERT(this->isTwoSided()); return fBack; } 83 84 /** 85 * Given a thing to draw into the stencil clip, a fill type, and a set op 86 * this function determines: 87 * 1. Whether the thing can be draw directly to the stencil clip or 88 * needs to be drawn to the client portion of the stencil first. 89 * 2. How many passes are needed. 90 * 3. What those passes are. 91 * 92 * @param op the set op to combine this element with the existing clip 93 * @param canBeDirect can the caller draw this element directly (without using stencil)? 94 * @param invertedFill is this path inverted 95 * @param drawDirectToClip out: true if caller should draw the element directly, false if it 96 * should draw it into the user stencil bits first. 97 * 98 * @return a null-terminated array of settings for stencil passes. 99 * 100 * If drawDirectToClip is false, the caller must first draw the element into the user 101 * stencil bits, and then cover the clip area with multiple passes using the returned 102 * stencil settings. 103 * 104 * If drawDirectToClip is true, the returned array will only have one pass and the 105 * caller should use those stencil settings while drawing the element directly. 106 */ 107 static GrUserStencilSettings const* const* GetClipPasses(SkRegion::Op op, 108 bool canBeDirect, 109 bool invertedFill, 110 bool* drawDirectToClip); 111 112 /** Gets the user stencil settings to directly set the clip bit. */ 113 static const GrUserStencilSettings* SetClipBitSettings(bool setToInside); 114 115 private: 116 // Internal flag for backends to optionally mark their tracked stencil state as invalid. 117 enum { kInvalid_PrivateFlag = (kLast_StencilFlag << 1) }; 118 119 uint32_t fFlags; 120 Face fFront; 121 Face fBack; 122 }; 123 124 #endif 125