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