3 * \brief Quad stencil testing
7 #include "main/glheader.h"
8 #include "main/imports.h"
9 #include "sp_context.h"
10 #include "sp_headers.h"
11 #include "sp_surface.h"
13 #include "pipe/p_defines.h"
16 /** Only 8-bit stencil supported */
17 #define STENCIL_MAX 0xff
21 * Do the basic stencil test (compare stencil buffer values against the
24 * \param stencilVals the stencil values from the stencil buffer
25 * \param func the stencil func (PIPE_FUNC_x)
26 * \param ref the stencil reference value
27 * \param valMask the stencil value mask indicating which bits of the stencil
28 * values and ref value are to be used.
29 * \return mask indicating which pixels passed the stencil test
32 do_stencil_test(const GLubyte stencilVals
[QUAD_SIZE
], GLuint func
,
33 GLbitfield ref
, GLbitfield valMask
)
35 GLbitfield passMask
= 0x0;
45 for (j
= 0; j
< QUAD_SIZE
; j
++) {
46 if ((stencilVals
[j
] & valMask
) < ref
) {
52 for (j
= 0; j
< QUAD_SIZE
; j
++) {
53 if ((stencilVals
[j
] & valMask
) == ref
) {
58 case PIPE_FUNC_LEQUAL
:
59 for (j
= 0; j
< QUAD_SIZE
; j
++) {
60 if ((stencilVals
[j
] & valMask
) <= ref
) {
65 case PIPE_FUNC_GREATER
:
66 for (j
= 0; j
< QUAD_SIZE
; j
++) {
67 if ((stencilVals
[j
] & valMask
) > ref
) {
72 case PIPE_FUNC_NOTEQUAL
:
73 for (j
= 0; j
< QUAD_SIZE
; j
++) {
74 if ((stencilVals
[j
] & valMask
) != ref
) {
79 case PIPE_FUNC_GEQUAL
:
80 for (j
= 0; j
< QUAD_SIZE
; j
++) {
81 if ((stencilVals
[j
] & valMask
) >= ref
) {
86 case PIPE_FUNC_ALWAYS
:
98 * Apply the stencil operator to stencil values.
100 * \param stencilVals the stencil buffer values (read and written)
101 * \param mask indicates which pixels to update
102 * \param op the stencil operator (PIPE_STENCIL_OP_x)
103 * \param ref the stencil reference value
104 * \param wrtMask writemask controlling which bits are changed in the
108 apply_stencil_op(GLubyte stencilVals
[QUAD_SIZE
],
109 GLbitfield mask
, GLuint op
, GLubyte ref
, GLubyte wrtMask
)
112 GLubyte newstencil
[QUAD_SIZE
];
114 for (j
= 0; j
< QUAD_SIZE
; j
++) {
115 newstencil
[j
] = stencilVals
[j
];
119 case PIPE_STENCIL_OP_KEEP
:
122 case PIPE_STENCIL_OP_ZERO
:
123 for (j
= 0; j
< QUAD_SIZE
; j
++) {
124 if (mask
& (1 << j
)) {
129 case PIPE_STENCIL_OP_REPLACE
:
130 for (j
= 0; j
< QUAD_SIZE
; j
++) {
131 if (mask
& (1 << j
)) {
136 case PIPE_STENCIL_OP_INCR
:
137 for (j
= 0; j
< QUAD_SIZE
; j
++) {
138 if (mask
& (1 << j
)) {
139 if (stencilVals
[j
] < STENCIL_MAX
) {
140 newstencil
[j
] = stencilVals
[j
] + 1;
145 case PIPE_STENCIL_OP_DECR
:
146 for (j
= 0; j
< QUAD_SIZE
; j
++) {
147 if (mask
& (1 << j
)) {
148 if (stencilVals
[j
] > 0) {
149 newstencil
[j
] = stencilVals
[j
] - 1;
154 case PIPE_STENCIL_OP_INCR_WRAP
:
155 for (j
= 0; j
< QUAD_SIZE
; j
++) {
156 if (mask
& (1 << j
)) {
157 newstencil
[j
] = stencilVals
[j
] + 1;
161 case PIPE_STENCIL_OP_DECR_WRAP
:
162 for (j
= 0; j
< QUAD_SIZE
; j
++) {
163 if (mask
& (1 << j
)) {
164 newstencil
[j
] = stencilVals
[j
] - 1;
168 case PIPE_STENCIL_OP_INVERT
:
169 for (j
= 0; j
< QUAD_SIZE
; j
++) {
170 if (mask
& (1 << j
)) {
171 newstencil
[j
] = ~stencilVals
[j
];
180 * update the stencil values
182 if (wrtMask
!= STENCIL_MAX
) {
183 /* apply bit-wise stencil buffer writemask */
184 for (j
= 0; j
< QUAD_SIZE
; j
++) {
185 stencilVals
[j
] = (wrtMask
& newstencil
[j
]) | (~wrtMask
& stencilVals
[j
]);
189 for (j
= 0; j
< QUAD_SIZE
; j
++) {
190 stencilVals
[j
] = newstencil
[j
];
197 * Do stencil (and depth) testing. Stenciling depends on the outcome of
201 stencil_test_quad(struct quad_stage
*qs
, struct quad_header
*quad
)
203 struct softpipe_context
*softpipe
= qs
->softpipe
;
204 struct softpipe_surface
*s_surf
= softpipe_surface(softpipe
->framebuffer
.sbuf
);
205 GLuint func
, zFailOp
, zPassOp
, failOp
;
206 GLubyte ref
, wrtMask
, valMask
;
207 GLubyte stencilVals
[QUAD_SIZE
];
209 /* choose front or back face function, operator, etc */
210 /* XXX we could do these initializations once per primitive */
211 if (softpipe
->stencil
.back_enabled
&& quad
->facing
) {
212 func
= softpipe
->stencil
.back_func
;
213 failOp
= softpipe
->stencil
.back_fail_op
;
214 zFailOp
= softpipe
->stencil
.back_zfail_op
;
215 zPassOp
= softpipe
->stencil
.back_zpass_op
;
216 ref
= softpipe
->stencil
.ref_value
[1];
217 wrtMask
= softpipe
->stencil
.write_mask
[1];
218 valMask
= softpipe
->stencil
.value_mask
[1];
221 func
= softpipe
->stencil
.front_func
;
222 failOp
= softpipe
->stencil
.front_fail_op
;
223 zFailOp
= softpipe
->stencil
.front_zfail_op
;
224 zPassOp
= softpipe
->stencil
.front_zpass_op
;
225 ref
= softpipe
->stencil
.ref_value
[0];
226 wrtMask
= softpipe
->stencil
.write_mask
[0];
227 valMask
= softpipe
->stencil
.value_mask
[0];
230 assert(s_surf
); /* shouldn't get here if there's no stencil buffer */
231 s_surf
->read_quad_stencil(s_surf
, quad
->x0
, quad
->y0
, stencilVals
);
233 /* do the stencil test first */
235 GLbitfield passMask
, failMask
;
236 passMask
= do_stencil_test(stencilVals
, func
, ref
, valMask
);
237 failMask
= quad
->mask
& ~passMask
;
238 quad
->mask
&= passMask
;
240 if (failOp
!= PIPE_STENCIL_OP_KEEP
) {
241 apply_stencil_op(stencilVals
, failMask
, failOp
, ref
, wrtMask
);
247 /* now the pixels that passed the stencil test are depth tested */
248 if (softpipe
->depth_test
.enabled
) {
249 const GLbitfield origMask
= quad
->mask
;
251 sp_depth_test_quad(qs
, quad
); /* quad->mask is updated */
253 /* update stencil buffer values according to z pass/fail result */
254 if (zFailOp
!= PIPE_STENCIL_OP_KEEP
) {
255 const GLbitfield failMask
= origMask
& ~quad
->mask
;
256 apply_stencil_op(stencilVals
, failMask
, zFailOp
, ref
, wrtMask
);
259 if (zPassOp
!= PIPE_STENCIL_OP_KEEP
) {
260 const GLbitfield passMask
= origMask
& quad
->mask
;
261 apply_stencil_op(stencilVals
, passMask
, zPassOp
, ref
, wrtMask
);
265 /* no depth test, apply Zpass operator to stencil buffer values */
266 apply_stencil_op(stencilVals
, quad
->mask
, zPassOp
, ref
, wrtMask
);
271 s_surf
->write_quad_stencil(s_surf
, quad
->x0
, quad
->y0
, stencilVals
);
274 qs
->next
->run(qs
->next
, quad
);
278 static void stencil_begin(struct quad_stage
*qs
)
281 qs
->next
->begin(qs
->next
);
285 struct quad_stage
*sp_quad_stencil_test_stage( struct softpipe_context
*softpipe
)
287 struct quad_stage
*stage
= CALLOC_STRUCT(quad_stage
);
289 stage
->softpipe
= softpipe
;
290 stage
->begin
= stencil_begin
;
291 stage
->run
= stencil_test_quad
;