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 */
39enum 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 */
74enum 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
87enum 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 */
103struct 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)
121GR_STATIC_ASSERT(sizeof(GrStencilSettingsStruct) % 4 == 0);
122GR_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 */
173class GrStencilSettings : private GrStencilSettingsStruct {
174
175public:
176    GrStencilSettings() {
177        fPad0 = fPad1 = 0;
178        this->setDisabled();
179    }
180
181    GrStencilOp frontPassOp() const { return fFrontPassOp; }
182    GrStencilOp backPassOp() const { return fBackPassOp; }
183    GrStencilOp frontFailOp() const { return fFrontFailOp; }
184    GrStencilOp backFailOp() const { return fBackFailOp; }
185    GrStencilFunc frontFunc() const { return fFrontFunc; }
186    GrStencilFunc backFunc() const { return fBackFunc; }
187    unsigned short frontFuncMask() const { return fFrontFuncMask; }
188    unsigned short backFuncMask() const { return fBackFuncMask; }
189    unsigned short frontFuncRef() const { return fFrontFuncRef; }
190    unsigned short backFuncRef() const { return fBackFuncRef; }
191    unsigned short frontWriteMask() const {return fFrontWriteMask; }
192    unsigned short backWriteMask() const { return fBackWriteMask; }
193
194    void setFrontPassOp(GrStencilOp op) { fFrontPassOp = op; fFlags = 0;}
195    void setBackPassOp(GrStencilOp op) { fBackPassOp = op; fFlags = 0;}
196    void setFrontFailOp(GrStencilOp op) {fFrontFailOp = op; fFlags = 0;}
197    void setBackFailOp(GrStencilOp op) { fBackFailOp = op; fFlags = 0;}
198    void setFrontFunc(GrStencilFunc func) { fFrontFunc = func; fFlags = 0;}
199    void setBackFunc(GrStencilFunc func) { fBackFunc = func; fFlags = 0;}
200    void setFrontFuncMask(unsigned short mask) { fFrontFuncMask = mask; }
201    void setBackFuncMask(unsigned short mask) { fBackFuncMask = mask; }
202    void setFrontFuncRef(unsigned short ref) { fFrontFuncRef = ref; }
203    void setBackFuncRef(unsigned short ref) { fBackFuncRef = ref; }
204    void setFrontWriteMask(unsigned short writeMask) { fFrontWriteMask = writeMask; }
205    void setBackWriteMask(unsigned short writeMask) { fBackWriteMask = writeMask; }
206
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
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
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
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
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
291private:
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
329GR_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