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 177 GrStencilSettings() { 178 fPad0 = fPad1 = 0; 179 this->setDisabled(); 180 } 181 182 GrStencilOp passOp(Face f) const { return static_cast<GrStencilOp>(fPassOps[f]); } 183 GrStencilOp failOp(Face f) const { return static_cast<GrStencilOp>(fFailOps[f]); } 184 GrStencilFunc func(Face f) const { return static_cast<GrStencilFunc>(fFuncs[f]); } 185 uint16_t funcMask(Face f) const { return fFuncMasks[f]; } 186 uint16_t funcRef(Face f) const { return fFuncRefs[f]; } 187 uint16_t writeMask(Face f) const { return fWriteMasks[f]; } 188 189 void setPassOp(Face f, GrStencilOp op) { fPassOps[f] = op; fFlags = 0;} 190 void setFailOp(Face f, GrStencilOp op) { fFailOps[f] = op; fFlags = 0;} 191 void setFunc(Face f, GrStencilFunc func) { fFuncs[f] = func; fFlags = 0;} 192 void setFuncMask(Face f, unsigned short mask) { fFuncMasks[f] = mask; } 193 void setFuncRef(Face f, unsigned short ref) { fFuncRefs[f] = ref; } 194 void setWriteMask(Face f, unsigned short writeMask) { fWriteMasks[f] = writeMask; } 195 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 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 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 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 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 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 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 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