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 
GrStencilSettings()177     GrStencilSettings() {
178         fPad0 = fPad1 = 0;
179         this->setDisabled();
180     }
181 
passOp(Face f)182     GrStencilOp passOp(Face f) const { return static_cast<GrStencilOp>(fPassOps[f]); }
failOp(Face f)183     GrStencilOp failOp(Face f) const { return static_cast<GrStencilOp>(fFailOps[f]); }
func(Face f)184     GrStencilFunc func(Face f) const { return static_cast<GrStencilFunc>(fFuncs[f]); }
funcMask(Face f)185     uint16_t funcMask(Face f) const  { return fFuncMasks[f]; }
funcRef(Face f)186     uint16_t funcRef(Face f) const   { return fFuncRefs[f]; }
writeMask(Face f)187     uint16_t writeMask(Face f) const { return fWriteMasks[f]; }
188 
setPassOp(Face f,GrStencilOp op)189     void setPassOp(Face f, GrStencilOp op) { fPassOps[f] = op; fFlags = 0;}
setFailOp(Face f,GrStencilOp op)190     void setFailOp(Face f, GrStencilOp op) { fFailOps[f] = op; fFlags = 0;}
setFunc(Face f,GrStencilFunc func)191     void setFunc(Face f, GrStencilFunc func) { fFuncs[f] = func; fFlags = 0;}
setFuncMask(Face f,unsigned short mask)192     void setFuncMask(Face f, unsigned short mask) { fFuncMasks[f] = mask; }
setFuncRef(Face f,unsigned short ref)193     void setFuncRef(Face f, unsigned short ref) { fFuncRefs[f] = ref; }
setWriteMask(Face f,unsigned short writeMask)194     void setWriteMask(Face f, unsigned short writeMask) { fWriteMasks[f] = writeMask; }
195 
copyFrontSettingsToBack()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 
setSame(GrStencilOp passOp,GrStencilOp failOp,GrStencilFunc func,unsigned short funcMask,unsigned short funcRef,unsigned short writeMask)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 
setDisabled()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 
isTwoSided()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 
usesWrapOp()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 
isDisabled()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 
doesWrite()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 
invalidate()278     void invalidate()  {
279         // write an illegal value to the first member
280         fPassOps[0] = kStencilOpCount;
281         fFlags = 0;
282     }
283 
isValid()284     bool isValid() const {
285         return fPassOps[0] < kStencilOpCount;
286     }
287 
288     bool operator == (const GrStencilSettings& s) const {
289         static const size_t gCompareSize = sizeof(GrStencilSettings) -
290                                            sizeof(fFlags);
291         SkASSERT((const char*)&fFlags + sizeof(fFlags) ==
292                  (const char*)this + sizeof(GrStencilSettings));
293         if (this->isDisabled() & s.isDisabled()) { // using & not &&
294             return true;
295         }
296         return 0 == memcmp(this, &s, gCompareSize);
297     }
298 
299     bool operator != (const GrStencilSettings& s) const {
300         return !(*this == s);
301     }
302 
303     GrStencilSettings& operator =(const GrStencilSettings& s) {
304         memcpy(this, &s, sizeof(GrStencilSettings));
305         return *this;
306     }
307 
308 private:
309     friend class GrClipMaskManager;
310 
311     enum {
312         kMaxStencilClipPasses = 2  // maximum number of passes to add a clip
313                                    // element to the stencil buffer.
314     };
315 
316     /**
317      * Given a thing to draw into the stencil clip, a fill type, and a set op
318      * this function determines:
319      *      1. Whether the thing can be draw directly to the stencil clip or
320      *      needs to be drawn to the client portion of the stencil first.
321      *      2. How many passes are needed.
322      *      3. What those passes are.
323      *      4. The fill rule that should actually be used to render (will
324      *         always be non-inverted).
325      *
326      * @param op                the set op to combine this element with the
327      *                          existing clip
328      * @param stencilClipMask   mask with just the stencil bit used for clipping
329      *                          enabled.
330      * @param invertedFill      is this path inverted
331      * @param numPasses         out: the number of passes needed to add the
332      *                               element to the clip.
333      * @param settings          out: the stencil settings to use for each pass
334      *
335      * @return true if the clip element's geometry can be drawn directly to the
336      *         stencil clip bit. Will only be true if canBeDirect is true.
337      *         numPasses will be 1 if return value is true.
338      */
339     static bool GetClipPasses(SkRegion::Op op,
340                               bool canBeDirect,
341                               unsigned int stencilClipMask,
342                               bool invertedFill,
343                               int* numPasses,
344                               GrStencilSettings settings[kMaxStencilClipPasses]);
345 };
346 
347 GR_STATIC_ASSERT(sizeof(GrStencilSettingsStruct) == sizeof(GrStencilSettings));
348 
349 #define GR_STATIC_CONST_STENCIL_STRUCT(STRUCT_NAME,                          \
350     FRONT_PASS_OP,    BACK_PASS_OP,                                          \
351     FRONT_FAIL_OP,    BACK_FAIL_OP,                                          \
352     FRONT_FUNC,       BACK_FUNC,                                             \
353     FRONT_MASK,       BACK_MASK,                                             \
354     FRONT_REF,        BACK_REF,                                              \
355     FRONT_WRITE_MASK, BACK_WRITE_MASK)                                       \
356     static const GrStencilSettingsStruct STRUCT_NAME = {                     \
357        {(FRONT_PASS_OP),    (BACK_PASS_OP)   },                              \
358        {(FRONT_FAIL_OP),    (BACK_FAIL_OP)   },                              \
359        {(FRONT_FUNC),       (BACK_FUNC)      },                              \
360         (0),                (0),                                             \
361        {(FRONT_MASK),       (BACK_MASK)      },                              \
362        {(FRONT_REF),        (BACK_REF)       },                              \
363        {(FRONT_WRITE_MASK), (BACK_WRITE_MASK)},                              \
364         GR_STENCIL_SETTINGS_DEFAULT_FLAGS(                                   \
365             FRONT_PASS_OP, BACK_PASS_OP, FRONT_FAIL_OP, BACK_FAIL_OP,        \
366             FRONT_FUNC, BACK_FUNC)                                           \
367     };
368 
369 #define GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(STRUCT_PTR)            \
370     reinterpret_cast<const GrStencilSettings*>(STRUCT_PTR)
371 
372 #define GR_STATIC_CONST_SAME_STENCIL_STRUCT(STRUCT_NAME,                     \
373     PASS_OP, FAIL_OP, FUNC, MASK, REF, WRITE_MASK)                           \
374     GR_STATIC_CONST_STENCIL_STRUCT(STRUCT_NAME, (PASS_OP), (PASS_OP),        \
375     (FAIL_OP),(FAIL_OP), (FUNC), (FUNC), (MASK), (MASK), (REF), (REF),       \
376     (WRITE_MASK),(WRITE_MASK))
377 
378 #define GR_STATIC_CONST_STENCIL(NAME,                                        \
379     FRONT_PASS_OP,    BACK_PASS_OP,                                          \
380     FRONT_FAIL_OP,    BACK_FAIL_OP,                                          \
381     FRONT_FUNC,       BACK_FUNC,                                             \
382     FRONT_MASK,       BACK_MASK,                                             \
383     FRONT_REF,        BACK_REF,                                              \
384     FRONT_WRITE_MASK, BACK_WRITE_MASK)                                       \
385     GR_STATIC_CONST_STENCIL_STRUCT(NAME ## _STRUCT,                          \
386     (FRONT_PASS_OP),(BACK_PASS_OP),(FRONT_FAIL_OP),(BACK_FAIL_OP),           \
387     (FRONT_FUNC),(BACK_FUNC),(FRONT_MASK),(BACK_MASK),                       \
388     (FRONT_REF),(BACK_REF),(FRONT_WRITE_MASK),(BACK_WRITE_MASK))             \
389     static const GrStencilSettings& NAME =                                   \
390         *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&(NAME ## _STRUCT));
391 
392 
393 #define GR_STATIC_CONST_SAME_STENCIL(NAME,                                   \
394     PASS_OP, FAIL_OP, FUNC, MASK, REF, WRITE_MASK)                           \
395     GR_STATIC_CONST_STENCIL(NAME, (PASS_OP), (PASS_OP), (FAIL_OP),           \
396     (FAIL_OP), (FUNC), (FUNC), (MASK), (MASK), (REF), (REF), (WRITE_MASK),   \
397     (WRITE_MASK))
398 
399 #endif
400