GrUserStencilSettings.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  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. #ifndef GrUserStencilSettings_DEFINED
  8. #define GrUserStencilSettings_DEFINED
  9. #include "include/gpu/GrTypes.h"
  10. /**
  11. * Gr uses the stencil buffer to implement complex clipping inside the
  12. * GrOpList class. The GrOpList makes a subset of the stencil buffer
  13. * bits available for other uses by external code (user bits). Client code can
  14. * modify these bits. GrOpList will ignore ref, mask, and writemask bits
  15. * provided by clients that fall outside the user range.
  16. *
  17. * When code outside the GrOpList class uses the stencil buffer the contract
  18. * is as follows:
  19. *
  20. * > Normal stencil funcs allow the client to pass / fail regardless of the
  21. * reserved clip bits.
  22. * > Additional functions allow a test against the clip along with a limited
  23. * set of tests against the user bits.
  24. * > Client can assume all user bits are zero initially.
  25. * > Client must ensure that after all its passes are finished it has only
  26. * written to the color buffer in the region inside the clip. Furthermore, it
  27. * must zero all user bits that were modifed (both inside and outside the
  28. * clip).
  29. */
  30. enum GrStencilFlags {
  31. kDisabled_StencilFlag = (1 << 0),
  32. kTestAlwaysPasses_StencilFlag = (1 << 1),
  33. kNoModifyStencil_StencilFlag = (1 << 2),
  34. kNoWrapOps_StencilFlag = (1 << 3),
  35. kSingleSided_StencilFlag = (1 << 4),
  36. kLast_StencilFlag = kSingleSided_StencilFlag,
  37. kAll_StencilFlags = kLast_StencilFlag | (kLast_StencilFlag - 1)
  38. };
  39. template<typename TTest, typename TOp> struct GrTStencilFaceSettings {
  40. uint16_t fRef; // Reference value for stencil test and ops.
  41. TTest fTest; // Stencil test function, where fRef is on the left side.
  42. uint16_t fTestMask; // Bitwise "and" to perform on fRef and stencil values before testing.
  43. // (e.g. (fRef & fTestMask) < (stencil & fTestMask))
  44. TOp fPassOp; // Op to perform when the test passes.
  45. TOp fFailOp; // Op to perform when the test fails.
  46. uint16_t fWriteMask; // Indicates which bits in the stencil buffer should be updated.
  47. // (e.g. stencil = (newValue & fWriteMask) | (stencil & ~fWriteMask))
  48. };
  49. enum class GrUserStencilTest : uint16_t {
  50. // Tests that respect the clip bit. If a stencil clip is not in effect, the "IfInClip" is
  51. // ignored and these only act on user bits.
  52. kAlwaysIfInClip,
  53. kEqualIfInClip,
  54. kLessIfInClip,
  55. kLEqualIfInClip,
  56. // Tests that ignore the clip bit. The client is responsible to ensure no color write occurs
  57. // outside the clip if it is in use.
  58. kAlways,
  59. kNever,
  60. kGreater,
  61. kGEqual,
  62. kLess,
  63. kLEqual,
  64. kEqual,
  65. kNotEqual
  66. };
  67. constexpr static GrUserStencilTest kLastClippedStencilTest = GrUserStencilTest::kLEqualIfInClip;
  68. constexpr static int kGrUserStencilTestCount = 1 + (int)GrUserStencilTest::kNotEqual;
  69. enum class GrUserStencilOp : uint8_t {
  70. kKeep,
  71. // Ops that only modify user bits. These must not be paired with ops that modify the clip bit.
  72. kZero,
  73. kReplace, // Replace stencil value with fRef (only the bits enabled in fWriteMask).
  74. kInvert,
  75. kIncWrap,
  76. kDecWrap,
  77. // These two should only be used if wrap ops are not supported, or if the math is guaranteed
  78. // to not overflow. The user bits may or may not clamp, depending on the state of non-user bits.
  79. kIncMaybeClamp,
  80. kDecMaybeClamp,
  81. // Ops that only modify the clip bit. These must not be paired with ops that modify user bits.
  82. kZeroClipBit,
  83. kSetClipBit,
  84. kInvertClipBit,
  85. // Ops that modify both clip and user bits. These can only be paired with kKeep or each other.
  86. kSetClipAndReplaceUserBits,
  87. kZeroClipAndUserBits
  88. };
  89. constexpr static GrUserStencilOp kLastUserOnlyStencilOp = GrUserStencilOp::kDecMaybeClamp;
  90. constexpr static GrUserStencilOp kLastClipOnlyStencilOp = GrUserStencilOp::kInvertClipBit;
  91. constexpr static int kGrUserStencilOpCount = 1 + (int)GrUserStencilOp::kZeroClipAndUserBits;
  92. /**
  93. * This struct is a compile-time constant representation of user stencil settings. It describes in
  94. * abstract terms how a draw will use the stencil buffer. It gets ODR-used at runtime to define a
  95. * draw's stencil settings, and is later translated into concrete settings when the pipeline is
  96. * finalized.
  97. */
  98. struct GrUserStencilSettings {
  99. typedef GrTStencilFaceSettings<GrUserStencilTest, GrUserStencilOp> Face;
  100. template<GrUserStencilTest, GrUserStencilOp PassOp, GrUserStencilOp FailOp> struct Attrs;
  101. // Unfortunately, this is the only way to pass template arguments to a constructor.
  102. template<uint16_t Ref, GrUserStencilTest Test, uint16_t TestMask,
  103. GrUserStencilOp PassOp, GrUserStencilOp FailOp, uint16_t WriteMask> struct Init {};
  104. template<uint16_t FtRef, uint16_t BkRef,
  105. GrUserStencilTest FtTest, GrUserStencilTest BkTest,
  106. uint16_t FtTestMask, uint16_t BkTestMask,
  107. GrUserStencilOp FtPassOp, GrUserStencilOp BkPassOp,
  108. GrUserStencilOp FtFailOp, GrUserStencilOp BkFailOp,
  109. uint16_t FtWriteMask, uint16_t BkWriteMask> struct InitSeparate {};
  110. template<uint16_t Ref, GrUserStencilTest Test, uint16_t TestMask,
  111. GrUserStencilOp PassOp, GrUserStencilOp FailOp, uint16_t WriteMask>
  112. constexpr static Init<Ref, Test, TestMask, PassOp, FailOp, WriteMask> StaticInit() {
  113. return Init<Ref, Test, TestMask, PassOp, FailOp, WriteMask>();
  114. }
  115. template<uint16_t FtRef, uint16_t BkRef,
  116. GrUserStencilTest FtTest, GrUserStencilTest BkTest,
  117. uint16_t FtTestMask, uint16_t BkTestMask,
  118. GrUserStencilOp FtPassOp, GrUserStencilOp BkPassOp,
  119. GrUserStencilOp FtFailOp, GrUserStencilOp BkFailOp,
  120. uint16_t FtWriteMask, uint16_t BkWriteMask>
  121. constexpr static InitSeparate<FtRef, BkRef, FtTest, BkTest, FtTestMask, BkTestMask,
  122. FtPassOp, BkPassOp, FtFailOp, BkFailOp, FtWriteMask,
  123. BkWriteMask> StaticInitSeparate() {
  124. return InitSeparate<FtRef, BkRef, FtTest, BkTest, FtTestMask, BkTestMask,
  125. FtPassOp, BkPassOp, FtFailOp, BkFailOp, FtWriteMask, BkWriteMask>();
  126. }
  127. // We construct with template arguments in order to enforce that the struct be compile-time
  128. // constant and to make use of static asserts.
  129. template<uint16_t Ref, GrUserStencilTest Test, uint16_t TestMask,
  130. GrUserStencilOp PassOp, GrUserStencilOp FailOp, uint16_t WriteMask,
  131. typename Attrs = Attrs<Test, PassOp, FailOp> >
  132. constexpr explicit GrUserStencilSettings(
  133. const Init<Ref, Test, TestMask, PassOp, FailOp, WriteMask>&)
  134. : fFrontFlags{(uint16_t)(Attrs::Flags(false) | kSingleSided_StencilFlag),
  135. (uint16_t)(Attrs::Flags(true) | kSingleSided_StencilFlag)}
  136. , fFront{Ref, Test, Attrs::EffectiveTestMask(TestMask), PassOp, FailOp,
  137. Attrs::EffectiveWriteMask(WriteMask)}
  138. , fBackFlags{(uint16_t)(Attrs::Flags(false) | kSingleSided_StencilFlag),
  139. (uint16_t)(Attrs::Flags(true) | kSingleSided_StencilFlag)}
  140. , fBack{Ref, Test, Attrs::EffectiveTestMask(TestMask), PassOp, FailOp,
  141. Attrs::EffectiveWriteMask(WriteMask)} {
  142. }
  143. template<uint16_t FtRef, uint16_t BkRef,
  144. GrUserStencilTest FtTest, GrUserStencilTest BkTest,
  145. uint16_t FtTestMask, uint16_t BkTestMask,
  146. GrUserStencilOp FtPassOp, GrUserStencilOp BkPassOp,
  147. GrUserStencilOp FtFailOp, GrUserStencilOp BkFailOp,
  148. uint16_t FtWriteMask, uint16_t BkWriteMask,
  149. typename FtAttrs = Attrs<FtTest, FtPassOp, FtFailOp>,
  150. typename BkAttrs = Attrs<BkTest, BkPassOp, BkFailOp> >
  151. constexpr explicit GrUserStencilSettings(
  152. const InitSeparate<FtRef, BkRef, FtTest, BkTest, FtTestMask, BkTestMask,
  153. FtPassOp, BkPassOp, FtFailOp, BkFailOp, FtWriteMask, BkWriteMask>&)
  154. : fFrontFlags{FtAttrs::Flags(false), FtAttrs::Flags(true)}
  155. , fFront{FtRef, FtTest, FtAttrs::EffectiveTestMask(FtTestMask), FtPassOp, FtFailOp,
  156. FtAttrs::EffectiveWriteMask(FtWriteMask)}
  157. , fBackFlags{BkAttrs::Flags(false), BkAttrs::Flags(true)}
  158. , fBack{BkRef, BkTest, BkAttrs::EffectiveTestMask(BkTestMask), BkPassOp, BkFailOp,
  159. BkAttrs::EffectiveWriteMask(BkWriteMask)} {}
  160. // This struct can only be constructed with static initializers.
  161. GrUserStencilSettings() = delete;
  162. GrUserStencilSettings(const GrUserStencilSettings&) = delete;
  163. uint16_t flags(bool hasStencilClip) const {
  164. return fFrontFlags[hasStencilClip] & fBackFlags[hasStencilClip];
  165. }
  166. bool isDisabled(bool hasStencilClip) const {
  167. return this->flags(hasStencilClip) & kDisabled_StencilFlag;
  168. }
  169. bool testAlwaysPasses(bool hasStencilClip) const {
  170. return this->flags(hasStencilClip) & kTestAlwaysPasses_StencilFlag;
  171. }
  172. bool isTwoSided(bool hasStencilClip) const {
  173. return !(this->flags(hasStencilClip) & kSingleSided_StencilFlag);
  174. }
  175. bool usesWrapOp(bool hasStencilClip) const {
  176. return !(this->flags(hasStencilClip) & kNoWrapOps_StencilFlag);
  177. }
  178. const uint16_t fFrontFlags[2]; // frontFlagsForDraw = fFrontFlags[hasStencilClip].
  179. const Face fFront;
  180. const uint16_t fBackFlags[2]; // backFlagsForDraw = fBackFlags[hasStencilClip].
  181. const Face fBack;
  182. static const GrUserStencilSettings& kUnused;
  183. bool isUnused() const { return this == &kUnused; }
  184. };
  185. template<GrUserStencilTest Test, GrUserStencilOp PassOp, GrUserStencilOp FailOp>
  186. struct GrUserStencilSettings::Attrs {
  187. // Ensure an op that only modifies user bits isn't paired with one that modifies clip bits.
  188. GR_STATIC_ASSERT(GrUserStencilOp::kKeep == PassOp || GrUserStencilOp::kKeep == FailOp ||
  189. (PassOp <= kLastUserOnlyStencilOp) == (FailOp <= kLastUserOnlyStencilOp));
  190. // Ensure an op that only modifies clip bits isn't paired with one that modifies clip and user.
  191. GR_STATIC_ASSERT(GrUserStencilOp::kKeep == PassOp || GrUserStencilOp::kKeep == FailOp ||
  192. (PassOp <= kLastClipOnlyStencilOp) == (FailOp <= kLastClipOnlyStencilOp));
  193. constexpr static bool TestAlwaysPasses(bool hasStencilClip) {
  194. return (!hasStencilClip && GrUserStencilTest::kAlwaysIfInClip == Test) ||
  195. GrUserStencilTest::kAlways == Test;
  196. }
  197. constexpr static bool DoesNotModifyStencil(bool hasStencilClip) {
  198. return (GrUserStencilTest::kNever == Test || GrUserStencilOp::kKeep == PassOp) &&
  199. (TestAlwaysPasses(hasStencilClip) || GrUserStencilOp::kKeep == FailOp);
  200. }
  201. constexpr static bool IsDisabled(bool hasStencilClip) {
  202. return TestAlwaysPasses(hasStencilClip) && DoesNotModifyStencil(hasStencilClip);
  203. }
  204. constexpr static bool UsesWrapOps() {
  205. return GrUserStencilOp::kIncWrap == PassOp || GrUserStencilOp::kDecWrap == PassOp ||
  206. GrUserStencilOp::kIncWrap == FailOp || GrUserStencilOp::kDecWrap == FailOp;
  207. }
  208. constexpr static bool TestIgnoresRef() {
  209. return (GrUserStencilTest::kAlwaysIfInClip == Test || GrUserStencilTest::kAlways == Test ||
  210. GrUserStencilTest::kNever == Test);
  211. }
  212. constexpr static uint16_t Flags(bool hasStencilClip) {
  213. return (IsDisabled(hasStencilClip) ? kDisabled_StencilFlag : 0) |
  214. (TestAlwaysPasses(hasStencilClip) ? kTestAlwaysPasses_StencilFlag : 0) |
  215. (DoesNotModifyStencil(hasStencilClip) ? kNoModifyStencil_StencilFlag : 0) |
  216. (UsesWrapOps() ? 0 : kNoWrapOps_StencilFlag);
  217. }
  218. constexpr static uint16_t EffectiveTestMask(uint16_t testMask) {
  219. return TestIgnoresRef() ? 0 : testMask;
  220. }
  221. constexpr static uint16_t EffectiveWriteMask(uint16_t writeMask) {
  222. // We don't modify the mask differently when hasStencilClip=false because either the entire
  223. // face gets disabled in that case (e.g. Test=kAlwaysIfInClip, PassOp=kKeep), or else the
  224. // effective mask stays the same either way.
  225. return DoesNotModifyStencil(true) ? 0 : writeMask;
  226. }
  227. };
  228. #endif