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