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