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 8 9#include "src/gpu/GrStencilSettings.h" 10 11#include "src/gpu/GrProcessor.h" 12 13constexpr const GrUserStencilSettings gUnused( 14 GrUserStencilSettings::StaticInit< 15 0x0000, 16 GrUserStencilTest::kAlwaysIfInClip, 17 0xffff, 18 GrUserStencilOp::kKeep, 19 GrUserStencilOp::kKeep, 20 0x0000>() 21); 22 23static_assert(kAll_StencilFlags == (gUnused.fCWFlags[0] & gUnused.fCCWFlags[0])); 24 25const GrUserStencilSettings& GrUserStencilSettings::kUnused = gUnused; 26 27void GrStencilSettings::reset(const GrUserStencilSettings& user, bool hasStencilClip, 28 int numStencilBits) { 29 uint16_t cwFlags = user.fCWFlags[hasStencilClip]; 30 if (cwFlags & kSingleSided_StencilFlag) { 31 SkASSERT(cwFlags == user.fCCWFlags[hasStencilClip]); 32 fFlags = cwFlags; 33 if (!this->isDisabled()) { 34 fCWFace.reset(user.fCWFace, hasStencilClip, numStencilBits); 35 } 36 return; 37 } 38 39 uint16_t ccwFlags = user.fCCWFlags[hasStencilClip]; 40 fFlags = cwFlags & ccwFlags; 41 if (this->isDisabled()) { 42 return; 43 } 44 if (!(cwFlags & kDisabled_StencilFlag)) { 45 fCWFace.reset(user.fCWFace, hasStencilClip, numStencilBits); 46 } else { 47 fCWFace.setDisabled(); 48 } 49 if (!(ccwFlags & kDisabled_StencilFlag)) { 50 fCCWFace.reset(user.fCCWFace, hasStencilClip, numStencilBits); 51 } else { 52 fCCWFace.setDisabled(); 53 } 54} 55 56void GrStencilSettings::reset(const GrStencilSettings& that) { 57 fFlags = that.fFlags; 58 if ((kInvalid_PrivateFlag | kDisabled_StencilFlag) & fFlags) { 59 return; 60 } 61 if (!this->isTwoSided()) { 62 memcpy(&fCWFace, &that.fCWFace, sizeof(Face)); 63 } else { 64 memcpy(&fCWFace, &that.fCWFace, 2 * sizeof(Face)); 65 static_assert(sizeof(Face) == 66 offsetof(GrStencilSettings, fCCWFace) - offsetof(GrStencilSettings, fCWFace)); 67 } 68} 69 70bool GrStencilSettings::operator==(const GrStencilSettings& that) const { 71 if ((kInvalid_PrivateFlag | kDisabled_StencilFlag) & (fFlags | that.fFlags)) { 72 // At least one is invalid and/or disabled. 73 if (kInvalid_PrivateFlag & (fFlags | that.fFlags)) { 74 return false; // We never allow invalid stencils to be equal. 75 } 76 // They're only equal if both are disabled. 77 return kDisabled_StencilFlag & (fFlags & that.fFlags); 78 } 79 if (kSingleSided_StencilFlag & (fFlags & that.fFlags)) { 80 return 0 == memcmp(&fCWFace, &that.fCWFace, sizeof(Face)); // Both are single sided. 81 } else if (kSingleSided_StencilFlag & (fFlags | that.fFlags)) { 82 return false; 83 } else { 84 return 0 == memcmp(&fCWFace, &that.fCWFace, 2 * sizeof(Face)); 85 static_assert(sizeof(Face) == 86 offsetof(GrStencilSettings, fCCWFace) - offsetof(GrStencilSettings, fCWFace)); 87 } 88 // memcmp relies on GrStencilSettings::Face being tightly packed. 89 static_assert(0 == offsetof(Face, fRef)); 90 static_assert(2 == sizeof(Face::fRef)); 91 static_assert(2 == offsetof(Face, fTest)); 92 static_assert(2 == sizeof(Face::fTest)); 93 static_assert(4 == offsetof(Face, fTestMask)); 94 static_assert(2 == sizeof(Face::fTestMask)); 95 static_assert(6 == offsetof(Face, fPassOp)); 96 static_assert(1 == sizeof(Face::fPassOp)); 97 static_assert(7 == offsetof(Face, fFailOp)); 98 static_assert(1 == sizeof(Face::fFailOp)); 99 static_assert(8 == offsetof(Face, fWriteMask)); 100 static_assert(2 == sizeof(Face::fWriteMask)); 101 static_assert(10 == sizeof(Face)); 102} 103 104static constexpr GrStencilTest gUserStencilTestToRaw[kGrUserStencilTestCount] = { 105 // Tests that respect the clip. 106 GrStencilTest::kAlways, // kAlwaysIfInClip (This is only for when there is not a stencil clip). 107 GrStencilTest::kEqual, // kEqualIfInClip. 108 GrStencilTest::kLess, // kLessIfInClip. 109 GrStencilTest::kLEqual, // kLEqualIfInClip. 110 111 // Tests that ignore the clip. 112 GrStencilTest::kAlways, 113 GrStencilTest::kNever, 114 GrStencilTest::kGreater, 115 GrStencilTest::kGEqual, 116 GrStencilTest::kLess, 117 GrStencilTest::kLEqual, 118 GrStencilTest::kEqual, 119 GrStencilTest::kNotEqual 120}; 121 122static_assert(0 == (int)GrUserStencilTest::kAlwaysIfInClip); 123static_assert(1 == (int)GrUserStencilTest::kEqualIfInClip); 124static_assert(2 == (int)GrUserStencilTest::kLessIfInClip); 125static_assert(3 == (int)GrUserStencilTest::kLEqualIfInClip); 126static_assert(4 == (int)GrUserStencilTest::kAlways); 127static_assert(5 == (int)GrUserStencilTest::kNever); 128static_assert(6 == (int)GrUserStencilTest::kGreater); 129static_assert(7 == (int)GrUserStencilTest::kGEqual); 130static_assert(8 == (int)GrUserStencilTest::kLess); 131static_assert(9 == (int)GrUserStencilTest::kLEqual); 132static_assert(10 == (int)GrUserStencilTest::kEqual); 133static_assert(11 == (int)GrUserStencilTest::kNotEqual); 134 135static constexpr GrStencilOp gUserStencilOpToRaw[kGrUserStencilOpCount] = { 136 GrStencilOp::kKeep, 137 138 // Ops that only modify user bits. 139 GrStencilOp::kZero, 140 GrStencilOp::kReplace, 141 GrStencilOp::kInvert, 142 GrStencilOp::kIncWrap, 143 GrStencilOp::kDecWrap, 144 GrStencilOp::kIncClamp, // kIncMaybeClamp. 145 GrStencilOp::kDecClamp, // kDecMaybeClamp. 146 147 // Ops that only modify the clip bit. 148 GrStencilOp::kZero, // kZeroClipBit. 149 GrStencilOp::kReplace, // kSetClipBit. 150 GrStencilOp::kInvert, // kInvertClipBit. 151 152 // Ops that modify clip and user bits. 153 GrStencilOp::kReplace, // kSetClipAndReplaceUserBits. 154 GrStencilOp::kZero // kZeroClipAndUserBits. 155}; 156 157static_assert(0 == (int)GrUserStencilOp::kKeep); 158static_assert(1 == (int)GrUserStencilOp::kZero); 159static_assert(2 == (int)GrUserStencilOp::kReplace); 160static_assert(3 == (int)GrUserStencilOp::kInvert); 161static_assert(4 == (int)GrUserStencilOp::kIncWrap); 162static_assert(5 == (int)GrUserStencilOp::kDecWrap); 163static_assert(6 == (int)GrUserStencilOp::kIncMaybeClamp); 164static_assert(7 == (int)GrUserStencilOp::kDecMaybeClamp); 165static_assert(8 == (int)GrUserStencilOp::kZeroClipBit); 166static_assert(9 == (int)GrUserStencilOp::kSetClipBit); 167static_assert(10 == (int)GrUserStencilOp::kInvertClipBit); 168static_assert(11 == (int)GrUserStencilOp::kSetClipAndReplaceUserBits); 169static_assert(12 == (int)GrUserStencilOp::kZeroClipAndUserBits); 170 171void GrStencilSettings::Face::reset(const GrUserStencilSettings::Face& user, bool hasStencilClip, 172 int numStencilBits) { 173 SkASSERT(user.fTest < (GrUserStencilTest)kGrUserStencilTestCount); 174 SkASSERT(user.fPassOp < (GrUserStencilOp)kGrUserStencilOpCount); 175 SkASSERT(user.fFailOp < (GrUserStencilOp)kGrUserStencilOpCount); 176 SkASSERT(numStencilBits > 0 && numStencilBits <= 16); 177 int clipBit = 1 << (numStencilBits - 1); 178 int userMask = clipBit - 1; 179 180 GrUserStencilOp maxOp = std::max(user.fPassOp, user.fFailOp); 181 SkDEBUGCODE(GrUserStencilOp otherOp = std::min(user.fPassOp, user.fFailOp);) 182 if (maxOp <= kLastUserOnlyStencilOp) { 183 // Ops that only modify user bits. 184 fWriteMask = user.fWriteMask & userMask; 185 SkASSERT(otherOp <= kLastUserOnlyStencilOp); 186 } else if (maxOp <= kLastClipOnlyStencilOp) { 187 // Ops that only modify the clip bit. 188 fWriteMask = clipBit; 189 SkASSERT(GrUserStencilOp::kKeep == otherOp || 190 (otherOp > kLastUserOnlyStencilOp && otherOp <= kLastClipOnlyStencilOp)); 191 } else { 192 // Ops that modify both clip and user bits. 193 fWriteMask = clipBit | (user.fWriteMask & userMask); 194 SkASSERT(GrUserStencilOp::kKeep == otherOp || otherOp > kLastClipOnlyStencilOp); 195 } 196 197 fFailOp = gUserStencilOpToRaw[(int)user.fFailOp]; 198 fPassOp = gUserStencilOpToRaw[(int)user.fPassOp]; 199 200 if (!hasStencilClip || user.fTest > kLastClippedStencilTest) { 201 // Ignore the clip. 202 fTestMask = user.fTestMask & userMask; 203 fTest = gUserStencilTestToRaw[(int)user.fTest]; 204 } else if (GrUserStencilTest::kAlwaysIfInClip != user.fTest) { 205 // Respect the clip. 206 fTestMask = clipBit | (user.fTestMask & userMask); 207 fTest = gUserStencilTestToRaw[(int)user.fTest]; 208 } else { 209 // Test only for clip. 210 fTestMask = clipBit; 211 fTest = GrStencilTest::kEqual; 212 } 213 214 fRef = (clipBit | user.fRef) & (fTestMask | fWriteMask); 215} 216 217void GrStencilSettings::Face::setDisabled() { 218 memset(this, 0, sizeof(*this)); 219 static_assert(0 == (int)GrStencilTest::kAlways); 220 static_assert(0 == (int)GrStencilOp::kKeep); 221} 222 223static constexpr GrUserStencilSettings gZeroStencilClipBit( 224 GrUserStencilSettings::StaticInit< 225 0x0000, 226 GrUserStencilTest::kAlways, 227 0xffff, 228 GrUserStencilOp::kZeroClipBit, 229 GrUserStencilOp::kZeroClipBit, 230 0x0000>() 231); 232static constexpr GrUserStencilSettings gSetStencilClipBit( 233 GrUserStencilSettings::StaticInit< 234 0x0000, 235 GrUserStencilTest::kAlways, 236 0xffff, 237 GrUserStencilOp::kSetClipBit, 238 GrUserStencilOp::kSetClipBit, 239 0x0000>() 240); 241 242const GrUserStencilSettings* GrStencilSettings::SetClipBitSettings(bool setToInside) { 243 return setToInside ? &gSetStencilClipBit : &gZeroStencilClipBit; 244} 245 246void GrStencilSettings::genKey(GrProcessorKeyBuilder* b, bool includeRefs) const { 247 b->addBits(6, fFlags, "stencilFlags"); 248 if (this->isDisabled()) { 249 return; 250 } 251 if (!this->isTwoSided()) { 252 if (includeRefs) { 253 b->addBytes(sizeof(Face), &fCWFace, "stencilCWFace"); 254 } else { 255 Face tempFace = fCWFace; 256 tempFace.fRef = 0; 257 b->addBytes(sizeof(Face), &tempFace, "stencilCWFace"); 258 } 259 } else { 260 if (includeRefs) { 261 b->addBytes(sizeof(Face), &fCWFace, "stencilCWFace"); 262 b->addBytes(sizeof(Face), &fCCWFace, "stencilCCWFace"); 263 } else { 264 Face tempFaces[2]; 265 tempFaces[0] = fCWFace; 266 tempFaces[0].fRef = 0; 267 tempFaces[1] = fCCWFace; 268 tempFaces[1].fRef = 0; 269 b->addBytes(sizeof(Face), &tempFaces[0], "stencilCWFace"); 270 b->addBytes(sizeof(Face), &tempFaces[1], "stencilCCWFace"); 271 } 272 } 273 // We rely on GrStencilSettings::Face being tightly packed for the key to be reliable. 274 static_assert(0 == offsetof(Face, fRef)); 275 static_assert(2 == sizeof(Face::fRef)); 276 static_assert(2 == offsetof(Face, fTest)); 277 static_assert(2 == sizeof(Face::fTest)); 278 static_assert(4 == offsetof(Face, fTestMask)); 279 static_assert(2 == sizeof(Face::fTestMask)); 280 static_assert(6 == offsetof(Face, fPassOp)); 281 static_assert(1 == sizeof(Face::fPassOp)); 282 static_assert(7 == offsetof(Face, fFailOp)); 283 static_assert(1 == sizeof(Face::fFailOp)); 284 static_assert(8 == offsetof(Face, fWriteMask)); 285 static_assert(2 == sizeof(Face::fWriteMask)); 286 static_assert(10 == sizeof(Face)); 287} 288