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 "GrStencilSettings.h" 10 11 #include "GrProcessor.h" 12 13 constexpr const GrUserStencilSettings gUnused( 14 GrUserStencilSettings::StaticInit< 15 0x0000, 16 GrUserStencilTest::kAlwaysIfInClip, 17 0xffff, 18 GrUserStencilOp::kKeep, 19 GrUserStencilOp::kKeep, 20 0x0000>() 21 ); 22 23 GR_STATIC_ASSERT(kAll_StencilFlags == (gUnused.fFrontFlags[0] & gUnused.fBackFlags[0])); 24 25 const GrUserStencilSettings& GrUserStencilSettings::kUnused = gUnused; 26 27 void GrStencilSettings::reset(const GrUserStencilSettings& user, bool hasStencilClip, 28 int numStencilBits) { 29 uint16_t frontFlags = user.fFrontFlags[hasStencilClip]; 30 if (frontFlags & kSingleSided_StencilFlag) { 31 SkASSERT(frontFlags == user.fBackFlags[hasStencilClip]); 32 fFlags = frontFlags; 33 if (!this->isDisabled()) { 34 fFront.reset(user.fFront, hasStencilClip, numStencilBits); 35 } 36 return; 37 } 38 39 uint16_t backFlags = user.fBackFlags[hasStencilClip]; 40 fFlags = frontFlags & backFlags; 41 if (this->isDisabled()) { 42 return; 43 } 44 if (!(frontFlags & kDisabled_StencilFlag)) { 45 fFront.reset(user.fFront, hasStencilClip, numStencilBits); 46 } else { 47 fFront.setDisabled(); 48 } 49 if (!(backFlags & kDisabled_StencilFlag)) { 50 fBack.reset(user.fBack, hasStencilClip, numStencilBits); 51 } else { 52 fBack.setDisabled(); 53 } 54 } 55 56 void 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(&fFront, &that.fFront, sizeof(Face)); 63 } else { 64 memcpy(&fFront, &that.fFront, 2 * sizeof(Face)); 65 GR_STATIC_ASSERT(sizeof(Face) == 66 offsetof(GrStencilSettings, fBack) - offsetof(GrStencilSettings, fFront)); 67 } 68 } 69 70 bool 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(&fFront, &that.fFront, sizeof(Face)); // Both are single sided. 81 } else if (kSingleSided_StencilFlag & (fFlags | that.fFlags)) { 82 return false; 83 } else { 84 return 0 == memcmp(&fFront, &that.fFront, 2 * sizeof(Face)); 85 GR_STATIC_ASSERT(sizeof(Face) == 86 offsetof(GrStencilSettings, fBack) - offsetof(GrStencilSettings, fFront)); 87 } 88 // memcmp relies on GrStencilSettings::Face being tightly packed. 89 GR_STATIC_ASSERT(0 == offsetof(Face, fRef)); 90 GR_STATIC_ASSERT(2 == sizeof(Face::fRef)); 91 GR_STATIC_ASSERT(2 == offsetof(Face, fTest)); 92 GR_STATIC_ASSERT(2 == sizeof(Face::fTest)); 93 GR_STATIC_ASSERT(4 == offsetof(Face, fTestMask)); 94 GR_STATIC_ASSERT(2 == sizeof(Face::fTestMask)); 95 GR_STATIC_ASSERT(6 == offsetof(Face, fPassOp)); 96 GR_STATIC_ASSERT(1 == sizeof(Face::fPassOp)); 97 GR_STATIC_ASSERT(7 == offsetof(Face, fFailOp)); 98 GR_STATIC_ASSERT(1 == sizeof(Face::fFailOp)); 99 GR_STATIC_ASSERT(8 == offsetof(Face, fWriteMask)); 100 GR_STATIC_ASSERT(2 == sizeof(Face::fWriteMask)); 101 GR_STATIC_ASSERT(10 == sizeof(Face)); 102 } 103 104 static 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 122 GR_STATIC_ASSERT(0 == (int)GrUserStencilTest::kAlwaysIfInClip); 123 GR_STATIC_ASSERT(1 == (int)GrUserStencilTest::kEqualIfInClip); 124 GR_STATIC_ASSERT(2 == (int)GrUserStencilTest::kLessIfInClip); 125 GR_STATIC_ASSERT(3 == (int)GrUserStencilTest::kLEqualIfInClip); 126 GR_STATIC_ASSERT(4 == (int)GrUserStencilTest::kAlways); 127 GR_STATIC_ASSERT(5 == (int)GrUserStencilTest::kNever); 128 GR_STATIC_ASSERT(6 == (int)GrUserStencilTest::kGreater); 129 GR_STATIC_ASSERT(7 == (int)GrUserStencilTest::kGEqual); 130 GR_STATIC_ASSERT(8 == (int)GrUserStencilTest::kLess); 131 GR_STATIC_ASSERT(9 == (int)GrUserStencilTest::kLEqual); 132 GR_STATIC_ASSERT(10 == (int)GrUserStencilTest::kEqual); 133 GR_STATIC_ASSERT(11 == (int)GrUserStencilTest::kNotEqual); 134 135 static 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 157 GR_STATIC_ASSERT(0 == (int)GrUserStencilOp::kKeep); 158 GR_STATIC_ASSERT(1 == (int)GrUserStencilOp::kZero); 159 GR_STATIC_ASSERT(2 == (int)GrUserStencilOp::kReplace); 160 GR_STATIC_ASSERT(3 == (int)GrUserStencilOp::kInvert); 161 GR_STATIC_ASSERT(4 == (int)GrUserStencilOp::kIncWrap); 162 GR_STATIC_ASSERT(5 == (int)GrUserStencilOp::kDecWrap); 163 GR_STATIC_ASSERT(6 == (int)GrUserStencilOp::kIncMaybeClamp); 164 GR_STATIC_ASSERT(7 == (int)GrUserStencilOp::kDecMaybeClamp); 165 GR_STATIC_ASSERT(8 == (int)GrUserStencilOp::kZeroClipBit); 166 GR_STATIC_ASSERT(9 == (int)GrUserStencilOp::kSetClipBit); 167 GR_STATIC_ASSERT(10 == (int)GrUserStencilOp::kInvertClipBit); 168 GR_STATIC_ASSERT(11 == (int)GrUserStencilOp::kSetClipAndReplaceUserBits); 169 GR_STATIC_ASSERT(12 == (int)GrUserStencilOp::kZeroClipAndUserBits); 170 171 void 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 = SkTMax(user.fPassOp, user.fFailOp); 181 SkDEBUGCODE(GrUserStencilOp otherOp = SkTMin(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 217 void GrStencilSettings::Face::setDisabled() { 218 memset(this, 0, sizeof(*this)); 219 GR_STATIC_ASSERT(0 == (int)GrStencilTest::kAlways); 220 GR_STATIC_ASSERT(0 == (int)GrStencilOp::kKeep); 221 } 222 223 //////////////////////////////////////////////////////////////////////////////// 224 // Stencil Rules for Merging user stencil space into clip 225 // 226 227 /////// 228 // Replace 229 static constexpr GrUserStencilSettings gUserToClipReplace( 230 GrUserStencilSettings::StaticInit< 231 0x0000, 232 GrUserStencilTest::kNotEqual, 233 0xffff, 234 GrUserStencilOp::kSetClipAndReplaceUserBits, 235 GrUserStencilOp::kZeroClipAndUserBits, 236 0xffff>() 237 ); 238 239 static constexpr GrUserStencilSettings gInvUserToClipReplace( 240 GrUserStencilSettings::StaticInit< 241 0x0000, 242 GrUserStencilTest::kEqual, 243 0xffff, 244 GrUserStencilOp::kSetClipAndReplaceUserBits, 245 GrUserStencilOp::kZeroClipAndUserBits, 246 0xffff>() 247 ); 248 249 /////// 250 // Intersect 251 static constexpr GrUserStencilSettings gUserToClipIsect( 252 GrUserStencilSettings::StaticInit< 253 0x0000, 254 GrUserStencilTest::kLessIfInClip, // "0 < userBits" is equivalent to "0 != userBits". 255 0xffff, 256 GrUserStencilOp::kSetClipAndReplaceUserBits, 257 GrUserStencilOp::kZeroClipAndUserBits, 258 0xffff>() 259 ); 260 261 /////// 262 // Difference 263 static constexpr GrUserStencilSettings gUserToClipDiff( 264 GrUserStencilSettings::StaticInit< 265 0x0000, 266 GrUserStencilTest::kEqualIfInClip, 267 0xffff, 268 GrUserStencilOp::kSetClipAndReplaceUserBits, 269 GrUserStencilOp::kZeroClipAndUserBits, 270 0xffff>() 271 ); 272 273 /////// 274 // Union 275 static constexpr GrUserStencilSettings gUserToClipUnion( 276 GrUserStencilSettings::StaticInit< 277 0x0000, 278 GrUserStencilTest::kNotEqual, 279 0xffff, 280 GrUserStencilOp::kSetClipAndReplaceUserBits, 281 GrUserStencilOp::kKeep, 282 0xffff>() 283 ); 284 285 static constexpr GrUserStencilSettings gInvUserToClipUnionPass0( // Does not zero user bits. 286 GrUserStencilSettings::StaticInit< 287 0x0000, 288 GrUserStencilTest::kEqual, 289 0xffff, 290 GrUserStencilOp::kSetClipBit, 291 GrUserStencilOp::kKeep, 292 0x0000>() 293 ); 294 295 /////// 296 // Xor 297 static constexpr GrUserStencilSettings gUserToClipXorPass0( // Does not zero user bits. 298 GrUserStencilSettings::StaticInit< 299 0x0000, 300 GrUserStencilTest::kNotEqual, 301 0xffff, 302 GrUserStencilOp::kInvertClipBit, 303 GrUserStencilOp::kKeep, 304 0x0000>() 305 ); 306 307 static constexpr GrUserStencilSettings gInvUserToClipXorPass0( // Does not zero user bits. 308 GrUserStencilSettings::StaticInit< 309 0x0000, 310 GrUserStencilTest::kEqual, 311 0xffff, 312 GrUserStencilOp::kInvertClipBit, 313 GrUserStencilOp::kKeep, 314 0x0000>() 315 ); 316 317 /////// 318 // Reverse Diff 319 static constexpr GrUserStencilSettings gUserToClipRDiffPass0( // Does not zero user bits. 320 GrUserStencilSettings::StaticInit< 321 0x0000, 322 GrUserStencilTest::kNotEqual, 323 0xffff, 324 GrUserStencilOp::kInvertClipBit, 325 GrUserStencilOp::kZeroClipBit, 326 0x0000>() 327 ); 328 329 static constexpr GrUserStencilSettings gInvUserToClipRDiffPass0( // Does not zero user bits. 330 GrUserStencilSettings::StaticInit< 331 0x0000, 332 GrUserStencilTest::kEqual, 333 0xffff, 334 GrUserStencilOp::kInvertClipBit, 335 GrUserStencilOp::kZeroClipBit, 336 0x0000>() 337 ); 338 339 /////// 340 // Second pass to clear user bits (only needed sometimes) 341 static constexpr GrUserStencilSettings gZeroUserBits( 342 GrUserStencilSettings::StaticInit< 343 0x0000, 344 GrUserStencilTest::kNotEqual, 345 0xffff, 346 GrUserStencilOp::kZero, 347 GrUserStencilOp::kKeep, 348 0xffff>() 349 ); 350 351 static constexpr const GrUserStencilSettings* gUserToClipTable[2][1 + SkRegion::kLastOp][3] = { 352 { /* Normal fill. */ 353 {&gUserToClipDiff, nullptr, nullptr}, // kDifference_Op. 354 {&gUserToClipIsect, nullptr, nullptr}, // kIntersect_Op. 355 {&gUserToClipUnion, nullptr, nullptr}, // kUnion_Op. 356 {&gUserToClipXorPass0, &gZeroUserBits, nullptr}, // kXOR_Op. 357 {&gUserToClipRDiffPass0, &gZeroUserBits, nullptr}, // kReverseDifference_Op. 358 {&gUserToClipReplace, nullptr, nullptr} // kReplace_Op. 359 360 }, /* Inverse fill. */ { 361 {&gUserToClipIsect, nullptr, nullptr}, // ~diff (aka isect). 362 {&gUserToClipDiff, nullptr, nullptr}, // ~isect (aka diff). 363 {&gInvUserToClipUnionPass0, &gZeroUserBits, nullptr}, // ~union. 364 {&gInvUserToClipXorPass0, &gZeroUserBits, nullptr}, // ~xor. 365 {&gInvUserToClipRDiffPass0, &gZeroUserBits, nullptr}, // ~reverse diff. 366 {&gInvUserToClipReplace, nullptr, nullptr} // ~replace. 367 } 368 }; 369 370 GR_STATIC_ASSERT(0 == SkRegion::kDifference_Op); 371 GR_STATIC_ASSERT(1 == SkRegion::kIntersect_Op); 372 GR_STATIC_ASSERT(2 == SkRegion::kUnion_Op); 373 GR_STATIC_ASSERT(3 == SkRegion::kXOR_Op); 374 GR_STATIC_ASSERT(4 == SkRegion::kReverseDifference_Op); 375 GR_STATIC_ASSERT(5 == SkRegion::kReplace_Op); 376 377 /////// 378 // Direct to Stencil 379 380 // We can render a clip element directly without first writing to the client 381 // portion of the clip when the fill is not inverse and the set operation will 382 // only modify the in/out status of samples covered by the clip element. 383 384 // this one only works if used right after stencil clip was cleared. 385 // Our clip mask creation code doesn't allow midstream replace ops. 386 static constexpr GrUserStencilSettings gReplaceClip( 387 GrUserStencilSettings::StaticInit< 388 0x0000, 389 GrUserStencilTest::kAlways, 390 0xffff, 391 GrUserStencilOp::kSetClipBit, 392 GrUserStencilOp::kSetClipBit, 393 0x0000>() 394 ); 395 396 static constexpr GrUserStencilSettings gUnionClip( 397 GrUserStencilSettings::StaticInit< 398 0x0000, 399 GrUserStencilTest::kAlwaysIfInClip, 400 0xffff, 401 GrUserStencilOp::kKeep, 402 GrUserStencilOp::kSetClipBit, 403 0x0000>() 404 ); 405 406 static constexpr GrUserStencilSettings gXorClip( 407 GrUserStencilSettings::StaticInit< 408 0x0000, 409 GrUserStencilTest::kAlways, 410 0xffff, 411 GrUserStencilOp::kInvertClipBit, 412 GrUserStencilOp::kInvertClipBit, 413 0x0000>() 414 ); 415 416 static constexpr GrUserStencilSettings gDiffClip( 417 GrUserStencilSettings::StaticInit< 418 0x0000, 419 GrUserStencilTest::kAlwaysIfInClip, 420 0xffff, 421 GrUserStencilOp::kZeroClipBit, 422 GrUserStencilOp::kKeep, 423 0x0000>() 424 ); 425 426 static constexpr const GrUserStencilSettings* gDirectDrawTable[1 + SkRegion::kLastOp][2] = { 427 {&gDiffClip, nullptr}, // kDifference_Op. 428 {nullptr, nullptr}, // kIntersect_Op. 429 {&gUnionClip, nullptr}, // kUnion_Op. 430 {&gXorClip, nullptr}, // kXOR_Op. 431 {nullptr, nullptr}, // kReverseDifference_Op. 432 {&gReplaceClip, nullptr} // kReplace_Op. 433 }; 434 435 GR_STATIC_ASSERT(0 == SkRegion::kDifference_Op); 436 GR_STATIC_ASSERT(1 == SkRegion::kIntersect_Op); 437 GR_STATIC_ASSERT(2 == SkRegion::kUnion_Op); 438 GR_STATIC_ASSERT(3 == SkRegion::kXOR_Op); 439 GR_STATIC_ASSERT(4 == SkRegion::kReverseDifference_Op); 440 GR_STATIC_ASSERT(5 == SkRegion::kReplace_Op); 441 442 GrUserStencilSettings const* const* GrStencilSettings::GetClipPasses(SkRegion::Op op, 443 bool canBeDirect, 444 bool invertedFill, 445 bool* drawDirectToClip) { 446 SkASSERT((unsigned)op <= SkRegion::kLastOp); 447 if (canBeDirect && !invertedFill) { // TODO: inverse fill + intersect op can be direct. 448 GrUserStencilSettings const* const* directPass = gDirectDrawTable[op]; 449 if (directPass[0]) { 450 *drawDirectToClip = true; 451 return directPass; 452 } 453 } 454 *drawDirectToClip = false; 455 return gUserToClipTable[invertedFill][op]; 456 } 457 458 static constexpr GrUserStencilSettings gZeroStencilClipBit( 459 GrUserStencilSettings::StaticInit< 460 0x0000, 461 GrUserStencilTest::kAlways, 462 0xffff, 463 GrUserStencilOp::kZeroClipBit, 464 GrUserStencilOp::kZeroClipBit, 465 0x0000>() 466 ); 467 468 const GrUserStencilSettings* GrStencilSettings::SetClipBitSettings(bool setToInside) { 469 return setToInside ? &gReplaceClip : &gZeroStencilClipBit; 470 } 471 472 void GrStencilSettings::genKey(GrProcessorKeyBuilder* b) const { 473 b->add32(fFlags); 474 if (this->isDisabled()) { 475 return; 476 } 477 if (!this->isTwoSided()) { 478 constexpr int kCount16 = sizeof(Face) / sizeof(uint16_t); 479 GR_STATIC_ASSERT(0 == sizeof(Face) % sizeof(uint16_t)); 480 uint16_t* key = reinterpret_cast<uint16_t*>(b->add32n((kCount16 + 1) / 2)); 481 memcpy(key, &fFront, sizeof(Face)); 482 key[kCount16] = 0; 483 GR_STATIC_ASSERT(1 == kCount16 % 2); 484 } else { 485 constexpr int kCount32 = (2 * sizeof(Face)) / sizeof(uint32_t); 486 GR_STATIC_ASSERT(0 == (2 * sizeof(Face)) % sizeof(uint32_t)); 487 uint32_t* key = b->add32n(kCount32); 488 memcpy(key, &fFront, 2 * sizeof(Face)); 489 GR_STATIC_ASSERT(sizeof(Face) == 490 offsetof(GrStencilSettings, fBack) - offsetof(GrStencilSettings, fFront)); 491 } 492 // We rely on GrStencilSettings::Face being tightly packed for the key to be reliable. 493 GR_STATIC_ASSERT(0 == offsetof(Face, fRef)); 494 GR_STATIC_ASSERT(2 == sizeof(Face::fRef)); 495 GR_STATIC_ASSERT(2 == offsetof(Face, fTest)); 496 GR_STATIC_ASSERT(2 == sizeof(Face::fTest)); 497 GR_STATIC_ASSERT(4 == offsetof(Face, fTestMask)); 498 GR_STATIC_ASSERT(2 == sizeof(Face::fTestMask)); 499 GR_STATIC_ASSERT(6 == offsetof(Face, fPassOp)); 500 GR_STATIC_ASSERT(1 == sizeof(Face::fPassOp)); 501 GR_STATIC_ASSERT(7 == offsetof(Face, fFailOp)); 502 GR_STATIC_ASSERT(1 == sizeof(Face::fFailOp)); 503 GR_STATIC_ASSERT(8 == offsetof(Face, fWriteMask)); 504 GR_STATIC_ASSERT(2 == sizeof(Face::fWriteMask)); 505 GR_STATIC_ASSERT(10 == sizeof(Face)); 506 } 507