GrStencilSettings.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  1. /*
  2. * Copyright 2011 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. #include "src/gpu/GrStencilSettings.h"
  8. #include "src/gpu/GrProcessor.h"
  9. constexpr const GrUserStencilSettings gUnused(
  10. GrUserStencilSettings::StaticInit<
  11. 0x0000,
  12. GrUserStencilTest::kAlwaysIfInClip,
  13. 0xffff,
  14. GrUserStencilOp::kKeep,
  15. GrUserStencilOp::kKeep,
  16. 0x0000>()
  17. );
  18. GR_STATIC_ASSERT(kAll_StencilFlags == (gUnused.fFrontFlags[0] & gUnused.fBackFlags[0]));
  19. const GrUserStencilSettings& GrUserStencilSettings::kUnused = gUnused;
  20. void GrStencilSettings::reset(const GrUserStencilSettings& user, bool hasStencilClip,
  21. int numStencilBits) {
  22. uint16_t frontFlags = user.fFrontFlags[hasStencilClip];
  23. if (frontFlags & kSingleSided_StencilFlag) {
  24. SkASSERT(frontFlags == user.fBackFlags[hasStencilClip]);
  25. fFlags = frontFlags;
  26. if (!this->isDisabled()) {
  27. fFront.reset(user.fFront, hasStencilClip, numStencilBits);
  28. }
  29. return;
  30. }
  31. uint16_t backFlags = user.fBackFlags[hasStencilClip];
  32. fFlags = frontFlags & backFlags;
  33. if (this->isDisabled()) {
  34. return;
  35. }
  36. if (!(frontFlags & kDisabled_StencilFlag)) {
  37. fFront.reset(user.fFront, hasStencilClip, numStencilBits);
  38. } else {
  39. fFront.setDisabled();
  40. }
  41. if (!(backFlags & kDisabled_StencilFlag)) {
  42. fBack.reset(user.fBack, hasStencilClip, numStencilBits);
  43. } else {
  44. fBack.setDisabled();
  45. }
  46. }
  47. void GrStencilSettings::reset(const GrStencilSettings& that) {
  48. fFlags = that.fFlags;
  49. if ((kInvalid_PrivateFlag | kDisabled_StencilFlag) & fFlags) {
  50. return;
  51. }
  52. if (!this->isTwoSided()) {
  53. memcpy(&fFront, &that.fFront, sizeof(Face));
  54. } else {
  55. memcpy(&fFront, &that.fFront, 2 * sizeof(Face));
  56. GR_STATIC_ASSERT(sizeof(Face) ==
  57. offsetof(GrStencilSettings, fBack) - offsetof(GrStencilSettings, fFront));
  58. }
  59. }
  60. bool GrStencilSettings::operator==(const GrStencilSettings& that) const {
  61. if ((kInvalid_PrivateFlag | kDisabled_StencilFlag) & (fFlags | that.fFlags)) {
  62. // At least one is invalid and/or disabled.
  63. if (kInvalid_PrivateFlag & (fFlags | that.fFlags)) {
  64. return false; // We never allow invalid stencils to be equal.
  65. }
  66. // They're only equal if both are disabled.
  67. return kDisabled_StencilFlag & (fFlags & that.fFlags);
  68. }
  69. if (kSingleSided_StencilFlag & (fFlags & that.fFlags)) {
  70. return 0 == memcmp(&fFront, &that.fFront, sizeof(Face)); // Both are single sided.
  71. } else if (kSingleSided_StencilFlag & (fFlags | that.fFlags)) {
  72. return false;
  73. } else {
  74. return 0 == memcmp(&fFront, &that.fFront, 2 * sizeof(Face));
  75. GR_STATIC_ASSERT(sizeof(Face) ==
  76. offsetof(GrStencilSettings, fBack) - offsetof(GrStencilSettings, fFront));
  77. }
  78. // memcmp relies on GrStencilSettings::Face being tightly packed.
  79. GR_STATIC_ASSERT(0 == offsetof(Face, fRef));
  80. GR_STATIC_ASSERT(2 == sizeof(Face::fRef));
  81. GR_STATIC_ASSERT(2 == offsetof(Face, fTest));
  82. GR_STATIC_ASSERT(2 == sizeof(Face::fTest));
  83. GR_STATIC_ASSERT(4 == offsetof(Face, fTestMask));
  84. GR_STATIC_ASSERT(2 == sizeof(Face::fTestMask));
  85. GR_STATIC_ASSERT(6 == offsetof(Face, fPassOp));
  86. GR_STATIC_ASSERT(1 == sizeof(Face::fPassOp));
  87. GR_STATIC_ASSERT(7 == offsetof(Face, fFailOp));
  88. GR_STATIC_ASSERT(1 == sizeof(Face::fFailOp));
  89. GR_STATIC_ASSERT(8 == offsetof(Face, fWriteMask));
  90. GR_STATIC_ASSERT(2 == sizeof(Face::fWriteMask));
  91. GR_STATIC_ASSERT(10 == sizeof(Face));
  92. }
  93. static constexpr GrStencilTest gUserStencilTestToRaw[kGrUserStencilTestCount] = {
  94. // Tests that respect the clip.
  95. GrStencilTest::kAlways, // kAlwaysIfInClip (This is only for when there is not a stencil clip).
  96. GrStencilTest::kEqual, // kEqualIfInClip.
  97. GrStencilTest::kLess, // kLessIfInClip.
  98. GrStencilTest::kLEqual, // kLEqualIfInClip.
  99. // Tests that ignore the clip.
  100. GrStencilTest::kAlways,
  101. GrStencilTest::kNever,
  102. GrStencilTest::kGreater,
  103. GrStencilTest::kGEqual,
  104. GrStencilTest::kLess,
  105. GrStencilTest::kLEqual,
  106. GrStencilTest::kEqual,
  107. GrStencilTest::kNotEqual
  108. };
  109. GR_STATIC_ASSERT(0 == (int)GrUserStencilTest::kAlwaysIfInClip);
  110. GR_STATIC_ASSERT(1 == (int)GrUserStencilTest::kEqualIfInClip);
  111. GR_STATIC_ASSERT(2 == (int)GrUserStencilTest::kLessIfInClip);
  112. GR_STATIC_ASSERT(3 == (int)GrUserStencilTest::kLEqualIfInClip);
  113. GR_STATIC_ASSERT(4 == (int)GrUserStencilTest::kAlways);
  114. GR_STATIC_ASSERT(5 == (int)GrUserStencilTest::kNever);
  115. GR_STATIC_ASSERT(6 == (int)GrUserStencilTest::kGreater);
  116. GR_STATIC_ASSERT(7 == (int)GrUserStencilTest::kGEqual);
  117. GR_STATIC_ASSERT(8 == (int)GrUserStencilTest::kLess);
  118. GR_STATIC_ASSERT(9 == (int)GrUserStencilTest::kLEqual);
  119. GR_STATIC_ASSERT(10 == (int)GrUserStencilTest::kEqual);
  120. GR_STATIC_ASSERT(11 == (int)GrUserStencilTest::kNotEqual);
  121. static constexpr GrStencilOp gUserStencilOpToRaw[kGrUserStencilOpCount] = {
  122. GrStencilOp::kKeep,
  123. // Ops that only modify user bits.
  124. GrStencilOp::kZero,
  125. GrStencilOp::kReplace,
  126. GrStencilOp::kInvert,
  127. GrStencilOp::kIncWrap,
  128. GrStencilOp::kDecWrap,
  129. GrStencilOp::kIncClamp, // kIncMaybeClamp.
  130. GrStencilOp::kDecClamp, // kDecMaybeClamp.
  131. // Ops that only modify the clip bit.
  132. GrStencilOp::kZero, // kZeroClipBit.
  133. GrStencilOp::kReplace, // kSetClipBit.
  134. GrStencilOp::kInvert, // kInvertClipBit.
  135. // Ops that modify clip and user bits.
  136. GrStencilOp::kReplace, // kSetClipAndReplaceUserBits.
  137. GrStencilOp::kZero // kZeroClipAndUserBits.
  138. };
  139. GR_STATIC_ASSERT(0 == (int)GrUserStencilOp::kKeep);
  140. GR_STATIC_ASSERT(1 == (int)GrUserStencilOp::kZero);
  141. GR_STATIC_ASSERT(2 == (int)GrUserStencilOp::kReplace);
  142. GR_STATIC_ASSERT(3 == (int)GrUserStencilOp::kInvert);
  143. GR_STATIC_ASSERT(4 == (int)GrUserStencilOp::kIncWrap);
  144. GR_STATIC_ASSERT(5 == (int)GrUserStencilOp::kDecWrap);
  145. GR_STATIC_ASSERT(6 == (int)GrUserStencilOp::kIncMaybeClamp);
  146. GR_STATIC_ASSERT(7 == (int)GrUserStencilOp::kDecMaybeClamp);
  147. GR_STATIC_ASSERT(8 == (int)GrUserStencilOp::kZeroClipBit);
  148. GR_STATIC_ASSERT(9 == (int)GrUserStencilOp::kSetClipBit);
  149. GR_STATIC_ASSERT(10 == (int)GrUserStencilOp::kInvertClipBit);
  150. GR_STATIC_ASSERT(11 == (int)GrUserStencilOp::kSetClipAndReplaceUserBits);
  151. GR_STATIC_ASSERT(12 == (int)GrUserStencilOp::kZeroClipAndUserBits);
  152. void GrStencilSettings::Face::reset(const GrUserStencilSettings::Face& user, bool hasStencilClip,
  153. int numStencilBits) {
  154. SkASSERT(user.fTest < (GrUserStencilTest)kGrUserStencilTestCount);
  155. SkASSERT(user.fPassOp < (GrUserStencilOp)kGrUserStencilOpCount);
  156. SkASSERT(user.fFailOp < (GrUserStencilOp)kGrUserStencilOpCount);
  157. SkASSERT(numStencilBits > 0 && numStencilBits <= 16);
  158. int clipBit = 1 << (numStencilBits - 1);
  159. int userMask = clipBit - 1;
  160. GrUserStencilOp maxOp = SkTMax(user.fPassOp, user.fFailOp);
  161. SkDEBUGCODE(GrUserStencilOp otherOp = SkTMin(user.fPassOp, user.fFailOp);)
  162. if (maxOp <= kLastUserOnlyStencilOp) {
  163. // Ops that only modify user bits.
  164. fWriteMask = user.fWriteMask & userMask;
  165. SkASSERT(otherOp <= kLastUserOnlyStencilOp);
  166. } else if (maxOp <= kLastClipOnlyStencilOp) {
  167. // Ops that only modify the clip bit.
  168. fWriteMask = clipBit;
  169. SkASSERT(GrUserStencilOp::kKeep == otherOp ||
  170. (otherOp > kLastUserOnlyStencilOp && otherOp <= kLastClipOnlyStencilOp));
  171. } else {
  172. // Ops that modify both clip and user bits.
  173. fWriteMask = clipBit | (user.fWriteMask & userMask);
  174. SkASSERT(GrUserStencilOp::kKeep == otherOp || otherOp > kLastClipOnlyStencilOp);
  175. }
  176. fFailOp = gUserStencilOpToRaw[(int)user.fFailOp];
  177. fPassOp = gUserStencilOpToRaw[(int)user.fPassOp];
  178. if (!hasStencilClip || user.fTest > kLastClippedStencilTest) {
  179. // Ignore the clip.
  180. fTestMask = user.fTestMask & userMask;
  181. fTest = gUserStencilTestToRaw[(int)user.fTest];
  182. } else if (GrUserStencilTest::kAlwaysIfInClip != user.fTest) {
  183. // Respect the clip.
  184. fTestMask = clipBit | (user.fTestMask & userMask);
  185. fTest = gUserStencilTestToRaw[(int)user.fTest];
  186. } else {
  187. // Test only for clip.
  188. fTestMask = clipBit;
  189. fTest = GrStencilTest::kEqual;
  190. }
  191. fRef = (clipBit | user.fRef) & (fTestMask | fWriteMask);
  192. }
  193. void GrStencilSettings::Face::setDisabled() {
  194. memset(this, 0, sizeof(*this));
  195. GR_STATIC_ASSERT(0 == (int)GrStencilTest::kAlways);
  196. GR_STATIC_ASSERT(0 == (int)GrStencilOp::kKeep);
  197. }
  198. ////////////////////////////////////////////////////////////////////////////////
  199. // Stencil Rules for Merging user stencil space into clip
  200. //
  201. ///////
  202. // Replace
  203. static constexpr GrUserStencilSettings gUserToClipReplace(
  204. GrUserStencilSettings::StaticInit<
  205. 0x0000,
  206. GrUserStencilTest::kNotEqual,
  207. 0xffff,
  208. GrUserStencilOp::kSetClipAndReplaceUserBits,
  209. GrUserStencilOp::kZeroClipAndUserBits,
  210. 0xffff>()
  211. );
  212. static constexpr GrUserStencilSettings gInvUserToClipReplace(
  213. GrUserStencilSettings::StaticInit<
  214. 0x0000,
  215. GrUserStencilTest::kEqual,
  216. 0xffff,
  217. GrUserStencilOp::kSetClipAndReplaceUserBits,
  218. GrUserStencilOp::kZeroClipAndUserBits,
  219. 0xffff>()
  220. );
  221. ///////
  222. // Intersect
  223. static constexpr GrUserStencilSettings gUserToClipIsect(
  224. GrUserStencilSettings::StaticInit<
  225. 0x0000,
  226. GrUserStencilTest::kLessIfInClip, // "0 < userBits" is equivalent to "0 != userBits".
  227. 0xffff,
  228. GrUserStencilOp::kSetClipAndReplaceUserBits,
  229. GrUserStencilOp::kZeroClipAndUserBits,
  230. 0xffff>()
  231. );
  232. ///////
  233. // Difference
  234. static constexpr GrUserStencilSettings gUserToClipDiff(
  235. GrUserStencilSettings::StaticInit<
  236. 0x0000,
  237. GrUserStencilTest::kEqualIfInClip,
  238. 0xffff,
  239. GrUserStencilOp::kSetClipAndReplaceUserBits,
  240. GrUserStencilOp::kZeroClipAndUserBits,
  241. 0xffff>()
  242. );
  243. ///////
  244. // Union
  245. static constexpr GrUserStencilSettings gUserToClipUnion(
  246. GrUserStencilSettings::StaticInit<
  247. 0x0000,
  248. GrUserStencilTest::kNotEqual,
  249. 0xffff,
  250. GrUserStencilOp::kSetClipAndReplaceUserBits,
  251. GrUserStencilOp::kKeep,
  252. 0xffff>()
  253. );
  254. static constexpr GrUserStencilSettings gInvUserToClipUnionPass0( // Does not zero user bits.
  255. GrUserStencilSettings::StaticInit<
  256. 0x0000,
  257. GrUserStencilTest::kEqual,
  258. 0xffff,
  259. GrUserStencilOp::kSetClipBit,
  260. GrUserStencilOp::kKeep,
  261. 0x0000>()
  262. );
  263. ///////
  264. // Xor
  265. static constexpr GrUserStencilSettings gUserToClipXorPass0( // Does not zero user bits.
  266. GrUserStencilSettings::StaticInit<
  267. 0x0000,
  268. GrUserStencilTest::kNotEqual,
  269. 0xffff,
  270. GrUserStencilOp::kInvertClipBit,
  271. GrUserStencilOp::kKeep,
  272. 0x0000>()
  273. );
  274. static constexpr GrUserStencilSettings gInvUserToClipXorPass0( // Does not zero user bits.
  275. GrUserStencilSettings::StaticInit<
  276. 0x0000,
  277. GrUserStencilTest::kEqual,
  278. 0xffff,
  279. GrUserStencilOp::kInvertClipBit,
  280. GrUserStencilOp::kKeep,
  281. 0x0000>()
  282. );
  283. ///////
  284. // Reverse Diff
  285. static constexpr GrUserStencilSettings gUserToClipRDiffPass0( // Does not zero user bits.
  286. GrUserStencilSettings::StaticInit<
  287. 0x0000,
  288. GrUserStencilTest::kNotEqual,
  289. 0xffff,
  290. GrUserStencilOp::kInvertClipBit,
  291. GrUserStencilOp::kZeroClipBit,
  292. 0x0000>()
  293. );
  294. static constexpr GrUserStencilSettings gInvUserToClipRDiffPass0( // Does not zero user bits.
  295. GrUserStencilSettings::StaticInit<
  296. 0x0000,
  297. GrUserStencilTest::kEqual,
  298. 0xffff,
  299. GrUserStencilOp::kInvertClipBit,
  300. GrUserStencilOp::kZeroClipBit,
  301. 0x0000>()
  302. );
  303. ///////
  304. // Second pass to clear user bits (only needed sometimes)
  305. static constexpr GrUserStencilSettings gZeroUserBits(
  306. GrUserStencilSettings::StaticInit<
  307. 0x0000,
  308. GrUserStencilTest::kNotEqual,
  309. 0xffff,
  310. GrUserStencilOp::kZero,
  311. GrUserStencilOp::kKeep,
  312. 0xffff>()
  313. );
  314. static constexpr const GrUserStencilSettings* gUserToClipTable[2][1 + SkRegion::kLastOp][3] = {
  315. { /* Normal fill. */
  316. {&gUserToClipDiff, nullptr, nullptr}, // kDifference_Op.
  317. {&gUserToClipIsect, nullptr, nullptr}, // kIntersect_Op.
  318. {&gUserToClipUnion, nullptr, nullptr}, // kUnion_Op.
  319. {&gUserToClipXorPass0, &gZeroUserBits, nullptr}, // kXOR_Op.
  320. {&gUserToClipRDiffPass0, &gZeroUserBits, nullptr}, // kReverseDifference_Op.
  321. {&gUserToClipReplace, nullptr, nullptr} // kReplace_Op.
  322. }, /* Inverse fill. */ {
  323. {&gUserToClipIsect, nullptr, nullptr}, // ~diff (aka isect).
  324. {&gUserToClipDiff, nullptr, nullptr}, // ~isect (aka diff).
  325. {&gInvUserToClipUnionPass0, &gZeroUserBits, nullptr}, // ~union.
  326. {&gInvUserToClipXorPass0, &gZeroUserBits, nullptr}, // ~xor.
  327. {&gInvUserToClipRDiffPass0, &gZeroUserBits, nullptr}, // ~reverse diff.
  328. {&gInvUserToClipReplace, nullptr, nullptr} // ~replace.
  329. }
  330. };
  331. GR_STATIC_ASSERT(0 == SkRegion::kDifference_Op);
  332. GR_STATIC_ASSERT(1 == SkRegion::kIntersect_Op);
  333. GR_STATIC_ASSERT(2 == SkRegion::kUnion_Op);
  334. GR_STATIC_ASSERT(3 == SkRegion::kXOR_Op);
  335. GR_STATIC_ASSERT(4 == SkRegion::kReverseDifference_Op);
  336. GR_STATIC_ASSERT(5 == SkRegion::kReplace_Op);
  337. ///////
  338. // Direct to Stencil
  339. // We can render a clip element directly without first writing to the client
  340. // portion of the clip when the fill is not inverse and the set operation will
  341. // only modify the in/out status of samples covered by the clip element.
  342. // this one only works if used right after stencil clip was cleared.
  343. // Our clip mask creation code doesn't allow midstream replace ops.
  344. static constexpr GrUserStencilSettings gReplaceClip(
  345. GrUserStencilSettings::StaticInit<
  346. 0x0000,
  347. GrUserStencilTest::kAlways,
  348. 0xffff,
  349. GrUserStencilOp::kSetClipBit,
  350. GrUserStencilOp::kSetClipBit,
  351. 0x0000>()
  352. );
  353. static constexpr GrUserStencilSettings gUnionClip(
  354. GrUserStencilSettings::StaticInit<
  355. 0x0000,
  356. GrUserStencilTest::kAlwaysIfInClip,
  357. 0xffff,
  358. GrUserStencilOp::kKeep,
  359. GrUserStencilOp::kSetClipBit,
  360. 0x0000>()
  361. );
  362. static constexpr GrUserStencilSettings gXorClip(
  363. GrUserStencilSettings::StaticInit<
  364. 0x0000,
  365. GrUserStencilTest::kAlways,
  366. 0xffff,
  367. GrUserStencilOp::kInvertClipBit,
  368. GrUserStencilOp::kInvertClipBit,
  369. 0x0000>()
  370. );
  371. static constexpr GrUserStencilSettings gDiffClip(
  372. GrUserStencilSettings::StaticInit<
  373. 0x0000,
  374. GrUserStencilTest::kAlwaysIfInClip,
  375. 0xffff,
  376. GrUserStencilOp::kZeroClipBit,
  377. GrUserStencilOp::kKeep,
  378. 0x0000>()
  379. );
  380. static constexpr const GrUserStencilSettings* gDirectDrawTable[1 + SkRegion::kLastOp][2] = {
  381. {&gDiffClip, nullptr}, // kDifference_Op.
  382. {nullptr, nullptr}, // kIntersect_Op.
  383. {&gUnionClip, nullptr}, // kUnion_Op.
  384. {&gXorClip, nullptr}, // kXOR_Op.
  385. {nullptr, nullptr}, // kReverseDifference_Op.
  386. {&gReplaceClip, nullptr} // kReplace_Op.
  387. };
  388. GR_STATIC_ASSERT(0 == SkRegion::kDifference_Op);
  389. GR_STATIC_ASSERT(1 == SkRegion::kIntersect_Op);
  390. GR_STATIC_ASSERT(2 == SkRegion::kUnion_Op);
  391. GR_STATIC_ASSERT(3 == SkRegion::kXOR_Op);
  392. GR_STATIC_ASSERT(4 == SkRegion::kReverseDifference_Op);
  393. GR_STATIC_ASSERT(5 == SkRegion::kReplace_Op);
  394. GrUserStencilSettings const* const* GrStencilSettings::GetClipPasses(SkRegion::Op op,
  395. bool canBeDirect,
  396. bool invertedFill,
  397. bool* drawDirectToClip) {
  398. SkASSERT((unsigned)op <= SkRegion::kLastOp);
  399. if (canBeDirect && !invertedFill) { // TODO: inverse fill + intersect op can be direct.
  400. GrUserStencilSettings const* const* directPass = gDirectDrawTable[op];
  401. if (directPass[0]) {
  402. *drawDirectToClip = true;
  403. return directPass;
  404. }
  405. }
  406. *drawDirectToClip = false;
  407. return gUserToClipTable[invertedFill][op];
  408. }
  409. static constexpr GrUserStencilSettings gZeroStencilClipBit(
  410. GrUserStencilSettings::StaticInit<
  411. 0x0000,
  412. GrUserStencilTest::kAlways,
  413. 0xffff,
  414. GrUserStencilOp::kZeroClipBit,
  415. GrUserStencilOp::kZeroClipBit,
  416. 0x0000>()
  417. );
  418. const GrUserStencilSettings* GrStencilSettings::SetClipBitSettings(bool setToInside) {
  419. return setToInside ? &gReplaceClip : &gZeroStencilClipBit;
  420. }
  421. void GrStencilSettings::genKey(GrProcessorKeyBuilder* b) const {
  422. b->add32(fFlags);
  423. if (this->isDisabled()) {
  424. return;
  425. }
  426. if (!this->isTwoSided()) {
  427. constexpr int kCount16 = sizeof(Face) / sizeof(uint16_t);
  428. GR_STATIC_ASSERT(0 == sizeof(Face) % sizeof(uint16_t));
  429. uint16_t* key = reinterpret_cast<uint16_t*>(b->add32n((kCount16 + 1) / 2));
  430. memcpy(key, &fFront, sizeof(Face));
  431. key[kCount16] = 0;
  432. GR_STATIC_ASSERT(1 == kCount16 % 2);
  433. } else {
  434. constexpr int kCount32 = (2 * sizeof(Face)) / sizeof(uint32_t);
  435. GR_STATIC_ASSERT(0 == (2 * sizeof(Face)) % sizeof(uint32_t));
  436. uint32_t* key = b->add32n(kCount32);
  437. memcpy(key, &fFront, 2 * sizeof(Face));
  438. GR_STATIC_ASSERT(sizeof(Face) ==
  439. offsetof(GrStencilSettings, fBack) - offsetof(GrStencilSettings, fFront));
  440. }
  441. // We rely on GrStencilSettings::Face being tightly packed for the key to be reliable.
  442. GR_STATIC_ASSERT(0 == offsetof(Face, fRef));
  443. GR_STATIC_ASSERT(2 == sizeof(Face::fRef));
  444. GR_STATIC_ASSERT(2 == offsetof(Face, fTest));
  445. GR_STATIC_ASSERT(2 == sizeof(Face::fTest));
  446. GR_STATIC_ASSERT(4 == offsetof(Face, fTestMask));
  447. GR_STATIC_ASSERT(2 == sizeof(Face::fTestMask));
  448. GR_STATIC_ASSERT(6 == offsetof(Face, fPassOp));
  449. GR_STATIC_ASSERT(1 == sizeof(Face::fPassOp));
  450. GR_STATIC_ASSERT(7 == offsetof(Face, fFailOp));
  451. GR_STATIC_ASSERT(1 == sizeof(Face::fFailOp));
  452. GR_STATIC_ASSERT(8 == offsetof(Face, fWriteMask));
  453. GR_STATIC_ASSERT(2 == sizeof(Face::fWriteMask));
  454. GR_STATIC_ASSERT(10 == sizeof(Face));
  455. }