blob: fa7d626a8745ed2a0be471da2f585268ae1990eb [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
egdaniel22281c12016-03-23 13:49:40 -070016class GrProcessorKeyBuilder;
17
bsalomon@google.comd302f142011-03-03 13:54:13 +000018/**
19 * Gr uses the stencil buffer to implement complex clipping inside the
20 * GrDrawTarget class. The GrDrawTarget makes a subset of the stencil buffer
21 * bits available for other uses by external code (clients). Client code can
22 * modify these bits. GrDrawTarget will ignore ref, mask, and writemask bits
bsalomon@google.comdea2f8d2011-08-01 15:51:05 +000023 * provided by clients that overlap the bits used to implement clipping.
bsalomon@google.comd302f142011-03-03 13:54:13 +000024 *
25 * When code outside the GrDrawTarget class uses the stencil buffer the contract
26 * is as follows:
27 *
bsalomon@google.comdea2f8d2011-08-01 15:51:05 +000028 * > Normal stencil funcs allow the client to pass / fail regardless of the
29 * reserved clip bits.
30 * > Additional functions allow a test against the clip along with a limited
31 * set of tests against the client bits.
bsalomon@google.comd302f142011-03-03 13:54:13 +000032 * > Client can assume all client bits are zero initially.
33 * > Client must ensure that after all its passes are finished it has only
34 * written to the color buffer in the region inside the clip. Furthermore, it
35 * must zero all client bits that were modifed (both inside and outside the
36 * clip).
37 */
38
39/**
40 * Determines which pixels pass / fail the stencil test.
41 * Stencil test passes if (ref & mask) FUNC (stencil & mask) is true
42 */
43enum GrStencilFunc {
44 kAlways_StencilFunc = 0,
45 kNever_StencilFunc,
46 kGreater_StencilFunc,
47 kGEqual_StencilFunc,
48 kLess_StencilFunc,
49 kLEqual_StencilFunc,
50 kEqual_StencilFunc,
51 kNotEqual_StencilFunc,
52
53 // Gr stores the current clip in the
54 // stencil buffer in the high bits that
55 // are not directly accessible modifiable
56 // via the GrDrawTarget interface. The below
57 // stencil funcs test against the current
58 // clip in addition to the GrDrawTarget
59 // client's stencil bits.
60
61 // pass if inside the clip
62 kAlwaysIfInClip_StencilFunc,
63 kEqualIfInClip_StencilFunc,
64 kLessIfInClip_StencilFunc,
65 kLEqualIfInClip_StencilFunc,
66 kNonZeroIfInClip_StencilFunc, // this one forces the ref to be 0
67
68 // counts
69 kStencilFuncCount,
70 kClipStencilFuncCount = kNonZeroIfInClip_StencilFunc -
71 kAlwaysIfInClip_StencilFunc + 1,
72 kBasicStencilFuncCount = kStencilFuncCount - kClipStencilFuncCount
73};
74
75/**
76 * Operations to perform based on whether stencil test passed failed.
77 */
78enum GrStencilOp {
79 kKeep_StencilOp = 0, // preserve existing stencil value
80 kReplace_StencilOp, // replace with reference value from stencl test
81 kIncWrap_StencilOp, // increment and wrap at max
82 kIncClamp_StencilOp, // increment and clamp at max
83 kDecWrap_StencilOp, // decrement and wrap at 0
84 kDecClamp_StencilOp, // decrement and clamp at 0
85 kZero_StencilOp, // zero stencil bits
86 kInvert_StencilOp, // invert stencil bits
87
88 kStencilOpCount
89};
90
digit@google.com9b482c42012-02-16 22:03:26 +000091enum GrStencilFlags {
92 kIsDisabled_StencilFlag = 0x1,
93 kNotDisabled_StencilFlag = 0x2,
94 kDoesWrite_StencilFlag = 0x4,
95 kDoesNotWrite_StencilFlag = 0x8,
96};
97
bsalomon@google.comd302f142011-03-03 13:54:13 +000098/**
bsalomon@google.com6b2445e2011-12-15 19:47:46 +000099 * GrStencilState needs to be a class with accessors and setters so that it
100 * can maintain flags related to its current state. However, we also want to
101 * be able to declare pre-made stencil settings at compile time (without
102 * inserting static initializer code). So all the data members are in this
103 * struct. A macro defined after the class can be used to jam an instance of
104 * this struct that is created from an initializer list into a
105 * GrStencilSettings. (We hang our heads in shame.)
bsalomon@google.comd302f142011-03-03 13:54:13 +0000106 */
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000107struct GrStencilSettingsStruct {
bsalomon@google.coma3201942012-06-21 19:58:20 +0000108 uint8_t fPassOps[2]; // op to perform when faces pass (GrStencilOp)
109 uint8_t fFailOps[2]; // op to perform when faces fail (GrStencilOp)
110 uint8_t fFuncs[2]; // test function for faces (GrStencilFunc)
111 uint8_t fPad0;
112 uint8_t fPad1;
113 uint16_t fFuncMasks[2]; // mask for face tests
114 uint16_t fFuncRefs[2]; // reference values for face tests
115 uint16_t fWriteMasks[2]; // stencil write masks
bsalomon@google.com39dab772012-01-03 19:39:31 +0000116 mutable uint32_t fFlags;
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000117};
bsalomon@google.com39dab772012-01-03 19:39:31 +0000118// We rely on this being packed and aligned (memcmp'ed and memcpy'ed)
119GR_STATIC_ASSERT(sizeof(GrStencilSettingsStruct) % 4 == 0);
120GR_STATIC_ASSERT(sizeof(GrStencilSettingsStruct) ==
121 4*sizeof(uint8_t) + // ops
122 2*sizeof(uint8_t) + // funcs
123 2*sizeof(uint8_t) + // pads
bsalomon@google.coma3201942012-06-21 19:58:20 +0000124 2*sizeof(uint16_t) + // func masks
125 2*sizeof(uint16_t) + // ref values
126 2*sizeof(uint16_t) + // write masks
bsalomon@google.com39dab772012-01-03 19:39:31 +0000127 sizeof(uint32_t)); // flags
bsalomon@google.comd302f142011-03-03 13:54:13 +0000128
digit@google.com9b482c42012-02-16 22:03:26 +0000129// This macro is used to compute the GrStencilSettingsStructs flags
130// associated to disabling. It is used both to define constant structure
131// initializers and inside GrStencilSettings::isDisabled()
132//
133#define GR_STENCIL_SETTINGS_IS_DISABLED( \
134 FRONT_PASS_OP, BACK_PASS_OP, \
135 FRONT_FAIL_OP, BACK_FAIL_OP, \
136 FRONT_FUNC, BACK_FUNC) \
137 ((FRONT_PASS_OP) == kKeep_StencilOp && \
138 (BACK_PASS_OP) == kKeep_StencilOp && \
139 (FRONT_FAIL_OP) == kKeep_StencilOp && \
140 (BACK_FAIL_OP) == kKeep_StencilOp && \
141 (FRONT_FUNC) == kAlways_StencilFunc && \
142 (BACK_FUNC) == kAlways_StencilFunc)
143
144#define GR_STENCIL_SETTINGS_DOES_WRITE( \
145 FRONT_PASS_OP, BACK_PASS_OP, \
146 FRONT_FAIL_OP, BACK_FAIL_OP, \
147 FRONT_FUNC, BACK_FUNC) \
148 (!(((FRONT_FUNC) == kNever_StencilFunc || \
149 (FRONT_PASS_OP) == kKeep_StencilOp) && \
150 ((BACK_FUNC) == kNever_StencilFunc || \
151 (BACK_PASS_OP) == kKeep_StencilOp) && \
152 ((FRONT_FUNC) == kAlways_StencilFunc || \
153 (FRONT_FAIL_OP) == kKeep_StencilOp) && \
154 ((BACK_FUNC) == kAlways_StencilFunc || \
155 (BACK_FAIL_OP) == kKeep_StencilOp)))
156
157#define GR_STENCIL_SETTINGS_DEFAULT_FLAGS( \
158 FRONT_PASS_OP, BACK_PASS_OP, \
159 FRONT_FAIL_OP, BACK_FAIL_OP, \
160 FRONT_FUNC, BACK_FUNC) \
161 ((GR_STENCIL_SETTINGS_IS_DISABLED(FRONT_PASS_OP,BACK_PASS_OP, \
162 FRONT_FAIL_OP,BACK_FAIL_OP,FRONT_FUNC,BACK_FUNC) ? \
163 kIsDisabled_StencilFlag : kNotDisabled_StencilFlag) | \
164 (GR_STENCIL_SETTINGS_DOES_WRITE(FRONT_PASS_OP,BACK_PASS_OP, \
165 FRONT_FAIL_OP,BACK_FAIL_OP,FRONT_FUNC,BACK_FUNC) ? \
166 kDoesWrite_StencilFlag : kDoesNotWrite_StencilFlag))
167
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000168/**
169 * Class representing stencil state.
170 */
171class GrStencilSettings : private GrStencilSettingsStruct {
172
173public:
bsalomon@google.coma3201942012-06-21 19:58:20 +0000174 enum Face {
175 kFront_Face = 0,
176 kBack_Face = 1,
177 };
178
bsalomon@google.com39dab772012-01-03 19:39:31 +0000179 GrStencilSettings() {
180 fPad0 = fPad1 = 0;
181 this->setDisabled();
bsalomon@google.comd302f142011-03-03 13:54:13 +0000182 }
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000183
bsalomon@google.coma3201942012-06-21 19:58:20 +0000184 GrStencilOp passOp(Face f) const { return static_cast<GrStencilOp>(fPassOps[f]); }
185 GrStencilOp failOp(Face f) const { return static_cast<GrStencilOp>(fFailOps[f]); }
186 GrStencilFunc func(Face f) const { return static_cast<GrStencilFunc>(fFuncs[f]); }
187 uint16_t funcMask(Face f) const { return fFuncMasks[f]; }
188 uint16_t funcRef(Face f) const { return fFuncRefs[f]; }
189 uint16_t writeMask(Face f) const { return fWriteMasks[f]; }
190
bsalomon@google.coma3201942012-06-21 19:58:20 +0000191 void setPassOp(Face f, GrStencilOp op) { fPassOps[f] = op; fFlags = 0;}
192 void setFailOp(Face f, GrStencilOp op) { fFailOps[f] = op; fFlags = 0;}
193 void setFunc(Face f, GrStencilFunc func) { fFuncs[f] = func; fFlags = 0;}
194 void setFuncMask(Face f, unsigned short mask) { fFuncMasks[f] = mask; }
195 void setFuncRef(Face f, unsigned short ref) { fFuncRefs[f] = ref; }
196 void setWriteMask(Face f, unsigned short writeMask) { fWriteMasks[f] = writeMask; }
197
198 void copyFrontSettingsToBack() {
199 fPassOps[kBack_Face] = fPassOps[kFront_Face];
200 fFailOps[kBack_Face] = fFailOps[kFront_Face];
201 fFuncs[kBack_Face] = fFuncs[kFront_Face];
202 fFuncMasks[kBack_Face] = fFuncMasks[kFront_Face];
203 fFuncRefs[kBack_Face] = fFuncRefs[kFront_Face];
204 fWriteMasks[kBack_Face] = fWriteMasks[kFront_Face];
205 fFlags = 0;
206 }
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000207
bsalomon@google.comd302f142011-03-03 13:54:13 +0000208 void setSame(GrStencilOp passOp,
209 GrStencilOp failOp,
210 GrStencilFunc func,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000211 unsigned short funcMask,
212 unsigned short funcRef,
213 unsigned short writeMask) {
bsalomon@google.coma3201942012-06-21 19:58:20 +0000214 fPassOps[kFront_Face] = fPassOps[kBack_Face] = passOp;
215 fFailOps[kFront_Face] = fFailOps[kBack_Face] = failOp;
216 fFuncs[kFront_Face] = fFuncs[kBack_Face] = func;
217 fFuncMasks[kFront_Face] = fFuncMasks[kBack_Face] = funcMask;
218 fFuncRefs[kFront_Face] = fFuncRefs[kBack_Face] = funcRef;
219 fWriteMasks[kFront_Face] = fWriteMasks[kBack_Face] = writeMask;
bsalomon@google.com39dab772012-01-03 19:39:31 +0000220 fFlags = 0;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000221 }
222
bsalomon@google.comd302f142011-03-03 13:54:13 +0000223 void setDisabled() {
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000224 memset(this, 0, sizeof(*this));
225 GR_STATIC_ASSERT(0 == kKeep_StencilOp);
226 GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
digit@google.com9b482c42012-02-16 22:03:26 +0000227 fFlags = kIsDisabled_StencilFlag | kDoesNotWrite_StencilFlag;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000228 }
bsalomon@google.com39dab772012-01-03 19:39:31 +0000229
bsalomon@google.com9e553c62012-06-22 12:23:29 +0000230 bool isTwoSided() const {
231 return fPassOps[kFront_Face] != fPassOps[kBack_Face] ||
232 fFailOps[kFront_Face] != fFailOps[kBack_Face] ||
233 fFuncs[kFront_Face] != fFuncs[kBack_Face] ||
234 fFuncMasks[kFront_Face] != fFuncMasks[kBack_Face] ||
235 fFuncRefs[kFront_Face] != fFuncRefs[kBack_Face] ||
236 fWriteMasks[kFront_Face] != fWriteMasks[kBack_Face];
237 }
238
239 bool usesWrapOp() const {
240 return kIncWrap_StencilOp == fPassOps[kFront_Face] ||
241 kDecWrap_StencilOp == fPassOps[kFront_Face] ||
242 kIncWrap_StencilOp == fPassOps[kBack_Face] ||
243 kDecWrap_StencilOp == fPassOps[kBack_Face] ||
244 kIncWrap_StencilOp == fFailOps[kFront_Face] ||
245 kDecWrap_StencilOp == fFailOps[kFront_Face] ||
246 kIncWrap_StencilOp == fFailOps[kBack_Face] ||
247 kDecWrap_StencilOp == fFailOps[kBack_Face];
248 }
249
bsalomon@google.comd302f142011-03-03 13:54:13 +0000250 bool isDisabled() const {
digit@google.com9b482c42012-02-16 22:03:26 +0000251 if (fFlags & kIsDisabled_StencilFlag) {
bsalomon@google.com39dab772012-01-03 19:39:31 +0000252 return true;
253 }
digit@google.com9b482c42012-02-16 22:03:26 +0000254 if (fFlags & kNotDisabled_StencilFlag) {
bsalomon@google.com39dab772012-01-03 19:39:31 +0000255 return false;
256 }
digit@google.com9b482c42012-02-16 22:03:26 +0000257 bool disabled = GR_STENCIL_SETTINGS_IS_DISABLED(
bsalomon@google.coma3201942012-06-21 19:58:20 +0000258 fPassOps[kFront_Face], fPassOps[kBack_Face],
259 fFailOps[kFront_Face], fFailOps[kBack_Face],
260 fFuncs[kFront_Face], fFuncs[kBack_Face]);
digit@google.com9b482c42012-02-16 22:03:26 +0000261 fFlags |= disabled ? kIsDisabled_StencilFlag : kNotDisabled_StencilFlag;
bsalomon@google.com39dab772012-01-03 19:39:31 +0000262 return disabled;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000263 }
bsalomon@google.com39dab772012-01-03 19:39:31 +0000264
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000265 bool doesWrite() const {
digit@google.com9b482c42012-02-16 22:03:26 +0000266 if (fFlags & kDoesWrite_StencilFlag) {
bsalomon@google.com39dab772012-01-03 19:39:31 +0000267 return true;
268 }
digit@google.com9b482c42012-02-16 22:03:26 +0000269 if (fFlags & kDoesNotWrite_StencilFlag) {
bsalomon@google.com39dab772012-01-03 19:39:31 +0000270 return false;
271 }
digit@google.com9b482c42012-02-16 22:03:26 +0000272 bool writes = GR_STENCIL_SETTINGS_DOES_WRITE(
bsalomon@google.coma3201942012-06-21 19:58:20 +0000273 fPassOps[kFront_Face], fPassOps[kBack_Face],
274 fFailOps[kFront_Face], fFailOps[kBack_Face],
275 fFuncs[kFront_Face], fFuncs[kBack_Face]);
digit@google.com9b482c42012-02-16 22:03:26 +0000276 fFlags |= writes ? kDoesWrite_StencilFlag : kDoesNotWrite_StencilFlag;
bsalomon@google.com39dab772012-01-03 19:39:31 +0000277 return writes;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000278 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000279
bsalomon@google.comd302f142011-03-03 13:54:13 +0000280 void invalidate() {
bsalomon@google.com39dab772012-01-03 19:39:31 +0000281 // write an illegal value to the first member
kkinnunen1517f932016-01-25 06:07:26 -0800282 fPassOps[0] = kStencilOpCount;
bsalomon@google.com39dab772012-01-03 19:39:31 +0000283 fFlags = 0;
284 }
285
kkinnunen1517f932016-01-25 06:07:26 -0800286 bool isValid() const {
287 return fPassOps[0] < kStencilOpCount;
288 }
289
egdaniel22281c12016-03-23 13:49:40 -0700290 void genKey(GrProcessorKeyBuilder* b) const;
291
bsalomon@google.com39dab772012-01-03 19:39:31 +0000292 bool operator == (const GrStencilSettings& s) const {
293 static const size_t gCompareSize = sizeof(GrStencilSettings) -
294 sizeof(fFlags);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000295 SkASSERT((const char*)&fFlags + sizeof(fFlags) ==
bsalomon@google.com39dab772012-01-03 19:39:31 +0000296 (const char*)this + sizeof(GrStencilSettings));
297 if (this->isDisabled() & s.isDisabled()) { // using & not &&
298 return true;
299 }
300 return 0 == memcmp(this, &s, gCompareSize);
301 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000302
bsalomon@google.com39dab772012-01-03 19:39:31 +0000303 bool operator != (const GrStencilSettings& s) const {
304 return !(*this == s);
305 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000306
bsalomon@google.com39dab772012-01-03 19:39:31 +0000307 GrStencilSettings& operator =(const GrStencilSettings& s) {
308 memcpy(this, &s, sizeof(GrStencilSettings));
309 return *this;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000310 }
311
312private:
robertphillips@google.com730ebe52012-04-16 16:33:13 +0000313 friend class GrClipMaskManager;
314
bsalomon@google.com39dab772012-01-03 19:39:31 +0000315 enum {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000316 kMaxStencilClipPasses = 2 // maximum number of passes to add a clip
bsalomon@google.comd302f142011-03-03 13:54:13 +0000317 // element to the stencil buffer.
318 };
319
320 /**
321 * Given a thing to draw into the stencil clip, a fill type, and a set op
322 * this function determines:
323 * 1. Whether the thing can be draw directly to the stencil clip or
324 * needs to be drawn to the client portion of the stencil first.
325 * 2. How many passes are needed.
326 * 3. What those passes are.
rmistry@google.comd6176b02012-08-23 18:14:13 +0000327 * 4. The fill rule that should actually be used to render (will
bsalomon@google.comd302f142011-03-03 13:54:13 +0000328 * always be non-inverted).
329 *
rmistry@google.comd6176b02012-08-23 18:14:13 +0000330 * @param op the set op to combine this element with the
bsalomon@google.comd302f142011-03-03 13:54:13 +0000331 * existing clip
332 * @param stencilClipMask mask with just the stencil bit used for clipping
333 * enabled.
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000334 * @param invertedFill is this path inverted
rmistry@google.comd6176b02012-08-23 18:14:13 +0000335 * @param numPasses out: the number of passes needed to add the
bsalomon@google.comd302f142011-03-03 13:54:13 +0000336 * element to the clip.
337 * @param settings out: the stencil settings to use for each pass
338 *
339 * @return true if the clip element's geometry can be drawn directly to the
340 * stencil clip bit. Will only be true if canBeDirect is true.
341 * numPasses will be 1 if return value is true.
342 */
rmistry@google.comd6176b02012-08-23 18:14:13 +0000343 static bool GetClipPasses(SkRegion::Op op,
bsalomon@google.comd302f142011-03-03 13:54:13 +0000344 bool canBeDirect,
345 unsigned int stencilClipMask,
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000346 bool invertedFill,
bsalomon@google.comd302f142011-03-03 13:54:13 +0000347 int* numPasses,
348 GrStencilSettings settings[kMaxStencilClipPasses]);
349};
350
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000351GR_STATIC_ASSERT(sizeof(GrStencilSettingsStruct) == sizeof(GrStencilSettings));
352
digit@google.com9b482c42012-02-16 22:03:26 +0000353#define GR_STATIC_CONST_STENCIL_STRUCT(STRUCT_NAME, \
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000354 FRONT_PASS_OP, BACK_PASS_OP, \
355 FRONT_FAIL_OP, BACK_FAIL_OP, \
356 FRONT_FUNC, BACK_FUNC, \
357 FRONT_MASK, BACK_MASK, \
358 FRONT_REF, BACK_REF, \
359 FRONT_WRITE_MASK, BACK_WRITE_MASK) \
digit@google.com9b482c42012-02-16 22:03:26 +0000360 static const GrStencilSettingsStruct STRUCT_NAME = { \
bsalomon@google.coma3201942012-06-21 19:58:20 +0000361 {(FRONT_PASS_OP), (BACK_PASS_OP) }, \
362 {(FRONT_FAIL_OP), (BACK_FAIL_OP) }, \
363 {(FRONT_FUNC), (BACK_FUNC) }, \
bsalomon@google.com39dab772012-01-03 19:39:31 +0000364 (0), (0), \
bsalomon@google.coma3201942012-06-21 19:58:20 +0000365 {(FRONT_MASK), (BACK_MASK) }, \
366 {(FRONT_REF), (BACK_REF) }, \
367 {(FRONT_WRITE_MASK), (BACK_WRITE_MASK)}, \
digit@google.com9b482c42012-02-16 22:03:26 +0000368 GR_STENCIL_SETTINGS_DEFAULT_FLAGS( \
369 FRONT_PASS_OP, BACK_PASS_OP, FRONT_FAIL_OP, BACK_FAIL_OP, \
370 FRONT_FUNC, BACK_FUNC) \
371 };
372
373#define GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(STRUCT_PTR) \
374 reinterpret_cast<const GrStencilSettings*>(STRUCT_PTR)
375
376#define GR_STATIC_CONST_SAME_STENCIL_STRUCT(STRUCT_NAME, \
377 PASS_OP, FAIL_OP, FUNC, MASK, REF, WRITE_MASK) \
378 GR_STATIC_CONST_STENCIL_STRUCT(STRUCT_NAME, (PASS_OP), (PASS_OP), \
379 (FAIL_OP),(FAIL_OP), (FUNC), (FUNC), (MASK), (MASK), (REF), (REF), \
380 (WRITE_MASK),(WRITE_MASK))
381
382#define GR_STATIC_CONST_STENCIL(NAME, \
383 FRONT_PASS_OP, BACK_PASS_OP, \
384 FRONT_FAIL_OP, BACK_FAIL_OP, \
385 FRONT_FUNC, BACK_FUNC, \
386 FRONT_MASK, BACK_MASK, \
387 FRONT_REF, BACK_REF, \
388 FRONT_WRITE_MASK, BACK_WRITE_MASK) \
389 GR_STATIC_CONST_STENCIL_STRUCT(NAME ## _STRUCT, \
390 (FRONT_PASS_OP),(BACK_PASS_OP),(FRONT_FAIL_OP),(BACK_FAIL_OP), \
391 (FRONT_FUNC),(BACK_FUNC),(FRONT_MASK),(BACK_MASK), \
392 (FRONT_REF),(BACK_REF),(FRONT_WRITE_MASK),(BACK_WRITE_MASK)) \
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000393 static const GrStencilSettings& NAME = \
digit@google.com9b482c42012-02-16 22:03:26 +0000394 *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&(NAME ## _STRUCT));
395
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000396
397#define GR_STATIC_CONST_SAME_STENCIL(NAME, \
398 PASS_OP, FAIL_OP, FUNC, MASK, REF, WRITE_MASK) \
399 GR_STATIC_CONST_STENCIL(NAME, (PASS_OP), (PASS_OP), (FAIL_OP), \
400 (FAIL_OP), (FUNC), (FUNC), (MASK), (MASK), (REF), (REF), (WRITE_MASK), \
401 (WRITE_MASK))
digit@google.com9b482c42012-02-16 22:03:26 +0000402
403#endif