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