• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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] = (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
396