Merge commit 'origin/gallium-0.1' into gallium-0.2
[mesa.git] / src / mesa / swrast / s_stencil.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.1
4 *
5 * Copyright (C) 1999-2007 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 "main/glheader.h"
27 #include "main/context.h"
28 #include "main/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 * Compute the zpass/zfail masks by comparing the pre- and post-depth test
397 * masks.
398 */
399 static INLINE void
400 compute_pass_fail_masks(GLuint n, const GLubyte origMask[],
401 const GLubyte newMask[],
402 GLubyte passMask[], GLubyte failMask[])
403 {
404 GLuint i;
405 for (i = 0; i < n; i++) {
406 ASSERT(newMask[i] == 0 || newMask[i] == 1);
407 passMask[i] = origMask[i] & newMask[i];
408 failMask[i] = origMask[i] & (newMask[i] ^ 1);
409 }
410 }
411
412
413 /**
414 * Apply stencil and depth testing to the span of pixels.
415 * Both software and hardware stencil buffers are acceptable.
416 * Input: n - number of pixels in the span
417 * x, y - location of leftmost pixel in span
418 * z - array [n] of z values
419 * mask - array [n] of flags (1=test this pixel, 0=skip the pixel)
420 * Output: mask - array [n] of flags (1=stencil and depth test passed)
421 * Return: GL_FALSE - all fragments failed the testing
422 * GL_TRUE - one or more fragments passed the testing
423 *
424 */
425 static GLboolean
426 stencil_and_ztest_span(GLcontext *ctx, SWspan *span, GLuint face)
427 {
428 struct gl_framebuffer *fb = ctx->DrawBuffer;
429 struct gl_renderbuffer *rb = fb->_StencilBuffer;
430 GLstencil stencilRow[MAX_WIDTH];
431 GLstencil *stencil;
432 const GLuint n = span->end;
433 const GLint x = span->x;
434 const GLint y = span->y;
435 GLubyte *mask = span->array->mask;
436
437 ASSERT((span->arrayMask & SPAN_XY) == 0);
438 ASSERT(ctx->Stencil.Enabled);
439 ASSERT(n <= MAX_WIDTH);
440 #ifdef DEBUG
441 if (ctx->Depth.Test) {
442 ASSERT(span->arrayMask & SPAN_Z);
443 }
444 #endif
445
446 stencil = (GLstencil *) rb->GetPointer(ctx, rb, x, y);
447 if (!stencil) {
448 rb->GetRow(ctx, rb, n, x, y, stencilRow);
449 stencil = stencilRow;
450 }
451
452 /*
453 * Apply the stencil test to the fragments.
454 * failMask[i] is 1 if the stencil test failed.
455 */
456 if (do_stencil_test( ctx, face, n, stencil, mask ) == GL_FALSE) {
457 /* all fragments failed the stencil test, we're done. */
458 span->writeAll = GL_FALSE;
459 if (!rb->GetPointer(ctx, rb, 0, 0)) {
460 /* put updated stencil values into buffer */
461 rb->PutRow(ctx, rb, n, x, y, stencil, NULL);
462 }
463 return GL_FALSE;
464 }
465
466 /*
467 * Some fragments passed the stencil test, apply depth test to them
468 * and apply Zpass and Zfail stencil ops.
469 */
470 if (ctx->Depth.Test == GL_FALSE) {
471 /*
472 * No depth buffer, just apply zpass stencil function to active pixels.
473 */
474 apply_stencil_op( ctx, ctx->Stencil.ZPassFunc[face], face, n, stencil, mask );
475 }
476 else {
477 /*
478 * Perform depth buffering, then apply zpass or zfail stencil function.
479 */
480 GLubyte passMask[MAX_WIDTH], failMask[MAX_WIDTH], origMask[MAX_WIDTH];
481
482 /* save the current mask bits */
483 _mesa_memcpy(origMask, mask, n * sizeof(GLubyte));
484
485 /* apply the depth test */
486 _swrast_depth_test_span(ctx, span);
487
488 compute_pass_fail_masks(n, origMask, mask, passMask, failMask);
489
490 /* apply the pass and fail operations */
491 if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
492 apply_stencil_op( ctx, ctx->Stencil.ZFailFunc[face], face,
493 n, stencil, failMask );
494 }
495 if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
496 apply_stencil_op( ctx, ctx->Stencil.ZPassFunc[face], face,
497 n, stencil, passMask );
498 }
499 }
500
501 /*
502 * Write updated stencil values back into hardware stencil buffer.
503 */
504 if (!rb->GetPointer(ctx, rb, 0, 0)) {
505 rb->PutRow(ctx, rb, n, x, y, stencil, NULL);
506 }
507
508 span->writeAll = GL_FALSE;
509
510 return GL_TRUE; /* one or more fragments passed both tests */
511 }
512
513
514
515 /*
516 * Return the address of a stencil buffer value given the window coords:
517 */
518 #define STENCIL_ADDRESS(X, Y) (stencilStart + (Y) * stride + (X))
519
520
521
522 /**
523 * Apply the given stencil operator for each pixel in the array whose
524 * mask flag is set.
525 * \note This is for software stencil buffers only.
526 * Input: n - number of pixels in the span
527 * x, y - array of [n] pixels
528 * operator - the stencil buffer operator
529 * mask - array [n] of flag: 1=apply operator, 0=don't apply operator
530 */
531 static void
532 apply_stencil_op_to_pixels( GLcontext *ctx,
533 GLuint n, const GLint x[], const GLint y[],
534 GLenum oper, GLuint face, const GLubyte mask[] )
535 {
536 struct gl_framebuffer *fb = ctx->DrawBuffer;
537 struct gl_renderbuffer *rb = fb->_StencilBuffer;
538 const GLstencil stencilMax = (1 << fb->Visual.stencilBits) - 1;
539 const GLstencil ref = ctx->Stencil.Ref[face];
540 const GLstencil wrtmask = ctx->Stencil.WriteMask[face];
541 const GLstencil invmask = (GLstencil) (~wrtmask);
542 GLuint i;
543 GLstencil *stencilStart = (GLubyte *) rb->Data;
544 const GLuint stride = rb->Width;
545
546 ASSERT(rb->GetPointer(ctx, rb, 0, 0));
547 ASSERT(sizeof(GLstencil) == 1);
548
549 switch (oper) {
550 case GL_KEEP:
551 /* do nothing */
552 break;
553 case GL_ZERO:
554 if (invmask==0) {
555 for (i=0;i<n;i++) {
556 if (mask[i]) {
557 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
558 *sptr = 0;
559 }
560 }
561 }
562 else {
563 for (i=0;i<n;i++) {
564 if (mask[i]) {
565 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
566 *sptr = (GLstencil) (invmask & *sptr);
567 }
568 }
569 }
570 break;
571 case GL_REPLACE:
572 if (invmask==0) {
573 for (i=0;i<n;i++) {
574 if (mask[i]) {
575 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
576 *sptr = ref;
577 }
578 }
579 }
580 else {
581 for (i=0;i<n;i++) {
582 if (mask[i]) {
583 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
584 *sptr = (GLstencil) ((invmask & *sptr ) | (wrtmask & ref));
585 }
586 }
587 }
588 break;
589 case GL_INCR:
590 if (invmask==0) {
591 for (i=0;i<n;i++) {
592 if (mask[i]) {
593 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
594 if (*sptr < stencilMax) {
595 *sptr = (GLstencil) (*sptr + 1);
596 }
597 }
598 }
599 }
600 else {
601 for (i=0;i<n;i++) {
602 if (mask[i]) {
603 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
604 if (*sptr < stencilMax) {
605 *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr+1)));
606 }
607 }
608 }
609 }
610 break;
611 case GL_DECR:
612 if (invmask==0) {
613 for (i=0;i<n;i++) {
614 if (mask[i]) {
615 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
616 if (*sptr>0) {
617 *sptr = (GLstencil) (*sptr - 1);
618 }
619 }
620 }
621 }
622 else {
623 for (i=0;i<n;i++) {
624 if (mask[i]) {
625 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
626 if (*sptr>0) {
627 *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr-1)));
628 }
629 }
630 }
631 }
632 break;
633 case GL_INCR_WRAP_EXT:
634 if (invmask==0) {
635 for (i=0;i<n;i++) {
636 if (mask[i]) {
637 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
638 *sptr = (GLstencil) (*sptr + 1);
639 }
640 }
641 }
642 else {
643 for (i=0;i<n;i++) {
644 if (mask[i]) {
645 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
646 *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr+1)));
647 }
648 }
649 }
650 break;
651 case GL_DECR_WRAP_EXT:
652 if (invmask==0) {
653 for (i=0;i<n;i++) {
654 if (mask[i]) {
655 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
656 *sptr = (GLstencil) (*sptr - 1);
657 }
658 }
659 }
660 else {
661 for (i=0;i<n;i++) {
662 if (mask[i]) {
663 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
664 *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr-1)));
665 }
666 }
667 }
668 break;
669 case GL_INVERT:
670 if (invmask==0) {
671 for (i=0;i<n;i++) {
672 if (mask[i]) {
673 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
674 *sptr = (GLstencil) (~*sptr);
675 }
676 }
677 }
678 else {
679 for (i=0;i<n;i++) {
680 if (mask[i]) {
681 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
682 *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & ~*sptr));
683 }
684 }
685 }
686 break;
687 default:
688 _mesa_problem(ctx, "Bad stencilop in apply_stencil_op_to_pixels");
689 }
690 }
691
692
693
694 /**
695 * Apply stencil test to an array of pixels before depth buffering.
696 *
697 * \note Used for software stencil buffer only.
698 * Input: n - number of pixels in the span
699 * x, y - array of [n] pixels to stencil
700 * mask - array [n] of flag: 0=skip the pixel, 1=stencil the pixel
701 * Output: mask - pixels which fail the stencil test will have their
702 * mask flag set to 0.
703 * \return GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed.
704 */
705 static GLboolean
706 stencil_test_pixels( GLcontext *ctx, GLuint face, GLuint n,
707 const GLint x[], const GLint y[], GLubyte mask[] )
708 {
709 const struct gl_framebuffer *fb = ctx->DrawBuffer;
710 struct gl_renderbuffer *rb = fb->_StencilBuffer;
711 GLubyte fail[MAX_WIDTH];
712 GLstencil r, s;
713 GLuint i;
714 GLboolean allfail = GL_FALSE;
715 const GLuint valueMask = ctx->Stencil.ValueMask[face];
716 const GLstencil *stencilStart = (GLstencil *) rb->Data;
717 const GLuint stride = rb->Width;
718
719 ASSERT(rb->GetPointer(ctx, rb, 0, 0));
720 ASSERT(sizeof(GLstencil) == 1);
721
722 /*
723 * Perform stencil test. The results of this operation are stored
724 * in the fail[] array:
725 * IF fail[i] is non-zero THEN
726 * the stencil fail operator is to be applied
727 * ELSE
728 * the stencil fail operator is not to be applied
729 * ENDIF
730 */
731
732 switch (ctx->Stencil.Function[face]) {
733 case GL_NEVER:
734 /* always fail */
735 for (i=0;i<n;i++) {
736 if (mask[i]) {
737 mask[i] = 0;
738 fail[i] = 1;
739 }
740 else {
741 fail[i] = 0;
742 }
743 }
744 allfail = GL_TRUE;
745 break;
746 case GL_LESS:
747 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
748 for (i=0;i<n;i++) {
749 if (mask[i]) {
750 const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
751 s = (GLstencil) (*sptr & valueMask);
752 if (r < s) {
753 /* passed */
754 fail[i] = 0;
755 }
756 else {
757 fail[i] = 1;
758 mask[i] = 0;
759 }
760 }
761 else {
762 fail[i] = 0;
763 }
764 }
765 break;
766 case GL_LEQUAL:
767 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
768 for (i=0;i<n;i++) {
769 if (mask[i]) {
770 const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
771 s = (GLstencil) (*sptr & valueMask);
772 if (r <= s) {
773 /* pass */
774 fail[i] = 0;
775 }
776 else {
777 fail[i] = 1;
778 mask[i] = 0;
779 }
780 }
781 else {
782 fail[i] = 0;
783 }
784 }
785 break;
786 case GL_GREATER:
787 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
788 for (i=0;i<n;i++) {
789 if (mask[i]) {
790 const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
791 s = (GLstencil) (*sptr & valueMask);
792 if (r > s) {
793 /* passed */
794 fail[i] = 0;
795 }
796 else {
797 fail[i] = 1;
798 mask[i] = 0;
799 }
800 }
801 else {
802 fail[i] = 0;
803 }
804 }
805 break;
806 case GL_GEQUAL:
807 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
808 for (i=0;i<n;i++) {
809 if (mask[i]) {
810 const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
811 s = (GLstencil) (*sptr & valueMask);
812 if (r >= s) {
813 /* passed */
814 fail[i] = 0;
815 }
816 else {
817 fail[i] = 1;
818 mask[i] = 0;
819 }
820 }
821 else {
822 fail[i] = 0;
823 }
824 }
825 break;
826 case GL_EQUAL:
827 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
828 for (i=0;i<n;i++) {
829 if (mask[i]) {
830 const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
831 s = (GLstencil) (*sptr & valueMask);
832 if (r == s) {
833 /* passed */
834 fail[i] = 0;
835 }
836 else {
837 fail[i] = 1;
838 mask[i] = 0;
839 }
840 }
841 else {
842 fail[i] = 0;
843 }
844 }
845 break;
846 case GL_NOTEQUAL:
847 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
848 for (i=0;i<n;i++) {
849 if (mask[i]) {
850 const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
851 s = (GLstencil) (*sptr & valueMask);
852 if (r != s) {
853 /* passed */
854 fail[i] = 0;
855 }
856 else {
857 fail[i] = 1;
858 mask[i] = 0;
859 }
860 }
861 else {
862 fail[i] = 0;
863 }
864 }
865 break;
866 case GL_ALWAYS:
867 /* always pass */
868 for (i=0;i<n;i++) {
869 fail[i] = 0;
870 }
871 break;
872 default:
873 _mesa_problem(ctx, "Bad stencil func in gl_stencil_pixels");
874 return 0;
875 }
876
877 if (ctx->Stencil.FailFunc[face] != GL_KEEP) {
878 apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.FailFunc[face],
879 face, fail );
880 }
881
882 return !allfail;
883 }
884
885
886
887
888 /**
889 * Apply stencil and depth testing to an array of pixels.
890 * This is used both for software and hardware stencil buffers.
891 *
892 * The comments in this function are a bit sparse but the code is
893 * almost identical to stencil_and_ztest_span(), which is well
894 * commented.
895 *
896 * Input: n - number of pixels in the array
897 * x, y - array of [n] pixel positions
898 * z - array [n] of z values
899 * mask - array [n] of flags (1=test this pixel, 0=skip the pixel)
900 * Output: mask - array [n] of flags (1=stencil and depth test passed)
901 * Return: GL_FALSE - all fragments failed the testing
902 * GL_TRUE - one or more fragments passed the testing
903 */
904 static GLboolean
905 stencil_and_ztest_pixels( GLcontext *ctx, SWspan *span, GLuint face )
906 {
907 GLubyte passMask[MAX_WIDTH], failMask[MAX_WIDTH], origMask[MAX_WIDTH];
908 struct gl_framebuffer *fb = ctx->DrawBuffer;
909 struct gl_renderbuffer *rb = fb->_StencilBuffer;
910 const GLuint n = span->end;
911 const GLint *x = span->array->x;
912 const GLint *y = span->array->y;
913 GLubyte *mask = span->array->mask;
914
915 ASSERT(span->arrayMask & SPAN_XY);
916 ASSERT(ctx->Stencil.Enabled);
917 ASSERT(n <= MAX_WIDTH);
918
919 if (!rb->GetPointer(ctx, rb, 0, 0)) {
920 /* No direct access */
921 GLstencil stencil[MAX_WIDTH];
922
923 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
924 _swrast_get_values(ctx, rb, n, x, y, stencil, sizeof(GLubyte));
925
926 _mesa_memcpy(origMask, mask, n * sizeof(GLubyte));
927
928 (void) do_stencil_test(ctx, face, n, stencil, mask);
929
930 if (ctx->Depth.Test == GL_FALSE) {
931 apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face,
932 n, stencil, mask);
933 }
934 else {
935 GLubyte tmpMask[MAX_WIDTH];
936 _mesa_memcpy(tmpMask, mask, n * sizeof(GLubyte));
937
938 _swrast_depth_test_span(ctx, span);
939
940 compute_pass_fail_masks(n, tmpMask, mask, passMask, failMask);
941
942 if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
943 apply_stencil_op(ctx, ctx->Stencil.ZFailFunc[face], face,
944 n, stencil, failMask);
945 }
946 if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
947 apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face,
948 n, stencil, passMask);
949 }
950 }
951
952 /* Write updated stencil values into hardware stencil buffer */
953 rb->PutValues(ctx, rb, n, x, y, stencil, origMask);
954
955 return GL_TRUE;
956 }
957 else {
958 /* Direct access to stencil buffer */
959
960 if (stencil_test_pixels(ctx, face, n, x, y, mask) == GL_FALSE) {
961 /* all fragments failed the stencil test, we're done. */
962 return GL_FALSE;
963 }
964
965 if (ctx->Depth.Test==GL_FALSE) {
966 apply_stencil_op_to_pixels(ctx, n, x, y,
967 ctx->Stencil.ZPassFunc[face], face, mask);
968 }
969 else {
970 _mesa_memcpy(origMask, mask, n * sizeof(GLubyte));
971
972 _swrast_depth_test_span(ctx, span);
973
974 compute_pass_fail_masks(n, origMask, mask, passMask, failMask);
975
976 if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
977 apply_stencil_op_to_pixels(ctx, n, x, y,
978 ctx->Stencil.ZFailFunc[face],
979 face, failMask);
980 }
981 if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
982 apply_stencil_op_to_pixels(ctx, n, x, y,
983 ctx->Stencil.ZPassFunc[face],
984 face, passMask);
985 }
986 }
987
988 return GL_TRUE; /* one or more fragments passed both tests */
989 }
990 }
991
992
993 /**
994 * /return GL_TRUE = one or more fragments passed,
995 * GL_FALSE = all fragments failed.
996 */
997 GLboolean
998 _swrast_stencil_and_ztest_span(GLcontext *ctx, SWspan *span)
999 {
1000 if (span->arrayMask & SPAN_XY)
1001 return stencil_and_ztest_pixels(ctx, span, span->facing);
1002 else
1003 return stencil_and_ztest_span(ctx, span, span->facing);
1004 }
1005
1006
1007 #if 0
1008 GLuint
1009 clip_span(GLuint bufferWidth, GLuint bufferHeight,
1010 GLint x, GLint y, GLuint *count)
1011 {
1012 GLuint n = *count;
1013 GLuint skipPixels = 0;
1014
1015 if (y < 0 || y >= bufferHeight || x + n <= 0 || x >= bufferWidth) {
1016 /* totally out of bounds */
1017 n = 0;
1018 }
1019 else {
1020 /* left clip */
1021 if (x < 0) {
1022 skipPixels = -x;
1023 x = 0;
1024 n -= skipPixels;
1025 }
1026 /* right clip */
1027 if (x + n > bufferWidth) {
1028 GLint dx = x + n - bufferWidth;
1029 n -= dx;
1030 }
1031 }
1032
1033 *count = n;
1034
1035 return skipPixels;
1036 }
1037 #endif
1038
1039
1040 /**
1041 * Return a span of stencil values from the stencil buffer.
1042 * Used for glRead/CopyPixels
1043 * Input: n - how many pixels
1044 * x,y - location of first pixel
1045 * Output: stencil - the array of stencil values
1046 */
1047 void
1048 _swrast_read_stencil_span(GLcontext *ctx, struct gl_renderbuffer *rb,
1049 GLint n, GLint x, GLint y, GLstencil stencil[])
1050 {
1051 if (y < 0 || y >= (GLint) rb->Height ||
1052 x + n <= 0 || x >= (GLint) rb->Width) {
1053 /* span is completely outside framebuffer */
1054 return; /* undefined values OK */
1055 }
1056
1057 if (x < 0) {
1058 GLint dx = -x;
1059 x = 0;
1060 n -= dx;
1061 stencil += dx;
1062 }
1063 if (x + n > (GLint) rb->Width) {
1064 GLint dx = x + n - rb->Width;
1065 n -= dx;
1066 }
1067 if (n <= 0) {
1068 return;
1069 }
1070
1071 rb->GetRow(ctx, rb, n, x, y, stencil);
1072 }
1073
1074
1075
1076 /**
1077 * Write a span of stencil values to the stencil buffer. This function
1078 * applies the stencil write mask when needed.
1079 * Used for glDraw/CopyPixels
1080 * Input: n - how many pixels
1081 * x, y - location of first pixel
1082 * stencil - the array of stencil values
1083 */
1084 void
1085 _swrast_write_stencil_span(GLcontext *ctx, GLint n, GLint x, GLint y,
1086 const GLstencil stencil[] )
1087 {
1088 struct gl_framebuffer *fb = ctx->DrawBuffer;
1089 struct gl_renderbuffer *rb = fb->_StencilBuffer;
1090 const GLuint stencilMax = (1 << fb->Visual.stencilBits) - 1;
1091 const GLuint stencilMask = ctx->Stencil.WriteMask[0];
1092
1093 if (y < 0 || y >= (GLint) rb->Height ||
1094 x + n <= 0 || x >= (GLint) rb->Width) {
1095 /* span is completely outside framebuffer */
1096 return; /* undefined values OK */
1097 }
1098 if (x < 0) {
1099 GLint dx = -x;
1100 x = 0;
1101 n -= dx;
1102 stencil += dx;
1103 }
1104 if (x + n > (GLint) rb->Width) {
1105 GLint dx = x + n - rb->Width;
1106 n -= dx;
1107 }
1108 if (n <= 0) {
1109 return;
1110 }
1111
1112 if ((stencilMask & stencilMax) != stencilMax) {
1113 /* need to apply writemask */
1114 GLstencil destVals[MAX_WIDTH], newVals[MAX_WIDTH];
1115 GLint i;
1116 rb->GetRow(ctx, rb, n, x, y, destVals);
1117 for (i = 0; i < n; i++) {
1118 newVals[i]
1119 = (stencil[i] & stencilMask) | (destVals[i] & ~stencilMask);
1120 }
1121 rb->PutRow(ctx, rb, n, x, y, newVals, NULL);
1122 }
1123 else {
1124 rb->PutRow(ctx, rb, n, x, y, stencil, NULL);
1125 }
1126 }
1127
1128
1129
1130 /**
1131 * Clear the stencil buffer.
1132 */
1133 void
1134 _swrast_clear_stencil_buffer( GLcontext *ctx, struct gl_renderbuffer *rb )
1135 {
1136 const GLubyte stencilBits = ctx->DrawBuffer->Visual.stencilBits;
1137 const GLuint mask = ctx->Stencil.WriteMask[0];
1138 const GLuint invMask = ~mask;
1139 const GLuint clearVal = (ctx->Stencil.Clear & mask);
1140 const GLuint stencilMax = (1 << stencilBits) - 1;
1141 GLint x, y, width, height;
1142
1143 if (!rb || mask == 0)
1144 return;
1145
1146 ASSERT(rb->DataType == GL_UNSIGNED_BYTE ||
1147 rb->DataType == GL_UNSIGNED_SHORT);
1148
1149 ASSERT(rb->_BaseFormat == GL_STENCIL_INDEX);
1150
1151 /* compute region to clear */
1152 x = ctx->DrawBuffer->_Xmin;
1153 y = ctx->DrawBuffer->_Ymin;
1154 width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
1155 height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
1156
1157 if (rb->GetPointer(ctx, rb, 0, 0)) {
1158 /* Direct buffer access */
1159 if ((mask & stencilMax) != stencilMax) {
1160 /* need to mask the clear */
1161 if (rb->DataType == GL_UNSIGNED_BYTE) {
1162 GLint i, j;
1163 for (i = 0; i < height; i++) {
1164 GLubyte *stencil = (GLubyte*) rb->GetPointer(ctx, rb, x, y + i);
1165 for (j = 0; j < width; j++) {
1166 stencil[j] = (stencil[j] & invMask) | clearVal;
1167 }
1168 }
1169 }
1170 else {
1171 GLint i, j;
1172 for (i = 0; i < height; i++) {
1173 GLushort *stencil = (GLushort*) rb->GetPointer(ctx, rb, x, y + i);
1174 for (j = 0; j < width; j++) {
1175 stencil[j] = (stencil[j] & invMask) | clearVal;
1176 }
1177 }
1178 }
1179 }
1180 else {
1181 /* no bit masking */
1182 if (width == (GLint) rb->Width && rb->DataType == GL_UNSIGNED_BYTE) {
1183 /* optimized case */
1184 /* Note: bottom-to-top raster assumed! */
1185 GLubyte *stencil = (GLubyte *) rb->GetPointer(ctx, rb, x, y);
1186 GLuint len = width * height * sizeof(GLubyte);
1187 _mesa_memset(stencil, clearVal, len);
1188 }
1189 else {
1190 /* general case */
1191 GLint i;
1192 for (i = 0; i < height; i++) {
1193 GLvoid *stencil = rb->GetPointer(ctx, rb, x, y + i);
1194 if (rb->DataType == GL_UNSIGNED_BYTE) {
1195 _mesa_memset(stencil, clearVal, width);
1196 }
1197 else {
1198 _mesa_memset16((short unsigned int*) stencil, clearVal, width);
1199 }
1200 }
1201 }
1202 }
1203 }
1204 else {
1205 /* no direct access */
1206 if ((mask & stencilMax) != stencilMax) {
1207 /* need to mask the clear */
1208 if (rb->DataType == GL_UNSIGNED_BYTE) {
1209 GLint i, j;
1210 for (i = 0; i < height; i++) {
1211 GLubyte stencil[MAX_WIDTH];
1212 rb->GetRow(ctx, rb, width, x, y + i, stencil);
1213 for (j = 0; j < width; j++) {
1214 stencil[j] = (stencil[j] & invMask) | clearVal;
1215 }
1216 rb->PutRow(ctx, rb, width, x, y + i, stencil, NULL);
1217 }
1218 }
1219 else {
1220 GLint i, j;
1221 for (i = 0; i < height; i++) {
1222 GLushort stencil[MAX_WIDTH];
1223 rb->GetRow(ctx, rb, width, x, y + i, stencil);
1224 for (j = 0; j < width; j++) {
1225 stencil[j] = (stencil[j] & invMask) | clearVal;
1226 }
1227 rb->PutRow(ctx, rb, width, x, y + i, stencil, NULL);
1228 }
1229 }
1230 }
1231 else {
1232 /* no bit masking */
1233 const GLubyte clear8 = (GLubyte) clearVal;
1234 const GLushort clear16 = (GLushort) clearVal;
1235 const void *clear;
1236 GLint i;
1237 if (rb->DataType == GL_UNSIGNED_BYTE) {
1238 clear = &clear8;
1239 }
1240 else {
1241 clear = &clear16;
1242 }
1243 for (i = 0; i < height; i++) {
1244 rb->PutMonoRow(ctx, rb, width, x, y + i, clear, NULL);
1245 }
1246 }
1247 }
1248 }