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 */
41enum 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 */
76enum 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
89enum 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 */
105struct 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)
117GR_STATIC_ASSERT(sizeof(GrStencilSettingsStruct) % 4 == 0);
118GR_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 */
169class GrStencilSettings : private GrStencilSettingsStruct {
170
171public:
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
304private:
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
343GR_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