blob: 78a156f9ea25c3e09ac95248472a860a270e13ac [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"
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
bsalomon@google.comdea2f8d2011-08-01 15:51:05 +000019 * provided by clients that overlap the bits used to implement clipping.
bsalomon@google.comd302f142011-03-03 13:54:13 +000020 *
21 * When code outside the GrDrawTarget class uses the stencil buffer the contract
22 * is as follows:
23 *
bsalomon@google.comdea2f8d2011-08-01 15:51:05 +000024 * > 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.
bsalomon@google.comd302f142011-03-03 13:54:13 +000028 * > 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
87/**
bsalomon@google.com6b2445e2011-12-15 19:47:46 +000088 * GrStencilState needs to be a class with accessors and setters so that it
89 * can maintain flags related to its current state. However, we also want to
90 * be able to declare pre-made stencil settings at compile time (without
91 * inserting static initializer code). So all the data members are in this
92 * struct. A macro defined after the class can be used to jam an instance of
93 * this struct that is created from an initializer list into a
94 * GrStencilSettings. (We hang our heads in shame.)
bsalomon@google.comd302f142011-03-03 13:54:13 +000095 */
bsalomon@google.com6b2445e2011-12-15 19:47:46 +000096struct GrStencilSettingsStruct {
tomhudson@google.com62b09682011-11-09 16:39:17 +000097 GrStencilOp fFrontPassOp : 8; // op to perform when front faces pass
98 GrStencilOp fBackPassOp : 8; // op to perform when back faces pass
99 GrStencilOp fFrontFailOp : 8; // op to perform when front faces fail
100 GrStencilOp fBackFailOp : 8; // op to perform when back faces fail
101 GrStencilFunc fFrontFunc : 8; // test function for front faces
102 GrStencilFunc fBackFunc : 8; // test function for back faces
103 unsigned short fFrontFuncMask; // mask for front face test
104 unsigned short fBackFuncMask; // mask for back face test
105 unsigned short fFrontFuncRef; // reference value for front face test
106 unsigned short fBackFuncRef; // reference value for back face test
107 unsigned short fFrontWriteMask; // stencil write mask for front faces
108 unsigned short fBackWriteMask; // stencil write mask for back faces
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000109};
bsalomon@google.comd302f142011-03-03 13:54:13 +0000110
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000111/**
112 * Class representing stencil state.
113 */
114class GrStencilSettings : private GrStencilSettingsStruct {
115
116public:
bsalomon@google.comd302f142011-03-03 13:54:13 +0000117 bool operator == (const GrStencilSettings& s) const {
tomhudson@google.com62b09682011-11-09 16:39:17 +0000118 // make sure this is tightly packed (< 4B padding).
119 GR_STATIC_ASSERT(sizeof(GrStencilSettings) / 4 ==
120 (4*sizeof(uint8_t) +
121 2*sizeof(uint8_t) +
122 6*sizeof(unsigned short) + 3) / 4);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000123 return 0 == memcmp(this, &s, sizeof(GrStencilSettings));
124 }
125
126 bool operator != (const GrStencilSettings& s) const {
127 return !(*this == s);
128 }
129
130 GrStencilSettings& operator =(const GrStencilSettings& s) {
131 memcpy(this, &s, sizeof(GrStencilSettings));
132 return *this;
133 }
134
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000135 GrStencilOp frontPassOp() const { return fFrontPassOp; }
136 GrStencilOp backPassOp() const { return fBackPassOp; }
137 GrStencilOp frontFailOp() const { return fFrontFailOp; }
138 GrStencilOp backFailOp() const { return fBackFailOp; }
139 GrStencilFunc frontFunc() const { return fFrontFunc; }
140 GrStencilFunc backFunc() const { return fBackFunc; }
141 unsigned short frontFuncMask() const { return fFrontFuncMask; }
142 unsigned short backFuncMask() const { return fBackFuncMask; }
143 unsigned short frontFuncRef() const { return fFrontFuncRef; }
144 unsigned short backFuncRef() const { return fBackFuncRef; }
145 unsigned short frontWriteMask() const {return fFrontWriteMask; }
146 unsigned short backWriteMask() const { return fBackWriteMask; }
147
148 void setFrontPassOp(GrStencilOp op) { fFrontPassOp = op; }
149 void setBackPassOp(GrStencilOp op) { fBackPassOp = op; }
150 void setFrontFailOp(GrStencilOp op) {fFrontFailOp = op; }
151 void setBackFailOp(GrStencilOp op) { fBackFailOp = op; }
152 void setFrontFunc(GrStencilFunc func) { fFrontFunc = func; }
153 void setBackFunc(GrStencilFunc func) { fBackFunc = func; }
154 void setFrontFuncMask(unsigned short mask) { fFrontFuncMask = mask; }
155 void setBackFuncMask(unsigned short mask) { fBackFuncMask = mask; }
156 void setFrontFuncRef(unsigned short ref) { fFrontFuncRef = ref; }
157 void setBackFuncRef(unsigned short ref) { fBackFuncRef = ref; }
158 void setFrontWriteMask(unsigned short writeMask) { fFrontWriteMask = writeMask; }
159 void setBackWriteMask(unsigned short writeMask) { fBackWriteMask = writeMask; }
160
bsalomon@google.comd302f142011-03-03 13:54:13 +0000161 void setSame(GrStencilOp passOp,
162 GrStencilOp failOp,
163 GrStencilFunc func,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000164 unsigned short funcMask,
165 unsigned short funcRef,
166 unsigned short writeMask) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000167 fFrontPassOp = passOp;
168 fBackPassOp = passOp;
169 fFrontFailOp = failOp;
170 fBackFailOp = failOp;
171 fFrontFunc = func;
172 fBackFunc = func;
173 fFrontFuncMask = funcMask;
174 fBackFuncMask = funcMask;
175 fFrontFuncRef = funcRef;
176 fBackFuncRef = funcRef;
177 fFrontWriteMask = writeMask;
178 fBackWriteMask = writeMask;
179 }
180
bsalomon@google.comd302f142011-03-03 13:54:13 +0000181 void setDisabled() {
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000182 memset(this, 0, sizeof(*this));
183 GR_STATIC_ASSERT(0 == kKeep_StencilOp);
184 GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000185 }
186 bool isDisabled() const {
187 return kKeep_StencilOp == fFrontPassOp &&
188 kKeep_StencilOp == fBackPassOp &&
189 kKeep_StencilOp == fFrontFailOp &&
bsalomon@google.comd7beab42011-05-27 16:42:30 +0000190 kKeep_StencilOp == fBackFailOp &&
bsalomon@google.comd302f142011-03-03 13:54:13 +0000191 kAlways_StencilFunc == fFrontFunc &&
192 kAlways_StencilFunc == fBackFunc;
193 }
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000194 bool doesWrite() const {
195 return !((kNever_StencilFunc == fFrontFunc ||
196 kKeep_StencilOp == fFrontPassOp) &&
197 (kNever_StencilFunc == fBackFunc ||
198 kKeep_StencilOp == fBackPassOp) &&
199 (kAlways_StencilFunc == fFrontFunc ||
200 kKeep_StencilOp == fFrontFailOp) &&
201 (kAlways_StencilFunc == fBackFunc ||
202 kKeep_StencilOp == fBackFailOp));
203 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000204 void invalidate() {
205 // just write an illegal value to the first member
tomhudson@google.com62b09682011-11-09 16:39:17 +0000206 fFrontPassOp = (GrStencilOp)(uint8_t)-1;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000207 }
208
209private:
210 friend class GrGpu;
211
212 enum {
213 kMaxStencilClipPasses = 2 // maximum number of passes to add a clip
214 // element to the stencil buffer.
215 };
216
217 /**
218 * Given a thing to draw into the stencil clip, a fill type, and a set op
219 * this function determines:
220 * 1. Whether the thing can be draw directly to the stencil clip or
221 * needs to be drawn to the client portion of the stencil first.
222 * 2. How many passes are needed.
223 * 3. What those passes are.
224 * 4. The fill rule that should actually be used to render (will
225 * always be non-inverted).
226 *
227 * @param op the set op to combine this element with the
228 * existing clip
229 * @param stencilClipMask mask with just the stencil bit used for clipping
230 * enabled.
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000231 * @param invertedFill is this path inverted
bsalomon@google.comd302f142011-03-03 13:54:13 +0000232 * @param numPasses out: the number of passes needed to add the
233 * element to the clip.
234 * @param settings out: the stencil settings to use for each pass
235 *
236 * @return true if the clip element's geometry can be drawn directly to the
237 * stencil clip bit. Will only be true if canBeDirect is true.
238 * numPasses will be 1 if return value is true.
239 */
240 static bool GetClipPasses(GrSetOp op,
241 bool canBeDirect,
242 unsigned int stencilClipMask,
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000243 bool invertedFill,
bsalomon@google.comd302f142011-03-03 13:54:13 +0000244 int* numPasses,
245 GrStencilSettings settings[kMaxStencilClipPasses]);
246};
247
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000248GR_STATIC_ASSERT(sizeof(GrStencilSettingsStruct) == sizeof(GrStencilSettings));
249
250#define GR_STATIC_CONST_STENCIL(NAME, \
251 FRONT_PASS_OP, BACK_PASS_OP, \
252 FRONT_FAIL_OP, BACK_FAIL_OP, \
253 FRONT_FUNC, BACK_FUNC, \
254 FRONT_MASK, BACK_MASK, \
255 FRONT_REF, BACK_REF, \
256 FRONT_WRITE_MASK, BACK_WRITE_MASK) \
257 static const GrStencilSettingsStruct NAME ## _STRUCT = { \
258 (FRONT_PASS_OP), (BACK_PASS_OP), \
259 (FRONT_FAIL_OP), (BACK_FAIL_OP), \
260 (FRONT_FUNC), (BACK_FUNC), \
261 (FRONT_MASK), (BACK_MASK), \
262 (FRONT_REF), (BACK_REF), \
263 (FRONT_WRITE_MASK), (BACK_WRITE_MASK) \
264 }; \
265 static const GrStencilSettings& NAME = \
266 *static_cast<const GrStencilSettings*>(&(NAME ## _STRUCT))
bsalomon@google.comd302f142011-03-03 13:54:13 +0000267#endif
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000268
269#define GR_STATIC_CONST_SAME_STENCIL(NAME, \
270 PASS_OP, FAIL_OP, FUNC, MASK, REF, WRITE_MASK) \
271 GR_STATIC_CONST_STENCIL(NAME, (PASS_OP), (PASS_OP), (FAIL_OP), \
272 (FAIL_OP), (FUNC), (FUNC), (MASK), (MASK), (REF), (REF), (WRITE_MASK), \
273 (WRITE_MASK))