fa5093a34072e53814132f58e3d195d469c6dbf2
[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 struct gl_context *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( struct gl_context *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 const GLuint valueMask = ctx->Stencil.ValueMask[face];
235 const GLstencil r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
236 GLstencil s;
237
238 ASSERT(n <= MAX_WIDTH);
239
240 /*
241 * Perform stencil test. The results of this operation are stored
242 * in the fail[] array:
243 * IF fail[i] is non-zero THEN
244 * the stencil fail operator is to be applied
245 * ELSE
246 * the stencil fail operator is not to be applied
247 * ENDIF
248 */
249 switch (ctx->Stencil.Function[face]) {
250 case GL_NEVER:
251 /* never pass; always fail */
252 for (i=0;i<n;i++) {
253 if (mask[i]) {
254 mask[i] = 0;
255 fail[i] = 1;
256 }
257 else {
258 fail[i] = 0;
259 }
260 }
261 allfail = GL_TRUE;
262 break;
263 case GL_LESS:
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 for (i=0;i<n;i++) {
283 if (mask[i]) {
284 s = (GLstencil) (stencil[i] & valueMask);
285 if (r <= s) {
286 /* pass */
287 fail[i] = 0;
288 }
289 else {
290 fail[i] = 1;
291 mask[i] = 0;
292 }
293 }
294 else {
295 fail[i] = 0;
296 }
297 }
298 break;
299 case GL_GREATER:
300 for (i=0;i<n;i++) {
301 if (mask[i]) {
302 s = (GLstencil) (stencil[i] & valueMask);
303 if (r > s) {
304 /* passed */
305 fail[i] = 0;
306 }
307 else {
308 fail[i] = 1;
309 mask[i] = 0;
310 }
311 }
312 else {
313 fail[i] = 0;
314 }
315 }
316 break;
317 case GL_GEQUAL:
318 for (i=0;i<n;i++) {
319 if (mask[i]) {
320 s = (GLstencil) (stencil[i] & valueMask);
321 if (r >= s) {
322 /* passed */
323 fail[i] = 0;
324 }
325 else {
326 fail[i] = 1;
327 mask[i] = 0;
328 }
329 }
330 else {
331 fail[i] = 0;
332 }
333 }
334 break;
335 case GL_EQUAL:
336 for (i=0;i<n;i++) {
337 if (mask[i]) {
338 s = (GLstencil) (stencil[i] & valueMask);
339 if (r == s) {
340 /* passed */
341 fail[i] = 0;
342 }
343 else {
344 fail[i] = 1;
345 mask[i] = 0;
346 }
347 }
348 else {
349 fail[i] = 0;
350 }
351 }
352 break;
353 case GL_NOTEQUAL:
354 for (i=0;i<n;i++) {
355 if (mask[i]) {
356 s = (GLstencil) (stencil[i] & valueMask);
357 if (r != s) {
358 /* passed */
359 fail[i] = 0;
360 }
361 else {
362 fail[i] = 1;
363 mask[i] = 0;
364 }
365 }
366 else {
367 fail[i] = 0;
368 }
369 }
370 break;
371 case GL_ALWAYS:
372 /* always pass */
373 for (i=0;i<n;i++) {
374 fail[i] = 0;
375 }
376 break;
377 default:
378 _mesa_problem(ctx, "Bad stencil func in gl_stencil_span");
379 return 0;
380 }
381
382 if (ctx->Stencil.FailFunc[face] != GL_KEEP) {
383 apply_stencil_op( ctx, ctx->Stencil.FailFunc[face], face, n, stencil, fail );
384 }
385
386 return !allfail;
387 }
388
389
390 /**
391 * Compute the zpass/zfail masks by comparing the pre- and post-depth test
392 * masks.
393 */
394 static INLINE void
395 compute_pass_fail_masks(GLuint n, const GLubyte origMask[],
396 const GLubyte newMask[],
397 GLubyte passMask[], GLubyte failMask[])
398 {
399 GLuint i;
400 for (i = 0; i < n; i++) {
401 ASSERT(newMask[i] == 0 || newMask[i] == 1);
402 passMask[i] = origMask[i] & newMask[i];
403 failMask[i] = origMask[i] & (newMask[i] ^ 1);
404 }
405 }
406
407
408 /**
409 * Apply stencil and depth testing to the span of pixels.
410 * Both software and hardware stencil buffers are acceptable.
411 * Input: n - number of pixels in the span
412 * x, y - location of leftmost pixel in span
413 * z - array [n] of z values
414 * mask - array [n] of flags (1=test this pixel, 0=skip the pixel)
415 * Output: mask - array [n] of flags (1=stencil and depth test passed)
416 * Return: GL_FALSE - all fragments failed the testing
417 * GL_TRUE - one or more fragments passed the testing
418 *
419 */
420 static GLboolean
421 stencil_and_ztest_span(struct gl_context *ctx, SWspan *span, GLuint face)
422 {
423 struct gl_framebuffer *fb = ctx->DrawBuffer;
424 struct gl_renderbuffer *rb = fb->_StencilBuffer;
425 GLstencil stencilRow[MAX_WIDTH];
426 GLstencil *stencil;
427 const GLuint n = span->end;
428 const GLint x = span->x;
429 const GLint y = span->y;
430 GLubyte *mask = span->array->mask;
431
432 ASSERT((span->arrayMask & SPAN_XY) == 0);
433 ASSERT(ctx->Stencil.Enabled);
434 ASSERT(n <= MAX_WIDTH);
435 #ifdef DEBUG
436 if (ctx->Depth.Test) {
437 ASSERT(span->arrayMask & SPAN_Z);
438 }
439 #endif
440
441 stencil = (GLstencil *) rb->GetPointer(ctx, rb, x, y);
442 if (!stencil) {
443 rb->GetRow(ctx, rb, n, x, y, stencilRow);
444 stencil = stencilRow;
445 }
446
447 /*
448 * Apply the stencil test to the fragments.
449 * failMask[i] is 1 if the stencil test failed.
450 */
451 if (do_stencil_test( ctx, face, n, stencil, mask ) == GL_FALSE) {
452 /* all fragments failed the stencil test, we're done. */
453 span->writeAll = GL_FALSE;
454 if (!rb->GetPointer(ctx, rb, 0, 0)) {
455 /* put updated stencil values into buffer */
456 rb->PutRow(ctx, rb, n, x, y, stencil, NULL);
457 }
458 return GL_FALSE;
459 }
460
461 /*
462 * Some fragments passed the stencil test, apply depth test to them
463 * and apply Zpass and Zfail stencil ops.
464 */
465 if (ctx->Depth.Test == GL_FALSE ||
466 ctx->DrawBuffer->_DepthBuffer == NULL) {
467 /*
468 * No depth buffer, just apply zpass stencil function to active pixels.
469 */
470 apply_stencil_op( ctx, ctx->Stencil.ZPassFunc[face], face, n, stencil, mask );
471 }
472 else {
473 /*
474 * Perform depth buffering, then apply zpass or zfail stencil function.
475 */
476 GLubyte passMask[MAX_WIDTH], failMask[MAX_WIDTH], origMask[MAX_WIDTH];
477
478 /* save the current mask bits */
479 memcpy(origMask, mask, n * sizeof(GLubyte));
480
481 /* apply the depth test */
482 _swrast_depth_test_span(ctx, span);
483
484 compute_pass_fail_masks(n, origMask, mask, passMask, failMask);
485
486 /* apply the pass and fail operations */
487 if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
488 apply_stencil_op( ctx, ctx->Stencil.ZFailFunc[face], face,
489 n, stencil, failMask );
490 }
491 if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
492 apply_stencil_op( ctx, ctx->Stencil.ZPassFunc[face], face,
493 n, stencil, passMask );
494 }
495 }
496
497 /*
498 * Write updated stencil values back into hardware stencil buffer.
499 */
500 if (!rb->GetPointer(ctx, rb, 0, 0)) {
501 rb->PutRow(ctx, rb, n, x, y, stencil, NULL);
502 }
503
504 span->writeAll = GL_FALSE;
505
506 return GL_TRUE; /* one or more fragments passed both tests */
507 }
508
509
510
511 /*
512 * Return the address of a stencil buffer value given the window coords:
513 */
514 #define STENCIL_ADDRESS(X, Y) (stencilStart + (Y) * stride + (X))
515
516
517
518 /**
519 * Apply the given stencil operator for each pixel in the array whose
520 * mask flag is set.
521 * \note This is for software stencil buffers only.
522 * Input: n - number of pixels in the span
523 * x, y - array of [n] pixels
524 * operator - the stencil buffer operator
525 * mask - array [n] of flag: 1=apply operator, 0=don't apply operator
526 */
527 static void
528 apply_stencil_op_to_pixels( struct gl_context *ctx,
529 GLuint n, const GLint x[], const GLint y[],
530 GLenum oper, GLuint face, const GLubyte mask[] )
531 {
532 struct gl_framebuffer *fb = ctx->DrawBuffer;
533 struct gl_renderbuffer *rb = fb->_StencilBuffer;
534 const GLstencil stencilMax = (1 << fb->Visual.stencilBits) - 1;
535 const GLstencil ref = ctx->Stencil.Ref[face];
536 const GLstencil wrtmask = ctx->Stencil.WriteMask[face];
537 const GLstencil invmask = (GLstencil) (~wrtmask);
538 GLuint i;
539 GLstencil *stencilStart = (GLubyte *) rb->Data;
540 const GLuint stride = rb->Width;
541
542 ASSERT(rb->GetPointer(ctx, rb, 0, 0));
543 ASSERT(sizeof(GLstencil) == 1);
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 < stencilMax) {
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 < stencilMax) {
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( struct gl_context *ctx, GLuint face, GLuint n,
703 const GLint x[], const GLint y[], GLubyte mask[] )
704 {
705 const struct gl_framebuffer *fb = ctx->DrawBuffer;
706 struct gl_renderbuffer *rb = fb->_StencilBuffer;
707 GLubyte fail[MAX_WIDTH];
708 GLstencil r, s;
709 GLuint i;
710 GLboolean allfail = GL_FALSE;
711 const GLuint valueMask = ctx->Stencil.ValueMask[face];
712 const GLstencil *stencilStart = (GLstencil *) rb->Data;
713 const GLuint stride = rb->Width;
714
715 ASSERT(rb->GetPointer(ctx, rb, 0, 0));
716 ASSERT(sizeof(GLstencil) == 1);
717
718 /*
719 * Perform stencil test. The results of this operation are stored
720 * in the fail[] array:
721 * IF fail[i] is non-zero THEN
722 * the stencil fail operator is to be applied
723 * ELSE
724 * the stencil fail operator is not to be applied
725 * ENDIF
726 */
727
728 switch (ctx->Stencil.Function[face]) {
729 case GL_NEVER:
730 /* always fail */
731 for (i=0;i<n;i++) {
732 if (mask[i]) {
733 mask[i] = 0;
734 fail[i] = 1;
735 }
736 else {
737 fail[i] = 0;
738 }
739 }
740 allfail = GL_TRUE;
741 break;
742 case GL_LESS:
743 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
744 for (i=0;i<n;i++) {
745 if (mask[i]) {
746 const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
747 s = (GLstencil) (*sptr & valueMask);
748 if (r < s) {
749 /* passed */
750 fail[i] = 0;
751 }
752 else {
753 fail[i] = 1;
754 mask[i] = 0;
755 }
756 }
757 else {
758 fail[i] = 0;
759 }
760 }
761 break;
762 case GL_LEQUAL:
763 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
764 for (i=0;i<n;i++) {
765 if (mask[i]) {
766 const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
767 s = (GLstencil) (*sptr & valueMask);
768 if (r <= s) {
769 /* pass */
770 fail[i] = 0;
771 }
772 else {
773 fail[i] = 1;
774 mask[i] = 0;
775 }
776 }
777 else {
778 fail[i] = 0;
779 }
780 }
781 break;
782 case GL_GREATER:
783 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
784 for (i=0;i<n;i++) {
785 if (mask[i]) {
786 const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
787 s = (GLstencil) (*sptr & valueMask);
788 if (r > s) {
789 /* passed */
790 fail[i] = 0;
791 }
792 else {
793 fail[i] = 1;
794 mask[i] = 0;
795 }
796 }
797 else {
798 fail[i] = 0;
799 }
800 }
801 break;
802 case GL_GEQUAL:
803 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
804 for (i=0;i<n;i++) {
805 if (mask[i]) {
806 const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
807 s = (GLstencil) (*sptr & valueMask);
808 if (r >= s) {
809 /* passed */
810 fail[i] = 0;
811 }
812 else {
813 fail[i] = 1;
814 mask[i] = 0;
815 }
816 }
817 else {
818 fail[i] = 0;
819 }
820 }
821 break;
822 case GL_EQUAL:
823 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
824 for (i=0;i<n;i++) {
825 if (mask[i]) {
826 const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
827 s = (GLstencil) (*sptr & valueMask);
828 if (r == s) {
829 /* passed */
830 fail[i] = 0;
831 }
832 else {
833 fail[i] = 1;
834 mask[i] = 0;
835 }
836 }
837 else {
838 fail[i] = 0;
839 }
840 }
841 break;
842 case GL_NOTEQUAL:
843 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
844 for (i=0;i<n;i++) {
845 if (mask[i]) {
846 const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
847 s = (GLstencil) (*sptr & valueMask);
848 if (r != s) {
849 /* passed */
850 fail[i] = 0;
851 }
852 else {
853 fail[i] = 1;
854 mask[i] = 0;
855 }
856 }
857 else {
858 fail[i] = 0;
859 }
860 }
861 break;
862 case GL_ALWAYS:
863 /* always pass */
864 for (i=0;i<n;i++) {
865 fail[i] = 0;
866 }
867 break;
868 default:
869 _mesa_problem(ctx, "Bad stencil func in gl_stencil_pixels");
870 return 0;
871 }
872
873 if (ctx->Stencil.FailFunc[face] != GL_KEEP) {
874 apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.FailFunc[face],
875 face, fail );
876 }
877
878 return !allfail;
879 }
880
881
882
883
884 /**
885 * Apply stencil and depth testing to an array of pixels.
886 * This is used both for software and hardware stencil buffers.
887 *
888 * The comments in this function are a bit sparse but the code is
889 * almost identical to stencil_and_ztest_span(), which is well
890 * commented.
891 *
892 * Input: n - number of pixels in the array
893 * x, y - array of [n] pixel positions
894 * z - array [n] of z values
895 * mask - array [n] of flags (1=test this pixel, 0=skip the pixel)
896 * Output: mask - array [n] of flags (1=stencil and depth test passed)
897 * Return: GL_FALSE - all fragments failed the testing
898 * GL_TRUE - one or more fragments passed the testing
899 */
900 static GLboolean
901 stencil_and_ztest_pixels( struct gl_context *ctx, SWspan *span, GLuint face )
902 {
903 GLubyte passMask[MAX_WIDTH], failMask[MAX_WIDTH], origMask[MAX_WIDTH];
904 struct gl_framebuffer *fb = ctx->DrawBuffer;
905 struct gl_renderbuffer *rb = fb->_StencilBuffer;
906 const GLuint n = span->end;
907 const GLint *x = span->array->x;
908 const GLint *y = span->array->y;
909 GLubyte *mask = span->array->mask;
910
911 ASSERT(span->arrayMask & SPAN_XY);
912 ASSERT(ctx->Stencil.Enabled);
913 ASSERT(n <= MAX_WIDTH);
914
915 if (!rb->GetPointer(ctx, rb, 0, 0)) {
916 /* No direct access */
917 GLstencil stencil[MAX_WIDTH];
918
919 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
920 _swrast_get_values(ctx, rb, n, x, y, stencil, sizeof(GLubyte));
921
922 memcpy(origMask, mask, n * sizeof(GLubyte));
923
924 (void) do_stencil_test(ctx, face, n, stencil, mask);
925
926 if (ctx->Depth.Test == GL_FALSE) {
927 apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face,
928 n, stencil, mask);
929 }
930 else {
931 GLubyte tmpMask[MAX_WIDTH];
932 memcpy(tmpMask, mask, n * sizeof(GLubyte));
933
934 _swrast_depth_test_span(ctx, span);
935
936 compute_pass_fail_masks(n, tmpMask, mask, passMask, failMask);
937
938 if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
939 apply_stencil_op(ctx, ctx->Stencil.ZFailFunc[face], face,
940 n, stencil, failMask);
941 }
942 if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
943 apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face,
944 n, stencil, passMask);
945 }
946 }
947
948 /* Write updated stencil values into hardware stencil buffer */
949 rb->PutValues(ctx, rb, n, x, y, stencil, origMask);
950
951 return GL_TRUE;
952 }
953 else {
954 /* Direct access to stencil buffer */
955
956 if (stencil_test_pixels(ctx, face, n, x, y, mask) == GL_FALSE) {
957 /* all fragments failed the stencil test, we're done. */
958 return GL_FALSE;
959 }
960
961 if (ctx->Depth.Test==GL_FALSE) {
962 apply_stencil_op_to_pixels(ctx, n, x, y,
963 ctx->Stencil.ZPassFunc[face], face, mask);
964 }
965 else {
966 memcpy(origMask, mask, n * sizeof(GLubyte));
967
968 _swrast_depth_test_span(ctx, span);
969
970 compute_pass_fail_masks(n, origMask, mask, passMask, failMask);
971
972 if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
973 apply_stencil_op_to_pixels(ctx, n, x, y,
974 ctx->Stencil.ZFailFunc[face],
975 face, failMask);
976 }
977 if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
978 apply_stencil_op_to_pixels(ctx, n, x, y,
979 ctx->Stencil.ZPassFunc[face],
980 face, passMask);
981 }
982 }
983
984 return GL_TRUE; /* one or more fragments passed both tests */
985 }
986 }
987
988
989 /**
990 * /return GL_TRUE = one or more fragments passed,
991 * GL_FALSE = all fragments failed.
992 */
993 GLboolean
994 _swrast_stencil_and_ztest_span(struct gl_context *ctx, SWspan *span)
995 {
996 const GLuint face = (span->facing == 0) ? 0 : ctx->Stencil._BackFace;
997
998 if (span->arrayMask & SPAN_XY)
999 return stencil_and_ztest_pixels(ctx, span, face);
1000 else
1001 return stencil_and_ztest_span(ctx, span, face);
1002 }
1003
1004
1005 #if 0
1006 GLuint
1007 clip_span(GLuint bufferWidth, GLuint bufferHeight,
1008 GLint x, GLint y, GLuint *count)
1009 {
1010 GLuint n = *count;
1011 GLuint skipPixels = 0;
1012
1013 if (y < 0 || y >= bufferHeight || x + n <= 0 || x >= bufferWidth) {
1014 /* totally out of bounds */
1015 n = 0;
1016 }
1017 else {
1018 /* left clip */
1019 if (x < 0) {
1020 skipPixels = -x;
1021 x = 0;
1022 n -= skipPixels;
1023 }
1024 /* right clip */
1025 if (x + n > bufferWidth) {
1026 GLint dx = x + n - bufferWidth;
1027 n -= dx;
1028 }
1029 }
1030
1031 *count = n;
1032
1033 return skipPixels;
1034 }
1035 #endif
1036
1037
1038 /**
1039 * Return a span of stencil values from the stencil buffer.
1040 * Used for glRead/CopyPixels
1041 * Input: n - how many pixels
1042 * x,y - location of first pixel
1043 * Output: stencil - the array of stencil values
1044 */
1045 void
1046 _swrast_read_stencil_span(struct gl_context *ctx, struct gl_renderbuffer *rb,
1047 GLint n, GLint x, GLint y, GLstencil stencil[])
1048 {
1049 if (y < 0 || y >= (GLint) rb->Height ||
1050 x + n <= 0 || x >= (GLint) rb->Width) {
1051 /* span is completely outside framebuffer */
1052 return; /* undefined values OK */
1053 }
1054
1055 if (x < 0) {
1056 GLint dx = -x;
1057 x = 0;
1058 n -= dx;
1059 stencil += dx;
1060 }
1061 if (x + n > (GLint) rb->Width) {
1062 GLint dx = x + n - rb->Width;
1063 n -= dx;
1064 }
1065 if (n <= 0) {
1066 return;
1067 }
1068
1069 rb->GetRow(ctx, rb, n, x, y, stencil);
1070 }
1071
1072
1073
1074 /**
1075 * Write a span of stencil values to the stencil buffer. This function
1076 * applies the stencil write mask when needed.
1077 * Used for glDraw/CopyPixels
1078 * Input: n - how many pixels
1079 * x, y - location of first pixel
1080 * stencil - the array of stencil values
1081 */
1082 void
1083 _swrast_write_stencil_span(struct gl_context *ctx, GLint n, GLint x, GLint y,
1084 const GLstencil stencil[] )
1085 {
1086 struct gl_framebuffer *fb = ctx->DrawBuffer;
1087 struct gl_renderbuffer *rb = fb->_StencilBuffer;
1088 const GLuint stencilMax = (1 << fb->Visual.stencilBits) - 1;
1089 const GLuint stencilMask = ctx->Stencil.WriteMask[0];
1090
1091 if (y < 0 || y >= (GLint) rb->Height ||
1092 x + n <= 0 || x >= (GLint) rb->Width) {
1093 /* span is completely outside framebuffer */
1094 return; /* undefined values OK */
1095 }
1096 if (x < 0) {
1097 GLint dx = -x;
1098 x = 0;
1099 n -= dx;
1100 stencil += dx;
1101 }
1102 if (x + n > (GLint) rb->Width) {
1103 GLint dx = x + n - rb->Width;
1104 n -= dx;
1105 }
1106 if (n <= 0) {
1107 return;
1108 }
1109
1110 if ((stencilMask & stencilMax) != stencilMax) {
1111 /* need to apply writemask */
1112 GLstencil destVals[MAX_WIDTH], newVals[MAX_WIDTH];
1113 GLint i;
1114 rb->GetRow(ctx, rb, n, x, y, destVals);
1115 for (i = 0; i < n; i++) {
1116 newVals[i]
1117 = (stencil[i] & stencilMask) | (destVals[i] & ~stencilMask);
1118 }
1119 rb->PutRow(ctx, rb, n, x, y, newVals, NULL);
1120 }
1121 else {
1122 rb->PutRow(ctx, rb, n, x, y, stencil, NULL);
1123 }
1124 }
1125
1126
1127
1128 /**
1129 * Clear the stencil buffer.
1130 */
1131 void
1132 _swrast_clear_stencil_buffer( struct gl_context *ctx, struct gl_renderbuffer *rb )
1133 {
1134 const GLubyte stencilBits = ctx->DrawBuffer->Visual.stencilBits;
1135 const GLuint mask = ctx->Stencil.WriteMask[0];
1136 const GLuint invMask = ~mask;
1137 const GLuint clearVal = (ctx->Stencil.Clear & mask);
1138 const GLuint stencilMax = (1 << stencilBits) - 1;
1139 GLint x, y, width, height;
1140
1141 if (!rb || mask == 0)
1142 return;
1143
1144 ASSERT(rb->DataType == GL_UNSIGNED_BYTE ||
1145 rb->DataType == GL_UNSIGNED_SHORT);
1146
1147 ASSERT(rb->_BaseFormat == GL_STENCIL_INDEX);
1148
1149 /* compute region to clear */
1150 x = ctx->DrawBuffer->_Xmin;
1151 y = ctx->DrawBuffer->_Ymin;
1152 width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
1153 height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
1154
1155 if (rb->GetPointer(ctx, rb, 0, 0)) {
1156 /* Direct buffer access */
1157 if ((mask & stencilMax) != stencilMax) {
1158 /* need to mask the clear */
1159 if (rb->DataType == GL_UNSIGNED_BYTE) {
1160 GLint i, j;
1161 for (i = 0; i < height; i++) {
1162 GLubyte *stencil = (GLubyte*) rb->GetPointer(ctx, rb, x, y + i);
1163 for (j = 0; j < width; j++) {
1164 stencil[j] = (stencil[j] & invMask) | clearVal;
1165 }
1166 }
1167 }
1168 else {
1169 GLint i, j;
1170 for (i = 0; i < height; i++) {
1171 GLushort *stencil = (GLushort*) rb->GetPointer(ctx, rb, x, y + i);
1172 for (j = 0; j < width; j++) {
1173 stencil[j] = (stencil[j] & invMask) | clearVal;
1174 }
1175 }
1176 }
1177 }
1178 else {
1179 /* no bit masking */
1180 if (width == (GLint) rb->Width && rb->DataType == GL_UNSIGNED_BYTE) {
1181 /* optimized case */
1182 /* Note: bottom-to-top raster assumed! */
1183 GLubyte *stencil = (GLubyte *) rb->GetPointer(ctx, rb, x, y);
1184 GLuint len = width * height * sizeof(GLubyte);
1185 memset(stencil, clearVal, len);
1186 }
1187 else {
1188 /* general case */
1189 GLint i;
1190 for (i = 0; i < height; i++) {
1191 GLvoid *stencil = rb->GetPointer(ctx, rb, x, y + i);
1192 if (rb->DataType == GL_UNSIGNED_BYTE) {
1193 memset(stencil, clearVal, width);
1194 }
1195 else {
1196 _mesa_memset16((short unsigned int*) stencil, clearVal, width);
1197 }
1198 }
1199 }
1200 }
1201 }
1202 else {
1203 /* no direct access */
1204 if ((mask & stencilMax) != stencilMax) {
1205 /* need to mask the clear */
1206 if (rb->DataType == GL_UNSIGNED_BYTE) {
1207 GLint i, j;
1208 for (i = 0; i < height; i++) {
1209 GLubyte stencil[MAX_WIDTH];
1210 rb->GetRow(ctx, rb, width, x, y + i, stencil);
1211 for (j = 0; j < width; j++) {
1212 stencil[j] = (stencil[j] & invMask) | clearVal;
1213 }
1214 rb->PutRow(ctx, rb, width, x, y + i, stencil, NULL);
1215 }
1216 }
1217 else {
1218 GLint i, j;
1219 for (i = 0; i < height; i++) {
1220 GLushort stencil[MAX_WIDTH];
1221 rb->GetRow(ctx, rb, width, x, y + i, stencil);
1222 for (j = 0; j < width; j++) {
1223 stencil[j] = (stencil[j] & invMask) | clearVal;
1224 }
1225 rb->PutRow(ctx, rb, width, x, y + i, stencil, NULL);
1226 }
1227 }
1228 }
1229 else {
1230 /* no bit masking */
1231 const GLubyte clear8 = (GLubyte) clearVal;
1232 const GLushort clear16 = (GLushort) clearVal;
1233 const void *clear;
1234 GLint i;
1235 if (rb->DataType == GL_UNSIGNED_BYTE) {
1236 clear = &clear8;
1237 }
1238 else {
1239 clear = &clear16;
1240 }
1241 for (i = 0; i < height; i++) {
1242 rb->PutMonoRow(ctx, rb, width, x, y + i, clear, NULL);
1243 }
1244 }
1245 }
1246 }