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