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: 176 GrStencilSettings() { 177 fPad0 = fPad1 = 0; 178 this->setDisabled(); 179 } 180 181 GrStencilOp frontPassOp() const { return fFrontPassOp; } 182 GrStencilOp backPassOp() const { return fBackPassOp; } 183 GrStencilOp frontFailOp() const { return fFrontFailOp; } 184 GrStencilOp backFailOp() const { return fBackFailOp; } 185 GrStencilFunc frontFunc() const { return fFrontFunc; } 186 GrStencilFunc backFunc() const { return fBackFunc; } 187 unsigned short frontFuncMask() const { return fFrontFuncMask; } 188 unsigned short backFuncMask() const { return fBackFuncMask; } 189 unsigned short frontFuncRef() const { return fFrontFuncRef; } 190 unsigned short backFuncRef() const { return fBackFuncRef; } 191 unsigned short frontWriteMask() const {return fFrontWriteMask; } 192 unsigned short backWriteMask() const { return fBackWriteMask; } 193 194 void setFrontPassOp(GrStencilOp op) { fFrontPassOp = op; fFlags = 0;} 195 void setBackPassOp(GrStencilOp op) { fBackPassOp = op; fFlags = 0;} 196 void setFrontFailOp(GrStencilOp op) {fFrontFailOp = op; fFlags = 0;} 197 void setBackFailOp(GrStencilOp op) { fBackFailOp = op; fFlags = 0;} 198 void setFrontFunc(GrStencilFunc func) { fFrontFunc = func; fFlags = 0;} 199 void setBackFunc(GrStencilFunc func) { fBackFunc = func; fFlags = 0;} 200 void setFrontFuncMask(unsigned short mask) { fFrontFuncMask = mask; } 201 void setBackFuncMask(unsigned short mask) { fBackFuncMask = mask; } 202 void setFrontFuncRef(unsigned short ref) { fFrontFuncRef = ref; } 203 void setBackFuncRef(unsigned short ref) { fBackFuncRef = ref; } 204 void setFrontWriteMask(unsigned short writeMask) { fFrontWriteMask = writeMask; } 205 void setBackWriteMask(unsigned short writeMask) { fBackWriteMask = writeMask; } 206 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 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 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 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 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