ReactOS 0.4.15-dev-7788-g1ad9096
stencil.c
Go to the documentation of this file.
1/* $Id: stencil.c,v 1.8 1998/01/01 00:52:11 brianp Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version: 2.6
6 * Copyright (C) 1995-1997 Brian Paul
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the Free
20 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23
24/*
25 * $Log: stencil.c,v $
26 * Revision 1.8 1998/01/01 00:52:11 brianp
27 * added some tests to prevent crashing if Driver.DepthTestPixels not defined
28 *
29 * Revision 1.7 1997/07/24 01:21:56 brianp
30 * changed precompiled header symbol from PCH to PC_HEADER
31 *
32 * Revision 1.6 1997/05/28 03:26:29 brianp
33 * added precompiled header (PCH) support
34 *
35 * Revision 1.5 1997/04/29 01:26:37 brianp
36 * fixed a few return statements which were missing values
37 *
38 * Revision 1.4 1997/04/20 20:29:11 brianp
39 * replaced abort() with gl_problem()
40 *
41 * Revision 1.3 1997/02/27 19:58:35 brianp
42 * don't try to clear stencil buffer if there isn't one
43 *
44 * Revision 1.2 1996/09/15 14:18:55 brianp
45 * now use GLframebuffer and GLvisual
46 *
47 * Revision 1.1 1996/09/13 01:38:16 brianp
48 * Initial revision
49 *
50 */
51
52
53#ifdef PC_HEADER
54#include "all.h"
55#else
56#include <stdlib.h>
57#include <string.h>
58#include "context.h"
59#include "dlist.h"
60#include "macros.h"
61#include "pb.h"
62#include "stencil.h"
63#include "types.h"
64#endif
65
66
67/*
68 * Return the address of a stencil buffer value given the window coords:
69 */
70#define STENCIL_ADDRESS(X,Y) (ctx->Buffer->Stencil + ctx->Buffer->Width * (Y) + (X))
71
72
74{
75 if (INSIDE_BEGIN_END(ctx)) {
76 gl_error( ctx, GL_INVALID_OPERATION, "glClearStencil" );
77 return;
78 }
79 ctx->Stencil.Clear = (GLstencil) s;
80}
81
82
83
85{
86 GLint maxref;
87
88 if (INSIDE_BEGIN_END(ctx)) {
89 gl_error( ctx, GL_INVALID_OPERATION, "glStencilFunc" );
90 return;
91 }
92
93 switch (func) {
94 case GL_NEVER:
95 case GL_LESS:
96 case GL_LEQUAL:
97 case GL_GREATER:
98 case GL_GEQUAL:
99 case GL_EQUAL:
100 case GL_NOTEQUAL:
101 case GL_ALWAYS:
102 ctx->Stencil.Function = func;
103 break;
104 default:
105 gl_error( ctx, GL_INVALID_ENUM, "glStencilFunc" );
106 return;
107 }
108
109 maxref = (1 << STENCIL_BITS) - 1;
110 ctx->Stencil.Ref = CLAMP( ref, 0, maxref );
111 ctx->Stencil.ValueMask = mask;
112}
113
114
115
117{
118 if (INSIDE_BEGIN_END(ctx)) {
119 gl_error( ctx, GL_INVALID_OPERATION, "glStencilMask" );
120 return;
121 }
122 ctx->Stencil.WriteMask = (GLstencil) mask;
123}
124
125
126
127void gl_StencilOp( GLcontext *ctx, GLenum fail, GLenum zfail, GLenum zpass )
128{
129 if (INSIDE_BEGIN_END(ctx)) {
130 gl_error( ctx, GL_INVALID_OPERATION, "glStencilOp" );
131 return;
132 }
133 switch (fail) {
134 case GL_KEEP:
135 case GL_ZERO:
136 case GL_REPLACE:
137 case GL_INCR:
138 case GL_DECR:
139 case GL_INVERT:
140 ctx->Stencil.FailFunc = fail;
141 break;
142 default:
143 gl_error( ctx, GL_INVALID_ENUM, "glStencilOp" );
144 return;
145 }
146 switch (zfail) {
147 case GL_KEEP:
148 case GL_ZERO:
149 case GL_REPLACE:
150 case GL_INCR:
151 case GL_DECR:
152 case GL_INVERT:
153 ctx->Stencil.ZFailFunc = zfail;
154 break;
155 default:
156 gl_error( ctx, GL_INVALID_ENUM, "glStencilOp" );
157 return;
158 }
159 switch (zpass) {
160 case GL_KEEP:
161 case GL_ZERO:
162 case GL_REPLACE:
163 case GL_INCR:
164 case GL_DECR:
165 case GL_INVERT:
166 ctx->Stencil.ZPassFunc = zpass;
167 break;
168 default:
169 gl_error( ctx, GL_INVALID_ENUM, "glStencilOp" );
170 return;
171 }
172}
173
174
175
176/* Stencil Logic:
177
178IF stencil test fails THEN
179 Don't write the pixel (RGBA,Z)
180 Execute FailOp
181ELSE
182 Write the pixel
183ENDIF
184
185Perform Depth Test
186
187IF depth test passes OR no depth buffer THEN
188 Execute ZPass
189 Write the pixel
190ELSE
191 Execute ZFail
192ENDIF
193
194*/
195
196
197
198
199/*
200 * Apply the given stencil operator for each pixel in the span whose
201 * mask flag is set.
202 * Input: n - number of pixels in the span
203 * x, y - location of leftmost pixel in the span
204 * oper - the stencil buffer operator
205 * mask - array [n] of flag: 1=apply operator, 0=don't apply operator
206 */
208 GLuint n, GLint x, GLint y,
209 GLenum oper, GLubyte mask[] )
210{
211 GLint i;
212 GLstencil s, ref;
213 GLstencil wrtmask, invmask;
215
216 wrtmask = ctx->Stencil.WriteMask;
217 invmask = ~ctx->Stencil.WriteMask;
218 ref = ctx->Stencil.Ref;
220
221 switch (oper) {
222 case GL_KEEP:
223 /* do nothing */
224 break;
225 case GL_ZERO:
226 if (invmask==0) {
227 for (i=0;i<n;i++) {
228 if (mask[i]) {
229 stencil[i] = 0;
230 }
231 }
232 }
233 else {
234 for (i=0;i<n;i++) {
235 if (mask[i]) {
236 stencil[i] = stencil[i] & invmask;
237 }
238 }
239 }
240 break;
241 case GL_REPLACE:
242 if (invmask==0) {
243 for (i=0;i<n;i++) {
244 if (mask[i]) {
245 stencil[i] = ref;
246 }
247 }
248 }
249 else {
250 for (i=0;i<n;i++) {
251 if (mask[i]) {
252 s = stencil[i];
253 stencil[i] = (invmask & s ) | (wrtmask & ref);
254 }
255 }
256 }
257 break;
258 case GL_INCR:
259 if (invmask==0) {
260 for (i=0;i<n;i++) {
261 if (mask[i]) {
262 s = stencil[i];
263 if (s<0xff) {
264 stencil[i] = s+1;
265 }
266 }
267 }
268 }
269 else {
270 for (i=0;i<n;i++) {
271 if (mask[i]) {
272 /* VERIFY logic of adding 1 to a write-masked value */
273 s = stencil[i];
274 if (s<0xff) {
275 stencil[i] = (invmask & s) | (wrtmask & (s+1));
276 }
277 }
278 }
279 }
280 break;
281 case GL_DECR:
282 if (invmask==0) {
283 for (i=0;i<n;i++) {
284 if (mask[i]) {
285 s = stencil[i];
286 if (s>0) {
287 stencil[i] = s-1;
288 }
289 }
290 }
291 }
292 else {
293 for (i=0;i<n;i++) {
294 if (mask[i]) {
295 /* VERIFY logic of subtracting 1 to a write-masked value */
296 s = stencil[i];
297 if (s>0) {
298 stencil[i] = (invmask & s) | (wrtmask & (s-1));
299 }
300 }
301 }
302 }
303 break;
304 case GL_INVERT:
305 if (invmask==0) {
306 for (i=0;i<n;i++) {
307 if (mask[i]) {
308 s = stencil[i];
309 stencil[i] = ~s;
310 }
311 }
312 }
313 else {
314 for (i=0;i<n;i++) {
315 if (mask[i]) {
316 s = stencil[i];
317 stencil[i] = (invmask & s) | (wrtmask & ~s);
318 }
319 }
320 }
321 break;
322 default:
323 gl_problem(ctx, "Bad stencilop in apply_stencil_op_to_span");
324 }
325}
326
327
328
329
330/*
331 * Apply stencil test to a span of pixels before depth buffering.
332 * Input: n - number of pixels in the span
333 * x, y - coordinate of left-most pixel in the span
334 * mask - array [n] of flag: 0=skip the pixel, 1=stencil the pixel
335 * Output: mask - pixels which fail the stencil test will have their
336 * mask flag set to 0.
337 * Return: 0 = all pixels failed, 1 = zero or more pixels passed.
338 */
341{
342 GLubyte fail[MAX_WIDTH];
343 GLint allfail = 0;
344 GLuint i;
345 GLstencil r, s;
347
349
350 /*
351 * Perform stencil test. The results of this operation are stored
352 * in the fail[] array:
353 * IF fail[i] is non-zero THEN
354 * the stencil fail operator is to be applied
355 * ELSE
356 * the stencil fail operator is not to be applied
357 * ENDIF
358 */
359 switch (ctx->Stencil.Function) {
360 case GL_NEVER:
361 /* always fail */
362 for (i=0;i<n;i++) {
363 if (mask[i]) {
364 mask[i] = 0;
365 fail[i] = 1;
366 }
367 else {
368 fail[i] = 0;
369 }
370 }
371 allfail = 1;
372 break;
373 case GL_LESS:
374 r = ctx->Stencil.Ref & ctx->Stencil.ValueMask;
375 for (i=0;i<n;i++) {
376 if (mask[i]) {
377 s = stencil[i] & ctx->Stencil.ValueMask;
378 if (r < s) {
379 /* passed */
380 fail[i] = 0;
381 }
382 else {
383 fail[i] = 1;
384 mask[i] = 0;
385 }
386 }
387 else {
388 fail[i] = 0;
389 }
390 }
391 break;
392 case GL_LEQUAL:
393 r = ctx->Stencil.Ref & ctx->Stencil.ValueMask;
394 for (i=0;i<n;i++) {
395 if (mask[i]) {
396 s = stencil[i] & ctx->Stencil.ValueMask;
397 if (r <= s) {
398 /* pass */
399 fail[i] = 0;
400 }
401 else {
402 fail[i] = 1;
403 mask[i] = 0;
404 }
405 }
406 else {
407 fail[i] = 0;
408 }
409 }
410 break;
411 case GL_GREATER:
412 r = ctx->Stencil.Ref & ctx->Stencil.ValueMask;
413 for (i=0;i<n;i++) {
414 if (mask[i]) {
415 s = stencil[i] & ctx->Stencil.ValueMask;
416 if (r > s) {
417 /* passed */
418 fail[i] = 0;
419 }
420 else {
421 fail[i] = 1;
422 mask[i] = 0;
423 }
424 }
425 else {
426 fail[i] = 0;
427 }
428 }
429 break;
430 case GL_GEQUAL:
431 r = ctx->Stencil.Ref & ctx->Stencil.ValueMask;
432 for (i=0;i<n;i++) {
433 if (mask[i]) {
434 s = stencil[i] & ctx->Stencil.ValueMask;
435 if (r >= s) {
436 /* passed */
437 fail[i] = 0;
438 }
439 else {
440 fail[i] = 1;
441 mask[i] = 0;
442 }
443 }
444 else {
445 fail[i] = 0;
446 }
447 }
448 break;
449 case GL_EQUAL:
450 r = ctx->Stencil.Ref & ctx->Stencil.ValueMask;
451 for (i=0;i<n;i++) {
452 if (mask[i]) {
453 s = stencil[i] & ctx->Stencil.ValueMask;
454 if (r == s) {
455 /* passed */
456 fail[i] = 0;
457 }
458 else {
459 fail[i] = 1;
460 mask[i] = 0;
461 }
462 }
463 else {
464 fail[i] = 0;
465 }
466 }
467 break;
468 case GL_NOTEQUAL:
469 r = ctx->Stencil.Ref & ctx->Stencil.ValueMask;
470 for (i=0;i<n;i++) {
471 if (mask[i]) {
472 s = stencil[i] & ctx->Stencil.ValueMask;
473 if (r != s) {
474 /* passed */
475 fail[i] = 0;
476 }
477 else {
478 fail[i] = 1;
479 mask[i] = 0;
480 }
481 }
482 else {
483 fail[i] = 0;
484 }
485 }
486 break;
487 case GL_ALWAYS:
488 /* always pass */
489 for (i=0;i<n;i++) {
490 fail[i] = 0;
491 }
492 break;
493 default:
494 gl_problem(ctx, "Bad stencil func in gl_stencil_span");
495 return 0;
496 }
497
498 apply_stencil_op_to_span( ctx, n, x, y, ctx->Stencil.FailFunc, fail );
499
500 return (allfail) ? 0 : 1;
501}
502
503
504
505
506/*
507 * Apply the combination depth-buffer/stencil operator to a span of pixels.
508 * Input: n - number of pixels in the span
509 * x, y - location of leftmost pixel in span
510 * z - array [n] of z values
511 * Input: mask - array [n] of flags (1=test this pixel, 0=skip the pixel)
512 * Output: mask - array [n] of flags (1=depth test passed, 0=failed)
513 */
515 GLuint n, GLint x, GLint y, const GLdepth z[],
516 GLubyte mask[] )
517{
518 if (ctx->Depth.Test==GL_FALSE) {
519 /*
520 * No depth buffer, just apply zpass stencil function to active pixels.
521 */
522 apply_stencil_op_to_span( ctx, n, x, y, ctx->Stencil.ZPassFunc, mask );
523 }
524 else {
525 /*
526 * Perform depth buffering, then apply zpass or zfail stencil function.
527 */
528 GLubyte passmask[MAX_WIDTH], failmask[MAX_WIDTH], oldmask[MAX_WIDTH];
529 GLuint i;
530
531 /* init pass and fail masks to zero, copy mask[] to oldmask[] */
532 for (i=0;i<n;i++) {
533 passmask[i] = failmask[i] = 0;
534 oldmask[i] = mask[i];
535 }
536
537 /* apply the depth test */
538 if (ctx->Driver.DepthTestSpan)
539 (*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask );
540
541 /* set the stencil pass/fail flags according to result of depth test */
542 for (i=0;i<n;i++) {
543 if (oldmask[i]) {
544 if (mask[i]) {
545 passmask[i] = 1;
546 }
547 else {
548 failmask[i] = 1;
549 }
550 }
551 }
552
553 /* apply the pass and fail operations */
554 apply_stencil_op_to_span( ctx, n, x, y, ctx->Stencil.ZFailFunc, failmask );
555 apply_stencil_op_to_span( ctx, n, x, y, ctx->Stencil.ZPassFunc, passmask );
556 }
557}
558
559
560
561
562/*
563 * Apply the given stencil operator for each pixel in the array whose
564 * mask flag is set.
565 * Input: n - number of pixels in the span
566 * x, y - array of [n] pixels
567 * operator - the stencil buffer operator
568 * mask - array [n] of flag: 1=apply operator, 0=don't apply operator
569 */
571 GLuint n, const GLint x[],
572 const GLint y[],
573 GLenum oper, GLubyte mask[] )
574{
575 GLint i;
577 GLstencil wrtmask, invmask;
578
579 wrtmask = ctx->Stencil.WriteMask;
580 invmask = ~ctx->Stencil.WriteMask;
581
582 ref = ctx->Stencil.Ref;
583
584 switch (oper) {
585 case GL_KEEP:
586 /* do nothing */
587 break;
588 case GL_ZERO:
589 if (invmask==0) {
590 for (i=0;i<n;i++) {
591 if (mask[i]) {
592 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
593 *sptr = 0;
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 *sptr = invmask & *sptr;
602 }
603 }
604 }
605 break;
606 case GL_REPLACE:
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 *sptr = ref;
612 }
613 }
614 }
615 else {
616 for (i=0;i<n;i++) {
617 if (mask[i]) {
618 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
619 *sptr = (invmask & *sptr ) | (wrtmask & ref);
620 }
621 }
622 }
623 break;
624 case GL_INCR:
625 if (invmask==0) {
626 for (i=0;i<n;i++) {
627 if (mask[i]) {
628 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
629 if (*sptr < 0xff) {
630 *sptr = *sptr + 1;
631 }
632 }
633 }
634 }
635 else {
636 for (i=0;i<n;i++) {
637 if (mask[i]) {
638 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
639 if (*sptr<0xff) {
640 *sptr = (invmask & *sptr) | (wrtmask & (*sptr+1));
641 }
642 }
643 }
644 }
645 break;
646 case GL_DECR:
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 if (*sptr>0) {
652 *sptr = *sptr - 1;
653 }
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 if (*sptr>0) {
662 *sptr = (invmask & *sptr) | (wrtmask & (*sptr-1));
663 }
664 }
665 }
666 }
667 break;
668 case GL_INVERT:
669 if (invmask==0) {
670 for (i=0;i<n;i++) {
671 if (mask[i]) {
672 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
673 *sptr = ~*sptr;
674 }
675 }
676 }
677 else {
678 for (i=0;i<n;i++) {
679 if (mask[i]) {
680 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
681 *sptr = (invmask & *sptr) | (wrtmask & ~*sptr);
682 }
683 }
684 }
685 break;
686 default:
687 gl_problem(ctx, "Bad stencilop in apply_stencil_op_to_pixels");
688 }
689}
690
691
692
693/*
694 * Apply stencil test to an array of pixels before depth buffering.
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: 0 = all pixels failed, 1 = zero or more pixels passed.
701 */
703 GLuint n, const GLint x[], const GLint y[],
704 GLubyte mask[] )
705{
706 GLubyte fail[PB_SIZE];
707 GLstencil r, s;
708 GLuint i;
709 GLint allfail = 0;
710
711 /*
712 * Perform stencil test. The results of this operation are stored
713 * in the fail[] array:
714 * IF fail[i] is non-zero THEN
715 * the stencil fail operator is to be applied
716 * ELSE
717 * the stencil fail operator is not to be applied
718 * ENDIF
719 */
720
721 switch (ctx->Stencil.Function) {
722 case GL_NEVER:
723 /* always fail */
724 for (i=0;i<n;i++) {
725 if (mask[i]) {
726 mask[i] = 0;
727 fail[i] = 1;
728 }
729 else {
730 fail[i] = 0;
731 }
732 }
733 allfail = 1;
734 break;
735 case GL_LESS:
736 r = ctx->Stencil.Ref & ctx->Stencil.ValueMask;
737 for (i=0;i<n;i++) {
738 if (mask[i]) {
739 GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
740 s = *sptr & ctx->Stencil.ValueMask;
741 if (r < s) {
742 /* passed */
743 fail[i] = 0;
744 }
745 else {
746 fail[i] = 1;
747 mask[i] = 0;
748 }
749 }
750 else {
751 fail[i] = 0;
752 }
753 }
754 break;
755 case GL_LEQUAL:
756 r = ctx->Stencil.Ref & ctx->Stencil.ValueMask;
757 for (i=0;i<n;i++) {
758 if (mask[i]) {
759 GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
760 s = *sptr & ctx->Stencil.ValueMask;
761 if (r <= s) {
762 /* pass */
763 fail[i] = 0;
764 }
765 else {
766 fail[i] = 1;
767 mask[i] = 0;
768 }
769 }
770 else {
771 fail[i] = 0;
772 }
773 }
774 break;
775 case GL_GREATER:
776 r = ctx->Stencil.Ref & ctx->Stencil.ValueMask;
777 for (i=0;i<n;i++) {
778 if (mask[i]) {
779 GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
780 s = *sptr & ctx->Stencil.ValueMask;
781 if (r > s) {
782 /* passed */
783 fail[i] = 0;
784 }
785 else {
786 fail[i] = 1;
787 mask[i] = 0;
788 }
789 }
790 else {
791 fail[i] = 0;
792 }
793 }
794 break;
795 case GL_GEQUAL:
796 r = ctx->Stencil.Ref & ctx->Stencil.ValueMask;
797 for (i=0;i<n;i++) {
798 if (mask[i]) {
799 GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
800 s = *sptr & ctx->Stencil.ValueMask;
801 if (r >= s) {
802 /* passed */
803 fail[i] = 0;
804 }
805 else {
806 fail[i] = 1;
807 mask[i] = 0;
808 }
809 }
810 else {
811 fail[i] = 0;
812 }
813 }
814 break;
815 case GL_EQUAL:
816 r = ctx->Stencil.Ref & ctx->Stencil.ValueMask;
817 for (i=0;i<n;i++) {
818 if (mask[i]) {
819 GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
820 s = *sptr & ctx->Stencil.ValueMask;
821 if (r == s) {
822 /* passed */
823 fail[i] = 0;
824 }
825 else {
826 fail[i] = 1;
827 mask[i] = 0;
828 }
829 }
830 else {
831 fail[i] = 0;
832 }
833 }
834 break;
835 case GL_NOTEQUAL:
836 r = ctx->Stencil.Ref & ctx->Stencil.ValueMask;
837 for (i=0;i<n;i++) {
838 if (mask[i]) {
839 GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
840 s = *sptr & ctx->Stencil.ValueMask;
841 if (r != s) {
842 /* passed */
843 fail[i] = 0;
844 }
845 else {
846 fail[i] = 1;
847 mask[i] = 0;
848 }
849 }
850 else {
851 fail[i] = 0;
852 }
853 }
854 break;
855 case GL_ALWAYS:
856 /* always pass */
857 for (i=0;i<n;i++) {
858 fail[i] = 0;
859 }
860 break;
861 default:
862 gl_problem(ctx, "Bad stencil func in gl_stencil_pixels");
863 return 0;
864 }
865
866 apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.FailFunc, fail );
867
868 return (allfail) ? 0 : 1;
869}
870
871
872
873
874/*
875 * Apply the combination depth-buffer/stencil operator to a span of pixels.
876 * Input: n - number of pixels in the span
877 * x, y - array of [n] pixels to stencil
878 * z - array [n] of z values
879 * Input: mask - array [n] of flags (1=test this pixel, 0=skip the pixel)
880 * Output: mask - array [n] of flags (1=depth test passed, 0=failed)
881 */
883 GLuint n, const GLint x[], const GLint y[],
884 const GLdepth z[], GLubyte mask[] )
885{
886 if (ctx->Depth.Test==GL_FALSE) {
887 /*
888 * No depth buffer, just apply zpass stencil function to active pixels.
889 */
890 apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.ZPassFunc, mask );
891 }
892 else {
893 /*
894 * Perform depth buffering, then apply zpass or zfail stencil function.
895 */
896 GLubyte passmask[PB_SIZE], failmask[PB_SIZE], oldmask[PB_SIZE];
897 GLuint i;
898
899 /* init pass and fail masks to zero */
900 for (i=0;i<n;i++) {
901 passmask[i] = failmask[i] = 0;
902 oldmask[i] = mask[i];
903 }
904
905 /* apply the depth test */
906 if (ctx->Driver.DepthTestPixels)
907 (*ctx->Driver.DepthTestPixels)( ctx, n, x, y, z, mask );
908
909 /* set the stencil pass/fail flags according to result of depth test */
910 for (i=0;i<n;i++) {
911 if (oldmask[i]) {
912 if (mask[i]) {
913 passmask[i] = 1;
914 }
915 else {
916 failmask[i] = 1;
917 }
918 }
919 }
920
921 /* apply the pass and fail operations */
923 ctx->Stencil.ZFailFunc, failmask );
925 ctx->Stencil.ZPassFunc, passmask );
926 }
927
928}
929
930
931
932/*
933 * Return a span of stencil values from the stencil buffer.
934 * Input: n - how many pixels
935 * x,y - location of first pixel
936 * Output: stencil - the array of stencil values
937 */
940{
941 GLstencil *s;
942
943 if (ctx->Buffer->Stencil) {
944 s = STENCIL_ADDRESS( x, y );
945 MEMCPY( stencil, s, n * sizeof(GLubyte) );
946 }
947}
948
949
950
951/*
952 * Write a span of stencil values to the stencil buffer.
953 * Input: n - how many pixels
954 * x,y - location of first pixel
955 * stencil - the array of stencil values
956 */
958 GLuint n, GLint x, GLint y,
959 const GLubyte stencil[] )
960{
961 GLstencil *s;
962
963 if (ctx->Buffer->Stencil) {
964 s = STENCIL_ADDRESS( x, y );
965 MEMCPY( s, stencil, n * sizeof(GLubyte) );
966 }
967}
968
969
970
971/*
972 * Allocate a new stencil buffer. If there's an old one it will be
973 * deallocated first. The new stencil buffer will be uninitialized.
974 */
976{
977 GLuint buffersize = ctx->Buffer->Width * ctx->Buffer->Height;
978
979 /* deallocate current stencil buffer if present */
980 if (ctx->Buffer->Stencil) {
981 free(ctx->Buffer->Stencil);
982 ctx->Buffer->Stencil = NULL;
983 }
984
985 /* allocate new stencil buffer */
986 ctx->Buffer->Stencil = (GLstencil *) malloc(buffersize * sizeof(GLstencil));
987 if (!ctx->Buffer->Stencil) {
988 /* out of memory */
989 ctx->Stencil.Enabled = GL_FALSE;
990 gl_error( ctx, GL_OUT_OF_MEMORY, "gl_alloc_stencil_buffer" );
991 }
992}
993
994
995
996
997/*
998 * Clear the stencil buffer. If the stencil buffer doesn't exist yet we'll
999 * allocate it now.
1000 */
1002{
1003 if (ctx->Visual->StencilBits==0 || !ctx->Buffer->Stencil) {
1004 /* no stencil buffer */
1005 return;
1006 }
1007
1008 if (ctx->Scissor.Enabled) {
1009 /* clear scissor region only */
1010 GLint y;
1011 GLint width = ctx->Buffer->Xmax - ctx->Buffer->Xmin + 1;
1012 for (y=ctx->Buffer->Ymin; y<=ctx->Buffer->Ymax; y++) {
1013 GLstencil *ptr = STENCIL_ADDRESS( ctx->Buffer->Xmin, y );
1014 MEMSET( ptr, ctx->Stencil.Clear, width * sizeof(GLstencil) );
1015 }
1016 }
1017 else {
1018 /* clear whole stencil buffer */
1019 MEMSET( ctx->Buffer->Stencil, ctx->Stencil.Clear,
1020 ctx->Buffer->Width * ctx->Buffer->Height * sizeof(GLstencil) );
1021 }
1022}
Definition: bufpool.h:45
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define NULL
Definition: types.h:112
#define MAX_WIDTH
Definition: config.h:130
#define STENCIL_BITS
Definition: config.h:152
void gl_problem(const GLcontext *ctx, const char *s)
Definition: context.c:1394
void gl_error(GLcontext *ctx, GLenum error, const char *s)
Definition: context.c:1421
GLubyte GLstencil
Definition: types.h:208
GLint GLdepth
Definition: types.h:218
#define GL_NEVER
Definition: gl.h:293
unsigned char GLubyte
Definition: gl.h:157
#define GL_ALWAYS
Definition: gl.h:300
#define GL_LESS
Definition: gl.h:294
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
#define GL_NOTEQUAL
Definition: gl.h:298
#define GL_DECR
Definition: gl.h:462
#define GL_INVALID_OPERATION
Definition: gl.h:696
unsigned int GLenum
Definition: gl.h:150
GLdouble s
Definition: gl.h:2039
unsigned int GLuint
Definition: gl.h:159
#define GL_ZERO
Definition: gl.h:374
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
#define GL_LEQUAL
Definition: gl.h:296
#define GL_GEQUAL
Definition: gl.h:299
#define GL_GREATER
Definition: gl.h:297
#define GL_INCR
Definition: gl.h:461
#define GL_FALSE
Definition: gl.h:173
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
#define GL_EQUAL
Definition: gl.h:295
int GLint
Definition: gl.h:156
#define GL_OUT_OF_MEMORY
Definition: gl.h:699
GLint GLint GLsizei width
Definition: gl.h:1546
#define GL_REPLACE
Definition: gl.h:460
#define GL_INVALID_ENUM
Definition: gl.h:694
#define GL_INVERT
Definition: gl.h:435
#define GL_KEEP
Definition: gl.h:459
GLenum func
Definition: glext.h:6028
GLdouble n
Definition: glext.h:7729
GLenum GLint GLuint mask
Definition: glext.h:6028
GLint GLfloat GLint stencil
Definition: glext.h:6260
GLdouble GLdouble z
Definition: glext.h:5874
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define MEMSET(DST, VAL, N)
Definition: macros.h:241
#define MEMCPY(DST, SRC, BYTES)
Definition: macros.h:231
#define INSIDE_BEGIN_END(CTX)
Definition: macros.h:135
static PVOID ptr
Definition: dispmode.c:27
#define PB_SIZE
Definition: pb.h:52
GLint gl_stencil_span(GLcontext *ctx, GLuint n, GLint x, GLint y, GLubyte mask[])
Definition: stencil.c:339
void gl_clear_stencil_buffer(GLcontext *ctx)
Definition: stencil.c:1001
void gl_depth_stencil_pixels(GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], const GLdepth z[], GLubyte mask[])
Definition: stencil.c:882
void gl_StencilOp(GLcontext *ctx, GLenum fail, GLenum zfail, GLenum zpass)
Definition: stencil.c:127
#define STENCIL_ADDRESS(X, Y)
Definition: stencil.c:70
void gl_alloc_stencil_buffer(GLcontext *ctx)
Definition: stencil.c:975
void gl_write_stencil_span(GLcontext *ctx, GLuint n, GLint x, GLint y, const GLubyte stencil[])
Definition: stencil.c:957
void gl_StencilFunc(GLcontext *ctx, GLenum func, GLint ref, GLuint mask)
Definition: stencil.c:84
void gl_read_stencil_span(GLcontext *ctx, GLuint n, GLint x, GLint y, GLubyte stencil[])
Definition: stencil.c:938
GLint gl_stencil_pixels(GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], GLubyte mask[])
Definition: stencil.c:702
void gl_StencilMask(GLcontext *ctx, GLuint mask)
Definition: stencil.c:116
void gl_ClearStencil(GLcontext *ctx, GLint s)
Definition: stencil.c:73
static void apply_stencil_op_to_span(GLcontext *ctx, GLuint n, GLint x, GLint y, GLenum oper, GLubyte mask[])
Definition: stencil.c:207
void gl_depth_stencil_span(GLcontext *ctx, GLuint n, GLint x, GLint y, const GLdepth z[], GLubyte mask[])
Definition: stencil.c:514
static void apply_stencil_op_to_pixels(GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], GLenum oper, GLubyte mask[])
Definition: stencil.c:570
Definition: send.c:48
#define CLAMP(f, min, max)
Definition: tif_color.c:177