GrStencil.cpp revision 1cab2921ab279367f8206cdadc9259d12e603548
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 24GR_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 32GR_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 42GR_STATIC_CONST_SAME_STENCIL(gUserToClipIsect, 43 kReplace_StencilOp, 44 kZero_StencilOp, 45 kLess_StencilFunc, 46 0xffff, 47 0x0000, // set clip bit 48 0xffff); 49 50GR_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 60GR_STATIC_CONST_SAME_STENCIL(gUserToClipDiff, 61 kReplace_StencilOp, 62 kZero_StencilOp, 63 kEqual_StencilFunc, 64 0xffff, 65 0x0000, // set clip bit 66 0xffff); 67 68GR_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. 80GR_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 89GR_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 99GR_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 109GR_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 120GR_STATIC_CONST_SAME_STENCIL(gUserToClipXorPass0, 121 kInvert_StencilOp, 122 kKeep_StencilOp, 123 kEqual_StencilFunc, 124 0xffff, // unset clip bit 125 0x0000, 126 0xffff); 127 128GR_STATIC_CONST_SAME_STENCIL(gUserToClipXorPass1, 129 kReplace_StencilOp, 130 kZero_StencilOp, 131 kGreater_StencilFunc, 132 0xffff, 133 0x0000, // set clip bit 134 0xffff); 135 136GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipXorPass0, 137 kInvert_StencilOp, 138 kKeep_StencilOp, 139 kEqual_StencilFunc, 140 0xffff, // unset clip bit 141 0x0000, 142 0xffff); 143 144GR_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 154GR_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 162GR_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 170GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipRDiff, 171 kInvert_StencilOp, 172 kZero_StencilOp, 173 kEqual_StencilFunc, 174 0xffff, 175 0x0000, 176 0x0000 // set clip bit 177); 178/////// 179// Direct to Stencil 180 181// We can render a clip element directly without first writing to the client 182// portion of the clip when the fill is not inverse and the set operation will 183// only modify the in/out status of samples covered by the clip element. 184 185// this one only works if used right after stencil clip was cleared. 186// Our GrClip doesn't allow midstream replace ops. 187GR_STATIC_CONST_SAME_STENCIL(gReplaceClip, 188 kReplace_StencilOp, 189 kReplace_StencilOp, 190 kAlways_StencilFunc, 191 0xffff, 192 0x0000, // set clip bit 193 0x0000 // set clipBit 194); 195 196GR_STATIC_CONST_SAME_STENCIL(gUnionClip, 197 kReplace_StencilOp, 198 kReplace_StencilOp, 199 kAlways_StencilFunc, 200 0xffff, 201 0x0000, // set clip bit 202 0x0000 // set clip bit 203); 204 205GR_STATIC_CONST_SAME_STENCIL(gXorClip, 206 kInvert_StencilOp, 207 kInvert_StencilOp, 208 kAlways_StencilFunc, 209 0xffff, 210 0x0000, 211 0x0000 // set clip bit 212); 213 214GR_STATIC_CONST_SAME_STENCIL(gDiffClip, 215 kZero_StencilOp, 216 kZero_StencilOp, 217 kAlways_StencilFunc, 218 0xffff, 219 0x0000, 220 0x0000 // set clip bit 221); 222 223bool GrStencilSettings::GetClipPasses(GrSetOp op, 224 bool canBeDirect, 225 unsigned int stencilClipMask, 226 bool invertedFill, 227 int* numPasses, 228 GrStencilSettings settings[kMaxStencilClipPasses]) { 229 if (canBeDirect && !invertedFill) { 230 *numPasses = 0; 231 switch (op) { 232 case kReplace_SetOp: 233 *numPasses = 1; 234 settings[0] = gReplaceClip; 235 break; 236 case kUnion_SetOp: 237 *numPasses = 1; 238 settings[0] = gUnionClip; 239 break; 240 case kXor_SetOp: 241 *numPasses = 1; 242 settings[0] = gXorClip; 243 break; 244 case kDifference_SetOp: 245 *numPasses = 1; 246 settings[0] = gDiffClip; 247 break; 248 default: // suppress warning 249 break; 250 } 251 if (1 == *numPasses) { 252 settings[0].fFrontFuncRef |= stencilClipMask; 253 settings[0].fFrontWriteMask |= stencilClipMask; 254 settings[0].fBackFuncRef = settings[0].fFrontFuncRef; 255 settings[0].fBackWriteMask = settings[0].fFrontWriteMask; 256 return true; 257 } 258 } 259 switch (op) { 260 // if we make the path renderer go to stencil we always give it a 261 // non-inverted fill and we use the stencil rules on the client->clipbit 262 // pass to select either the zeros or nonzeros. 263 case kReplace_SetOp: 264 *numPasses= 1; 265 settings[0] = invertedFill ? gInvUserToClipReplace : gUserToClipReplace; 266 settings[0].fFrontFuncMask &= ~stencilClipMask; 267 settings[0].fFrontFuncRef |= stencilClipMask; 268 settings[0].fBackFuncMask = settings[0].fFrontFuncMask; 269 settings[0].fBackFuncRef = settings[0].fFrontFuncRef; 270 break; 271 case kIntersect_SetOp: 272 *numPasses = 1; 273 settings[0] = invertedFill ? gInvUserToClipIsect : gUserToClipIsect; 274 settings[0].fFrontFuncRef = stencilClipMask; 275 settings[0].fBackFuncRef = settings[0].fFrontFuncRef; 276 break; 277 case kUnion_SetOp: 278 *numPasses = 2; 279 if (invertedFill) { 280 settings[0] = gInvUserToClipUnionPass0; 281 settings[0].fFrontFuncMask &= ~stencilClipMask; 282 settings[0].fBackFuncMask = settings[0].fFrontFuncMask; 283 settings[0].fFrontFuncRef |= stencilClipMask; 284 settings[0].fBackFuncRef = settings[0].fFrontFuncRef; 285 settings[0].fFrontWriteMask |= stencilClipMask; 286 settings[0].fBackWriteMask = settings[0].fFrontWriteMask; 287 288 settings[1] = gInvUserToClipUnionPass1; 289 settings[1].fFrontWriteMask &= ~stencilClipMask; 290 settings[1].fBackWriteMask &= settings[1].fFrontWriteMask; 291 292 } else { 293 settings[0] = gUserToClipUnionPass0; 294 settings[0].fFrontFuncMask &= ~stencilClipMask; 295 settings[0].fFrontFuncRef |= stencilClipMask; 296 settings[0].fBackFuncMask = settings[0].fFrontFuncMask; 297 settings[0].fBackFuncRef = settings[0].fFrontFuncRef; 298 299 settings[1] = gUserToClipUnionPass1; 300 settings[1].fFrontFuncRef |= stencilClipMask; 301 settings[1].fBackFuncRef = settings[1].fFrontFuncRef; 302 } 303 break; 304 case kXor_SetOp: 305 *numPasses = 2; 306 if (invertedFill) { 307 settings[0] = gInvUserToClipXorPass0; 308 settings[0].fFrontFuncMask &= ~stencilClipMask; 309 settings[0].fBackFuncMask = settings[0].fFrontFuncMask; 310 311 settings[1] = gInvUserToClipXorPass1; 312 settings[1].fFrontFuncRef |= stencilClipMask; 313 settings[1].fBackFuncRef = settings[1].fFrontFuncRef; 314 } else { 315 settings[0] = gUserToClipXorPass0; 316 settings[0].fFrontFuncMask &= ~stencilClipMask; 317 settings[0].fBackFuncMask = settings[0].fFrontFuncMask; 318 319 settings[1] = gUserToClipXorPass1; 320 settings[1].fFrontFuncRef |= stencilClipMask; 321 settings[1].fBackFuncRef = settings[1].fFrontFuncRef; 322 } 323 break; 324 case kDifference_SetOp: 325 *numPasses = 1; 326 settings[0] = invertedFill ? gInvUserToClipDiff : gUserToClipDiff; 327 settings[0].fFrontFuncRef |= stencilClipMask; 328 settings[0].fBackFuncRef = settings[0].fFrontFuncRef; 329 break; 330 case kReverseDifference_SetOp: 331 if (invertedFill) { 332 *numPasses = 1; 333 settings[0] = gInvUserToClipRDiff; 334 settings[0].fFrontWriteMask |= stencilClipMask; 335 settings[0].fBackWriteMask = settings[0].fFrontWriteMask; 336 } else { 337 *numPasses = 2; 338 settings[0] = gUserToClipRDiffPass0; 339 settings[0].fFrontFuncMask &= ~stencilClipMask; 340 settings[0].fBackFuncMask = settings[0].fFrontFuncMask; 341 settings[0].fFrontFuncRef |= stencilClipMask; 342 settings[0].fBackFuncRef = settings[0].fFrontFuncRef; 343 344 settings[1] = gUserToClipRDiffPass1; 345 settings[1].fFrontFuncMask |= stencilClipMask; 346 settings[1].fFrontFuncRef |= stencilClipMask; 347 settings[1].fBackFuncMask = settings[1].fFrontFuncMask; 348 settings[1].fBackFuncRef = settings[1].fFrontFuncRef; 349 } 350 break; 351 default: 352 GrCrash("Unknown set op"); 353 } 354 return false; 355} 356