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] = kStencilOpCount; 281 fFlags = 0; 282 } 283 isValid()284 bool isValid() const { 285 return fPassOps[0] < kStencilOpCount; 286 } 287 288 bool operator == (const GrStencilSettings& s) const { 289 static const size_t gCompareSize = sizeof(GrStencilSettings) - 290 sizeof(fFlags); 291 SkASSERT((const char*)&fFlags + sizeof(fFlags) == 292 (const char*)this + sizeof(GrStencilSettings)); 293 if (this->isDisabled() & s.isDisabled()) { // using & not && 294 return true; 295 } 296 return 0 == memcmp(this, &s, gCompareSize); 297 } 298 299 bool operator != (const GrStencilSettings& s) const { 300 return !(*this == s); 301 } 302 303 GrStencilSettings& operator =(const GrStencilSettings& s) { 304 memcpy(this, &s, sizeof(GrStencilSettings)); 305 return *this; 306 } 307 308 private: 309 friend class GrClipMaskManager; 310 311 enum { 312 kMaxStencilClipPasses = 2 // maximum number of passes to add a clip 313 // element to the stencil buffer. 314 }; 315 316 /** 317 * Given a thing to draw into the stencil clip, a fill type, and a set op 318 * this function determines: 319 * 1. Whether the thing can be draw directly to the stencil clip or 320 * needs to be drawn to the client portion of the stencil first. 321 * 2. How many passes are needed. 322 * 3. What those passes are. 323 * 4. The fill rule that should actually be used to render (will 324 * always be non-inverted). 325 * 326 * @param op the set op to combine this element with the 327 * existing clip 328 * @param stencilClipMask mask with just the stencil bit used for clipping 329 * enabled. 330 * @param invertedFill is this path inverted 331 * @param numPasses out: the number of passes needed to add the 332 * element to the clip. 333 * @param settings out: the stencil settings to use for each pass 334 * 335 * @return true if the clip element's geometry can be drawn directly to the 336 * stencil clip bit. Will only be true if canBeDirect is true. 337 * numPasses will be 1 if return value is true. 338 */ 339 static bool GetClipPasses(SkRegion::Op op, 340 bool canBeDirect, 341 unsigned int stencilClipMask, 342 bool invertedFill, 343 int* numPasses, 344 GrStencilSettings settings[kMaxStencilClipPasses]); 345 }; 346 347 GR_STATIC_ASSERT(sizeof(GrStencilSettingsStruct) == sizeof(GrStencilSettings)); 348 349 #define GR_STATIC_CONST_STENCIL_STRUCT(STRUCT_NAME, \ 350 FRONT_PASS_OP, BACK_PASS_OP, \ 351 FRONT_FAIL_OP, BACK_FAIL_OP, \ 352 FRONT_FUNC, BACK_FUNC, \ 353 FRONT_MASK, BACK_MASK, \ 354 FRONT_REF, BACK_REF, \ 355 FRONT_WRITE_MASK, BACK_WRITE_MASK) \ 356 static const GrStencilSettingsStruct STRUCT_NAME = { \ 357 {(FRONT_PASS_OP), (BACK_PASS_OP) }, \ 358 {(FRONT_FAIL_OP), (BACK_FAIL_OP) }, \ 359 {(FRONT_FUNC), (BACK_FUNC) }, \ 360 (0), (0), \ 361 {(FRONT_MASK), (BACK_MASK) }, \ 362 {(FRONT_REF), (BACK_REF) }, \ 363 {(FRONT_WRITE_MASK), (BACK_WRITE_MASK)}, \ 364 GR_STENCIL_SETTINGS_DEFAULT_FLAGS( \ 365 FRONT_PASS_OP, BACK_PASS_OP, FRONT_FAIL_OP, BACK_FAIL_OP, \ 366 FRONT_FUNC, BACK_FUNC) \ 367 }; 368 369 #define GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(STRUCT_PTR) \ 370 reinterpret_cast<const GrStencilSettings*>(STRUCT_PTR) 371 372 #define GR_STATIC_CONST_SAME_STENCIL_STRUCT(STRUCT_NAME, \ 373 PASS_OP, FAIL_OP, FUNC, MASK, REF, WRITE_MASK) \ 374 GR_STATIC_CONST_STENCIL_STRUCT(STRUCT_NAME, (PASS_OP), (PASS_OP), \ 375 (FAIL_OP),(FAIL_OP), (FUNC), (FUNC), (MASK), (MASK), (REF), (REF), \ 376 (WRITE_MASK),(WRITE_MASK)) 377 378 #define GR_STATIC_CONST_STENCIL(NAME, \ 379 FRONT_PASS_OP, BACK_PASS_OP, \ 380 FRONT_FAIL_OP, BACK_FAIL_OP, \ 381 FRONT_FUNC, BACK_FUNC, \ 382 FRONT_MASK, BACK_MASK, \ 383 FRONT_REF, BACK_REF, \ 384 FRONT_WRITE_MASK, BACK_WRITE_MASK) \ 385 GR_STATIC_CONST_STENCIL_STRUCT(NAME ## _STRUCT, \ 386 (FRONT_PASS_OP),(BACK_PASS_OP),(FRONT_FAIL_OP),(BACK_FAIL_OP), \ 387 (FRONT_FUNC),(BACK_FUNC),(FRONT_MASK),(BACK_MASK), \ 388 (FRONT_REF),(BACK_REF),(FRONT_WRITE_MASK),(BACK_WRITE_MASK)) \ 389 static const GrStencilSettings& NAME = \ 390 *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&(NAME ## _STRUCT)); 391 392 393 #define GR_STATIC_CONST_SAME_STENCIL(NAME, \ 394 PASS_OP, FAIL_OP, FUNC, MASK, REF, WRITE_MASK) \ 395 GR_STATIC_CONST_STENCIL(NAME, (PASS_OP), (PASS_OP), (FAIL_OP), \ 396 (FAIL_OP), (FUNC), (FUNC), (MASK), (MASK), (REF), (REF), (WRITE_MASK), \ 397 (WRITE_MASK)) 398 399 #endif 400