blob: 28042b0b2eb95ef6ad900c1bc0f6c03f3e3aa0a8 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
bsalomon@google.comd302f142011-03-03 13:54:13 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * 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.
bsalomon@google.comd302f142011-03-03 13:54:13 +00007 */
8
epoger@google.comec3ed6a2011-07-28 14:26:00 +00009
bsalomon@google.comd302f142011-03-03 13:54:13 +000010#ifndef GrStencil_DEFINED
11#define GrStencil_DEFINED
12
13#include "GrTypes.h"
robertphillips@google.com0f191f32012-04-25 15:23:36 +000014#include "SkRegion.h"
15
bsalomon@google.comd302f142011-03-03 13:54:13 +000016/**
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
bsalomon@google.comdea2f8d2011-08-01 15:51:05 +000021 * provided by clients that overlap the bits used to implement clipping.
bsalomon@google.comd302f142011-03-03 13:54:13 +000022 *
23 * When code outside the GrDrawTarget class uses the stencil buffer the contract
24 * is as follows:
25 *
bsalomon@google.comdea2f8d2011-08-01 15:51:05 +000026 * > 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.
bsalomon@google.comd302f142011-03-03 13:54:13 +000030 * > 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
digit@google.com9b482c42012-02-16 22:03:26 +000089enum GrStencilFlags {
90 kIsDisabled_StencilFlag = 0x1,
91 kNotDisabled_StencilFlag = 0x2,
92 kDoesWrite_StencilFlag = 0x4,
93 kDoesNotWrite_StencilFlag = 0x8,
94};
95
bsalomon@google.comd302f142011-03-03 13:54:13 +000096/**
bsalomon@google.com6b2445e2011-12-15 19:47:46 +000097 * 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.)
bsalomon@google.comd302f142011-03-03 13:54:13 +0000104 */
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000105struct GrStencilSettingsStruct {
bsalomon@google.coma3201942012-06-21 19:58:20 +0000106 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
bsalomon@google.com39dab772012-01-03 19:39:31 +0000114 mutable uint32_t fFlags;
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000115};
bsalomon@google.com39dab772012-01-03 19:39:31 +0000116// 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
bsalomon@google.coma3201942012-06-21 19:58:20 +0000122 2*sizeof(uint16_t) + // func masks
123 2*sizeof(uint16_t) + // ref values
124 2*sizeof(uint16_t) + // write masks
bsalomon@google.com39dab772012-01-03 19:39:31 +0000125 sizeof(uint32_t)); // flags
bsalomon@google.comd302f142011-03-03 13:54:13 +0000126
digit@google.com9b482c42012-02-16 22:03:26 +0000127// 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
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000166/**
167 * Class representing stencil state.
168 */
169class GrStencilSettings : private GrStencilSettingsStruct {
170
171public:
bsalomon@google.coma3201942012-06-21 19:58:20 +0000172 enum Face {
173 kFront_Face = 0,
174 kBack_Face = 1,
175 };
176
bsalomon@google.com39dab772012-01-03 19:39:31 +0000177 GrStencilSettings() {
178 fPad0 = fPad1 = 0;
179 this->setDisabled();
bsalomon@google.comd302f142011-03-03 13:54:13 +0000180 }
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000181
bsalomon@google.coma3201942012-06-21 19:58:20 +0000182 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
bsalomon@google.coma3201942012-06-21 19:58:20 +0000189 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 }
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000205
bsalomon@google.comd302f142011-03-03 13:54:13 +0000206 void setSame(GrStencilOp passOp,
207 GrStencilOp failOp,
208 GrStencilFunc func,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000209 unsigned short funcMask,
210 unsigned short funcRef,
211 unsigned short writeMask) {
bsalomon@google.coma3201942012-06-21 19:58:20 +0000212 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;
bsalomon@google.com39dab772012-01-03 19:39:31 +0000218 fFlags = 0;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000219 }
220
bsalomon@google.comd302f142011-03-03 13:54:13 +0000221 void setDisabled() {
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000222 memset(this, 0, sizeof(*this));
223 GR_STATIC_ASSERT(0 == kKeep_StencilOp);
224 GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
digit@google.com9b482c42012-02-16 22:03:26 +0000225 fFlags = kIsDisabled_StencilFlag | kDoesNotWrite_StencilFlag;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000226 }
bsalomon@google.com39dab772012-01-03 19:39:31 +0000227
bsalomon@google.com9e553c62012-06-22 12:23:29 +0000228 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
bsalomon@google.comd302f142011-03-03 13:54:13 +0000248 bool isDisabled() const {
digit@google.com9b482c42012-02-16 22:03:26 +0000249 if (fFlags & kIsDisabled_StencilFlag) {
bsalomon@google.com39dab772012-01-03 19:39:31 +0000250 return true;
251 }
digit@google.com9b482c42012-02-16 22:03:26 +0000252 if (fFlags & kNotDisabled_StencilFlag) {
bsalomon@google.com39dab772012-01-03 19:39:31 +0000253 return false;
254 }
digit@google.com9b482c42012-02-16 22:03:26 +0000255 bool disabled = GR_STENCIL_SETTINGS_IS_DISABLED(
bsalomon@google.coma3201942012-06-21 19:58:20 +0000256 fPassOps[kFront_Face], fPassOps[kBack_Face],
257 fFailOps[kFront_Face], fFailOps[kBack_Face],
258 fFuncs[kFront_Face], fFuncs[kBack_Face]);
digit@google.com9b482c42012-02-16 22:03:26 +0000259 fFlags |= disabled ? kIsDisabled_StencilFlag : kNotDisabled_StencilFlag;
bsalomon@google.com39dab772012-01-03 19:39:31 +0000260 return disabled;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000261 }
bsalomon@google.com39dab772012-01-03 19:39:31 +0000262
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000263 bool doesWrite() const {
digit@google.com9b482c42012-02-16 22:03:26 +0000264 if (fFlags & kDoesWrite_StencilFlag) {
bsalomon@google.com39dab772012-01-03 19:39:31 +0000265 return true;
266 }
digit@google.com9b482c42012-02-16 22:03:26 +0000267 if (fFlags & kDoesNotWrite_StencilFlag) {
bsalomon@google.com39dab772012-01-03 19:39:31 +0000268 return false;
269 }
digit@google.com9b482c42012-02-16 22:03:26 +0000270 bool writes = GR_STENCIL_SETTINGS_DOES_WRITE(
bsalomon@google.coma3201942012-06-21 19:58:20 +0000271 fPassOps[kFront_Face], fPassOps[kBack_Face],
272 fFailOps[kFront_Face], fFailOps[kBack_Face],
273 fFuncs[kFront_Face], fFuncs[kBack_Face]);
digit@google.com9b482c42012-02-16 22:03:26 +0000274 fFlags |= writes ? kDoesWrite_StencilFlag : kDoesNotWrite_StencilFlag;
bsalomon@google.com39dab772012-01-03 19:39:31 +0000275 return writes;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000276 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000277
bsalomon@google.comd302f142011-03-03 13:54:13 +0000278 void invalidate() {
bsalomon@google.com39dab772012-01-03 19:39:31 +0000279 // write an illegal value to the first member
kkinnunen1517f932016-01-25 06:07:26 -0800280 fPassOps[0] = kStencilOpCount;
bsalomon@google.com39dab772012-01-03 19:39:31 +0000281 fFlags = 0;
282 }
283
kkinnunen1517f932016-01-25 06:07:26 -0800284 bool isValid() const {
285 return fPassOps[0] < kStencilOpCount;
286 }
287
bsalomon@google.com39dab772012-01-03 19:39:31 +0000288 bool operator == (const GrStencilSettings& s) const {
289 static const size_t gCompareSize = sizeof(GrStencilSettings) -
290 sizeof(fFlags);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000291 SkASSERT((const char*)&fFlags + sizeof(fFlags) ==
bsalomon@google.com39dab772012-01-03 19:39:31 +0000292 (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 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000298
bsalomon@google.com39dab772012-01-03 19:39:31 +0000299 bool operator != (const GrStencilSettings& s) const {
300 return !(*this == s);
301 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000302
bsalomon@google.com39dab772012-01-03 19:39:31 +0000303 GrStencilSettings& operator =(const GrStencilSettings& s) {
304 memcpy(this, &s, sizeof(GrStencilSettings));
305 return *this;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000306 }
307
308private:
robertphillips@google.com730ebe52012-04-16 16:33:13 +0000309 friend class GrClipMaskManager;
310
bsalomon@google.com39dab772012-01-03 19:39:31 +0000311 enum {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000312 kMaxStencilClipPasses = 2 // maximum number of passes to add a clip
bsalomon@google.comd302f142011-03-03 13:54:13 +0000313 // 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.
rmistry@google.comd6176b02012-08-23 18:14:13 +0000323 * 4. The fill rule that should actually be used to render (will
bsalomon@google.comd302f142011-03-03 13:54:13 +0000324 * always be non-inverted).
325 *
rmistry@google.comd6176b02012-08-23 18:14:13 +0000326 * @param op the set op to combine this element with the
bsalomon@google.comd302f142011-03-03 13:54:13 +0000327 * existing clip
328 * @param stencilClipMask mask with just the stencil bit used for clipping
329 * enabled.
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000330 * @param invertedFill is this path inverted
rmistry@google.comd6176b02012-08-23 18:14:13 +0000331 * @param numPasses out: the number of passes needed to add the
bsalomon@google.comd302f142011-03-03 13:54:13 +0000332 * 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 */
rmistry@google.comd6176b02012-08-23 18:14:13 +0000339 static bool GetClipPasses(SkRegion::Op op,
bsalomon@google.comd302f142011-03-03 13:54:13 +0000340 bool canBeDirect,
341 unsigned int stencilClipMask,
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000342 bool invertedFill,
bsalomon@google.comd302f142011-03-03 13:54:13 +0000343 int* numPasses,
344 GrStencilSettings settings[kMaxStencilClipPasses]);
345};
346
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000347GR_STATIC_ASSERT(sizeof(GrStencilSettingsStruct) == sizeof(GrStencilSettings));
348
digit@google.com9b482c42012-02-16 22:03:26 +0000349#define GR_STATIC_CONST_STENCIL_STRUCT(STRUCT_NAME, \
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000350 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) \
digit@google.com9b482c42012-02-16 22:03:26 +0000356 static const GrStencilSettingsStruct STRUCT_NAME = { \
bsalomon@google.coma3201942012-06-21 19:58:20 +0000357 {(FRONT_PASS_OP), (BACK_PASS_OP) }, \
358 {(FRONT_FAIL_OP), (BACK_FAIL_OP) }, \
359 {(FRONT_FUNC), (BACK_FUNC) }, \
bsalomon@google.com39dab772012-01-03 19:39:31 +0000360 (0), (0), \
bsalomon@google.coma3201942012-06-21 19:58:20 +0000361 {(FRONT_MASK), (BACK_MASK) }, \
362 {(FRONT_REF), (BACK_REF) }, \
363 {(FRONT_WRITE_MASK), (BACK_WRITE_MASK)}, \
digit@google.com9b482c42012-02-16 22:03:26 +0000364 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)) \
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000389 static const GrStencilSettings& NAME = \
digit@google.com9b482c42012-02-16 22:03:26 +0000390 *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&(NAME ## _STRUCT));
391
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000392
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))
digit@google.com9b482c42012-02-16 22:03:26 +0000398
399#endif