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 #ifndef GrStencil_DEFINED 11 #define GrStencil_DEFINED 12 13 #include "GrTypes.h" 14 #include "SkRegion.h" 15 16 /** 17 * Gr uses the stencil buffer to implement complex clipping inside the 18 * GrDrawTarget class. The GrDrawTarget makes a subset of the stencil buffer 19 * bits available for other uses by external code (clients). Client code can 20 * modify these bits. GrDrawTarget will ignore ref, mask, and writemask bits 21 * provided by clients that overlap the bits used to implement clipping. 22 * 23 * When code outside the GrDrawTarget class uses the stencil buffer the contract 24 * is as follows: 25 * 26 * > Normal stencil funcs allow the client to pass / fail regardless of the 27 * reserved clip bits. 28 * > Additional functions allow a test against the clip along with a limited 29 * set of tests against the client bits. 30 * > Client can assume all client bits are zero initially. 31 * > Client must ensure that after all its passes are finished it has only 32 * written to the color buffer in the region inside the clip. Furthermore, it 33 * must zero all client bits that were modifed (both inside and outside the 34 * clip). 35 */ 36 37 /** 38 * Determines which pixels pass / fail the stencil test. 39 * Stencil test passes if (ref & mask) FUNC (stencil & mask) is true 40 */ 41 enum GrStencilFunc { 42 kAlways_StencilFunc = 0, 43 kNever_StencilFunc, 44 kGreater_StencilFunc, 45 kGEqual_StencilFunc, 46 kLess_StencilFunc, 47 kLEqual_StencilFunc, 48 kEqual_StencilFunc, 49 kNotEqual_StencilFunc, 50 51 // Gr stores the current clip in the 52 // stencil buffer in the high bits that 53 // are not directly accessible modifiable 54 // via the GrDrawTarget interface. The below 55 // stencil funcs test against the current 56 // clip in addition to the GrDrawTarget 57 // client's stencil bits. 58 59 // pass if inside the clip 60 kAlwaysIfInClip_StencilFunc, 61 kEqualIfInClip_StencilFunc, 62 kLessIfInClip_StencilFunc, 63 kLEqualIfInClip_StencilFunc, 64 kNonZeroIfInClip_StencilFunc, // this one forces the ref to be 0 65 66 // counts 67 kStencilFuncCount, 68 kClipStencilFuncCount = kNonZeroIfInClip_StencilFunc - 69 kAlwaysIfInClip_StencilFunc + 1, 70 kBasicStencilFuncCount = kStencilFuncCount - kClipStencilFuncCount 71 }; 72 73 /** 74 * Operations to perform based on whether stencil test passed failed. 75 */ 76 enum GrStencilOp { 77 kKeep_StencilOp = 0, // preserve existing stencil value 78 kReplace_StencilOp, // replace with reference value from stencl test 79 kIncWrap_StencilOp, // increment and wrap at max 80 kIncClamp_StencilOp, // increment and clamp at max 81 kDecWrap_StencilOp, // decrement and wrap at 0 82 kDecClamp_StencilOp, // decrement and clamp at 0 83 kZero_StencilOp, // zero stencil bits 84 kInvert_StencilOp, // invert stencil bits 85 86 kStencilOpCount 87 }; 88 89 enum GrStencilFlags { 90 kIsDisabled_StencilFlag = 0x1, 91 kNotDisabled_StencilFlag = 0x2, 92 kDoesWrite_StencilFlag = 0x4, 93 kDoesNotWrite_StencilFlag = 0x8, 94 }; 95 96 /** 97 * GrStencilState needs to be a class with accessors and setters so that it 98 * can maintain flags related to its current state. However, we also want to 99 * be able to declare pre-made stencil settings at compile time (without 100 * inserting static initializer code). So all the data members are in this 101 * struct. A macro defined after the class can be used to jam an instance of 102 * this struct that is created from an initializer list into a 103 * GrStencilSettings. (We hang our heads in shame.) 104 */ 105 struct GrStencilSettingsStruct { 106 uint8_t fPassOps[2]; // op to perform when faces pass (GrStencilOp) 107 uint8_t fFailOps[2]; // op to perform when faces fail (GrStencilOp) 108 uint8_t fFuncs[2]; // test function for faces (GrStencilFunc) 109 uint8_t fPad0; 110 uint8_t fPad1; 111 uint16_t fFuncMasks[2]; // mask for face tests 112 uint16_t fFuncRefs[2]; // reference values for face tests 113 uint16_t fWriteMasks[2]; // stencil write masks 114 mutable uint32_t fFlags; 115 }; 116 // We rely on this being packed and aligned (memcmp'ed and memcpy'ed) 117 GR_STATIC_ASSERT(sizeof(GrStencilSettingsStruct) % 4 == 0); 118 GR_STATIC_ASSERT(sizeof(GrStencilSettingsStruct) == 119 4*sizeof(uint8_t) + // ops 120 2*sizeof(uint8_t) + // funcs 121 2*sizeof(uint8_t) + // pads 122 2*sizeof(uint16_t) + // func masks 123 2*sizeof(uint16_t) + // ref values 124 2*sizeof(uint16_t) + // write masks 125 sizeof(uint32_t)); // flags 126 127 // This macro is used to compute the GrStencilSettingsStructs flags 128 // associated to disabling. It is used both to define constant structure 129 // initializers and inside GrStencilSettings::isDisabled() 130 // 131 #define GR_STENCIL_SETTINGS_IS_DISABLED( \ 132 FRONT_PASS_OP, BACK_PASS_OP, \ 133 FRONT_FAIL_OP, BACK_FAIL_OP, \ 134 FRONT_FUNC, BACK_FUNC) \ 135 ((FRONT_PASS_OP) == kKeep_StencilOp && \ 136 (BACK_PASS_OP) == kKeep_StencilOp && \ 137 (FRONT_FAIL_OP) == kKeep_StencilOp && \ 138 (BACK_FAIL_OP) == kKeep_StencilOp && \ 139 (FRONT_FUNC) == kAlways_StencilFunc && \ 140 (BACK_FUNC) == kAlways_StencilFunc) 141 142 #define GR_STENCIL_SETTINGS_DOES_WRITE( \ 143 FRONT_PASS_OP, BACK_PASS_OP, \ 144 FRONT_FAIL_OP, BACK_FAIL_OP, \ 145 FRONT_FUNC, BACK_FUNC) \ 146 (!(((FRONT_FUNC) == kNever_StencilFunc || \ 147 (FRONT_PASS_OP) == kKeep_StencilOp) && \ 148 ((BACK_FUNC) == kNever_StencilFunc || \ 149 (BACK_PASS_OP) == kKeep_StencilOp) && \ 150 ((FRONT_FUNC) == kAlways_StencilFunc || \ 151 (FRONT_FAIL_OP) == kKeep_StencilOp) && \ 152 ((BACK_FUNC) == kAlways_StencilFunc || \ 153 (BACK_FAIL_OP) == kKeep_StencilOp))) 154 155 #define GR_STENCIL_SETTINGS_DEFAULT_FLAGS( \ 156 FRONT_PASS_OP, BACK_PASS_OP, \ 157 FRONT_FAIL_OP, BACK_FAIL_OP, \ 158 FRONT_FUNC, BACK_FUNC) \ 159 ((GR_STENCIL_SETTINGS_IS_DISABLED(FRONT_PASS_OP,BACK_PASS_OP, \ 160 FRONT_FAIL_OP,BACK_FAIL_OP,FRONT_FUNC,BACK_FUNC) ? \ 161 kIsDisabled_StencilFlag : kNotDisabled_StencilFlag) | \ 162 (GR_STENCIL_SETTINGS_DOES_WRITE(FRONT_PASS_OP,BACK_PASS_OP, \ 163 FRONT_FAIL_OP,BACK_FAIL_OP,FRONT_FUNC,BACK_FUNC) ? \ 164 kDoesWrite_StencilFlag : kDoesNotWrite_StencilFlag)) 165 166 /** 167 * Class representing stencil state. 168 */ 169 class GrStencilSettings : private GrStencilSettingsStruct { 170 171 public: 172 enum Face { 173 kFront_Face = 0, 174 kBack_Face = 1, 175 }; 176 GrStencilSettings()177 GrStencilSettings() { 178 fPad0 = fPad1 = 0; 179 this->setDisabled(); 180 } 181 passOp(Face f)182 GrStencilOp passOp(Face f) const { return static_cast<GrStencilOp>(fPassOps[f]); } failOp(Face f)183 GrStencilOp failOp(Face f) const { return static_cast<GrStencilOp>(fFailOps[f]); } func(Face f)184 GrStencilFunc func(Face f) const { return static_cast<GrStencilFunc>(fFuncs[f]); } funcMask(Face f)185 uint16_t funcMask(Face f) const { return fFuncMasks[f]; } funcRef(Face f)186 uint16_t funcRef(Face f) const { return fFuncRefs[f]; } writeMask(Face f)187 uint16_t writeMask(Face f) const { return fWriteMasks[f]; } 188 setPassOp(Face f,GrStencilOp op)189 void setPassOp(Face f, GrStencilOp op) { fPassOps[f] = op; fFlags = 0;} setFailOp(Face f,GrStencilOp op)190 void setFailOp(Face f, GrStencilOp op) { fFailOps[f] = op; fFlags = 0;} setFunc(Face f,GrStencilFunc func)191 void setFunc(Face f, GrStencilFunc func) { fFuncs[f] = func; fFlags = 0;} setFuncMask(Face f,unsigned short mask)192 void setFuncMask(Face f, unsigned short mask) { fFuncMasks[f] = mask; } setFuncRef(Face f,unsigned short ref)193 void setFuncRef(Face f, unsigned short ref) { fFuncRefs[f] = ref; } setWriteMask(Face f,unsigned short writeMask)194 void setWriteMask(Face f, unsigned short writeMask) { fWriteMasks[f] = writeMask; } 195 copyFrontSettingsToBack()196 void copyFrontSettingsToBack() { 197 fPassOps[kBack_Face] = fPassOps[kFront_Face]; 198 fFailOps[kBack_Face] = fFailOps[kFront_Face]; 199 fFuncs[kBack_Face] = fFuncs[kFront_Face]; 200 fFuncMasks[kBack_Face] = fFuncMasks[kFront_Face]; 201 fFuncRefs[kBack_Face] = fFuncRefs[kFront_Face]; 202 fWriteMasks[kBack_Face] = fWriteMasks[kFront_Face]; 203 fFlags = 0; 204 } 205 setSame(GrStencilOp passOp,GrStencilOp failOp,GrStencilFunc func,unsigned short funcMask,unsigned short funcRef,unsigned short writeMask)206 void setSame(GrStencilOp passOp, 207 GrStencilOp failOp, 208 GrStencilFunc func, 209 unsigned short funcMask, 210 unsigned short funcRef, 211 unsigned short writeMask) { 212 fPassOps[kFront_Face] = fPassOps[kBack_Face] = passOp; 213 fFailOps[kFront_Face] = fFailOps[kBack_Face] = failOp; 214 fFuncs[kFront_Face] = fFuncs[kBack_Face] = func; 215 fFuncMasks[kFront_Face] = fFuncMasks[kBack_Face] = funcMask; 216 fFuncRefs[kFront_Face] = fFuncRefs[kBack_Face] = funcRef; 217 fWriteMasks[kFront_Face] = fWriteMasks[kBack_Face] = writeMask; 218 fFlags = 0; 219 } 220 setDisabled()221 void setDisabled() { 222 memset(this, 0, sizeof(*this)); 223 GR_STATIC_ASSERT(0 == kKeep_StencilOp); 224 GR_STATIC_ASSERT(0 == kAlways_StencilFunc); 225 fFlags = kIsDisabled_StencilFlag | kDoesNotWrite_StencilFlag; 226 } 227 isTwoSided()228 bool isTwoSided() const { 229 return fPassOps[kFront_Face] != fPassOps[kBack_Face] || 230 fFailOps[kFront_Face] != fFailOps[kBack_Face] || 231 fFuncs[kFront_Face] != fFuncs[kBack_Face] || 232 fFuncMasks[kFront_Face] != fFuncMasks[kBack_Face] || 233 fFuncRefs[kFront_Face] != fFuncRefs[kBack_Face] || 234 fWriteMasks[kFront_Face] != fWriteMasks[kBack_Face]; 235 } 236 usesWrapOp()237 bool usesWrapOp() const { 238 return kIncWrap_StencilOp == fPassOps[kFront_Face] || 239 kDecWrap_StencilOp == fPassOps[kFront_Face] || 240 kIncWrap_StencilOp == fPassOps[kBack_Face] || 241 kDecWrap_StencilOp == fPassOps[kBack_Face] || 242 kIncWrap_StencilOp == fFailOps[kFront_Face] || 243 kDecWrap_StencilOp == fFailOps[kFront_Face] || 244 kIncWrap_StencilOp == fFailOps[kBack_Face] || 245 kDecWrap_StencilOp == fFailOps[kBack_Face]; 246 } 247 isDisabled()248 bool isDisabled() const { 249 if (fFlags & kIsDisabled_StencilFlag) { 250 return true; 251 } 252 if (fFlags & kNotDisabled_StencilFlag) { 253 return false; 254 } 255 bool disabled = GR_STENCIL_SETTINGS_IS_DISABLED( 256 fPassOps[kFront_Face], fPassOps[kBack_Face], 257 fFailOps[kFront_Face], fFailOps[kBack_Face], 258 fFuncs[kFront_Face], fFuncs[kBack_Face]); 259 fFlags |= disabled ? kIsDisabled_StencilFlag : kNotDisabled_StencilFlag; 260 return disabled; 261 } 262 doesWrite()263 bool doesWrite() const { 264 if (fFlags & kDoesWrite_StencilFlag) { 265 return true; 266 } 267 if (fFlags & kDoesNotWrite_StencilFlag) { 268 return false; 269 } 270 bool writes = GR_STENCIL_SETTINGS_DOES_WRITE( 271 fPassOps[kFront_Face], fPassOps[kBack_Face], 272 fFailOps[kFront_Face], fFailOps[kBack_Face], 273 fFuncs[kFront_Face], fFuncs[kBack_Face]); 274 fFlags |= writes ? kDoesWrite_StencilFlag : kDoesNotWrite_StencilFlag; 275 return writes; 276 } 277 invalidate()278 void invalidate() { 279 // write an illegal value to the first member 280 fPassOps[0] = (GrStencilOp)(uint8_t)-1; 281 fFlags = 0; 282 } 283 284 bool operator == (const GrStencilSettings& s) const { 285 static const size_t gCompareSize = sizeof(GrStencilSettings) - 286 sizeof(fFlags); 287 SkASSERT((const char*)&fFlags + sizeof(fFlags) == 288 (const char*)this + sizeof(GrStencilSettings)); 289 if (this->isDisabled() & s.isDisabled()) { // using & not && 290 return true; 291 } 292 return 0 == memcmp(this, &s, gCompareSize); 293 } 294 295 bool operator != (const GrStencilSettings& s) const { 296 return !(*this == s); 297 } 298 299 GrStencilSettings& operator =(const GrStencilSettings& s) { 300 memcpy(this, &s, sizeof(GrStencilSettings)); 301 return *this; 302 } 303 304 private: 305 friend class GrClipMaskManager; 306 307 enum { 308 kMaxStencilClipPasses = 2 // maximum number of passes to add a clip 309 // element to the stencil buffer. 310 }; 311 312 /** 313 * Given a thing to draw into the stencil clip, a fill type, and a set op 314 * this function determines: 315 * 1. Whether the thing can be draw directly to the stencil clip or 316 * needs to be drawn to the client portion of the stencil first. 317 * 2. How many passes are needed. 318 * 3. What those passes are. 319 * 4. The fill rule that should actually be used to render (will 320 * always be non-inverted). 321 * 322 * @param op the set op to combine this element with the 323 * existing clip 324 * @param stencilClipMask mask with just the stencil bit used for clipping 325 * enabled. 326 * @param invertedFill is this path inverted 327 * @param numPasses out: the number of passes needed to add the 328 * element to the clip. 329 * @param settings out: the stencil settings to use for each pass 330 * 331 * @return true if the clip element's geometry can be drawn directly to the 332 * stencil clip bit. Will only be true if canBeDirect is true. 333 * numPasses will be 1 if return value is true. 334 */ 335 static bool GetClipPasses(SkRegion::Op op, 336 bool canBeDirect, 337 unsigned int stencilClipMask, 338 bool invertedFill, 339 int* numPasses, 340 GrStencilSettings settings[kMaxStencilClipPasses]); 341 }; 342 343 GR_STATIC_ASSERT(sizeof(GrStencilSettingsStruct) == sizeof(GrStencilSettings)); 344 345 #define GR_STATIC_CONST_STENCIL_STRUCT(STRUCT_NAME, \ 346 FRONT_PASS_OP, BACK_PASS_OP, \ 347 FRONT_FAIL_OP, BACK_FAIL_OP, \ 348 FRONT_FUNC, BACK_FUNC, \ 349 FRONT_MASK, BACK_MASK, \ 350 FRONT_REF, BACK_REF, \ 351 FRONT_WRITE_MASK, BACK_WRITE_MASK) \ 352 static const GrStencilSettingsStruct STRUCT_NAME = { \ 353 {(FRONT_PASS_OP), (BACK_PASS_OP) }, \ 354 {(FRONT_FAIL_OP), (BACK_FAIL_OP) }, \ 355 {(FRONT_FUNC), (BACK_FUNC) }, \ 356 (0), (0), \ 357 {(FRONT_MASK), (BACK_MASK) }, \ 358 {(FRONT_REF), (BACK_REF) }, \ 359 {(FRONT_WRITE_MASK), (BACK_WRITE_MASK)}, \ 360 GR_STENCIL_SETTINGS_DEFAULT_FLAGS( \ 361 FRONT_PASS_OP, BACK_PASS_OP, FRONT_FAIL_OP, BACK_FAIL_OP, \ 362 FRONT_FUNC, BACK_FUNC) \ 363 }; 364 365 #define GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(STRUCT_PTR) \ 366 reinterpret_cast<const GrStencilSettings*>(STRUCT_PTR) 367 368 #define GR_STATIC_CONST_SAME_STENCIL_STRUCT(STRUCT_NAME, \ 369 PASS_OP, FAIL_OP, FUNC, MASK, REF, WRITE_MASK) \ 370 GR_STATIC_CONST_STENCIL_STRUCT(STRUCT_NAME, (PASS_OP), (PASS_OP), \ 371 (FAIL_OP),(FAIL_OP), (FUNC), (FUNC), (MASK), (MASK), (REF), (REF), \ 372 (WRITE_MASK),(WRITE_MASK)) 373 374 #define GR_STATIC_CONST_STENCIL(NAME, \ 375 FRONT_PASS_OP, BACK_PASS_OP, \ 376 FRONT_FAIL_OP, BACK_FAIL_OP, \ 377 FRONT_FUNC, BACK_FUNC, \ 378 FRONT_MASK, BACK_MASK, \ 379 FRONT_REF, BACK_REF, \ 380 FRONT_WRITE_MASK, BACK_WRITE_MASK) \ 381 GR_STATIC_CONST_STENCIL_STRUCT(NAME ## _STRUCT, \ 382 (FRONT_PASS_OP),(BACK_PASS_OP),(FRONT_FAIL_OP),(BACK_FAIL_OP), \ 383 (FRONT_FUNC),(BACK_FUNC),(FRONT_MASK),(BACK_MASK), \ 384 (FRONT_REF),(BACK_REF),(FRONT_WRITE_MASK),(BACK_WRITE_MASK)) \ 385 static const GrStencilSettings& NAME = \ 386 *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&(NAME ## _STRUCT)); 387 388 389 #define GR_STATIC_CONST_SAME_STENCIL(NAME, \ 390 PASS_OP, FAIL_OP, FUNC, MASK, REF, WRITE_MASK) \ 391 GR_STATIC_CONST_STENCIL(NAME, (PASS_OP), (PASS_OP), (FAIL_OP), \ 392 (FAIL_OP), (FUNC), (FUNC), (MASK), (MASK), (REF), (REF), (WRITE_MASK), \ 393 (WRITE_MASK)) 394 395 #endif 396