1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/gpu/GrStencil.h 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 +#ifndef GrStencil_DEFINED 1.14 +#define GrStencil_DEFINED 1.15 + 1.16 +#include "GrTypes.h" 1.17 +#include "SkRegion.h" 1.18 + 1.19 +/** 1.20 + * Gr uses the stencil buffer to implement complex clipping inside the 1.21 + * GrDrawTarget class. The GrDrawTarget makes a subset of the stencil buffer 1.22 + * bits available for other uses by external code (clients). Client code can 1.23 + * modify these bits. GrDrawTarget will ignore ref, mask, and writemask bits 1.24 + * provided by clients that overlap the bits used to implement clipping. 1.25 + * 1.26 + * When code outside the GrDrawTarget class uses the stencil buffer the contract 1.27 + * is as follows: 1.28 + * 1.29 + * > Normal stencil funcs allow the client to pass / fail regardless of the 1.30 + * reserved clip bits. 1.31 + * > Additional functions allow a test against the clip along with a limited 1.32 + * set of tests against the client bits. 1.33 + * > Client can assume all client bits are zero initially. 1.34 + * > Client must ensure that after all its passes are finished it has only 1.35 + * written to the color buffer in the region inside the clip. Furthermore, it 1.36 + * must zero all client bits that were modifed (both inside and outside the 1.37 + * clip). 1.38 + */ 1.39 + 1.40 +/** 1.41 + * Determines which pixels pass / fail the stencil test. 1.42 + * Stencil test passes if (ref & mask) FUNC (stencil & mask) is true 1.43 + */ 1.44 +enum GrStencilFunc { 1.45 + kAlways_StencilFunc = 0, 1.46 + kNever_StencilFunc, 1.47 + kGreater_StencilFunc, 1.48 + kGEqual_StencilFunc, 1.49 + kLess_StencilFunc, 1.50 + kLEqual_StencilFunc, 1.51 + kEqual_StencilFunc, 1.52 + kNotEqual_StencilFunc, 1.53 + 1.54 + // Gr stores the current clip in the 1.55 + // stencil buffer in the high bits that 1.56 + // are not directly accessible modifiable 1.57 + // via the GrDrawTarget interface. The below 1.58 + // stencil funcs test against the current 1.59 + // clip in addition to the GrDrawTarget 1.60 + // client's stencil bits. 1.61 + 1.62 + // pass if inside the clip 1.63 + kAlwaysIfInClip_StencilFunc, 1.64 + kEqualIfInClip_StencilFunc, 1.65 + kLessIfInClip_StencilFunc, 1.66 + kLEqualIfInClip_StencilFunc, 1.67 + kNonZeroIfInClip_StencilFunc, // this one forces the ref to be 0 1.68 + 1.69 + // counts 1.70 + kStencilFuncCount, 1.71 + kClipStencilFuncCount = kNonZeroIfInClip_StencilFunc - 1.72 + kAlwaysIfInClip_StencilFunc + 1, 1.73 + kBasicStencilFuncCount = kStencilFuncCount - kClipStencilFuncCount 1.74 +}; 1.75 + 1.76 +/** 1.77 + * Operations to perform based on whether stencil test passed failed. 1.78 + */ 1.79 +enum GrStencilOp { 1.80 + kKeep_StencilOp = 0, // preserve existing stencil value 1.81 + kReplace_StencilOp, // replace with reference value from stencl test 1.82 + kIncWrap_StencilOp, // increment and wrap at max 1.83 + kIncClamp_StencilOp, // increment and clamp at max 1.84 + kDecWrap_StencilOp, // decrement and wrap at 0 1.85 + kDecClamp_StencilOp, // decrement and clamp at 0 1.86 + kZero_StencilOp, // zero stencil bits 1.87 + kInvert_StencilOp, // invert stencil bits 1.88 + 1.89 + kStencilOpCount 1.90 +}; 1.91 + 1.92 +enum GrStencilFlags { 1.93 + kIsDisabled_StencilFlag = 0x1, 1.94 + kNotDisabled_StencilFlag = 0x2, 1.95 + kDoesWrite_StencilFlag = 0x4, 1.96 + kDoesNotWrite_StencilFlag = 0x8, 1.97 +}; 1.98 + 1.99 +/** 1.100 + * GrStencilState needs to be a class with accessors and setters so that it 1.101 + * can maintain flags related to its current state. However, we also want to 1.102 + * be able to declare pre-made stencil settings at compile time (without 1.103 + * inserting static initializer code). So all the data members are in this 1.104 + * struct. A macro defined after the class can be used to jam an instance of 1.105 + * this struct that is created from an initializer list into a 1.106 + * GrStencilSettings. (We hang our heads in shame.) 1.107 + */ 1.108 +struct GrStencilSettingsStruct { 1.109 + uint8_t fPassOps[2]; // op to perform when faces pass (GrStencilOp) 1.110 + uint8_t fFailOps[2]; // op to perform when faces fail (GrStencilOp) 1.111 + uint8_t fFuncs[2]; // test function for faces (GrStencilFunc) 1.112 + uint8_t fPad0; 1.113 + uint8_t fPad1; 1.114 + uint16_t fFuncMasks[2]; // mask for face tests 1.115 + uint16_t fFuncRefs[2]; // reference values for face tests 1.116 + uint16_t fWriteMasks[2]; // stencil write masks 1.117 + mutable uint32_t fFlags; 1.118 +}; 1.119 +// We rely on this being packed and aligned (memcmp'ed and memcpy'ed) 1.120 +GR_STATIC_ASSERT(sizeof(GrStencilSettingsStruct) % 4 == 0); 1.121 +GR_STATIC_ASSERT(sizeof(GrStencilSettingsStruct) == 1.122 + 4*sizeof(uint8_t) + // ops 1.123 + 2*sizeof(uint8_t) + // funcs 1.124 + 2*sizeof(uint8_t) + // pads 1.125 + 2*sizeof(uint16_t) + // func masks 1.126 + 2*sizeof(uint16_t) + // ref values 1.127 + 2*sizeof(uint16_t) + // write masks 1.128 + sizeof(uint32_t)); // flags 1.129 + 1.130 +// This macro is used to compute the GrStencilSettingsStructs flags 1.131 +// associated to disabling. It is used both to define constant structure 1.132 +// initializers and inside GrStencilSettings::isDisabled() 1.133 +// 1.134 +#define GR_STENCIL_SETTINGS_IS_DISABLED( \ 1.135 + FRONT_PASS_OP, BACK_PASS_OP, \ 1.136 + FRONT_FAIL_OP, BACK_FAIL_OP, \ 1.137 + FRONT_FUNC, BACK_FUNC) \ 1.138 + ((FRONT_PASS_OP) == kKeep_StencilOp && \ 1.139 + (BACK_PASS_OP) == kKeep_StencilOp && \ 1.140 + (FRONT_FAIL_OP) == kKeep_StencilOp && \ 1.141 + (BACK_FAIL_OP) == kKeep_StencilOp && \ 1.142 + (FRONT_FUNC) == kAlways_StencilFunc && \ 1.143 + (BACK_FUNC) == kAlways_StencilFunc) 1.144 + 1.145 +#define GR_STENCIL_SETTINGS_DOES_WRITE( \ 1.146 + FRONT_PASS_OP, BACK_PASS_OP, \ 1.147 + FRONT_FAIL_OP, BACK_FAIL_OP, \ 1.148 + FRONT_FUNC, BACK_FUNC) \ 1.149 + (!(((FRONT_FUNC) == kNever_StencilFunc || \ 1.150 + (FRONT_PASS_OP) == kKeep_StencilOp) && \ 1.151 + ((BACK_FUNC) == kNever_StencilFunc || \ 1.152 + (BACK_PASS_OP) == kKeep_StencilOp) && \ 1.153 + ((FRONT_FUNC) == kAlways_StencilFunc || \ 1.154 + (FRONT_FAIL_OP) == kKeep_StencilOp) && \ 1.155 + ((BACK_FUNC) == kAlways_StencilFunc || \ 1.156 + (BACK_FAIL_OP) == kKeep_StencilOp))) 1.157 + 1.158 +#define GR_STENCIL_SETTINGS_DEFAULT_FLAGS( \ 1.159 + FRONT_PASS_OP, BACK_PASS_OP, \ 1.160 + FRONT_FAIL_OP, BACK_FAIL_OP, \ 1.161 + FRONT_FUNC, BACK_FUNC) \ 1.162 + ((GR_STENCIL_SETTINGS_IS_DISABLED(FRONT_PASS_OP,BACK_PASS_OP, \ 1.163 + FRONT_FAIL_OP,BACK_FAIL_OP,FRONT_FUNC,BACK_FUNC) ? \ 1.164 + kIsDisabled_StencilFlag : kNotDisabled_StencilFlag) | \ 1.165 + (GR_STENCIL_SETTINGS_DOES_WRITE(FRONT_PASS_OP,BACK_PASS_OP, \ 1.166 + FRONT_FAIL_OP,BACK_FAIL_OP,FRONT_FUNC,BACK_FUNC) ? \ 1.167 + kDoesWrite_StencilFlag : kDoesNotWrite_StencilFlag)) 1.168 + 1.169 +/** 1.170 + * Class representing stencil state. 1.171 + */ 1.172 +class GrStencilSettings : private GrStencilSettingsStruct { 1.173 + 1.174 +public: 1.175 + enum Face { 1.176 + kFront_Face = 0, 1.177 + kBack_Face = 1, 1.178 + }; 1.179 + 1.180 + GrStencilSettings() { 1.181 + fPad0 = fPad1 = 0; 1.182 + this->setDisabled(); 1.183 + } 1.184 + 1.185 + GrStencilOp passOp(Face f) const { return static_cast<GrStencilOp>(fPassOps[f]); } 1.186 + GrStencilOp failOp(Face f) const { return static_cast<GrStencilOp>(fFailOps[f]); } 1.187 + GrStencilFunc func(Face f) const { return static_cast<GrStencilFunc>(fFuncs[f]); } 1.188 + uint16_t funcMask(Face f) const { return fFuncMasks[f]; } 1.189 + uint16_t funcRef(Face f) const { return fFuncRefs[f]; } 1.190 + uint16_t writeMask(Face f) const { return fWriteMasks[f]; } 1.191 + 1.192 + void setPassOp(Face f, GrStencilOp op) { fPassOps[f] = op; fFlags = 0;} 1.193 + void setFailOp(Face f, GrStencilOp op) { fFailOps[f] = op; fFlags = 0;} 1.194 + void setFunc(Face f, GrStencilFunc func) { fFuncs[f] = func; fFlags = 0;} 1.195 + void setFuncMask(Face f, unsigned short mask) { fFuncMasks[f] = mask; } 1.196 + void setFuncRef(Face f, unsigned short ref) { fFuncRefs[f] = ref; } 1.197 + void setWriteMask(Face f, unsigned short writeMask) { fWriteMasks[f] = writeMask; } 1.198 + 1.199 + void copyFrontSettingsToBack() { 1.200 + fPassOps[kBack_Face] = fPassOps[kFront_Face]; 1.201 + fFailOps[kBack_Face] = fFailOps[kFront_Face]; 1.202 + fFuncs[kBack_Face] = fFuncs[kFront_Face]; 1.203 + fFuncMasks[kBack_Face] = fFuncMasks[kFront_Face]; 1.204 + fFuncRefs[kBack_Face] = fFuncRefs[kFront_Face]; 1.205 + fWriteMasks[kBack_Face] = fWriteMasks[kFront_Face]; 1.206 + fFlags = 0; 1.207 + } 1.208 + 1.209 + void setSame(GrStencilOp passOp, 1.210 + GrStencilOp failOp, 1.211 + GrStencilFunc func, 1.212 + unsigned short funcMask, 1.213 + unsigned short funcRef, 1.214 + unsigned short writeMask) { 1.215 + fPassOps[kFront_Face] = fPassOps[kBack_Face] = passOp; 1.216 + fFailOps[kFront_Face] = fFailOps[kBack_Face] = failOp; 1.217 + fFuncs[kFront_Face] = fFuncs[kBack_Face] = func; 1.218 + fFuncMasks[kFront_Face] = fFuncMasks[kBack_Face] = funcMask; 1.219 + fFuncRefs[kFront_Face] = fFuncRefs[kBack_Face] = funcRef; 1.220 + fWriteMasks[kFront_Face] = fWriteMasks[kBack_Face] = writeMask; 1.221 + fFlags = 0; 1.222 + } 1.223 + 1.224 + void setDisabled() { 1.225 + memset(this, 0, sizeof(*this)); 1.226 + GR_STATIC_ASSERT(0 == kKeep_StencilOp); 1.227 + GR_STATIC_ASSERT(0 == kAlways_StencilFunc); 1.228 + fFlags = kIsDisabled_StencilFlag | kDoesNotWrite_StencilFlag; 1.229 + } 1.230 + 1.231 + bool isTwoSided() const { 1.232 + return fPassOps[kFront_Face] != fPassOps[kBack_Face] || 1.233 + fFailOps[kFront_Face] != fFailOps[kBack_Face] || 1.234 + fFuncs[kFront_Face] != fFuncs[kBack_Face] || 1.235 + fFuncMasks[kFront_Face] != fFuncMasks[kBack_Face] || 1.236 + fFuncRefs[kFront_Face] != fFuncRefs[kBack_Face] || 1.237 + fWriteMasks[kFront_Face] != fWriteMasks[kBack_Face]; 1.238 + } 1.239 + 1.240 + bool usesWrapOp() const { 1.241 + return kIncWrap_StencilOp == fPassOps[kFront_Face] || 1.242 + kDecWrap_StencilOp == fPassOps[kFront_Face] || 1.243 + kIncWrap_StencilOp == fPassOps[kBack_Face] || 1.244 + kDecWrap_StencilOp == fPassOps[kBack_Face] || 1.245 + kIncWrap_StencilOp == fFailOps[kFront_Face] || 1.246 + kDecWrap_StencilOp == fFailOps[kFront_Face] || 1.247 + kIncWrap_StencilOp == fFailOps[kBack_Face] || 1.248 + kDecWrap_StencilOp == fFailOps[kBack_Face]; 1.249 + } 1.250 + 1.251 + bool isDisabled() const { 1.252 + if (fFlags & kIsDisabled_StencilFlag) { 1.253 + return true; 1.254 + } 1.255 + if (fFlags & kNotDisabled_StencilFlag) { 1.256 + return false; 1.257 + } 1.258 + bool disabled = GR_STENCIL_SETTINGS_IS_DISABLED( 1.259 + fPassOps[kFront_Face], fPassOps[kBack_Face], 1.260 + fFailOps[kFront_Face], fFailOps[kBack_Face], 1.261 + fFuncs[kFront_Face], fFuncs[kBack_Face]); 1.262 + fFlags |= disabled ? kIsDisabled_StencilFlag : kNotDisabled_StencilFlag; 1.263 + return disabled; 1.264 + } 1.265 + 1.266 + bool doesWrite() const { 1.267 + if (fFlags & kDoesWrite_StencilFlag) { 1.268 + return true; 1.269 + } 1.270 + if (fFlags & kDoesNotWrite_StencilFlag) { 1.271 + return false; 1.272 + } 1.273 + bool writes = GR_STENCIL_SETTINGS_DOES_WRITE( 1.274 + fPassOps[kFront_Face], fPassOps[kBack_Face], 1.275 + fFailOps[kFront_Face], fFailOps[kBack_Face], 1.276 + fFuncs[kFront_Face], fFuncs[kBack_Face]); 1.277 + fFlags |= writes ? kDoesWrite_StencilFlag : kDoesNotWrite_StencilFlag; 1.278 + return writes; 1.279 + } 1.280 + 1.281 + void invalidate() { 1.282 + // write an illegal value to the first member 1.283 + fPassOps[0] = (GrStencilOp)(uint8_t)-1; 1.284 + fFlags = 0; 1.285 + } 1.286 + 1.287 + bool operator == (const GrStencilSettings& s) const { 1.288 + static const size_t gCompareSize = sizeof(GrStencilSettings) - 1.289 + sizeof(fFlags); 1.290 + SkASSERT((const char*)&fFlags + sizeof(fFlags) == 1.291 + (const char*)this + sizeof(GrStencilSettings)); 1.292 + if (this->isDisabled() & s.isDisabled()) { // using & not && 1.293 + return true; 1.294 + } 1.295 + return 0 == memcmp(this, &s, gCompareSize); 1.296 + } 1.297 + 1.298 + bool operator != (const GrStencilSettings& s) const { 1.299 + return !(*this == s); 1.300 + } 1.301 + 1.302 + GrStencilSettings& operator =(const GrStencilSettings& s) { 1.303 + memcpy(this, &s, sizeof(GrStencilSettings)); 1.304 + return *this; 1.305 + } 1.306 + 1.307 +private: 1.308 + friend class GrClipMaskManager; 1.309 + 1.310 + enum { 1.311 + kMaxStencilClipPasses = 2 // maximum number of passes to add a clip 1.312 + // element to the stencil buffer. 1.313 + }; 1.314 + 1.315 + /** 1.316 + * Given a thing to draw into the stencil clip, a fill type, and a set op 1.317 + * this function determines: 1.318 + * 1. Whether the thing can be draw directly to the stencil clip or 1.319 + * needs to be drawn to the client portion of the stencil first. 1.320 + * 2. How many passes are needed. 1.321 + * 3. What those passes are. 1.322 + * 4. The fill rule that should actually be used to render (will 1.323 + * always be non-inverted). 1.324 + * 1.325 + * @param op the set op to combine this element with the 1.326 + * existing clip 1.327 + * @param stencilClipMask mask with just the stencil bit used for clipping 1.328 + * enabled. 1.329 + * @param invertedFill is this path inverted 1.330 + * @param numPasses out: the number of passes needed to add the 1.331 + * element to the clip. 1.332 + * @param settings out: the stencil settings to use for each pass 1.333 + * 1.334 + * @return true if the clip element's geometry can be drawn directly to the 1.335 + * stencil clip bit. Will only be true if canBeDirect is true. 1.336 + * numPasses will be 1 if return value is true. 1.337 + */ 1.338 + static bool GetClipPasses(SkRegion::Op op, 1.339 + bool canBeDirect, 1.340 + unsigned int stencilClipMask, 1.341 + bool invertedFill, 1.342 + int* numPasses, 1.343 + GrStencilSettings settings[kMaxStencilClipPasses]); 1.344 +}; 1.345 + 1.346 +GR_STATIC_ASSERT(sizeof(GrStencilSettingsStruct) == sizeof(GrStencilSettings)); 1.347 + 1.348 +#define GR_STATIC_CONST_STENCIL_STRUCT(STRUCT_NAME, \ 1.349 + FRONT_PASS_OP, BACK_PASS_OP, \ 1.350 + FRONT_FAIL_OP, BACK_FAIL_OP, \ 1.351 + FRONT_FUNC, BACK_FUNC, \ 1.352 + FRONT_MASK, BACK_MASK, \ 1.353 + FRONT_REF, BACK_REF, \ 1.354 + FRONT_WRITE_MASK, BACK_WRITE_MASK) \ 1.355 + static const GrStencilSettingsStruct STRUCT_NAME = { \ 1.356 + {(FRONT_PASS_OP), (BACK_PASS_OP) }, \ 1.357 + {(FRONT_FAIL_OP), (BACK_FAIL_OP) }, \ 1.358 + {(FRONT_FUNC), (BACK_FUNC) }, \ 1.359 + (0), (0), \ 1.360 + {(FRONT_MASK), (BACK_MASK) }, \ 1.361 + {(FRONT_REF), (BACK_REF) }, \ 1.362 + {(FRONT_WRITE_MASK), (BACK_WRITE_MASK)}, \ 1.363 + GR_STENCIL_SETTINGS_DEFAULT_FLAGS( \ 1.364 + FRONT_PASS_OP, BACK_PASS_OP, FRONT_FAIL_OP, BACK_FAIL_OP, \ 1.365 + FRONT_FUNC, BACK_FUNC) \ 1.366 + }; 1.367 + 1.368 +#define GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(STRUCT_PTR) \ 1.369 + reinterpret_cast<const GrStencilSettings*>(STRUCT_PTR) 1.370 + 1.371 +#define GR_STATIC_CONST_SAME_STENCIL_STRUCT(STRUCT_NAME, \ 1.372 + PASS_OP, FAIL_OP, FUNC, MASK, REF, WRITE_MASK) \ 1.373 + GR_STATIC_CONST_STENCIL_STRUCT(STRUCT_NAME, (PASS_OP), (PASS_OP), \ 1.374 + (FAIL_OP),(FAIL_OP), (FUNC), (FUNC), (MASK), (MASK), (REF), (REF), \ 1.375 + (WRITE_MASK),(WRITE_MASK)) 1.376 + 1.377 +#define GR_STATIC_CONST_STENCIL(NAME, \ 1.378 + FRONT_PASS_OP, BACK_PASS_OP, \ 1.379 + FRONT_FAIL_OP, BACK_FAIL_OP, \ 1.380 + FRONT_FUNC, BACK_FUNC, \ 1.381 + FRONT_MASK, BACK_MASK, \ 1.382 + FRONT_REF, BACK_REF, \ 1.383 + FRONT_WRITE_MASK, BACK_WRITE_MASK) \ 1.384 + GR_STATIC_CONST_STENCIL_STRUCT(NAME ## _STRUCT, \ 1.385 + (FRONT_PASS_OP),(BACK_PASS_OP),(FRONT_FAIL_OP),(BACK_FAIL_OP), \ 1.386 + (FRONT_FUNC),(BACK_FUNC),(FRONT_MASK),(BACK_MASK), \ 1.387 + (FRONT_REF),(BACK_REF),(FRONT_WRITE_MASK),(BACK_WRITE_MASK)) \ 1.388 + static const GrStencilSettings& NAME = \ 1.389 + *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&(NAME ## _STRUCT)); 1.390 + 1.391 + 1.392 +#define GR_STATIC_CONST_SAME_STENCIL(NAME, \ 1.393 + PASS_OP, FAIL_OP, FUNC, MASK, REF, WRITE_MASK) \ 1.394 + GR_STATIC_CONST_STENCIL(NAME, (PASS_OP), (PASS_OP), (FAIL_OP), \ 1.395 + (FAIL_OP), (FUNC), (FUNC), (MASK), (MASK), (REF), (REF), (WRITE_MASK), \ 1.396 + (WRITE_MASK)) 1.397 + 1.398 +#endif