38182ad613bd1da5da03934033e2b8b3ed5d77f4
[mesa.git] / src / mesa / swrast / s_stencil.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.1
4 *
5 * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25
26 #include "glheader.h"
27 #include "context.h"
28 #include "macros.h"
29 #include "imports.h"
30
31 #include "s_context.h"
32 #include "s_depth.h"
33 #include "s_stencil.h"
34
35
36
37 /* Stencil Logic:
38
39 IF stencil test fails THEN
40 Apply fail-op to stencil value
41 Don't write the pixel (RGBA,Z)
42 ELSE
43 IF doing depth test && depth test fails THEN
44 Apply zfail-op to stencil value
45 Write RGBA and Z to appropriate buffers
46 ELSE
47 Apply zpass-op to stencil value
48 ENDIF
49
50 */
51
52
53 /*
54 * Return the address of a stencil buffer value given the window coords:
55 */
56 #define STENCIL_ADDRESS(X,Y) \
57 (ctx->DrawBuffer->Stencil + ctx->DrawBuffer->Width * (Y) + (X))
58
59
60
61 /**
62 * Apply the given stencil operator to the array of stencil values.
63 * Don't touch stencil[i] if mask[i] is zero.
64 * Input: n - size of stencil array
65 * oper - the stencil buffer operator
66 * face - 0 or 1 for front or back face operation
67 * stencil - array of stencil values
68 * mask - array [n] of flag: 1=apply operator, 0=don't apply operator
69 * Output: stencil - modified values
70 */
71 static void
72 apply_stencil_op( const GLcontext *ctx, GLenum oper, GLuint face,
73 GLuint n, GLstencil stencil[], const GLubyte mask[] )
74 {
75 const GLstencil ref = ctx->Stencil.Ref[face];
76 const GLstencil wrtmask = ctx->Stencil.WriteMask[face];
77 const GLstencil invmask = (GLstencil) (~wrtmask);
78 GLuint i;
79
80 switch (oper) {
81 case GL_KEEP:
82 /* do nothing */
83 break;
84 case GL_ZERO:
85 if (invmask==0) {
86 for (i=0;i<n;i++) {
87 if (mask[i]) {
88 stencil[i] = 0;
89 }
90 }
91 }
92 else {
93 for (i=0;i<n;i++) {
94 if (mask[i]) {
95 stencil[i] = (GLstencil) (stencil[i] & invmask);
96 }
97 }
98 }
99 break;
100 case GL_REPLACE:
101 if (invmask==0) {
102 for (i=0;i<n;i++) {
103 if (mask[i]) {
104 stencil[i] = ref;
105 }
106 }
107 }
108 else {
109 for (i=0;i<n;i++) {
110 if (mask[i]) {
111 GLstencil s = stencil[i];
112 stencil[i] = (GLstencil) ((invmask & s ) | (wrtmask & ref));
113 }
114 }
115 }
116 break;
117 case GL_INCR:
118 if (invmask==0) {
119 for (i=0;i<n;i++) {
120 if (mask[i]) {
121 GLstencil s = stencil[i];
122 if (s < STENCIL_MAX) {
123 stencil[i] = (GLstencil) (s+1);
124 }
125 }
126 }
127 }
128 else {
129 for (i=0;i<n;i++) {
130 if (mask[i]) {
131 /* VERIFY logic of adding 1 to a write-masked value */
132 GLstencil s = stencil[i];
133 if (s < STENCIL_MAX) {
134 stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s+1)));
135 }
136 }
137 }
138 }
139 break;
140 case GL_DECR:
141 if (invmask==0) {
142 for (i=0;i<n;i++) {
143 if (mask[i]) {
144 GLstencil s = stencil[i];
145 if (s>0) {
146 stencil[i] = (GLstencil) (s-1);
147 }
148 }
149 }
150 }
151 else {
152 for (i=0;i<n;i++) {
153 if (mask[i]) {
154 /* VERIFY logic of subtracting 1 to a write-masked value */
155 GLstencil s = stencil[i];
156 if (s>0) {
157 stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s-1)));
158 }
159 }
160 }
161 }
162 break;
163 case GL_INCR_WRAP_EXT:
164 if (invmask==0) {
165 for (i=0;i<n;i++) {
166 if (mask[i]) {
167 stencil[i]++;
168 }
169 }
170 }
171 else {
172 for (i=0;i<n;i++) {
173 if (mask[i]) {
174 GLstencil s = stencil[i];
175 stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s+1)));
176 }
177 }
178 }
179 break;
180 case GL_DECR_WRAP_EXT:
181 if (invmask==0) {
182 for (i=0;i<n;i++) {
183 if (mask[i]) {
184 stencil[i]--;
185 }
186 }
187 }
188 else {
189 for (i=0;i<n;i++) {
190 if (mask[i]) {
191 GLstencil s = stencil[i];
192 stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s-1)));
193 }
194 }
195 }
196 break;
197 case GL_INVERT:
198 if (invmask==0) {
199 for (i=0;i<n;i++) {
200 if (mask[i]) {
201 GLstencil s = stencil[i];
202 stencil[i] = (GLstencil) ~s;
203 }
204 }
205 }
206 else {
207 for (i=0;i<n;i++) {
208 if (mask[i]) {
209 GLstencil s = stencil[i];
210 stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & ~s));
211 }
212 }
213 }
214 break;
215 default:
216 _mesa_problem(ctx, "Bad stencil op in apply_stencil_op");
217 }
218 }
219
220
221
222
223 /**
224 * Apply stencil test to an array of stencil values (before depth buffering).
225 * Input: face - 0 or 1 for front or back-face polygons
226 * n - number of pixels in the array
227 * stencil - array of [n] stencil values
228 * mask - array [n] of flag: 0=skip the pixel, 1=stencil the pixel
229 * Output: mask - pixels which fail the stencil test will have their
230 * mask flag set to 0.
231 * stencil - updated stencil values (where the test passed)
232 * Return: GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed.
233 */
234 static GLboolean
235 do_stencil_test( GLcontext *ctx, GLuint face, GLuint n, GLstencil stencil[],
236 GLubyte mask[] )
237 {
238 GLubyte fail[MAX_WIDTH];
239 GLboolean allfail = GL_FALSE;
240 GLuint i;
241 GLstencil r, s;
242 const GLuint valueMask = ctx->Stencil.ValueMask[face];
243
244 ASSERT(n <= MAX_WIDTH);
245
246 /*
247 * Perform stencil test. The results of this operation are stored
248 * in the fail[] array:
249 * IF fail[i] is non-zero THEN
250 * the stencil fail operator is to be applied
251 * ELSE
252 * the stencil fail operator is not to be applied
253 * ENDIF
254 */
255 switch (ctx->Stencil.Function[face]) {
256 case GL_NEVER:
257 /* never pass; always fail */
258 for (i=0;i<n;i++) {
259 if (mask[i]) {
260 mask[i] = 0;
261 fail[i] = 1;
262 }
263 else {
264 fail[i] = 0;
265 }
266 }
267 allfail = GL_TRUE;
268 break;
269 case GL_LESS:
270 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
271 for (i=0;i<n;i++) {
272 if (mask[i]) {
273 s = (GLstencil) (stencil[i] & valueMask);
274 if (r < s) {
275 /* passed */
276 fail[i] = 0;
277 }
278 else {
279 fail[i] = 1;
280 mask[i] = 0;
281 }
282 }
283 else {
284 fail[i] = 0;
285 }
286 }
287 break;
288 case GL_LEQUAL:
289 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
290 for (i=0;i<n;i++) {
291 if (mask[i]) {
292 s = (GLstencil) (stencil[i] & valueMask);
293 if (r <= s) {
294 /* pass */
295 fail[i] = 0;
296 }
297 else {
298 fail[i] = 1;
299 mask[i] = 0;
300 }
301 }
302 else {
303 fail[i] = 0;
304 }
305 }
306 break;
307 case GL_GREATER:
308 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
309 for (i=0;i<n;i++) {
310 if (mask[i]) {
311 s = (GLstencil) (stencil[i] & valueMask);
312 if (r > s) {
313 /* passed */
314 fail[i] = 0;
315 }
316 else {
317 fail[i] = 1;
318 mask[i] = 0;
319 }
320 }
321 else {
322 fail[i] = 0;
323 }
324 }
325 break;
326 case GL_GEQUAL:
327 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
328 for (i=0;i<n;i++) {
329 if (mask[i]) {
330 s = (GLstencil) (stencil[i] & valueMask);
331 if (r >= s) {
332 /* passed */
333 fail[i] = 0;
334 }
335 else {
336 fail[i] = 1;
337 mask[i] = 0;
338 }
339 }
340 else {
341 fail[i] = 0;
342 }
343 }
344 break;
345 case GL_EQUAL:
346 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
347 for (i=0;i<n;i++) {
348 if (mask[i]) {
349 s = (GLstencil) (stencil[i] & valueMask);
350 if (r == s) {
351 /* passed */
352 fail[i] = 0;
353 }
354 else {
355 fail[i] = 1;
356 mask[i] = 0;
357 }
358 }
359 else {
360 fail[i] = 0;
361 }
362 }
363 break;
364 case GL_NOTEQUAL:
365 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
366 for (i=0;i<n;i++) {
367 if (mask[i]) {
368 s = (GLstencil) (stencil[i] & valueMask);
369 if (r != s) {
370 /* passed */
371 fail[i] = 0;
372 }
373 else {
374 fail[i] = 1;
375 mask[i] = 0;
376 }
377 }
378 else {
379 fail[i] = 0;
380 }
381 }
382 break;
383 case GL_ALWAYS:
384 /* always pass */
385 for (i=0;i<n;i++) {
386 fail[i] = 0;
387 }
388 break;
389 default:
390 _mesa_problem(ctx, "Bad stencil func in gl_stencil_span");
391 return 0;
392 }
393
394 if (ctx->Stencil.FailFunc[face] != GL_KEEP) {
395 apply_stencil_op( ctx, ctx->Stencil.FailFunc[face], face, n, stencil, fail );
396 }
397
398 return !allfail;
399 }
400
401
402
403 /**
404 * Apply stencil and depth testing to the span of pixels.
405 * Both software and hardware stencil buffers are acceptable.
406 * Input: n - number of pixels in the span
407 * x, y - location of leftmost pixel in span
408 * z - array [n] of z values
409 * mask - array [n] of flags (1=test this pixel, 0=skip the pixel)
410 * Output: mask - array [n] of flags (1=stencil and depth test passed)
411 * Return: GL_FALSE - all fragments failed the testing
412 * GL_TRUE - one or more fragments passed the testing
413 *
414 */
415 static GLboolean
416 stencil_and_ztest_span(GLcontext *ctx, struct sw_span *span, GLuint face)
417 {
418 SWcontext *swrast = SWRAST_CONTEXT(ctx);
419 GLstencil stencilRow[MAX_WIDTH];
420 GLstencil *stencil;
421 const GLuint n = span->end;
422 const GLint x = span->x;
423 const GLint y = span->y;
424 GLubyte *mask = span->array->mask;
425
426 ASSERT((span->arrayMask & SPAN_XY) == 0);
427 ASSERT(ctx->Stencil.Enabled);
428 ASSERT(n <= MAX_WIDTH);
429 #ifdef DEBUG
430 if (ctx->Depth.Test) {
431 ASSERT(span->arrayMask & SPAN_Z);
432 }
433 #endif
434
435 /* Get initial stencil values */
436 if (swrast->Driver.WriteStencilSpan) {
437 /* Get stencil values from the hardware stencil buffer */
438 ASSERT(swrast->Driver.ReadStencilSpan);
439 (*swrast->Driver.ReadStencilSpan)(ctx, n, x, y, stencilRow);
440 stencil = stencilRow;
441 }
442 else {
443 /* Get pointer into software stencil buffer */
444 stencil = STENCIL_ADDRESS(x, y);
445 }
446
447 /*
448 * Apply the stencil test to the fragments.
449 * failMask[i] is 1 if the stencil test failed.
450 */
451 if (do_stencil_test( ctx, face, n, stencil, mask ) == GL_FALSE) {
452 /* all fragments failed the stencil test, we're done. */
453 span->writeAll = GL_FALSE;
454 return GL_FALSE;
455 }
456
457 /*
458 * Some fragments passed the stencil test, apply depth test to them
459 * and apply Zpass and Zfail stencil ops.
460 */
461 if (ctx->Depth.Test == GL_FALSE) {
462 /*
463 * No depth buffer, just apply zpass stencil function to active pixels.
464 */
465 apply_stencil_op( ctx, ctx->Stencil.ZPassFunc[face], face, n, stencil, mask );
466 }
467 else {
468 /*
469 * Perform depth buffering, then apply zpass or zfail stencil function.
470 */
471 GLubyte passmask[MAX_WIDTH], failmask[MAX_WIDTH], oldmask[MAX_WIDTH];
472 GLuint i;
473
474 /* save the current mask bits */
475 MEMCPY(oldmask, mask, n * sizeof(GLubyte));
476
477 /* apply the depth test */
478 _swrast_depth_test_span(ctx, span);
479
480 /* Set the stencil pass/fail flags according to result of depth testing.
481 * if oldmask[i] == 0 then
482 * Don't touch the stencil value
483 * else if oldmask[i] and newmask[i] then
484 * Depth test passed
485 * else
486 * assert(oldmask[i] && !newmask[i])
487 * Depth test failed
488 * endif
489 */
490 for (i=0;i<n;i++) {
491 ASSERT(mask[i] == 0 || mask[i] == 1);
492 passmask[i] = oldmask[i] & mask[i];
493 failmask[i] = oldmask[i] & (mask[i] ^ 1);
494 }
495
496 /* apply the pass and fail operations */
497 if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
498 apply_stencil_op( ctx, ctx->Stencil.ZFailFunc[face], face,
499 n, stencil, failmask );
500 }
501 if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
502 apply_stencil_op( ctx, ctx->Stencil.ZPassFunc[face], face,
503 n, stencil, passmask );
504 }
505 }
506
507 /*
508 * Write updated stencil values back into hardware stencil buffer.
509 */
510 if (swrast->Driver.WriteStencilSpan) {
511 ASSERT(stencil == stencilRow);
512 (swrast->Driver.WriteStencilSpan)(ctx, n, x, y, stencil, mask );
513 }
514
515 span->writeAll = GL_FALSE;
516
517 return GL_TRUE; /* one or more fragments passed both tests */
518 }
519
520
521
522
523 /**
524 * Apply the given stencil operator for each pixel in the array whose
525 * mask flag is set.
526 * \note This is for software stencil buffers only.
527 * Input: n - number of pixels in the span
528 * x, y - array of [n] pixels
529 * operator - the stencil buffer operator
530 * mask - array [n] of flag: 1=apply operator, 0=don't apply operator
531 */
532 static void
533 apply_stencil_op_to_pixels( const GLcontext *ctx,
534 GLuint n, const GLint x[], const GLint y[],
535 GLenum oper, GLuint face, const GLubyte mask[] )
536 {
537 const GLstencil ref = ctx->Stencil.Ref[face];
538 const GLstencil wrtmask = ctx->Stencil.WriteMask[face];
539 const GLstencil invmask = (GLstencil) (~wrtmask);
540 GLuint i;
541
542 ASSERT(!SWRAST_CONTEXT(ctx)->Driver.WriteStencilSpan); /* software stencil buffer only! */
543
544 switch (oper) {
545 case GL_KEEP:
546 /* do nothing */
547 break;
548 case GL_ZERO:
549 if (invmask==0) {
550 for (i=0;i<n;i++) {
551 if (mask[i]) {
552 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
553 *sptr = 0;
554 }
555 }
556 }
557 else {
558 for (i=0;i<n;i++) {
559 if (mask[i]) {
560 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
561 *sptr = (GLstencil) (invmask & *sptr);
562 }
563 }
564 }
565 break;
566 case GL_REPLACE:
567 if (invmask==0) {
568 for (i=0;i<n;i++) {
569 if (mask[i]) {
570 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
571 *sptr = ref;
572 }
573 }
574 }
575 else {
576 for (i=0;i<n;i++) {
577 if (mask[i]) {
578 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
579 *sptr = (GLstencil) ((invmask & *sptr ) | (wrtmask & ref));
580 }
581 }
582 }
583 break;
584 case GL_INCR:
585 if (invmask==0) {
586 for (i=0;i<n;i++) {
587 if (mask[i]) {
588 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
589 if (*sptr < STENCIL_MAX) {
590 *sptr = (GLstencil) (*sptr + 1);
591 }
592 }
593 }
594 }
595 else {
596 for (i=0;i<n;i++) {
597 if (mask[i]) {
598 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
599 if (*sptr < STENCIL_MAX) {
600 *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr+1)));
601 }
602 }
603 }
604 }
605 break;
606 case GL_DECR:
607 if (invmask==0) {
608 for (i=0;i<n;i++) {
609 if (mask[i]) {
610 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
611 if (*sptr>0) {
612 *sptr = (GLstencil) (*sptr - 1);
613 }
614 }
615 }
616 }
617 else {
618 for (i=0;i<n;i++) {
619 if (mask[i]) {
620 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
621 if (*sptr>0) {
622 *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr-1)));
623 }
624 }
625 }
626 }
627 break;
628 case GL_INCR_WRAP_EXT:
629 if (invmask==0) {
630 for (i=0;i<n;i++) {
631 if (mask[i]) {
632 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
633 *sptr = (GLstencil) (*sptr + 1);
634 }
635 }
636 }
637 else {
638 for (i=0;i<n;i++) {
639 if (mask[i]) {
640 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
641 *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr+1)));
642 }
643 }
644 }
645 break;
646 case GL_DECR_WRAP_EXT:
647 if (invmask==0) {
648 for (i=0;i<n;i++) {
649 if (mask[i]) {
650 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
651 *sptr = (GLstencil) (*sptr - 1);
652 }
653 }
654 }
655 else {
656 for (i=0;i<n;i++) {
657 if (mask[i]) {
658 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
659 *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr-1)));
660 }
661 }
662 }
663 break;
664 case GL_INVERT:
665 if (invmask==0) {
666 for (i=0;i<n;i++) {
667 if (mask[i]) {
668 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
669 *sptr = (GLstencil) (~*sptr);
670 }
671 }
672 }
673 else {
674 for (i=0;i<n;i++) {
675 if (mask[i]) {
676 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
677 *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & ~*sptr));
678 }
679 }
680 }
681 break;
682 default:
683 _mesa_problem(ctx, "Bad stencilop in apply_stencil_op_to_pixels");
684 }
685 }
686
687
688
689 /**
690 * Apply stencil test to an array of pixels before depth buffering.
691 *
692 * \note Used for software stencil buffer only.
693 * Input: n - number of pixels in the span
694 * x, y - array of [n] pixels to stencil
695 * mask - array [n] of flag: 0=skip the pixel, 1=stencil the pixel
696 * Output: mask - pixels which fail the stencil test will have their
697 * mask flag set to 0.
698 * \return GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed.
699 */
700 static GLboolean
701 stencil_test_pixels( GLcontext *ctx, GLuint face, GLuint n,
702 const GLint x[], const GLint y[], GLubyte mask[] )
703 {
704 GLubyte fail[MAX_WIDTH];
705 GLstencil r, s;
706 GLuint i;
707 GLboolean allfail = GL_FALSE;
708 const GLuint valueMask = ctx->Stencil.ValueMask[face];
709
710 /* software stencil buffer only! */
711 ASSERT(ctx->DrawBuffer->UseSoftwareStencilBuffer);
712 ASSERT(!SWRAST_CONTEXT(ctx)->Driver.ReadStencilSpan);
713 ASSERT(!SWRAST_CONTEXT(ctx)->Driver.WriteStencilSpan);
714
715 /*
716 * Perform stencil test. The results of this operation are stored
717 * in the fail[] array:
718 * IF fail[i] is non-zero THEN
719 * the stencil fail operator is to be applied
720 * ELSE
721 * the stencil fail operator is not to be applied
722 * ENDIF
723 */
724
725 switch (ctx->Stencil.Function[face]) {
726 case GL_NEVER:
727 /* always fail */
728 for (i=0;i<n;i++) {
729 if (mask[i]) {
730 mask[i] = 0;
731 fail[i] = 1;
732 }
733 else {
734 fail[i] = 0;
735 }
736 }
737 allfail = GL_TRUE;
738 break;
739 case GL_LESS:
740 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
741 for (i=0;i<n;i++) {
742 if (mask[i]) {
743 GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
744 s = (GLstencil) (*sptr & valueMask);
745 if (r < s) {
746 /* passed */
747 fail[i] = 0;
748 }
749 else {
750 fail[i] = 1;
751 mask[i] = 0;
752 }
753 }
754 else {
755 fail[i] = 0;
756 }
757 }
758 break;
759 case GL_LEQUAL:
760 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
761 for (i=0;i<n;i++) {
762 if (mask[i]) {
763 GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
764 s = (GLstencil) (*sptr & valueMask);
765 if (r <= s) {
766 /* pass */
767 fail[i] = 0;
768 }
769 else {
770 fail[i] = 1;
771 mask[i] = 0;
772 }
773 }
774 else {
775 fail[i] = 0;
776 }
777 }
778 break;
779 case GL_GREATER:
780 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
781 for (i=0;i<n;i++) {
782 if (mask[i]) {
783 GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
784 s = (GLstencil) (*sptr & valueMask);
785 if (r > s) {
786 /* passed */
787 fail[i] = 0;
788 }
789 else {
790 fail[i] = 1;
791 mask[i] = 0;
792 }
793 }
794 else {
795 fail[i] = 0;
796 }
797 }
798 break;
799 case GL_GEQUAL:
800 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
801 for (i=0;i<n;i++) {
802 if (mask[i]) {
803 GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
804 s = (GLstencil) (*sptr & valueMask);
805 if (r >= s) {
806 /* passed */
807 fail[i] = 0;
808 }
809 else {
810 fail[i] = 1;
811 mask[i] = 0;
812 }
813 }
814 else {
815 fail[i] = 0;
816 }
817 }
818 break;
819 case GL_EQUAL:
820 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
821 for (i=0;i<n;i++) {
822 if (mask[i]) {
823 GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
824 s = (GLstencil) (*sptr & valueMask);
825 if (r == s) {
826 /* passed */
827 fail[i] = 0;
828 }
829 else {
830 fail[i] = 1;
831 mask[i] = 0;
832 }
833 }
834 else {
835 fail[i] = 0;
836 }
837 }
838 break;
839 case GL_NOTEQUAL:
840 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
841 for (i=0;i<n;i++) {
842 if (mask[i]) {
843 GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
844 s = (GLstencil) (*sptr & valueMask);
845 if (r != s) {
846 /* passed */
847 fail[i] = 0;
848 }
849 else {
850 fail[i] = 1;
851 mask[i] = 0;
852 }
853 }
854 else {
855 fail[i] = 0;
856 }
857 }
858 break;
859 case GL_ALWAYS:
860 /* always pass */
861 for (i=0;i<n;i++) {
862 fail[i] = 0;
863 }
864 break;
865 default:
866 _mesa_problem(ctx, "Bad stencil func in gl_stencil_pixels");
867 return 0;
868 }
869
870 if (ctx->Stencil.FailFunc[face] != GL_KEEP) {
871 apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.FailFunc[face],
872 face, fail );
873 }
874
875 return !allfail;
876 }
877
878
879
880
881 /**
882 * Apply stencil and depth testing to an array of pixels.
883 * This is used both for software and hardware stencil buffers.
884 *
885 * The comments in this function are a bit sparse but the code is
886 * almost identical to stencil_and_ztest_span(), which is well
887 * commented.
888 *
889 * Input: n - number of pixels in the array
890 * x, y - array of [n] pixel positions
891 * z - array [n] of z values
892 * mask - array [n] of flags (1=test this pixel, 0=skip the pixel)
893 * Output: mask - array [n] of flags (1=stencil and depth test passed)
894 * Return: GL_FALSE - all fragments failed the testing
895 * GL_TRUE - one or more fragments passed the testing
896 */
897 static GLboolean
898 stencil_and_ztest_pixels( GLcontext *ctx, struct sw_span *span, GLuint face )
899 {
900 const GLuint n = span->end;
901 const GLint *x = span->array->x;
902 const GLint *y = span->array->y;
903 GLubyte *mask = span->array->mask;
904 SWcontext *swrast = SWRAST_CONTEXT(ctx);
905
906 ASSERT(span->arrayMask & SPAN_XY);
907 ASSERT(ctx->Stencil.Enabled);
908 ASSERT(n <= MAX_WIDTH);
909
910 if (swrast->Driver.WriteStencilPixels) {
911 /*** Hardware stencil buffer ***/
912 GLstencil stencil[MAX_WIDTH];
913 GLubyte origMask[MAX_WIDTH];
914
915 ASSERT(!ctx->DrawBuffer->UseSoftwareStencilBuffer);
916 ASSERT(swrast->Driver.ReadStencilPixels);
917 (*swrast->Driver.ReadStencilPixels)(ctx, n, x, y, stencil);
918
919 MEMCPY(origMask, mask, n * sizeof(GLubyte));
920
921 (void) do_stencil_test(ctx, face, n, stencil, mask);
922
923 if (ctx->Depth.Test == GL_FALSE) {
924 apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face,
925 n, stencil, mask);
926 }
927 else {
928 _swrast_depth_test_span(ctx, span);
929
930 if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
931 GLubyte failmask[MAX_WIDTH];
932 GLuint i;
933 for (i = 0; i < n; i++) {
934 ASSERT(mask[i] == 0 || mask[i] == 1);
935 failmask[i] = origMask[i] & (mask[i] ^ 1);
936 }
937 apply_stencil_op(ctx, ctx->Stencil.ZFailFunc[face], face,
938 n, stencil, failmask);
939 }
940 if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
941 GLubyte passmask[MAX_WIDTH];
942 GLuint i;
943 for (i = 0; i < n; i++) {
944 ASSERT(mask[i] == 0 || mask[i] == 1);
945 passmask[i] = origMask[i] & mask[i];
946 }
947 apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face,
948 n, stencil, passmask);
949 }
950 }
951
952 /* Write updated stencil values into hardware stencil buffer */
953 (swrast->Driver.WriteStencilPixels)(ctx, n, x, y, stencil, origMask);
954
955 return GL_TRUE;
956 }
957 else {
958 /*** Software stencil buffer ***/
959
960 ASSERT(ctx->DrawBuffer->UseSoftwareStencilBuffer);
961
962 if (stencil_test_pixels(ctx, face, n, x, y, mask) == GL_FALSE) {
963 /* all fragments failed the stencil test, we're done. */
964 return GL_FALSE;
965 }
966
967 if (ctx->Depth.Test==GL_FALSE) {
968 apply_stencil_op_to_pixels(ctx, n, x, y,
969 ctx->Stencil.ZPassFunc[face], face, mask);
970 }
971 else {
972 GLubyte passmask[MAX_WIDTH], failmask[MAX_WIDTH], oldmask[MAX_WIDTH];
973 GLuint i;
974
975 MEMCPY(oldmask, mask, n * sizeof(GLubyte));
976
977 _swrast_depth_test_span(ctx, span);
978
979 for (i=0;i<n;i++) {
980 ASSERT(mask[i] == 0 || mask[i] == 1);
981 passmask[i] = oldmask[i] & mask[i];
982 failmask[i] = oldmask[i] & (mask[i] ^ 1);
983 }
984
985 if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
986 apply_stencil_op_to_pixels(ctx, n, x, y,
987 ctx->Stencil.ZFailFunc[face],
988 face, failmask);
989 }
990 if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
991 apply_stencil_op_to_pixels(ctx, n, x, y,
992 ctx->Stencil.ZPassFunc[face],
993 face, passmask);
994 }
995 }
996
997 return GL_TRUE; /* one or more fragments passed both tests */
998 }
999 }
1000
1001
1002 /**
1003 * /return GL_TRUE = one or more fragments passed,
1004 * GL_FALSE = all fragments failed.
1005 */
1006 GLboolean
1007 _swrast_stencil_and_ztest_span(GLcontext *ctx, struct sw_span *span)
1008 {
1009 /* span->facing can only be non-zero if using two-sided stencil */
1010 ASSERT(ctx->Stencil.TestTwoSide || span->facing == 0);
1011 if (span->arrayMask & SPAN_XY)
1012 return stencil_and_ztest_pixels(ctx, span, span->facing);
1013 else
1014 return stencil_and_ztest_span(ctx, span, span->facing);
1015 }
1016
1017
1018 /**
1019 * Return a span of stencil values from the stencil buffer.
1020 * Used for glRead/CopyPixels
1021 * Input: n - how many pixels
1022 * x,y - location of first pixel
1023 * Output: stencil - the array of stencil values
1024 */
1025 void
1026 _swrast_read_stencil_span( GLcontext *ctx,
1027 GLint n, GLint x, GLint y, GLstencil stencil[] )
1028 {
1029 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1030 const GLint bufWidth = (GLint) ctx->DrawBuffer->Width;
1031 const GLint bufHeight = (GLint) ctx->DrawBuffer->Height;
1032
1033 if (y < 0 || y >= bufHeight || x + n <= 0 || x >= bufWidth) {
1034 /* span is completely outside framebuffer */
1035 return; /* undefined values OK */
1036 }
1037
1038 if (x < 0) {
1039 GLint dx = -x;
1040 x = 0;
1041 n -= dx;
1042 stencil += dx;
1043 }
1044 if (x + n > bufWidth) {
1045 GLint dx = x + n - bufWidth;
1046 n -= dx;
1047 }
1048 if (n <= 0) {
1049 return;
1050 }
1051
1052
1053 ASSERT(n >= 0);
1054 if (swrast->Driver.ReadStencilSpan) {
1055 (*swrast->Driver.ReadStencilSpan)( ctx, (GLuint) n, x, y, stencil );
1056 }
1057 else if (ctx->DrawBuffer->Stencil) {
1058 const GLstencil *s = STENCIL_ADDRESS( x, y );
1059 #if STENCIL_BITS == 8
1060 MEMCPY( stencil, s, n * sizeof(GLstencil) );
1061 #else
1062 GLuint i;
1063 for (i=0;i<n;i++)
1064 stencil[i] = s[i];
1065 #endif
1066 }
1067 }
1068
1069
1070
1071 /**
1072 * Write a span of stencil values to the stencil buffer.
1073 * Used for glDraw/CopyPixels
1074 * Input: n - how many pixels
1075 * x, y - location of first pixel
1076 * stencil - the array of stencil values
1077 */
1078 void
1079 _swrast_write_stencil_span( GLcontext *ctx, GLint n, GLint x, GLint y,
1080 const GLstencil stencil[] )
1081 {
1082 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1083 const GLstencil *ssrc = stencil;
1084 const GLint bufWidth = (GLint) ctx->DrawBuffer->Width;
1085 const GLint bufHeight = (GLint) ctx->DrawBuffer->Height;
1086
1087 if (y < 0 || y >= bufHeight || x + n <= 0 || x >= bufWidth) {
1088 /* span is completely outside framebuffer */
1089 return; /* undefined values OK */
1090 }
1091
1092 if (x < 0) {
1093 GLint dx = -x;
1094 x = 0;
1095 n -= dx;
1096 ssrc += dx;
1097 }
1098 if (x + n > bufWidth) {
1099 GLint dx = x + n - bufWidth;
1100 n -= dx;
1101 }
1102 if (n <= 0) {
1103 return;
1104 }
1105
1106 if (swrast->Driver.WriteStencilSpan) {
1107 (*swrast->Driver.WriteStencilSpan)( ctx, n, x, y, ssrc, NULL );
1108 }
1109 else if (ctx->DrawBuffer->Stencil) {
1110 GLstencil *s = STENCIL_ADDRESS( x, y );
1111 #if STENCIL_BITS == 8
1112 MEMCPY( s, ssrc, n * sizeof(GLstencil) );
1113 #else
1114 GLuint i;
1115 for (i=0;i<n;i++)
1116 s[i] = ssrc[i];
1117 #endif
1118 }
1119 }
1120
1121
1122
1123 /**
1124 * Allocate a new stencil buffer. If there's an old one it will be
1125 * deallocated first. The new stencil buffer will be uninitialized.
1126 */
1127 void
1128 _swrast_alloc_stencil_buffer( GLframebuffer *buffer )
1129 {
1130 ASSERT(buffer->UseSoftwareStencilBuffer);
1131
1132 /* deallocate current stencil buffer if present */
1133 if (buffer->Stencil) {
1134 MESA_PBUFFER_FREE(buffer->Stencil);
1135 buffer->Stencil = NULL;
1136 }
1137
1138 /* allocate new stencil buffer */
1139 buffer->Stencil = (GLstencil *)
1140 MESA_PBUFFER_ALLOC(buffer->Width * buffer->Height * sizeof(GLstencil));
1141 if (!buffer->Stencil) {
1142 /* out of memory */
1143 _mesa_error( NULL, GL_OUT_OF_MEMORY, "_swrast_alloc_stencil_buffer" );
1144 }
1145 }
1146
1147
1148
1149 /**
1150 * Clear the software (malloc'd) stencil buffer.
1151 */
1152 static void
1153 clear_software_stencil_buffer( GLcontext *ctx )
1154 {
1155 if (ctx->Visual.stencilBits==0 || !ctx->DrawBuffer->Stencil) {
1156 /* no stencil buffer */
1157 return;
1158 }
1159
1160 if (ctx->Scissor.Enabled) {
1161 /* clear scissor region only */
1162 const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
1163 if (ctx->Stencil.WriteMask[0] != STENCIL_MAX) {
1164 /* must apply mask to the clear */
1165 GLint y;
1166 for (y = ctx->DrawBuffer->_Ymin; y < ctx->DrawBuffer->_Ymax; y++) {
1167 const GLstencil mask = ctx->Stencil.WriteMask[0];
1168 const GLstencil invMask = ~mask;
1169 const GLstencil clearVal = (ctx->Stencil.Clear & mask);
1170 GLstencil *stencil = STENCIL_ADDRESS( ctx->DrawBuffer->_Xmin, y );
1171 GLint i;
1172 for (i = 0; i < width; i++) {
1173 stencil[i] = (stencil[i] & invMask) | clearVal;
1174 }
1175 }
1176 }
1177 else {
1178 /* no masking */
1179 GLint y;
1180 for (y = ctx->DrawBuffer->_Ymin; y < ctx->DrawBuffer->_Ymax; y++) {
1181 GLstencil *stencil = STENCIL_ADDRESS( ctx->DrawBuffer->_Xmin, y );
1182 #if STENCIL_BITS==8
1183 MEMSET( stencil, ctx->Stencil.Clear, width * sizeof(GLstencil) );
1184 #else
1185 GLint i;
1186 for (i = 0; i < width; i++)
1187 stencil[i] = ctx->Stencil.Clear;
1188 #endif
1189 }
1190 }
1191 }
1192 else {
1193 /* clear whole stencil buffer */
1194 if (ctx->Stencil.WriteMask[0] != STENCIL_MAX) {
1195 /* must apply mask to the clear */
1196 const GLuint n = ctx->DrawBuffer->Width * ctx->DrawBuffer->Height;
1197 GLstencil *stencil = ctx->DrawBuffer->Stencil;
1198 const GLstencil mask = ctx->Stencil.WriteMask[0];
1199 const GLstencil invMask = ~mask;
1200 const GLstencil clearVal = (ctx->Stencil.Clear & mask);
1201 GLuint i;
1202 for (i = 0; i < n; i++) {
1203 stencil[i] = (stencil[i] & invMask) | clearVal;
1204 }
1205 }
1206 else {
1207 /* clear whole buffer without masking */
1208 const GLuint n = ctx->DrawBuffer->Width * ctx->DrawBuffer->Height;
1209 GLstencil *stencil = ctx->DrawBuffer->Stencil;
1210
1211 #if STENCIL_BITS==8
1212 MEMSET(stencil, ctx->Stencil.Clear, n * sizeof(GLstencil) );
1213 #else
1214 GLuint i;
1215 for (i = 0; i < n; i++) {
1216 stencil[i] = ctx->Stencil.Clear;
1217 }
1218 #endif
1219 }
1220 }
1221 }
1222
1223
1224
1225 /**
1226 * Clear the hardware (in graphics card) stencil buffer.
1227 * This is done with the Driver.WriteStencilSpan() and Driver.ReadStencilSpan()
1228 * functions.
1229 * Actually, if there is a hardware stencil buffer it really should have
1230 * been cleared in Driver.Clear()! However, if the hardware does not
1231 * support scissored clears or masked clears (i.e. glStencilMask) then
1232 * we have to use the span-based functions.
1233 */
1234 static void
1235 clear_hardware_stencil_buffer( GLcontext *ctx )
1236 {
1237 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1238 ASSERT(swrast->Driver.WriteStencilSpan);
1239 ASSERT(swrast->Driver.ReadStencilSpan);
1240
1241 if (ctx->Scissor.Enabled) {
1242 /* clear scissor region only */
1243 const GLint x = ctx->DrawBuffer->_Xmin;
1244 const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
1245 if (ctx->Stencil.WriteMask[0] != STENCIL_MAX) {
1246 /* must apply mask to the clear */
1247 GLint y;
1248 for (y = ctx->DrawBuffer->_Ymin; y < ctx->DrawBuffer->_Ymax; y++) {
1249 const GLstencil mask = ctx->Stencil.WriteMask[0];
1250 const GLstencil invMask = ~mask;
1251 const GLstencil clearVal = (ctx->Stencil.Clear & mask);
1252 GLstencil stencil[MAX_WIDTH];
1253 GLint i;
1254 (*swrast->Driver.ReadStencilSpan)(ctx, width, x, y, stencil);
1255 for (i = 0; i < width; i++) {
1256 stencil[i] = (stencil[i] & invMask) | clearVal;
1257 }
1258 (*swrast->Driver.WriteStencilSpan)(ctx, width, x, y, stencil, NULL);
1259 }
1260 }
1261 else {
1262 /* no masking */
1263 GLstencil stencil[MAX_WIDTH];
1264 GLint y, i;
1265 for (i = 0; i < width; i++) {
1266 stencil[i] = ctx->Stencil.Clear;
1267 }
1268 for (y = ctx->DrawBuffer->_Ymin; y < ctx->DrawBuffer->_Ymax; y++) {
1269 (*swrast->Driver.WriteStencilSpan)(ctx, width, x, y, stencil, NULL);
1270 }
1271 }
1272 }
1273 else {
1274 /* clear whole stencil buffer */
1275 if (ctx->Stencil.WriteMask[0] != STENCIL_MAX) {
1276 /* must apply mask to the clear */
1277 const GLstencil mask = ctx->Stencil.WriteMask[0];
1278 const GLstencil invMask = ~mask;
1279 const GLstencil clearVal = (ctx->Stencil.Clear & mask);
1280 const GLint width = ctx->DrawBuffer->Width;
1281 const GLint height = ctx->DrawBuffer->Height;
1282 const GLint x = ctx->DrawBuffer->_Xmin;
1283 GLint y;
1284 for (y = 0; y < height; y++) {
1285 GLstencil stencil[MAX_WIDTH];
1286 GLint i;
1287 (*swrast->Driver.ReadStencilSpan)(ctx, width, x, y, stencil);
1288 for (i = 0; i < width; i++) {
1289 stencil[i] = (stencil[i] & invMask) | clearVal;
1290 }
1291 (*swrast->Driver.WriteStencilSpan)(ctx, width, x, y, stencil, NULL);
1292 }
1293 }
1294 else {
1295 /* clear whole buffer without masking */
1296 const GLint width = ctx->DrawBuffer->Width;
1297 const GLint height = ctx->DrawBuffer->Height;
1298 const GLint x = ctx->DrawBuffer->_Xmin;
1299 GLstencil stencil[MAX_WIDTH];
1300 GLint y, i;
1301 for (i = 0; i < width; i++) {
1302 stencil[i] = ctx->Stencil.Clear;
1303 }
1304 for (y = 0; y < height; y++) {
1305 (*swrast->Driver.WriteStencilSpan)(ctx, width, x, y, stencil, NULL);
1306 }
1307 }
1308 }
1309 }
1310
1311
1312
1313 /**
1314 * Clear the stencil buffer (hardware or software).
1315 */
1316 void
1317 _swrast_clear_stencil_buffer( GLcontext *ctx )
1318 {
1319 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1320 if (swrast->Driver.WriteStencilSpan) {
1321 ASSERT(swrast->Driver.ReadStencilSpan);
1322 clear_hardware_stencil_buffer(ctx);
1323 }
1324 else {
1325 clear_software_stencil_buffer(ctx);
1326 }
1327 }