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