blob: b8610f2017b85824f13d4adf137b68b9384e2beb [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/**
88 * Struct representing stencil state.
89 */
90struct GrStencilSettings {
91 GrStencilOp fFrontPassOp; // op to perform when front faces pass
92 GrStencilOp fBackPassOp; // op to perform when back faces pass
93 GrStencilOp fFrontFailOp; // op to perform when front faces fail
94 GrStencilOp fBackFailOp; // op to perform when back faces fail
95 GrStencilFunc fFrontFunc; // test function for front faces
96 GrStencilFunc fBackFunc; // test function for back faces
97 unsigned int fFrontFuncMask; // mask for front face test
98 unsigned int fBackFuncMask; // mask for back face test
99 unsigned int fFrontFuncRef; // reference value for front face test
100 unsigned int fBackFuncRef; // reference value for back face test
101 unsigned int fFrontWriteMask; // stencil write mask for front faces
102 unsigned int fBackWriteMask; // stencil write mask for back faces
103
104 bool operator == (const GrStencilSettings& s) const {
105 // make sure this is tightly packed.
106 GR_STATIC_ASSERT(0 == sizeof(GrStencilOp)%4);
107 GR_STATIC_ASSERT(0 == sizeof(GrStencilFunc)%4);
108 GR_STATIC_ASSERT(sizeof(GrStencilSettings) ==
109 4*sizeof(GrStencilOp) +
110 2*sizeof(GrStencilFunc) +
111 6*sizeof(unsigned int));
112 return 0 == memcmp(this, &s, sizeof(GrStencilSettings));
113 }
114
115 bool operator != (const GrStencilSettings& s) const {
116 return !(*this == s);
117 }
118
119 GrStencilSettings& operator =(const GrStencilSettings& s) {
120 memcpy(this, &s, sizeof(GrStencilSettings));
121 return *this;
122 }
123
124 void setSame(GrStencilOp passOp,
125 GrStencilOp failOp,
126 GrStencilFunc func,
127 unsigned int funcMask,
128 unsigned int funcRef,
129 unsigned int writeMask) {
130 fFrontPassOp = passOp;
131 fBackPassOp = passOp;
132 fFrontFailOp = failOp;
133 fBackFailOp = failOp;
134 fFrontFunc = func;
135 fBackFunc = func;
136 fFrontFuncMask = funcMask;
137 fBackFuncMask = funcMask;
138 fFrontFuncRef = funcRef;
139 fBackFuncRef = funcRef;
140 fFrontWriteMask = writeMask;
141 fBackWriteMask = writeMask;
142 }
143
144 // canonical value for disabled stenciling
145 static const GrStencilSettings gDisabled;
146 void setDisabled() {
147 *this = gDisabled;
148 }
149 bool isDisabled() const {
150 return kKeep_StencilOp == fFrontPassOp &&
151 kKeep_StencilOp == fBackPassOp &&
152 kKeep_StencilOp == fFrontFailOp &&
bsalomon@google.comd7beab42011-05-27 16:42:30 +0000153 kKeep_StencilOp == fBackFailOp &&
bsalomon@google.comd302f142011-03-03 13:54:13 +0000154 kAlways_StencilFunc == fFrontFunc &&
155 kAlways_StencilFunc == fBackFunc;
156 }
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000157 bool doesWrite() const {
158 return !((kNever_StencilFunc == fFrontFunc ||
159 kKeep_StencilOp == fFrontPassOp) &&
160 (kNever_StencilFunc == fBackFunc ||
161 kKeep_StencilOp == fBackPassOp) &&
162 (kAlways_StencilFunc == fFrontFunc ||
163 kKeep_StencilOp == fFrontFailOp) &&
164 (kAlways_StencilFunc == fBackFunc ||
165 kKeep_StencilOp == fBackFailOp));
166 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000167 void invalidate() {
168 // just write an illegal value to the first member
169 fFrontPassOp = (GrStencilOp)-1;
170 }
171
172private:
173 friend class GrGpu;
174
175 enum {
176 kMaxStencilClipPasses = 2 // maximum number of passes to add a clip
177 // element to the stencil buffer.
178 };
179
180 /**
181 * Given a thing to draw into the stencil clip, a fill type, and a set op
182 * this function determines:
183 * 1. Whether the thing can be draw directly to the stencil clip or
184 * needs to be drawn to the client portion of the stencil first.
185 * 2. How many passes are needed.
186 * 3. What those passes are.
187 * 4. The fill rule that should actually be used to render (will
188 * always be non-inverted).
189 *
190 * @param op the set op to combine this element with the
191 * existing clip
192 * @param stencilClipMask mask with just the stencil bit used for clipping
193 * enabled.
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000194 * @param invertedFill is this path inverted
bsalomon@google.comd302f142011-03-03 13:54:13 +0000195 * @param numPasses out: the number of passes needed to add the
196 * element to the clip.
197 * @param settings out: the stencil settings to use for each pass
198 *
199 * @return true if the clip element's geometry can be drawn directly to the
200 * stencil clip bit. Will only be true if canBeDirect is true.
201 * numPasses will be 1 if return value is true.
202 */
203 static bool GetClipPasses(GrSetOp op,
204 bool canBeDirect,
205 unsigned int stencilClipMask,
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000206 bool invertedFill,
bsalomon@google.comd302f142011-03-03 13:54:13 +0000207 int* numPasses,
208 GrStencilSettings settings[kMaxStencilClipPasses]);
209};
210
211#endif