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