|
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 |