1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/gpu/GrStencil.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,395 @@ 1.4 + 1.5 +/* 1.6 + * Copyright 2011 Google Inc. 1.7 + * 1.8 + * Use of this source code is governed by a BSD-style license that can be 1.9 + * found in the LICENSE file. 1.10 + */ 1.11 + 1.12 + 1.13 +#include "GrStencil.h" 1.14 + 1.15 +//////////////////////////////////////////////////////////////////////////////// 1.16 +// Stencil Rules for Merging user stencil space into clip 1.17 + 1.18 +// We can't include the clip bit in the ref or mask values because the division 1.19 +// between user and clip bits in the stencil depends on the number of stencil 1.20 +// bits in the runtime. Comments below indicate what the code should do to 1.21 +// incorporate the clip bit into these settings. 1.22 + 1.23 +/////// 1.24 +// Replace 1.25 + 1.26 +// set the ref to be the clip bit, but mask it out for the test 1.27 +GR_STATIC_CONST_SAME_STENCIL(gUserToClipReplace, 1.28 + kReplace_StencilOp, 1.29 + kZero_StencilOp, 1.30 + kLess_StencilFunc, 1.31 + 0xffff, // unset clip bit 1.32 + 0x0000, // set clip bit 1.33 + 0xffff); 1.34 + 1.35 +GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipReplace, 1.36 + kReplace_StencilOp, 1.37 + kZero_StencilOp, 1.38 + kEqual_StencilFunc, 1.39 + 0xffff, // unset clip bit 1.40 + 0x0000, // set clip bit 1.41 + 0xffff); 1.42 + 1.43 +/////// 1.44 +// Intersect 1.45 +GR_STATIC_CONST_SAME_STENCIL(gUserToClipIsect, 1.46 + kReplace_StencilOp, 1.47 + kZero_StencilOp, 1.48 + kLess_StencilFunc, 1.49 + 0xffff, 1.50 + 0x0000, // set clip bit 1.51 + 0xffff); 1.52 + 1.53 +GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipIsect, 1.54 + kReplace_StencilOp, 1.55 + kZero_StencilOp, 1.56 + kEqual_StencilFunc, 1.57 + 0xffff, 1.58 + 0x0000, // set clip bit 1.59 + 0xffff); 1.60 + 1.61 +/////// 1.62 +// Difference 1.63 +GR_STATIC_CONST_SAME_STENCIL(gUserToClipDiff, 1.64 + kReplace_StencilOp, 1.65 + kZero_StencilOp, 1.66 + kEqual_StencilFunc, 1.67 + 0xffff, 1.68 + 0x0000, // set clip bit 1.69 + 0xffff); 1.70 + 1.71 +GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipDiff, 1.72 + kReplace_StencilOp, 1.73 + kZero_StencilOp, 1.74 + kLess_StencilFunc, 1.75 + 0xffff, 1.76 + 0x0000, // set clip bit 1.77 + 0xffff); 1.78 + 1.79 +/////// 1.80 +// Union 1.81 + 1.82 +// first pass makes all the passing cases >= just clip bit set. 1.83 +GR_STATIC_CONST_SAME_STENCIL(gUserToClipUnionPass0, 1.84 + kReplace_StencilOp, 1.85 + kKeep_StencilOp, 1.86 + kLEqual_StencilFunc, 1.87 + 0xffff, 1.88 + 0x0001, // set clip bit 1.89 + 0xffff); 1.90 + 1.91 +// second pass allows anything greater than just clip bit set to pass 1.92 +GR_STATIC_CONST_SAME_STENCIL(gUserToClipUnionPass1, 1.93 + kReplace_StencilOp, 1.94 + kZero_StencilOp, 1.95 + kLEqual_StencilFunc, 1.96 + 0xffff, 1.97 + 0x0000, // set clip bit 1.98 + 0xffff); 1.99 + 1.100 +// first pass finds zeros in the user bits and if found sets 1.101 +// the clip bit to 1 1.102 +GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipUnionPass0, 1.103 + kReplace_StencilOp, 1.104 + kKeep_StencilOp, 1.105 + kEqual_StencilFunc, 1.106 + 0xffff, 1.107 + 0x0000, // set clip bit 1.108 + 0x0000 // set clip bit 1.109 +); 1.110 + 1.111 +// second pass zeros the user bits 1.112 +GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipUnionPass1, 1.113 + kZero_StencilOp, 1.114 + kZero_StencilOp, 1.115 + kLess_StencilFunc, 1.116 + 0xffff, 1.117 + 0x0000, 1.118 + 0xffff // unset clip bit 1.119 +); 1.120 + 1.121 +/////// 1.122 +// Xor 1.123 +GR_STATIC_CONST_SAME_STENCIL(gUserToClipXorPass0, 1.124 + kInvert_StencilOp, 1.125 + kKeep_StencilOp, 1.126 + kEqual_StencilFunc, 1.127 + 0xffff, // unset clip bit 1.128 + 0x0000, 1.129 + 0xffff); 1.130 + 1.131 +GR_STATIC_CONST_SAME_STENCIL(gUserToClipXorPass1, 1.132 + kReplace_StencilOp, 1.133 + kZero_StencilOp, 1.134 + kGreater_StencilFunc, 1.135 + 0xffff, 1.136 + 0x0000, // set clip bit 1.137 + 0xffff); 1.138 + 1.139 +GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipXorPass0, 1.140 + kInvert_StencilOp, 1.141 + kKeep_StencilOp, 1.142 + kEqual_StencilFunc, 1.143 + 0xffff, // unset clip bit 1.144 + 0x0000, 1.145 + 0xffff); 1.146 + 1.147 +GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipXorPass1, 1.148 + kReplace_StencilOp, 1.149 + kZero_StencilOp, 1.150 + kLess_StencilFunc, 1.151 + 0xffff, 1.152 + 0x0000, // set clip bit 1.153 + 0xffff); 1.154 + 1.155 +/////// 1.156 +// Reverse Diff 1.157 +GR_STATIC_CONST_SAME_STENCIL(gUserToClipRDiffPass0, 1.158 + kInvert_StencilOp, 1.159 + kZero_StencilOp, 1.160 + kLess_StencilFunc, 1.161 + 0xffff, // unset clip bit 1.162 + 0x0000, // set clip bit 1.163 + 0xffff); 1.164 + 1.165 +GR_STATIC_CONST_SAME_STENCIL(gUserToClipRDiffPass1, 1.166 + kReplace_StencilOp, 1.167 + kZero_StencilOp, 1.168 + kEqual_StencilFunc, 1.169 + 0x0000, // set clip bit 1.170 + 0x0000, // set clip bit 1.171 + 0xffff); 1.172 + 1.173 +// We are looking for stencil values that are all zero. The first pass sets the 1.174 +// clip bit if the stencil is all zeros. The second pass clears the user bits. 1.175 +GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipRDiffPass0, 1.176 + kInvert_StencilOp, 1.177 + kZero_StencilOp, 1.178 + kEqual_StencilFunc, 1.179 + 0xffff, 1.180 + 0x0000, 1.181 + 0x0000 // set clip bit 1.182 +); 1.183 + 1.184 +GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipRDiffPass1, 1.185 + kZero_StencilOp, 1.186 + kZero_StencilOp, 1.187 + kAlways_StencilFunc, 1.188 + 0xffff, 1.189 + 0x0000, 1.190 + 0xffff // unset clip bit 1.191 +); 1.192 + 1.193 +/////// 1.194 +// Direct to Stencil 1.195 + 1.196 +// We can render a clip element directly without first writing to the client 1.197 +// portion of the clip when the fill is not inverse and the set operation will 1.198 +// only modify the in/out status of samples covered by the clip element. 1.199 + 1.200 +// this one only works if used right after stencil clip was cleared. 1.201 +// Our clip mask creation code doesn't allow midstream replace ops. 1.202 +GR_STATIC_CONST_SAME_STENCIL(gReplaceClip, 1.203 + kReplace_StencilOp, 1.204 + kReplace_StencilOp, 1.205 + kAlways_StencilFunc, 1.206 + 0xffff, 1.207 + 0x0000, // set clip bit 1.208 + 0x0000 // set clipBit 1.209 +); 1.210 + 1.211 +GR_STATIC_CONST_SAME_STENCIL(gUnionClip, 1.212 + kReplace_StencilOp, 1.213 + kReplace_StencilOp, 1.214 + kAlways_StencilFunc, 1.215 + 0xffff, 1.216 + 0x0000, // set clip bit 1.217 + 0x0000 // set clip bit 1.218 +); 1.219 + 1.220 +GR_STATIC_CONST_SAME_STENCIL(gXorClip, 1.221 + kInvert_StencilOp, 1.222 + kInvert_StencilOp, 1.223 + kAlways_StencilFunc, 1.224 + 0xffff, 1.225 + 0x0000, 1.226 + 0x0000 // set clip bit 1.227 +); 1.228 + 1.229 +GR_STATIC_CONST_SAME_STENCIL(gDiffClip, 1.230 + kZero_StencilOp, 1.231 + kZero_StencilOp, 1.232 + kAlways_StencilFunc, 1.233 + 0xffff, 1.234 + 0x0000, 1.235 + 0x0000 // set clip bit 1.236 +); 1.237 + 1.238 +bool GrStencilSettings::GetClipPasses( 1.239 + SkRegion::Op op, 1.240 + bool canBeDirect, 1.241 + unsigned int stencilClipMask, 1.242 + bool invertedFill, 1.243 + int* numPasses, 1.244 + GrStencilSettings settings[kMaxStencilClipPasses]) { 1.245 + if (canBeDirect && !invertedFill) { 1.246 + *numPasses = 0; 1.247 + switch (op) { 1.248 + case SkRegion::kReplace_Op: 1.249 + *numPasses = 1; 1.250 + settings[0] = gReplaceClip; 1.251 + break; 1.252 + case SkRegion::kUnion_Op: 1.253 + *numPasses = 1; 1.254 + settings[0] = gUnionClip; 1.255 + break; 1.256 + case SkRegion::kXOR_Op: 1.257 + *numPasses = 1; 1.258 + settings[0] = gXorClip; 1.259 + break; 1.260 + case SkRegion::kDifference_Op: 1.261 + *numPasses = 1; 1.262 + settings[0] = gDiffClip; 1.263 + break; 1.264 + default: // suppress warning 1.265 + break; 1.266 + } 1.267 + if (1 == *numPasses) { 1.268 + settings[0].fFuncRefs[kFront_Face] |= stencilClipMask; 1.269 + settings[0].fWriteMasks[kFront_Face] |= stencilClipMask; 1.270 + settings[0].fFuncRefs[kBack_Face] = 1.271 + settings[0].fFuncRefs[kFront_Face]; 1.272 + settings[0].fWriteMasks[kBack_Face] = 1.273 + settings[0].fWriteMasks[kFront_Face]; 1.274 + return true; 1.275 + } 1.276 + } 1.277 + switch (op) { 1.278 + // if we make the path renderer go to stencil we always give it a 1.279 + // non-inverted fill and we use the stencil rules on the client->clipbit 1.280 + // pass to select either the zeros or nonzeros. 1.281 + case SkRegion::kReplace_Op: 1.282 + *numPasses= 1; 1.283 + settings[0] = invertedFill ? gInvUserToClipReplace : 1.284 + gUserToClipReplace; 1.285 + settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask; 1.286 + settings[0].fFuncRefs[kFront_Face] |= stencilClipMask; 1.287 + settings[0].fFuncMasks[kBack_Face] = 1.288 + settings[0].fFuncMasks[kFront_Face]; 1.289 + settings[0].fFuncRefs[kBack_Face] = 1.290 + settings[0].fFuncRefs[kFront_Face]; 1.291 + break; 1.292 + case SkRegion::kIntersect_Op: 1.293 + *numPasses = 1; 1.294 + settings[0] = invertedFill ? gInvUserToClipIsect : gUserToClipIsect; 1.295 + settings[0].fFuncRefs[kFront_Face] = stencilClipMask; 1.296 + settings[0].fFuncRefs[kBack_Face] = 1.297 + settings[0].fFuncRefs[kFront_Face]; 1.298 + break; 1.299 + case SkRegion::kUnion_Op: 1.300 + *numPasses = 2; 1.301 + if (invertedFill) { 1.302 + settings[0] = gInvUserToClipUnionPass0; 1.303 + settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask; 1.304 + settings[0].fFuncMasks[kBack_Face] = 1.305 + settings[0].fFuncMasks[kFront_Face]; 1.306 + settings[0].fFuncRefs[kFront_Face] |= stencilClipMask; 1.307 + settings[0].fFuncRefs[kBack_Face] = 1.308 + settings[0].fFuncRefs[kFront_Face]; 1.309 + settings[0].fWriteMasks[kFront_Face] |= stencilClipMask; 1.310 + settings[0].fWriteMasks[kBack_Face] = 1.311 + settings[0].fWriteMasks[kFront_Face]; 1.312 + 1.313 + settings[1] = gInvUserToClipUnionPass1; 1.314 + settings[1].fWriteMasks[kFront_Face] &= ~stencilClipMask; 1.315 + settings[1].fWriteMasks[kBack_Face] &= 1.316 + settings[1].fWriteMasks[kFront_Face]; 1.317 + 1.318 + } else { 1.319 + settings[0] = gUserToClipUnionPass0; 1.320 + settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask; 1.321 + settings[0].fFuncRefs[kFront_Face] |= stencilClipMask; 1.322 + settings[0].fFuncMasks[kBack_Face] = 1.323 + settings[0].fFuncMasks[kFront_Face]; 1.324 + settings[0].fFuncRefs[kBack_Face] = 1.325 + settings[0].fFuncRefs[kFront_Face]; 1.326 + 1.327 + settings[1] = gUserToClipUnionPass1; 1.328 + settings[1].fFuncRefs[kFront_Face] |= stencilClipMask; 1.329 + settings[1].fFuncRefs[kBack_Face] = 1.330 + settings[1].fFuncRefs[kFront_Face]; 1.331 + } 1.332 + break; 1.333 + case SkRegion::kXOR_Op: 1.334 + *numPasses = 2; 1.335 + if (invertedFill) { 1.336 + settings[0] = gInvUserToClipXorPass0; 1.337 + settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask; 1.338 + settings[0].fFuncMasks[kBack_Face] = 1.339 + settings[0].fFuncMasks[kFront_Face]; 1.340 + 1.341 + settings[1] = gInvUserToClipXorPass1; 1.342 + settings[1].fFuncRefs[kFront_Face] |= stencilClipMask; 1.343 + settings[1].fFuncRefs[kBack_Face] = 1.344 + settings[1].fFuncRefs[kFront_Face]; 1.345 + } else { 1.346 + settings[0] = gUserToClipXorPass0; 1.347 + settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask; 1.348 + settings[0].fFuncMasks[kBack_Face] = 1.349 + settings[0].fFuncMasks[kFront_Face]; 1.350 + 1.351 + settings[1] = gUserToClipXorPass1; 1.352 + settings[1].fFuncRefs[kFront_Face] |= stencilClipMask; 1.353 + settings[1].fFuncRefs[kBack_Face] = 1.354 + settings[1].fFuncRefs[kFront_Face]; 1.355 + } 1.356 + break; 1.357 + case SkRegion::kDifference_Op: 1.358 + *numPasses = 1; 1.359 + settings[0] = invertedFill ? gInvUserToClipDiff : gUserToClipDiff; 1.360 + settings[0].fFuncRefs[kFront_Face] |= stencilClipMask; 1.361 + settings[0].fFuncRefs[kBack_Face] = 1.362 + settings[0].fFuncRefs[kFront_Face]; 1.363 + break; 1.364 + case SkRegion::kReverseDifference_Op: 1.365 + if (invertedFill) { 1.366 + *numPasses = 2; 1.367 + settings[0] = gInvUserToClipRDiffPass0; 1.368 + settings[0].fWriteMasks[kFront_Face] |= stencilClipMask; 1.369 + settings[0].fWriteMasks[kBack_Face] = 1.370 + settings[0].fWriteMasks[kFront_Face]; 1.371 + settings[1] = gInvUserToClipRDiffPass1; 1.372 + settings[1].fWriteMasks[kFront_Face] &= ~stencilClipMask; 1.373 + settings[1].fWriteMasks[kBack_Face] = 1.374 + settings[1].fWriteMasks[kFront_Face]; 1.375 + } else { 1.376 + *numPasses = 2; 1.377 + settings[0] = gUserToClipRDiffPass0; 1.378 + settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask; 1.379 + settings[0].fFuncMasks[kBack_Face] = 1.380 + settings[0].fFuncMasks[kFront_Face]; 1.381 + settings[0].fFuncRefs[kFront_Face] |= stencilClipMask; 1.382 + settings[0].fFuncRefs[kBack_Face] = 1.383 + settings[0].fFuncRefs[kFront_Face]; 1.384 + 1.385 + settings[1] = gUserToClipRDiffPass1; 1.386 + settings[1].fFuncMasks[kFront_Face] |= stencilClipMask; 1.387 + settings[1].fFuncRefs[kFront_Face] |= stencilClipMask; 1.388 + settings[1].fFuncMasks[kBack_Face] = 1.389 + settings[1].fFuncMasks[kFront_Face]; 1.390 + settings[1].fFuncRefs[kBack_Face] = 1.391 + settings[1].fFuncRefs[kFront_Face]; 1.392 + } 1.393 + break; 1.394 + default: 1.395 + GrCrash("Unknown set op"); 1.396 + } 1.397 + return false; 1.398 +}