1 2 /* 3 * Copyright 2011 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10 #include "GrStencil.h" 11 12 //////////////////////////////////////////////////////////////////////////////// 13 // Stencil Rules for Merging user stencil space into clip 14 15 // We can't include the clip bit in the ref or mask values because the division 16 // between user and clip bits in the stencil depends on the number of stencil 17 // bits in the runtime. Comments below indicate what the code should do to 18 // incorporate the clip bit into these settings. 19 20 /////// 21 // Replace 22 23 // set the ref to be the clip bit, but mask it out for the test 24 GR_STATIC_CONST_SAME_STENCIL(gUserToClipReplace, 25 kReplace_StencilOp, 26 kZero_StencilOp, 27 kLess_StencilFunc, 28 0xffff, // unset clip bit 29 0x0000, // set clip bit 30 0xffff); 31 32 GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipReplace, 33 kReplace_StencilOp, 34 kZero_StencilOp, 35 kEqual_StencilFunc, 36 0xffff, // unset clip bit 37 0x0000, // set clip bit 38 0xffff); 39 40 /////// 41 // Intersect 42 GR_STATIC_CONST_SAME_STENCIL(gUserToClipIsect, 43 kReplace_StencilOp, 44 kZero_StencilOp, 45 kLess_StencilFunc, 46 0xffff, 47 0x0000, // set clip bit 48 0xffff); 49 50 GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipIsect, 51 kReplace_StencilOp, 52 kZero_StencilOp, 53 kEqual_StencilFunc, 54 0xffff, 55 0x0000, // set clip bit 56 0xffff); 57 58 /////// 59 // Difference 60 GR_STATIC_CONST_SAME_STENCIL(gUserToClipDiff, 61 kReplace_StencilOp, 62 kZero_StencilOp, 63 kEqual_StencilFunc, 64 0xffff, 65 0x0000, // set clip bit 66 0xffff); 67 68 GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipDiff, 69 kReplace_StencilOp, 70 kZero_StencilOp, 71 kLess_StencilFunc, 72 0xffff, 73 0x0000, // set clip bit 74 0xffff); 75 76 /////// 77 // Union 78 79 // first pass makes all the passing cases >= just clip bit set. 80 GR_STATIC_CONST_SAME_STENCIL(gUserToClipUnionPass0, 81 kReplace_StencilOp, 82 kKeep_StencilOp, 83 kLEqual_StencilFunc, 84 0xffff, 85 0x0001, // set clip bit 86 0xffff); 87 88 // second pass allows anything greater than just clip bit set to pass 89 GR_STATIC_CONST_SAME_STENCIL(gUserToClipUnionPass1, 90 kReplace_StencilOp, 91 kZero_StencilOp, 92 kLEqual_StencilFunc, 93 0xffff, 94 0x0000, // set clip bit 95 0xffff); 96 97 // first pass finds zeros in the user bits and if found sets 98 // the clip bit to 1 99 GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipUnionPass0, 100 kReplace_StencilOp, 101 kKeep_StencilOp, 102 kEqual_StencilFunc, 103 0xffff, 104 0x0000, // set clip bit 105 0x0000 // set clip bit 106 ); 107 108 // second pass zeros the user bits 109 GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipUnionPass1, 110 kZero_StencilOp, 111 kZero_StencilOp, 112 kLess_StencilFunc, 113 0xffff, 114 0x0000, 115 0xffff // unset clip bit 116 ); 117 118 /////// 119 // Xor 120 GR_STATIC_CONST_SAME_STENCIL(gUserToClipXorPass0, 121 kInvert_StencilOp, 122 kKeep_StencilOp, 123 kEqual_StencilFunc, 124 0xffff, // unset clip bit 125 0x0000, 126 0xffff); 127 128 GR_STATIC_CONST_SAME_STENCIL(gUserToClipXorPass1, 129 kReplace_StencilOp, 130 kZero_StencilOp, 131 kGreater_StencilFunc, 132 0xffff, 133 0x0000, // set clip bit 134 0xffff); 135 136 GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipXorPass0, 137 kInvert_StencilOp, 138 kKeep_StencilOp, 139 kEqual_StencilFunc, 140 0xffff, // unset clip bit 141 0x0000, 142 0xffff); 143 144 GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipXorPass1, 145 kReplace_StencilOp, 146 kZero_StencilOp, 147 kLess_StencilFunc, 148 0xffff, 149 0x0000, // set clip bit 150 0xffff); 151 152 /////// 153 // Reverse Diff 154 GR_STATIC_CONST_SAME_STENCIL(gUserToClipRDiffPass0, 155 kInvert_StencilOp, 156 kZero_StencilOp, 157 kLess_StencilFunc, 158 0xffff, // unset clip bit 159 0x0000, // set clip bit 160 0xffff); 161 162 GR_STATIC_CONST_SAME_STENCIL(gUserToClipRDiffPass1, 163 kReplace_StencilOp, 164 kZero_StencilOp, 165 kEqual_StencilFunc, 166 0x0000, // set clip bit 167 0x0000, // set clip bit 168 0xffff); 169 170 // We are looking for stencil values that are all zero. The first pass sets the 171 // clip bit if the stencil is all zeros. The second pass clears the user bits. 172 GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipRDiffPass0, 173 kInvert_StencilOp, 174 kZero_StencilOp, 175 kEqual_StencilFunc, 176 0xffff, 177 0x0000, 178 0x0000 // set clip bit 179 ); 180 181 GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipRDiffPass1, 182 kZero_StencilOp, 183 kZero_StencilOp, 184 kAlways_StencilFunc, 185 0xffff, 186 0x0000, 187 0xffff // unset clip bit 188 ); 189 190 /////// 191 // Direct to Stencil 192 193 // We can render a clip element directly without first writing to the client 194 // portion of the clip when the fill is not inverse and the set operation will 195 // only modify the in/out status of samples covered by the clip element. 196 197 // this one only works if used right after stencil clip was cleared. 198 // Our clip mask creation code doesn't allow midstream replace ops. 199 GR_STATIC_CONST_SAME_STENCIL(gReplaceClip, 200 kReplace_StencilOp, 201 kReplace_StencilOp, 202 kAlways_StencilFunc, 203 0xffff, 204 0x0000, // set clip bit 205 0x0000 // set clipBit 206 ); 207 208 GR_STATIC_CONST_SAME_STENCIL(gUnionClip, 209 kReplace_StencilOp, 210 kReplace_StencilOp, 211 kAlways_StencilFunc, 212 0xffff, 213 0x0000, // set clip bit 214 0x0000 // set clip bit 215 ); 216 217 GR_STATIC_CONST_SAME_STENCIL(gXorClip, 218 kInvert_StencilOp, 219 kInvert_StencilOp, 220 kAlways_StencilFunc, 221 0xffff, 222 0x0000, 223 0x0000 // set clip bit 224 ); 225 226 GR_STATIC_CONST_SAME_STENCIL(gDiffClip, 227 kZero_StencilOp, 228 kZero_StencilOp, 229 kAlways_StencilFunc, 230 0xffff, 231 0x0000, 232 0x0000 // set clip bit 233 ); 234 235 bool GrStencilSettings::GetClipPasses( 236 SkRegion::Op op, 237 bool canBeDirect, 238 unsigned int stencilClipMask, 239 bool invertedFill, 240 int* numPasses, 241 GrStencilSettings settings[kMaxStencilClipPasses]) { 242 if (canBeDirect && !invertedFill) { 243 *numPasses = 0; 244 switch (op) { 245 case SkRegion::kReplace_Op: 246 *numPasses = 1; 247 settings[0] = gReplaceClip; 248 break; 249 case SkRegion::kUnion_Op: 250 *numPasses = 1; 251 settings[0] = gUnionClip; 252 break; 253 case SkRegion::kXOR_Op: 254 *numPasses = 1; 255 settings[0] = gXorClip; 256 break; 257 case SkRegion::kDifference_Op: 258 *numPasses = 1; 259 settings[0] = gDiffClip; 260 break; 261 default: // suppress warning 262 break; 263 } 264 if (1 == *numPasses) { 265 settings[0].fFuncRefs[kFront_Face] |= stencilClipMask; 266 settings[0].fWriteMasks[kFront_Face] |= stencilClipMask; 267 settings[0].fFuncRefs[kBack_Face] = 268 settings[0].fFuncRefs[kFront_Face]; 269 settings[0].fWriteMasks[kBack_Face] = 270 settings[0].fWriteMasks[kFront_Face]; 271 return true; 272 } 273 } 274 switch (op) { 275 // if we make the path renderer go to stencil we always give it a 276 // non-inverted fill and we use the stencil rules on the client->clipbit 277 // pass to select either the zeros or nonzeros. 278 case SkRegion::kReplace_Op: 279 *numPasses= 1; 280 settings[0] = invertedFill ? gInvUserToClipReplace : 281 gUserToClipReplace; 282 settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask; 283 settings[0].fFuncRefs[kFront_Face] |= stencilClipMask; 284 settings[0].fFuncMasks[kBack_Face] = 285 settings[0].fFuncMasks[kFront_Face]; 286 settings[0].fFuncRefs[kBack_Face] = 287 settings[0].fFuncRefs[kFront_Face]; 288 break; 289 case SkRegion::kIntersect_Op: 290 *numPasses = 1; 291 settings[0] = invertedFill ? gInvUserToClipIsect : gUserToClipIsect; 292 settings[0].fFuncRefs[kFront_Face] = stencilClipMask; 293 settings[0].fFuncRefs[kBack_Face] = 294 settings[0].fFuncRefs[kFront_Face]; 295 break; 296 case SkRegion::kUnion_Op: 297 *numPasses = 2; 298 if (invertedFill) { 299 settings[0] = gInvUserToClipUnionPass0; 300 settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask; 301 settings[0].fFuncMasks[kBack_Face] = 302 settings[0].fFuncMasks[kFront_Face]; 303 settings[0].fFuncRefs[kFront_Face] |= stencilClipMask; 304 settings[0].fFuncRefs[kBack_Face] = 305 settings[0].fFuncRefs[kFront_Face]; 306 settings[0].fWriteMasks[kFront_Face] |= stencilClipMask; 307 settings[0].fWriteMasks[kBack_Face] = 308 settings[0].fWriteMasks[kFront_Face]; 309 310 settings[1] = gInvUserToClipUnionPass1; 311 settings[1].fWriteMasks[kFront_Face] &= ~stencilClipMask; 312 settings[1].fWriteMasks[kBack_Face] &= 313 settings[1].fWriteMasks[kFront_Face]; 314 315 } else { 316 settings[0] = gUserToClipUnionPass0; 317 settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask; 318 settings[0].fFuncRefs[kFront_Face] |= stencilClipMask; 319 settings[0].fFuncMasks[kBack_Face] = 320 settings[0].fFuncMasks[kFront_Face]; 321 settings[0].fFuncRefs[kBack_Face] = 322 settings[0].fFuncRefs[kFront_Face]; 323 324 settings[1] = gUserToClipUnionPass1; 325 settings[1].fFuncRefs[kFront_Face] |= stencilClipMask; 326 settings[1].fFuncRefs[kBack_Face] = 327 settings[1].fFuncRefs[kFront_Face]; 328 } 329 break; 330 case SkRegion::kXOR_Op: 331 *numPasses = 2; 332 if (invertedFill) { 333 settings[0] = gInvUserToClipXorPass0; 334 settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask; 335 settings[0].fFuncMasks[kBack_Face] = 336 settings[0].fFuncMasks[kFront_Face]; 337 338 settings[1] = gInvUserToClipXorPass1; 339 settings[1].fFuncRefs[kFront_Face] |= stencilClipMask; 340 settings[1].fFuncRefs[kBack_Face] = 341 settings[1].fFuncRefs[kFront_Face]; 342 } else { 343 settings[0] = gUserToClipXorPass0; 344 settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask; 345 settings[0].fFuncMasks[kBack_Face] = 346 settings[0].fFuncMasks[kFront_Face]; 347 348 settings[1] = gUserToClipXorPass1; 349 settings[1].fFuncRefs[kFront_Face] |= stencilClipMask; 350 settings[1].fFuncRefs[kBack_Face] = 351 settings[1].fFuncRefs[kFront_Face]; 352 } 353 break; 354 case SkRegion::kDifference_Op: 355 *numPasses = 1; 356 settings[0] = invertedFill ? gInvUserToClipDiff : gUserToClipDiff; 357 settings[0].fFuncRefs[kFront_Face] |= stencilClipMask; 358 settings[0].fFuncRefs[kBack_Face] = 359 settings[0].fFuncRefs[kFront_Face]; 360 break; 361 case SkRegion::kReverseDifference_Op: 362 if (invertedFill) { 363 *numPasses = 2; 364 settings[0] = gInvUserToClipRDiffPass0; 365 settings[0].fWriteMasks[kFront_Face] |= stencilClipMask; 366 settings[0].fWriteMasks[kBack_Face] = 367 settings[0].fWriteMasks[kFront_Face]; 368 settings[1] = gInvUserToClipRDiffPass1; 369 settings[1].fWriteMasks[kFront_Face] &= ~stencilClipMask; 370 settings[1].fWriteMasks[kBack_Face] = 371 settings[1].fWriteMasks[kFront_Face]; 372 } else { 373 *numPasses = 2; 374 settings[0] = gUserToClipRDiffPass0; 375 settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask; 376 settings[0].fFuncMasks[kBack_Face] = 377 settings[0].fFuncMasks[kFront_Face]; 378 settings[0].fFuncRefs[kFront_Face] |= stencilClipMask; 379 settings[0].fFuncRefs[kBack_Face] = 380 settings[0].fFuncRefs[kFront_Face]; 381 382 settings[1] = gUserToClipRDiffPass1; 383 settings[1].fFuncMasks[kFront_Face] |= stencilClipMask; 384 settings[1].fFuncRefs[kFront_Face] |= stencilClipMask; 385 settings[1].fFuncMasks[kBack_Face] = 386 settings[1].fFuncMasks[kFront_Face]; 387 settings[1].fFuncRefs[kBack_Face] = 388 settings[1].fFuncRefs[kFront_Face]; 389 } 390 break; 391 default: 392 SkFAIL("Unknown set op"); 393 } 394 return false; 395 } 396