Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 | 8 |
| 9 #ifndef GrStencil_DEFINED | 9 #ifndef GrStencil_DEFINED |
| 10 #define GrStencil_DEFINED | 10 #define GrStencil_DEFINED |
| 11 | 11 |
| 12 #include "GrTypes.h" | 12 #include "GrTypes.h" |
| 13 #include "SkRegion.h" | 13 #include "SkRegion.h" |
| 14 | 14 |
| 15 class GrProcessorKeyBuilder; | 15 class GrProcessorKeyBuilder; |
| 16 | 16 |
| 17 /** | 17 /** |
| 18 * Gr uses the stencil buffer to implement complex clipping inside the | 18 * Gr uses the stencil buffer to implement complex clipping inside the |
| 19 * GrDrawTarget class. The GrDrawTarget makes a subset of the stencil buffer | 19 * GrDrawTarget class. The GrDrawTarget makes a subset of the stencil buffer |
| 20 * bits available for other uses by external code (clients). Client code can | 20 * bits available for other uses by external code (user bits). Client code can |
| 21 * modify these bits. GrDrawTarget will ignore ref, mask, and writemask bits | 21 * modify these bits. GrDrawTarget will ignore ref, mask, and writemask bits |
| 22 * provided by clients that overlap the bits used to implement clipping. | 22 * provided by clients that fall outside the user range. |
| 23 * | 23 * |
| 24 * When code outside the GrDrawTarget class uses the stencil buffer the contract | 24 * When code outside the GrDrawTarget class uses the stencil buffer the contract |
| 25 * is as follows: | 25 * is as follows: |
| 26 * | 26 * |
| 27 * > Normal stencil funcs allow the client to pass / fail regardless of the | 27 * > Normal stencil funcs allow the client to pass / fail regardless of the |
| 28 * reserved clip bits. | 28 * reserved clip bits. |
| 29 * > Additional functions allow a test against the clip along with a limited | 29 * > Additional functions allow a test against the clip along with a limited |
| 30 * set of tests against the client bits. | 30 * set of tests against the user bits. |
| 31 * > Client can assume all client bits are zero initially. | 31 * > Client can assume all user bits are zero initially. |
| 32 * > Client must ensure that after all its passes are finished it has only | 32 * > Client must ensure that after all its passes are finished it has only |
| 33 * written to the color buffer in the region inside the clip. Furthermore, it | 33 * written to the color buffer in the region inside the clip. Furthermore, it |
| 34 * must zero all client bits that were modifed (both inside and outside the | 34 * must zero all user bits that were modifed (both inside and outside the |
| 35 * clip). | 35 * clip). |
| 36 */ | 36 */ |
| 37 | 37 |
| 38 enum GrStencilFlags { | |
| 39 kDisabled_StencilFlag = 0x1, | |
| 40 kNoModifyStencil_StencilFlag = 0x2, | |
| 41 kNoWrapOps_StencilFlag = 0x4, | |
| 42 kSingleSided_StencilFlag = 0x8, | |
| 43 | |
| 44 kLast_StencilFlag = kSingleSided_StencilFlag, | |
| 45 kAll_StencilFlags = kLast_StencilFlag | (kLast_StencilFlag - 1) | |
| 46 }; | |
| 47 | |
| 48 template<typename TTest, typename TOp> struct GrTStencilFaceSettings { | |
| 49 uint16_t fRef; // Reference value for stencil test and ops. | |
| 50 TTest fTest; // Stencil test function, where fRef is on the left side. | |
| 51 uint16_t fTestMask; // Bitwise "and" to perform on fRef and stencil valu es before testing. | |
| 52 // (e.g. (fRef & fTestMask) < (stencil & fTestMask)) | |
| 53 TOp fPassOp; // Op to perform when the test passes. | |
| 54 TOp fFailOp; // Op to perform when the test fails. | |
| 55 uint16_t fWriteMask; // Indicates which bits in the stencil buffer should be updated. | |
| 56 // (e.g. stencil = (newValue & fWriteMask) | (stenci l & ~fWriteMask)) | |
| 57 }; | |
| 58 | |
| 59 //////////////////////////////////////////////////////////////////////////////// //////////////////// | |
| 60 | |
| 61 enum class GrUserStencilTest : uint16_t { | |
| 62 // Tests that respect the clip bit (if in use). | |
|
bsalomon
2016/05/10 14:06:21
Maybe say that these tests "always fail when the c
Chris Dalton
2016/05/10 16:39:30
How's the reworded comment?
bsalomon
2016/05/10 20:10:58
better, thanks.
| |
| 63 kAlwaysIfInClip, | |
| 64 kEqualIfInClip, | |
| 65 kLessIfInClip, | |
| 66 kLEqualIfInClip, | |
| 67 | |
| 68 // Tests that ignore the clip bit. The client is responsible to ensure no co lor writes occur | |
| 69 // outside the clip when it is in use. | |
| 70 kAlways, | |
| 71 kNever, | |
| 72 kGreater, | |
| 73 kGEqual, | |
| 74 kLess, | |
| 75 kLEqual, | |
| 76 kEqual, | |
| 77 kNotEqual | |
| 78 }; | |
| 79 static constexpr GrUserStencilTest kLastClippedStencilTest = GrUserStencilTest:: kLEqualIfInClip; | |
| 80 static constexpr int kGrUserStencilTestCount = 1 + (int)GrUserStencilTest::kNotE qual; | |
| 81 | |
| 82 enum class GrUserStencilOp : uint8_t { | |
| 83 kKeep, | |
| 84 | |
| 85 // Ops that only modify user bits. These must not be paired with ops that mo dify the clip bit. | |
| 86 kZero, | |
| 87 kReplace, // Replace stencil value with fRef (only the bits enabled in fWrit eMask). | |
| 88 kInvert, | |
| 89 kIncWrap, | |
| 90 kDecWrap, | |
| 91 // These two should only be used if wrap ops are not supported, or if the ma th is guaranteed | |
| 92 // to not overflow. The user bits may or may not clamp, depending on the sta te of non-user bits. | |
| 93 kIncMaybeClamp, | |
| 94 kDecMaybeClamp, | |
| 95 | |
| 96 // Ops that only modify the clip bit. These must not be paired with ops that modify user bits. | |
| 97 kZeroClipBit, | |
| 98 kSetClipBit, | |
| 99 kInvertClipBit, | |
| 100 | |
| 101 // Ops that modify both clip and user bits. These can only be paired with kK eep or each other. | |
| 102 kSetClipAndReplaceUserBits, | |
| 103 kZeroClipAndUserBits | |
| 104 }; | |
| 105 static constexpr GrUserStencilOp kLastUserOnlyStencilOp = GrUserStencilOp::kDecM aybeClamp; | |
| 106 static constexpr GrUserStencilOp kLastClipOnlyStencilOp = GrUserStencilOp::kInve rtClipBit; | |
| 107 static constexpr int kGrUserStencilOpCount = 1 + (int)GrUserStencilOp::kZeroClip AndUserBits; | |
| 108 | |
| 38 /** | 109 /** |
| 39 * Determines which pixels pass / fail the stencil test. | 110 * This struct is a compile-time constant representation of user stencil setting s. It describes in |
| 40 * Stencil test passes if (ref & mask) FUNC (stencil & mask) is true | 111 * abstract terms how a draw will use the stencil buffer. It gets ODR-used at ru ntime to define a |
| 112 * draw's stencil settings, and is later translated into concrete settings when the pipeline is | |
| 113 * finalized. | |
| 41 */ | 114 */ |
| 42 enum GrStencilFunc { | 115 struct GrUserStencilSettings { |
| 43 kAlways_StencilFunc = 0, | 116 typedef GrTStencilFaceSettings<GrUserStencilTest, GrUserStencilOp> Face; |
| 44 kNever_StencilFunc, | 117 |
| 45 kGreater_StencilFunc, | 118 template<GrUserStencilTest, GrUserStencilOp PassOp, GrUserStencilOp FailOp> struct Attrs; |
| 46 kGEqual_StencilFunc, | 119 |
| 47 kLess_StencilFunc, | 120 // Unfortunately, this is the only way to pass template arguments to a const ructor. |
| 48 kLEqual_StencilFunc, | 121 template<uint16_t Ref, GrUserStencilTest Test, uint16_t TestMask, |
| 49 kEqual_StencilFunc, | 122 GrUserStencilOp PassOp, GrUserStencilOp FailOp, uint16_t WriteMask> struct Init {}; |
| 50 kNotEqual_StencilFunc, | 123 |
| 51 | 124 template<uint16_t FtRef, uint16_t BkRef, |
| 52 // Gr stores the current clip in the | 125 GrUserStencilTest FtTest, GrUserStencilTest BkTest, |
| 53 // stencil buffer in the high bits that | 126 uint16_t FtTestMask, uint16_t BkTestMask, |
| 54 // are not directly accessible modifiable | 127 GrUserStencilOp FtPassOp, GrUserStencilOp BkPassOp, |
| 55 // via the GrDrawTarget interface. The below | 128 GrUserStencilOp FtFailOp, GrUserStencilOp BkFailOp, |
| 56 // stencil funcs test against the current | 129 uint16_t FtWriteMask, uint16_t BkWriteMask> struct InitSeparat e {}; |
| 57 // clip in addition to the GrDrawTarget | 130 |
| 58 // client's stencil bits. | 131 template<uint16_t Ref, GrUserStencilTest Test, uint16_t TestMask, |
| 59 | 132 GrUserStencilOp PassOp, GrUserStencilOp FailOp, uint16_t WriteMask> |
| 60 // pass if inside the clip | 133 constexpr static Init<Ref, Test, TestMask, PassOp, FailOp, WriteMask> Static Init() { |
| 61 kAlwaysIfInClip_StencilFunc, | 134 return Init<Ref, Test, TestMask, PassOp, FailOp, WriteMask>(); |
| 62 kEqualIfInClip_StencilFunc, | 135 } |
| 63 kLessIfInClip_StencilFunc, | 136 |
| 64 kLEqualIfInClip_StencilFunc, | 137 template<uint16_t FtRef, uint16_t BkRef, |
| 65 kNonZeroIfInClip_StencilFunc, // this one forces the ref to be 0 | 138 GrUserStencilTest FtTest, GrUserStencilTest BkTest, |
| 66 | 139 uint16_t FtTestMask, uint16_t BkTestMask, |
| 67 kLast_StencilFunc = kNonZeroIfInClip_StencilFunc | 140 GrUserStencilOp FtPassOp, GrUserStencilOp BkPassOp, |
| 68 }; | 141 GrUserStencilOp FtFailOp, GrUserStencilOp BkFailOp, |
| 69 | 142 uint16_t FtWriteMask, uint16_t BkWriteMask> |
| 70 static const int kStencilFuncCnt = kLast_StencilFunc + 1; | 143 constexpr static InitSeparate<FtRef, BkRef, FtTest, BkTest, FtTestMask, BkTe stMask, |
| 71 static const int kClipStencilFuncCnt = | 144 FtPassOp, BkPassOp, FtFailOp, BkFailOp, FtWrit eMask, |
| 72 kNonZeroIfInClip_StencilFunc - kAlwaysIfInClip_StencilFunc + 1; | 145 BkWriteMask> StaticInitSeparate() { |
| 73 static const int kBasicStencilFuncCnt = kStencilFuncCnt - kClipStencilFuncCnt; | 146 return InitSeparate<FtRef, BkRef, FtTest, BkTest, FtTestMask, BkTestMask , |
| 147 FtPassOp, BkPassOp, FtFailOp, BkFailOp, FtWriteMask, BkWriteMask>(); | |
| 148 } | |
| 149 | |
| 150 // We construct with template arguments in order to enforce that the struct be compile-time | |
| 151 // constant and to make use of static asserts. | |
| 152 template<uint16_t Ref, GrUserStencilTest Test, uint16_t TestMask, | |
| 153 GrUserStencilOp PassOp, GrUserStencilOp FailOp, uint16_t WriteMask, | |
| 154 typename Attrs = Attrs<Test, PassOp, FailOp> > | |
| 155 constexpr explicit GrUserStencilSettings( | |
| 156 const Init<Ref, Test, TestMask, PassOp, FailOp, WriteMask>&) | |
| 157 : fFrontFlags{Attrs::Flags(false) | kSingleSided_StencilFlag, | |
| 158 Attrs::Flags(true) | kSingleSided_StencilFlag} | |
| 159 , fFront{Ref, Test, Attrs::EffectiveTestMask(TestMask), PassOp, FailOp, | |
| 160 Attrs::EffectiveWriteMask(WriteMask)} | |
| 161 , fBackFlags{Attrs::Flags(false) | kSingleSided_StencilFlag, | |
| 162 Attrs::Flags(true) | kSingleSided_StencilFlag} | |
| 163 , fBack{Ref, Test, Attrs::EffectiveTestMask(TestMask), PassOp, FailOp, | |
| 164 Attrs::EffectiveWriteMask(WriteMask)} { | |
| 165 } | |
| 166 | |
| 167 template<uint16_t FtRef, uint16_t BkRef, | |
| 168 GrUserStencilTest FtTest, GrUserStencilTest BkTest, | |
| 169 uint16_t FtTestMask, uint16_t BkTestMask, | |
| 170 GrUserStencilOp FtPassOp, GrUserStencilOp BkPassOp, | |
| 171 GrUserStencilOp FtFailOp, GrUserStencilOp BkFailOp, | |
| 172 uint16_t FtWriteMask, uint16_t BkWriteMask, | |
| 173 typename FtAttrs = Attrs<FtTest, FtPassOp, FtFailOp>, | |
| 174 typename BkAttrs = Attrs<BkTest, BkPassOp, BkFailOp> > | |
| 175 constexpr explicit GrUserStencilSettings( | |
| 176 const InitSeparate<FtRef, BkRef, FtTest, BkTest, FtTestMask, BkTestM ask, | |
| 177 FtPassOp, BkPassOp, FtFailOp, BkFailOp, FtWriteMa sk, BkWriteMask>&) | |
| 178 : fFrontFlags{FtAttrs::Flags(false), FtAttrs::Flags(true)} | |
| 179 , fFront{FtRef, FtTest, FtAttrs::EffectiveTestMask(FtTestMask), FtPassOp , FtFailOp, | |
| 180 FtAttrs::EffectiveWriteMask(FtWriteMask)} | |
| 181 , fBackFlags{BkAttrs::Flags(false), BkAttrs::Flags(true)} | |
| 182 , fBack{BkRef, BkTest, BkAttrs::EffectiveTestMask(BkTestMask), BkPassOp, BkFailOp, | |
| 183 BkAttrs::EffectiveWriteMask(BkWriteMask)} {} | |
| 184 | |
| 185 // This struct can only be constructed with static initializers. | |
| 186 GrUserStencilSettings() = delete; | |
| 187 GrUserStencilSettings(const GrUserStencilSettings&) = delete; | |
| 188 | |
| 189 const uint16_t fFrontFlags[2]; // frontFlagsForDraw = fFrontFlags[hasStenc ilClip]. | |
| 190 const Face fFront; | |
| 191 const uint16_t fBackFlags[2]; // backFlagsForDraw = fBackFlags[hasStencilC lip]. | |
| 192 const Face fBack; | |
| 193 | |
| 194 static const GrUserStencilSettings& kUnused; | |
| 195 }; | |
| 196 | |
| 197 template<GrUserStencilTest Test, GrUserStencilOp PassOp, GrUserStencilOp FailOp> | |
| 198 struct GrUserStencilSettings::Attrs { | |
| 199 // Ensure an op that only modifies user bits isn't paired with one that modi fies clip bits. | |
| 200 GR_STATIC_ASSERT(GrUserStencilOp::kKeep == PassOp || GrUserStencilOp::kKeep == FailOp || | |
| 201 (PassOp <= kLastUserOnlyStencilOp) == (FailOp <= kLastUserO nlyStencilOp)); | |
| 202 // Ensure an op that only modifies clip bits isn't paired with one that modi fies clip and user. | |
| 203 GR_STATIC_ASSERT(GrUserStencilOp::kKeep == PassOp || GrUserStencilOp::kKeep == FailOp || | |
| 204 (PassOp <= kLastClipOnlyStencilOp) == (FailOp <= kLastClipO nlyStencilOp)); | |
| 205 | |
| 206 static constexpr bool TestAlwaysPasses(bool hasStencilClip) { | |
| 207 return (!hasStencilClip && GrUserStencilTest::kAlwaysIfInClip == Test) | | | |
| 208 GrUserStencilTest::kAlways == Test; | |
| 209 } | |
| 210 static constexpr bool DoesNotModifyStencil(bool hasStencilClip) { | |
| 211 return (GrUserStencilTest::kNever == Test || GrUserStencilOp::kKeep == P assOp) && | |
| 212 (TestAlwaysPasses(hasStencilClip) || GrUserStencilOp::kKeep == F ailOp); | |
| 213 } | |
| 214 static constexpr bool IsDisabled(bool hasStencilClip) { | |
| 215 return TestAlwaysPasses(hasStencilClip) && DoesNotModifyStencil(hasStenc ilClip); | |
| 216 } | |
| 217 static constexpr bool UsesWrapOps() { | |
| 218 return GrUserStencilOp::kIncWrap == PassOp || GrUserStencilOp::kDecWrap == PassOp || | |
| 219 GrUserStencilOp::kIncWrap == FailOp || GrUserStencilOp::kDecWrap == FailOp; | |
| 220 } | |
| 221 static constexpr bool TestIgnoresRef() { | |
| 222 return (GrUserStencilTest::kAlwaysIfInClip == Test || GrUserStencilTest: :kAlways == Test || | |
| 223 GrUserStencilTest::kNever == Test); | |
| 224 } | |
| 225 static constexpr uint16_t Flags(bool hasStencilClip) { | |
| 226 return (IsDisabled(hasStencilClip) ? kDisabled_StencilFlag : 0) | | |
| 227 (DoesNotModifyStencil(hasStencilClip) ? kNoModifyStencil_StencilF lag : 0) | | |
| 228 (UsesWrapOps() ? 0 : kNoWrapOps_StencilFlag); | |
| 229 } | |
| 230 static constexpr uint16_t EffectiveTestMask(uint16_t testMask) { | |
| 231 return TestIgnoresRef() ? 0 : testMask; | |
| 232 } | |
| 233 static constexpr uint16_t EffectiveWriteMask(uint16_t writeMask) { | |
| 234 // We don't modify the mask differently when hasStencilClip=false becaus e either the entire | |
| 235 // face gets disabled in that case (e.g. Test=kAlwaysIfInClip, PassOp=kK eep), or the | |
| 236 // effective mask stays the same either way. | |
| 237 return DoesNotModifyStencil(true) ? 0 : writeMask; | |
| 238 } | |
| 239 }; | |
| 240 | |
| 241 //////////////////////////////////////////////////////////////////////////////// //////////////////// | |
| 242 | |
| 243 enum class GrStencilTest : uint16_t { | |
|
bsalomon
2016/05/10 14:06:21
I'm wondering if this could be in another file tha
Chris Dalton
2016/05/10 16:39:30
Done. Good idea.
| |
| 244 kAlways, | |
| 245 kNever, | |
| 246 kGreater, | |
| 247 kGEqual, | |
| 248 kLess, | |
| 249 kLEqual, | |
| 250 kEqual, | |
| 251 kNotEqual | |
| 252 }; | |
| 253 static constexpr int kGrStencilTestCount = 1 + (int)GrStencilTest::kNotEqual; | |
| 254 | |
| 255 enum class GrStencilOp : uint8_t { | |
| 256 kKeep, | |
| 257 kZero, | |
| 258 kReplace, // Replace stencil value with fRef (only the bits enabled in fWrit eMask). | |
| 259 kInvert, | |
| 260 kIncWrap, | |
| 261 kDecWrap, | |
| 262 // NOTE: clamping occurs before the write mask. So if the MSB is zero and ma sked out, stencil | |
| 263 // values will still wrap when using clamping ops. | |
| 264 kIncClamp, | |
| 265 kDecClamp | |
| 266 }; | |
| 267 static constexpr int kGrStencilOpCount = 1 + (int)GrStencilOp::kDecClamp; | |
| 74 | 268 |
| 75 /** | 269 /** |
| 76 * Operations to perform based on whether stencil test passed failed. | 270 * This class defines concrete stencil settings that map directly to the underly ing hardware. It |
| 77 */ | 271 * is deduced from user stencil settings, stencil clip status, and the number of bits in the |
| 78 enum GrStencilOp { | 272 * target stencil buffer. |
| 79 kKeep_StencilOp = 0, // preserve existing stencil value | |
| 80 kReplace_StencilOp, // replace with reference value from stencl test | |
| 81 kIncWrap_StencilOp, // increment and wrap at max | |
| 82 kIncClamp_StencilOp, // increment and clamp at max | |
| 83 kDecWrap_StencilOp, // decrement and wrap at 0 | |
| 84 kDecClamp_StencilOp, // decrement and clamp at 0 | |
| 85 kZero_StencilOp, // zero stencil bits | |
| 86 kInvert_StencilOp, // invert stencil bits | |
| 87 kLast_StencilOp = kInvert_StencilOp | |
| 88 }; | |
| 89 static const int kStencilOpCnt = kLast_StencilOp + 1; | |
| 90 | |
| 91 /** | |
| 92 * Class representing stencil state. | |
| 93 */ | 273 */ |
| 94 class GrStencilSettings { | 274 class GrStencilSettings { |
| 95 public: | 275 public: |
| 96 enum Face { | 276 GrStencilSettings() { this->setDisabled(); } |
| 97 kFront_Face = 0, | 277 GrStencilSettings(const GrUserStencilSettings& user, bool hasStencilClip, in t numStencilBits) { |
| 98 kBack_Face = 1, | 278 this->reset(user, hasStencilClip, numStencilBits); |
| 279 } | |
| 280 GrStencilSettings(const GrStencilSettings& that) { this->reset(that); } | |
| 281 GrStencilSettings& operator=(const GrStencilSettings& that) { this->reset(th at); return *this; } | |
| 282 | |
| 283 void invalidate() { fFlags |= kInvalid_PrivateFlag; } | |
| 284 void setDisabled() { fFlags = kAll_StencilFlags; } | |
| 285 void reset(const GrUserStencilSettings&, bool hasStencilClip, int numStencil Bits); | |
| 286 void reset(const GrStencilSettings&); | |
| 287 | |
| 288 bool isValid() const { return !(fFlags & kInvalid_PrivateFlag); } | |
| 289 bool isDisabled() const { SkASSERT(this->isValid()); return fFlags & kDisabl ed_StencilFlag; } | |
| 290 bool doesWrite() const { SkASSERT(this->isValid()); | |
| 291 return !(fFlags & kNoModifyStencil_StencilFlag); } | |
| 292 bool isTwoSided() const { SkASSERT(this->isValid()); | |
| 293 return !(fFlags & kSingleSided_StencilFlag); } | |
| 294 bool usesWrapOp() const { SkASSERT(this->isValid()); | |
| 295 return !(fFlags & kNoWrapOps_StencilFlag); } | |
| 296 | |
| 297 void genKey(GrProcessorKeyBuilder* b) const; | |
| 298 | |
| 299 bool operator!=(const GrStencilSettings& that) const { return !(*this == tha t); } | |
| 300 bool operator==(const GrStencilSettings&) const; | |
| 301 | |
| 302 struct Face : public GrTStencilFaceSettings<GrStencilTest, GrStencilOp> { | |
| 303 void reset(const GrUserStencilSettings::Face&, bool useStencilClip, int numStencilBits); | |
| 304 void setDisabled(); | |
| 99 }; | 305 }; |
| 100 | 306 |
| 101 constexpr GrStencilSettings(GrStencilOp passOp, | 307 const Face& front() const { SkASSERT(!this->isDisabled()); return fFront; } |
| 102 GrStencilOp failOp, | 308 const Face& back() const { SkASSERT(this->isTwoSided()); return fBack; } |
| 103 GrStencilFunc func, | |
| 104 unsigned short funcMask, | |
| 105 unsigned short funcRef, | |
| 106 unsigned short writeMask) | |
| 107 : fPassOps{(uint8_t)passOp, (uint8_t)passOp} | |
| 108 , fFailOps{(uint8_t)failOp, (uint8_t)failOp} | |
| 109 , fFuncs{(uint8_t)func, (uint8_t)func} | |
| 110 , fPad0(0) | |
| 111 , fPad1(0) | |
| 112 , fFuncMasks{funcMask, funcMask} | |
| 113 , fFuncRefs{funcRef, funcRef} | |
| 114 , fWriteMasks{writeMask, writeMask} | |
| 115 , fFlags(ComputeFlags(passOp, passOp, | |
| 116 failOp, failOp, | |
| 117 func, func, | |
| 118 writeMask, writeMask)) { | |
| 119 } | |
| 120 | |
| 121 constexpr GrStencilSettings(GrStencilOp frontPassOp, GrStencilOp backPassOp , | |
| 122 GrStencilOp frontFailOp, GrStencilOp backFailOp , | |
| 123 GrStencilFunc frontFunc, GrStencilFunc backFunc , | |
| 124 uint16_t frontFuncMask, uint16_t backFuncMask, | |
| 125 uint16_t frontFuncRef, uint16_t backFuncRef, | |
| 126 uint16_t frontWriteMask, uint16_t backWriteMask ) | |
| 127 : fPassOps{(uint8_t)frontPassOp, (uint8_t)backPassOp} | |
| 128 , fFailOps{(uint8_t)frontFailOp, (uint8_t)backFailOp} | |
| 129 , fFuncs{(uint8_t)frontFunc, (uint8_t)backFunc} | |
| 130 , fPad0(0) | |
| 131 , fPad1(0) | |
| 132 , fFuncMasks{frontFuncMask, backFuncMask} | |
| 133 , fFuncRefs{frontFuncRef, backFuncRef} | |
| 134 , fWriteMasks{frontWriteMask, backWriteMask} | |
| 135 , fFlags(ComputeFlags(frontPassOp, backPassOp, | |
| 136 frontFailOp, backFailOp, | |
| 137 frontFunc, backFunc, | |
| 138 frontWriteMask, backWriteMask)) { | |
| 139 } | |
| 140 | |
| 141 GrStencilSettings() { | |
| 142 fPad0 = fPad1 = 0; | |
| 143 this->setDisabled(); | |
| 144 } | |
| 145 | |
| 146 GrStencilOp passOp(Face f) const { return static_cast<GrStencilOp>(fPassOps[ f]); } | |
| 147 GrStencilOp failOp(Face f) const { return static_cast<GrStencilOp>(fFailOps[ f]); } | |
| 148 GrStencilFunc func(Face f) const { return static_cast<GrStencilFunc>(fFuncs[ f]); } | |
| 149 uint16_t funcMask(Face f) const { return fFuncMasks[f]; } | |
| 150 uint16_t funcRef(Face f) const { return fFuncRefs[f]; } | |
| 151 uint16_t writeMask(Face f) const { return fWriteMasks[f]; } | |
| 152 | |
| 153 void setPassOp(Face f, GrStencilOp op) { fPassOps[f] = op; fFlags = 0;} | |
| 154 void setFailOp(Face f, GrStencilOp op) { fFailOps[f] = op; fFlags = 0;} | |
| 155 void setFunc(Face f, GrStencilFunc func) { fFuncs[f] = func; fFlags = 0;} | |
| 156 void setFuncMask(Face f, unsigned short mask) { fFuncMasks[f] = mask; } | |
| 157 void setFuncRef(Face f, unsigned short ref) { fFuncRefs[f] = ref; } | |
| 158 void setWriteMask(Face f, unsigned short writeMask) { fWriteMasks[f] = write Mask; } | |
| 159 | |
| 160 void copyFrontSettingsToBack() { | |
| 161 fPassOps[kBack_Face] = fPassOps[kFront_Face]; | |
| 162 fFailOps[kBack_Face] = fFailOps[kFront_Face]; | |
| 163 fFuncs[kBack_Face] = fFuncs[kFront_Face]; | |
| 164 fFuncMasks[kBack_Face] = fFuncMasks[kFront_Face]; | |
| 165 fFuncRefs[kBack_Face] = fFuncRefs[kFront_Face]; | |
| 166 fWriteMasks[kBack_Face] = fWriteMasks[kFront_Face]; | |
| 167 fFlags = 0; | |
| 168 } | |
| 169 | |
| 170 void setDisabled() { | |
| 171 memset(this, 0, sizeof(*this)); | |
| 172 GR_STATIC_ASSERT(0 == kKeep_StencilOp); | |
| 173 GR_STATIC_ASSERT(0 == kAlways_StencilFunc); | |
| 174 fFlags = kIsDisabled_StencilFlag | kDoesNotWrite_StencilFlag; | |
| 175 } | |
| 176 | |
| 177 bool isTwoSided() const { | |
| 178 return fPassOps[kFront_Face] != fPassOps[kBack_Face] || | |
| 179 fFailOps[kFront_Face] != fFailOps[kBack_Face] || | |
| 180 fFuncs[kFront_Face] != fFuncs[kBack_Face] || | |
| 181 fFuncMasks[kFront_Face] != fFuncMasks[kBack_Face] || | |
| 182 fFuncRefs[kFront_Face] != fFuncRefs[kBack_Face] || | |
| 183 fWriteMasks[kFront_Face] != fWriteMasks[kBack_Face]; | |
| 184 } | |
| 185 | |
| 186 bool usesWrapOp() const { | |
| 187 return kIncWrap_StencilOp == fPassOps[kFront_Face] || | |
| 188 kDecWrap_StencilOp == fPassOps[kFront_Face] || | |
| 189 kIncWrap_StencilOp == fPassOps[kBack_Face] || | |
| 190 kDecWrap_StencilOp == fPassOps[kBack_Face] || | |
| 191 kIncWrap_StencilOp == fFailOps[kFront_Face] || | |
| 192 kDecWrap_StencilOp == fFailOps[kFront_Face] || | |
| 193 kIncWrap_StencilOp == fFailOps[kBack_Face] || | |
| 194 kDecWrap_StencilOp == fFailOps[kBack_Face]; | |
| 195 } | |
| 196 | |
| 197 bool isDisabled() const { | |
| 198 if (fFlags & kIsDisabled_StencilFlag) { | |
| 199 return true; | |
| 200 } | |
| 201 if (fFlags & kNotDisabled_StencilFlag) { | |
| 202 return false; | |
| 203 } | |
| 204 bool disabled = this->computeIsDisabled(); | |
| 205 fFlags |= disabled ? kIsDisabled_StencilFlag : kNotDisabled_StencilFlag; | |
| 206 return disabled; | |
| 207 } | |
| 208 | |
| 209 bool doesWrite() const { | |
| 210 if (fFlags & kDoesWrite_StencilFlag) { | |
| 211 return true; | |
| 212 } | |
| 213 if (fFlags & kDoesNotWrite_StencilFlag) { | |
| 214 return false; | |
| 215 } | |
| 216 bool writes = this->computeDoesWrite(); | |
| 217 fFlags |= writes ? kDoesWrite_StencilFlag : kDoesNotWrite_StencilFlag; | |
| 218 return writes; | |
| 219 } | |
| 220 | |
| 221 void invalidate() { | |
| 222 // write an illegal value to the first member | |
| 223 fPassOps[0] = kStencilOpCnt; | |
| 224 fFlags = 0; | |
| 225 } | |
| 226 | |
| 227 bool isValid() const { return fPassOps[0] < kStencilOpCnt; } | |
| 228 | |
| 229 void genKey(GrProcessorKeyBuilder* b) const; | |
| 230 | |
| 231 bool operator==(const GrStencilSettings& s) const { | |
| 232 static const size_t gCompareSize = sizeof(GrStencilSettings) - | |
| 233 sizeof(fFlags); | |
| 234 SkASSERT((const char*)&fFlags + sizeof(fFlags) == | |
| 235 (const char*)this + sizeof(GrStencilSettings)); | |
| 236 if (this->isDisabled() & s.isDisabled()) { // using & not && | |
| 237 return true; | |
| 238 } | |
| 239 return 0 == memcmp(this, &s, gCompareSize); | |
| 240 } | |
| 241 | |
| 242 bool operator!=(const GrStencilSettings& s) const { | |
| 243 return !(*this == s); | |
| 244 } | |
| 245 | |
| 246 GrStencilSettings& operator=(const GrStencilSettings& s) { | |
| 247 memcpy(this, &s, sizeof(GrStencilSettings)); | |
| 248 return *this; | |
| 249 } | |
| 250 | |
| 251 private: | |
| 252 friend class GrClipMaskManager; | |
| 253 | |
| 254 enum { | |
| 255 kMaxStencilClipPasses = 2 // maximum number of passes to add a clip | |
| 256 // element to the stencil buffer. | |
| 257 }; | |
| 258 | 309 |
| 259 /** | 310 /** |
| 260 * Given a thing to draw into the stencil clip, a fill type, and a set op | 311 * Given a thing to draw into the stencil clip, a fill type, and a set op |
| 261 * this function determines: | 312 * this function determines: |
| 262 * 1. Whether the thing can be draw directly to the stencil clip or | 313 * 1. Whether the thing can be draw directly to the stencil clip or |
| 263 * needs to be drawn to the client portion of the stencil first. | 314 * needs to be drawn to the client portion of the stencil first. |
| 264 * 2. How many passes are needed. | 315 * 2. How many passes are needed. |
| 265 * 3. What those passes are. | 316 * 3. What those passes are. |
| 266 * 4. The fill rule that should actually be used to render (will | |
| 267 * always be non-inverted). | |
| 268 * | 317 * |
| 269 * @param op the set op to combine this element with the | 318 * @param op the set op to combine this element with the exis ting clip |
| 270 * existing clip | 319 * @param canBeDirect can the caller draw this element directly (witho ut using stencil)? |
| 271 * @param stencilClipMask mask with just the stencil bit used for clipping | |
| 272 * enabled. | |
| 273 * @param invertedFill is this path inverted | 320 * @param invertedFill is this path inverted |
| 274 * @param numPasses out: the number of passes needed to add the | 321 * @param drawDirectToClip out: true if caller should draw the element dire ctly, false if it |
| 275 * element to the clip. | 322 * should draw it into the user stencil bits first. |
| 276 * @param settings out: the stencil settings to use for each pass | |
| 277 * | 323 * |
| 278 * @return true if the clip element's geometry can be drawn directly to the | 324 * @return a null-terminated array of settings for stencil passes. |
| 279 * stencil clip bit. Will only be true if canBeDirect is true. | 325 * |
| 280 * numPasses will be 1 if return value is true. | 326 * If drawDirectToClip is false, the caller must first draw the elem ent into the user |
| 327 * stencil bits, and then cover the clip area with multiple passes u sing the returned | |
| 328 * stencil settings. | |
| 329 * | |
| 330 * If drawDirectToClip is true, the returned array will only have on e pass and the | |
| 331 * caller should use those stencil settings while drawing the elemen t directly. | |
| 281 */ | 332 */ |
| 282 static bool GetClipPasses(SkRegion::Op op, | 333 static GrUserStencilSettings const* const* GetClipPasses(SkRegion::Op op, |
| 283 bool canBeDirect, | 334 bool canBeDirect, |
| 284 unsigned int stencilClipMask, | 335 bool invertedFill, |
| 285 bool invertedFill, | 336 bool* drawDirectToC lip); |
| 286 int* numPasses, | |
| 287 GrStencilSettings settings[kMaxStencilClipPasses]) ; | |
| 288 | 337 |
| 289 constexpr static bool IsDisabled(GrStencilOp frontPassOp, GrStencilOp backP assOp, | 338 private: |
| 290 GrStencilOp frontFailOp, GrStencilOp backF ailOp, | 339 // Internal flag for backends to optionally mark their tracked stencil state as invalid. |
| 291 GrStencilFunc frontFunc, GrStencilFunc bac kFunc) { | 340 enum { kInvalid_PrivateFlag = (kLast_StencilFlag << 1) }; |
| 292 return (((frontPassOp == kKeep_StencilOp && frontFailOp == kKeep_Stencil Op)) && | |
| 293 ((backPassOp == kKeep_StencilOp && backFailOp == kKeep_Stencil Op)) && | |
| 294 frontFunc == kAlways_StencilFunc && | |
| 295 backFunc == kAlways_StencilFunc); | |
| 296 } | |
| 297 | 341 |
| 298 constexpr static bool DoesWrite(GrStencilOp frontPassOp, GrStencilOp backPa ssOp, | 342 uint32_t fFlags; |
| 299 GrStencilOp frontFailOp, GrStencilOp backFa ilOp, | 343 Face fFront; |
| 300 GrStencilFunc frontFunc, GrStencilFunc back Func, | 344 Face fBack; |
| 301 uint16_t frontWriteMask, uint16_t backWrite Mask) { | |
| 302 return (0 != (frontWriteMask | backWriteMask)) && | |
| 303 // Can we write due to a front face passing the stencil test? | |
| 304 ((frontFunc != kNever_StencilFunc && frontPassOp != kKeep_Stenci lOp) || | |
| 305 // Can we write due to a back face passing the stencil test? | |
| 306 (backFunc != kNever_StencilFunc && backPassOp != kKeep_Stenci lOp) || | |
| 307 // Can we write due to a front face failing the stencil test? | |
| 308 (frontFunc != kAlways_StencilFunc && frontFailOp != kKeep_Stenci lOp) || | |
| 309 // Can we write due to a back face failing the stencil test? | |
| 310 (backFunc != kAlways_StencilFunc && backFailOp != kKeep_Stenci lOp)); | |
| 311 } | |
| 312 | |
| 313 constexpr static uint32_t ComputeFlags(GrStencilOp frontPassOp, GrStencilOp backPassOp, | |
| 314 GrStencilOp frontFailOp, GrStencilOp backFailOp, | |
| 315 GrStencilFunc frontFunc, GrStencilFu nc backFunc, | |
| 316 uint16_t frontWriteMask, uint16_t ba ckWriteMask) { | |
| 317 return (IsDisabled(frontPassOp, backPassOp, frontFailOp, backFailOp, | |
| 318 frontFunc, backFunc) | |
| 319 ? kIsDisabled_StencilFlag | |
| 320 : kNotDisabled_StencilFlag) | | |
| 321 (DoesWrite(frontPassOp, backPassOp, frontFailOp, backFailOp, | |
| 322 frontFunc, backFunc, frontWriteMask, backWriteMask) | |
| 323 ? kDoesWrite_StencilFlag | |
| 324 : kDoesNotWrite_StencilFlag); | |
| 325 } | |
| 326 | |
| 327 bool computeIsDisabled() const { | |
| 328 return IsDisabled((GrStencilOp) fPassOps[kFront_Face], (GrStencilOp) fPa ssOps[kBack_Face], | |
| 329 (GrStencilOp) fFailOps[kFront_Face], (GrStencilOp) fFa ilOps[kBack_Face], | |
| 330 (GrStencilFunc) fFuncs[kFront_Face], (GrStencilFunc) f Funcs[kBack_Face]); | |
| 331 } | |
| 332 bool computeDoesWrite() const { | |
| 333 return DoesWrite((GrStencilOp)fPassOps[kFront_Face], (GrStencilOp)fPassO ps[kBack_Face], | |
| 334 (GrStencilOp)fFailOps[kFront_Face], (GrStencilOp)fFailO ps[kBack_Face], | |
| 335 (GrStencilFunc)fFuncs[kFront_Face], (GrStencilFunc)fFun cs[kBack_Face], | |
| 336 fWriteMasks[kFront_Face], fWriteMasks[kBack_F ace]); | |
| 337 } | |
| 338 | |
| 339 enum GrStencilFlags { | |
| 340 kIsDisabled_StencilFlag = 0x1, | |
| 341 kNotDisabled_StencilFlag = 0x2, | |
| 342 kDoesWrite_StencilFlag = 0x4, | |
| 343 kDoesNotWrite_StencilFlag = 0x8, | |
| 344 }; | |
| 345 | |
| 346 uint8_t fPassOps[2]; // op to perform when faces pass (GrStencilOp) | |
| 347 uint8_t fFailOps[2]; // op to perform when faces fail (GrStencilOp) | |
| 348 uint8_t fFuncs[2]; // test function for faces (GrStencilFunc) | |
| 349 uint8_t fPad0; | |
| 350 uint8_t fPad1; | |
| 351 uint16_t fFuncMasks[2]; // mask for face tests | |
| 352 uint16_t fFuncRefs[2]; // reference values for face tests | |
| 353 uint16_t fWriteMasks[2]; // stencil write masks | |
| 354 mutable uint32_t fFlags; | |
| 355 | |
| 356 }; | 345 }; |
| 357 | 346 |
| 358 // We rely on this being packed and aligned (memcmp'ed and memcpy'ed) | |
| 359 GR_STATIC_ASSERT(sizeof(GrStencilSettings) % 4 == 0); | |
| 360 GR_STATIC_ASSERT(sizeof(GrStencilSettings) == | |
| 361 4*sizeof(uint8_t) + // ops | |
| 362 2*sizeof(uint8_t) + // funcs | |
| 363 2*sizeof(uint8_t) + // pads | |
| 364 2*sizeof(uint16_t) + // func masks | |
| 365 2*sizeof(uint16_t) + // ref values | |
| 366 2*sizeof(uint16_t) + // write masks | |
| 367 sizeof(uint32_t)); // flags | |
| 368 | |
| 369 #endif | 347 #endif |
| OLD | NEW |