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