Remove remnants of 'intel' from active state tracker code.
[mesa.git] / src / mesa / pipe / softpipe / sp_quad_stencil.c
1
2 /**
3 * \brief Quad stencil testing
4 */
5
6
7 #include "sp_context.h"
8 #include "sp_headers.h"
9 #include "sp_surface.h"
10 #include "sp_tile_cache.h"
11 #include "sp_quad.h"
12 #include "pipe/p_defines.h"
13 #include "pipe/p_util.h"
14
15
16 /** Only 8-bit stencil supported */
17 #define STENCIL_MAX 0xff
18
19
20 /**
21 * Do the basic stencil test (compare stencil buffer values against the
22 * reference value.
23 *
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
30 */
31 static unsigned
32 do_stencil_test(const ubyte stencilVals[QUAD_SIZE], unsigned func,
33 unsigned ref, unsigned valMask)
34 {
35 unsigned passMask = 0x0;
36 unsigned j;
37
38 ref &= valMask;
39
40 switch (func) {
41 case PIPE_FUNC_NEVER:
42 /* passMask = 0x0 */
43 break;
44 case PIPE_FUNC_LESS:
45 for (j = 0; j < QUAD_SIZE; j++) {
46 if (ref < (stencilVals[j] & valMask)) {
47 passMask |= (1 << j);
48 }
49 }
50 break;
51 case PIPE_FUNC_EQUAL:
52 for (j = 0; j < QUAD_SIZE; j++) {
53 if (ref == (stencilVals[j] & valMask)) {
54 passMask |= (1 << j);
55 }
56 }
57 break;
58 case PIPE_FUNC_LEQUAL:
59 for (j = 0; j < QUAD_SIZE; j++) {
60 if (ref <= (stencilVals[j] & valMask)) {
61 passMask |= (1 << j);
62 }
63 }
64 break;
65 case PIPE_FUNC_GREATER:
66 for (j = 0; j < QUAD_SIZE; j++) {
67 if (ref > (stencilVals[j] & valMask)) {
68 passMask |= (1 << j);
69 }
70 }
71 break;
72 case PIPE_FUNC_NOTEQUAL:
73 for (j = 0; j < QUAD_SIZE; j++) {
74 if (ref != (stencilVals[j] & valMask)) {
75 passMask |= (1 << j);
76 }
77 }
78 break;
79 case PIPE_FUNC_GEQUAL:
80 for (j = 0; j < QUAD_SIZE; j++) {
81 if (ref >= (stencilVals[j] & valMask)) {
82 passMask |= (1 << j);
83 }
84 }
85 break;
86 case PIPE_FUNC_ALWAYS:
87 passMask = MASK_ALL;
88 break;
89 default:
90 assert(0);
91 }
92
93 return passMask;
94 }
95
96
97 /**
98 * Apply the stencil operator to stencil values.
99 *
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
105 * stencil values
106 */
107 static void
108 apply_stencil_op(ubyte stencilVals[QUAD_SIZE],
109 unsigned mask, unsigned op, ubyte ref, ubyte wrtMask)
110 {
111 unsigned j;
112 ubyte newstencil[QUAD_SIZE];
113
114 for (j = 0; j < QUAD_SIZE; j++) {
115 newstencil[j] = stencilVals[j];
116 }
117
118 switch (op) {
119 case PIPE_STENCIL_OP_KEEP:
120 /* no-op */
121 break;
122 case PIPE_STENCIL_OP_ZERO:
123 for (j = 0; j < QUAD_SIZE; j++) {
124 if (mask & (1 << j)) {
125 newstencil[j] = 0;
126 }
127 }
128 break;
129 case PIPE_STENCIL_OP_REPLACE:
130 for (j = 0; j < QUAD_SIZE; j++) {
131 if (mask & (1 << j)) {
132 newstencil[j] = ref;
133 }
134 }
135 break;
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;
141 }
142 }
143 }
144 break;
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;
150 }
151 }
152 }
153 break;
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;
158 }
159 }
160 break;
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;
165 }
166 }
167 break;
168 case PIPE_STENCIL_OP_INVERT:
169 for (j = 0; j < QUAD_SIZE; j++) {
170 if (mask & (1 << j)) {
171 newstencil[j] = ~stencilVals[j];
172 }
173 }
174 break;
175 default:
176 assert(0);
177 }
178
179 /*
180 * update the stencil values
181 */
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]);
186 }
187 }
188 else {
189 for (j = 0; j < QUAD_SIZE; j++) {
190 stencilVals[j] = newstencil[j];
191 }
192 }
193 }
194
195
196 /**
197 * Do stencil (and depth) testing. Stenciling depends on the outcome of
198 * depth testing.
199 */
200 static void
201 stencil_test_quad(struct quad_stage *qs, struct quad_header *quad)
202 {
203 struct softpipe_context *softpipe = qs->softpipe;
204 struct pipe_surface *ps = softpipe->framebuffer.sbuf;
205 unsigned func, zFailOp, zPassOp, failOp;
206 ubyte ref, wrtMask, valMask;
207 ubyte stencilVals[QUAD_SIZE];
208 struct softpipe_cached_tile *tile
209 = sp_get_cached_tile(softpipe, softpipe->sbuf_cache, quad->x0, quad->y0);
210 uint j;
211
212 /* choose front or back face function, operator, etc */
213 /* XXX we could do these initializations once per primitive */
214 if (softpipe->depth_stencil->stencil.back_enabled && quad->facing) {
215 func = softpipe->depth_stencil->stencil.back_func;
216 failOp = softpipe->depth_stencil->stencil.back_fail_op;
217 zFailOp = softpipe->depth_stencil->stencil.back_zfail_op;
218 zPassOp = softpipe->depth_stencil->stencil.back_zpass_op;
219 ref = softpipe->depth_stencil->stencil.ref_value[1];
220 wrtMask = softpipe->depth_stencil->stencil.write_mask[1];
221 valMask = softpipe->depth_stencil->stencil.value_mask[1];
222 }
223 else {
224 func = softpipe->depth_stencil->stencil.front_func;
225 failOp = softpipe->depth_stencil->stencil.front_fail_op;
226 zFailOp = softpipe->depth_stencil->stencil.front_zfail_op;
227 zPassOp = softpipe->depth_stencil->stencil.front_zpass_op;
228 ref = softpipe->depth_stencil->stencil.ref_value[0];
229 wrtMask = softpipe->depth_stencil->stencil.write_mask[0];
230 valMask = softpipe->depth_stencil->stencil.value_mask[0];
231 }
232
233 assert(ps); /* shouldn't get here if there's no stencil buffer */
234
235 /* get stencil values from cached tile */
236 switch (ps->format) {
237 case PIPE_FORMAT_S8_Z24:
238 for (j = 0; j < QUAD_SIZE; j++) {
239 int x = quad->x0 % TILE_SIZE + (j & 1);
240 int y = quad->y0 % TILE_SIZE + (j >> 1);
241 stencilVals[j] = tile->data.depth32[y][x] >> 24;
242 }
243 break;
244 case PIPE_FORMAT_Z24_S8:
245 for (j = 0; j < QUAD_SIZE; j++) {
246 int x = quad->x0 % TILE_SIZE + (j & 1);
247 int y = quad->y0 % TILE_SIZE + (j >> 1);
248 stencilVals[j] = tile->data.depth32[y][x] & 0xff;
249 }
250 break;
251 case PIPE_FORMAT_U_S8:
252 for (j = 0; j < QUAD_SIZE; j++) {
253 int x = quad->x0 % TILE_SIZE + (j & 1);
254 int y = quad->y0 % TILE_SIZE + (j >> 1);
255 stencilVals[j] = tile->data.stencil8[y][x];
256 }
257 break;
258 default:
259 assert(0);
260 }
261
262 /* do the stencil test first */
263 {
264 unsigned passMask, failMask;
265 passMask = do_stencil_test(stencilVals, func, ref, valMask);
266 failMask = quad->mask & ~passMask;
267 quad->mask &= passMask;
268
269 if (failOp != PIPE_STENCIL_OP_KEEP) {
270 apply_stencil_op(stencilVals, failMask, failOp, ref, wrtMask);
271 }
272 }
273
274 if (quad->mask) {
275 /* now the pixels that passed the stencil test are depth tested */
276 if (softpipe->depth_stencil->depth.enabled) {
277 const unsigned origMask = quad->mask;
278
279 sp_depth_test_quad(qs, quad); /* quad->mask is updated */
280
281 /* update stencil buffer values according to z pass/fail result */
282 if (zFailOp != PIPE_STENCIL_OP_KEEP) {
283 const unsigned failMask = origMask & ~quad->mask;
284 apply_stencil_op(stencilVals, failMask, zFailOp, ref, wrtMask);
285 }
286
287 if (zPassOp != PIPE_STENCIL_OP_KEEP) {
288 const unsigned passMask = origMask & quad->mask;
289 apply_stencil_op(stencilVals, passMask, zPassOp, ref, wrtMask);
290 }
291 }
292 else {
293 /* no depth test, apply Zpass operator to stencil buffer values */
294 apply_stencil_op(stencilVals, quad->mask, zPassOp, ref, wrtMask);
295 }
296
297 }
298
299 /* put new stencil values into cached tile */
300 switch (ps->format) {
301 case PIPE_FORMAT_S8_Z24:
302 for (j = 0; j < QUAD_SIZE; j++) {
303 int x = quad->x0 % TILE_SIZE + (j & 1);
304 int y = quad->y0 % TILE_SIZE + (j >> 1);
305 uint s8z24 = tile->data.depth32[y][x];
306 s8z24 = (stencilVals[j] << 24) | (s8z24 & 0xffffff);
307 tile->data.depth32[y][x] = s8z24;
308 }
309 break;
310 case PIPE_FORMAT_Z24_S8:
311 for (j = 0; j < QUAD_SIZE; j++) {
312 int x = quad->x0 % TILE_SIZE + (j & 1);
313 int y = quad->y0 % TILE_SIZE + (j >> 1);
314 uint z24s8 = tile->data.depth32[y][x];
315 z24s8 = (z24s8 & 0xffffff00) | stencilVals[j];
316 tile->data.depth32[y][x] = z24s8;
317 }
318 break;
319 case PIPE_FORMAT_U_S8:
320 for (j = 0; j < QUAD_SIZE; j++) {
321 int x = quad->x0 % TILE_SIZE + (j & 1);
322 int y = quad->y0 % TILE_SIZE + (j >> 1);
323 tile->data.stencil8[y][x] = stencilVals[j];
324 }
325 break;
326 default:
327 assert(0);
328 }
329
330 if (quad->mask)
331 qs->next->run(qs->next, quad);
332 }
333
334
335 static void stencil_begin(struct quad_stage *qs)
336 {
337 if (qs->next)
338 qs->next->begin(qs->next);
339 }
340
341
342 static void stencil_destroy(struct quad_stage *qs)
343 {
344 FREE( qs );
345 }
346
347
348 struct quad_stage *sp_quad_stencil_test_stage( struct softpipe_context *softpipe )
349 {
350 struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
351
352 stage->softpipe = softpipe;
353 stage->begin = stencil_begin;
354 stage->run = stencil_test_quad;
355 stage->destroy = stencil_destroy;
356
357 return stage;
358 }