changed a renderbuffer check
[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 "macros.h"
29 #include "imports.h"
30 #include "fbobject.h"
31
32 #include "s_context.h"
33 #include "s_depth.h"
34 #include "s_stencil.h"
35 #include "s_span.h"
36
37
38
39 /* Stencil Logic:
40
41 IF stencil test fails THEN
42 Apply fail-op to stencil value
43 Don't write the pixel (RGBA,Z)
44 ELSE
45 IF doing depth test && depth test fails THEN
46 Apply zfail-op to stencil value
47 Write RGBA and Z to appropriate buffers
48 ELSE
49 Apply zpass-op to stencil value
50 ENDIF
51
52 */
53
54
55 /**
56 * Apply the given stencil operator to the array of stencil values.
57 * Don't touch stencil[i] if mask[i] is zero.
58 * Input: n - size of stencil array
59 * oper - the stencil buffer operator
60 * face - 0 or 1 for front or back face operation
61 * stencil - array of stencil values
62 * mask - array [n] of flag: 1=apply operator, 0=don't apply operator
63 * Output: stencil - modified values
64 */
65 static void
66 apply_stencil_op( const GLcontext *ctx, GLenum oper, GLuint face,
67 GLuint n, GLstencil stencil[], const GLubyte mask[] )
68 {
69 const GLstencil ref = ctx->Stencil.Ref[face];
70 const GLstencil wrtmask = ctx->Stencil.WriteMask[face];
71 const GLstencil invmask = (GLstencil) (~wrtmask);
72 const GLstencil stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1;
73 GLuint i;
74
75 switch (oper) {
76 case GL_KEEP:
77 /* do nothing */
78 break;
79 case GL_ZERO:
80 if (invmask==0) {
81 for (i=0;i<n;i++) {
82 if (mask[i]) {
83 stencil[i] = 0;
84 }
85 }
86 }
87 else {
88 for (i=0;i<n;i++) {
89 if (mask[i]) {
90 stencil[i] = (GLstencil) (stencil[i] & invmask);
91 }
92 }
93 }
94 break;
95 case GL_REPLACE:
96 if (invmask==0) {
97 for (i=0;i<n;i++) {
98 if (mask[i]) {
99 stencil[i] = ref;
100 }
101 }
102 }
103 else {
104 for (i=0;i<n;i++) {
105 if (mask[i]) {
106 GLstencil s = stencil[i];
107 stencil[i] = (GLstencil) ((invmask & s ) | (wrtmask & ref));
108 }
109 }
110 }
111 break;
112 case GL_INCR:
113 if (invmask==0) {
114 for (i=0;i<n;i++) {
115 if (mask[i]) {
116 GLstencil s = stencil[i];
117 if (s < stencilMax) {
118 stencil[i] = (GLstencil) (s+1);
119 }
120 }
121 }
122 }
123 else {
124 for (i=0;i<n;i++) {
125 if (mask[i]) {
126 /* VERIFY logic of adding 1 to a write-masked value */
127 GLstencil s = stencil[i];
128 if (s < stencilMax) {
129 stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s+1)));
130 }
131 }
132 }
133 }
134 break;
135 case GL_DECR:
136 if (invmask==0) {
137 for (i=0;i<n;i++) {
138 if (mask[i]) {
139 GLstencil s = stencil[i];
140 if (s>0) {
141 stencil[i] = (GLstencil) (s-1);
142 }
143 }
144 }
145 }
146 else {
147 for (i=0;i<n;i++) {
148 if (mask[i]) {
149 /* VERIFY logic of subtracting 1 to a write-masked value */
150 GLstencil s = stencil[i];
151 if (s>0) {
152 stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s-1)));
153 }
154 }
155 }
156 }
157 break;
158 case GL_INCR_WRAP_EXT:
159 if (invmask==0) {
160 for (i=0;i<n;i++) {
161 if (mask[i]) {
162 stencil[i]++;
163 }
164 }
165 }
166 else {
167 for (i=0;i<n;i++) {
168 if (mask[i]) {
169 GLstencil s = stencil[i];
170 stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s+1)));
171 }
172 }
173 }
174 break;
175 case GL_DECR_WRAP_EXT:
176 if (invmask==0) {
177 for (i=0;i<n;i++) {
178 if (mask[i]) {
179 stencil[i]--;
180 }
181 }
182 }
183 else {
184 for (i=0;i<n;i++) {
185 if (mask[i]) {
186 GLstencil s = stencil[i];
187 stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s-1)));
188 }
189 }
190 }
191 break;
192 case GL_INVERT:
193 if (invmask==0) {
194 for (i=0;i<n;i++) {
195 if (mask[i]) {
196 GLstencil s = stencil[i];
197 stencil[i] = (GLstencil) ~s;
198 }
199 }
200 }
201 else {
202 for (i=0;i<n;i++) {
203 if (mask[i]) {
204 GLstencil s = stencil[i];
205 stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & ~s));
206 }
207 }
208 }
209 break;
210 default:
211 _mesa_problem(ctx, "Bad stencil op in apply_stencil_op");
212 }
213 }
214
215
216
217
218 /**
219 * Apply stencil test to an array of stencil values (before depth buffering).
220 * Input: face - 0 or 1 for front or back-face polygons
221 * n - number of pixels in the array
222 * stencil - array of [n] stencil values
223 * mask - array [n] of flag: 0=skip the pixel, 1=stencil the pixel
224 * Output: mask - pixels which fail the stencil test will have their
225 * mask flag set to 0.
226 * stencil - updated stencil values (where the test passed)
227 * Return: GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed.
228 */
229 static GLboolean
230 do_stencil_test( GLcontext *ctx, GLuint face, GLuint n, GLstencil stencil[],
231 GLubyte mask[] )
232 {
233 GLubyte fail[MAX_WIDTH];
234 GLboolean allfail = GL_FALSE;
235 GLuint i;
236 GLstencil r, s;
237 const GLuint valueMask = ctx->Stencil.ValueMask[face];
238
239 ASSERT(n <= MAX_WIDTH);
240
241 /*
242 * Perform stencil test. The results of this operation are stored
243 * in the fail[] array:
244 * IF fail[i] is non-zero THEN
245 * the stencil fail operator is to be applied
246 * ELSE
247 * the stencil fail operator is not to be applied
248 * ENDIF
249 */
250 switch (ctx->Stencil.Function[face]) {
251 case GL_NEVER:
252 /* never pass; always fail */
253 for (i=0;i<n;i++) {
254 if (mask[i]) {
255 mask[i] = 0;
256 fail[i] = 1;
257 }
258 else {
259 fail[i] = 0;
260 }
261 }
262 allfail = GL_TRUE;
263 break;
264 case GL_LESS:
265 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
266 for (i=0;i<n;i++) {
267 if (mask[i]) {
268 s = (GLstencil) (stencil[i] & valueMask);
269 if (r < s) {
270 /* passed */
271 fail[i] = 0;
272 }
273 else {
274 fail[i] = 1;
275 mask[i] = 0;
276 }
277 }
278 else {
279 fail[i] = 0;
280 }
281 }
282 break;
283 case GL_LEQUAL:
284 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
285 for (i=0;i<n;i++) {
286 if (mask[i]) {
287 s = (GLstencil) (stencil[i] & valueMask);
288 if (r <= s) {
289 /* pass */
290 fail[i] = 0;
291 }
292 else {
293 fail[i] = 1;
294 mask[i] = 0;
295 }
296 }
297 else {
298 fail[i] = 0;
299 }
300 }
301 break;
302 case GL_GREATER:
303 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
304 for (i=0;i<n;i++) {
305 if (mask[i]) {
306 s = (GLstencil) (stencil[i] & valueMask);
307 if (r > s) {
308 /* passed */
309 fail[i] = 0;
310 }
311 else {
312 fail[i] = 1;
313 mask[i] = 0;
314 }
315 }
316 else {
317 fail[i] = 0;
318 }
319 }
320 break;
321 case GL_GEQUAL:
322 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
323 for (i=0;i<n;i++) {
324 if (mask[i]) {
325 s = (GLstencil) (stencil[i] & valueMask);
326 if (r >= s) {
327 /* passed */
328 fail[i] = 0;
329 }
330 else {
331 fail[i] = 1;
332 mask[i] = 0;
333 }
334 }
335 else {
336 fail[i] = 0;
337 }
338 }
339 break;
340 case GL_EQUAL:
341 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
342 for (i=0;i<n;i++) {
343 if (mask[i]) {
344 s = (GLstencil) (stencil[i] & valueMask);
345 if (r == s) {
346 /* passed */
347 fail[i] = 0;
348 }
349 else {
350 fail[i] = 1;
351 mask[i] = 0;
352 }
353 }
354 else {
355 fail[i] = 0;
356 }
357 }
358 break;
359 case GL_NOTEQUAL:
360 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
361 for (i=0;i<n;i++) {
362 if (mask[i]) {
363 s = (GLstencil) (stencil[i] & valueMask);
364 if (r != s) {
365 /* passed */
366 fail[i] = 0;
367 }
368 else {
369 fail[i] = 1;
370 mask[i] = 0;
371 }
372 }
373 else {
374 fail[i] = 0;
375 }
376 }
377 break;
378 case GL_ALWAYS:
379 /* always pass */
380 for (i=0;i<n;i++) {
381 fail[i] = 0;
382 }
383 break;
384 default:
385 _mesa_problem(ctx, "Bad stencil func in gl_stencil_span");
386 return 0;
387 }
388
389 if (ctx->Stencil.FailFunc[face] != GL_KEEP) {
390 apply_stencil_op( ctx, ctx->Stencil.FailFunc[face], face, n, stencil, fail );
391 }
392
393 return !allfail;
394 }
395
396
397
398 /**
399 * Apply stencil and depth testing to the span of pixels.
400 * Both software and hardware stencil buffers are acceptable.
401 * Input: n - number of pixels in the span
402 * x, y - location of leftmost pixel in span
403 * z - array [n] of z values
404 * mask - array [n] of flags (1=test this pixel, 0=skip the pixel)
405 * Output: mask - array [n] of flags (1=stencil and depth test passed)
406 * Return: GL_FALSE - all fragments failed the testing
407 * GL_TRUE - one or more fragments passed the testing
408 *
409 */
410 static GLboolean
411 stencil_and_ztest_span(GLcontext *ctx, struct sw_span *span, GLuint face)
412 {
413 struct gl_framebuffer *fb = ctx->DrawBuffer;
414 struct gl_renderbuffer *rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
415 GLstencil stencilRow[MAX_WIDTH];
416 GLstencil *stencil;
417 const GLuint n = span->end;
418 const GLint x = span->x;
419 const GLint y = span->y;
420 GLubyte *mask = span->array->mask;
421
422 ASSERT((span->arrayMask & SPAN_XY) == 0);
423 ASSERT(ctx->Stencil.Enabled);
424 ASSERT(n <= MAX_WIDTH);
425 #ifdef DEBUG
426 if (ctx->Depth.Test) {
427 ASSERT(span->arrayMask & SPAN_Z);
428 }
429 #endif
430
431 stencil = rb->GetPointer(ctx, rb, x, y);
432 if (!stencil) {
433 rb->GetRow(ctx, rb, n, x, y, stencilRow);
434 stencil = stencilRow;
435 }
436
437 /*
438 * Apply the stencil test to the fragments.
439 * failMask[i] is 1 if the stencil test failed.
440 */
441 if (do_stencil_test( ctx, face, n, stencil, mask ) == GL_FALSE) {
442 /* all fragments failed the stencil test, we're done. */
443 span->writeAll = GL_FALSE;
444 return GL_FALSE;
445 }
446
447 /*
448 * Some fragments passed the stencil test, apply depth test to them
449 * and apply Zpass and Zfail stencil ops.
450 */
451 if (ctx->Depth.Test == GL_FALSE) {
452 /*
453 * No depth buffer, just apply zpass stencil function to active pixels.
454 */
455 apply_stencil_op( ctx, ctx->Stencil.ZPassFunc[face], face, n, stencil, mask );
456 }
457 else {
458 /*
459 * Perform depth buffering, then apply zpass or zfail stencil function.
460 */
461 GLubyte passmask[MAX_WIDTH], failmask[MAX_WIDTH], oldmask[MAX_WIDTH];
462 GLuint i;
463
464 /* save the current mask bits */
465 _mesa_memcpy(oldmask, mask, n * sizeof(GLubyte));
466
467 /* apply the depth test */
468 _swrast_depth_test_span(ctx, span);
469
470 /* Set the stencil pass/fail flags according to result of depth testing.
471 * if oldmask[i] == 0 then
472 * Don't touch the stencil value
473 * else if oldmask[i] and newmask[i] then
474 * Depth test passed
475 * else
476 * assert(oldmask[i] && !newmask[i])
477 * Depth test failed
478 * endif
479 */
480 for (i=0;i<n;i++) {
481 ASSERT(mask[i] == 0 || mask[i] == 1);
482 passmask[i] = oldmask[i] & mask[i];
483 failmask[i] = oldmask[i] & (mask[i] ^ 1);
484 }
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, mask);
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( GLcontext *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->Attachment[BUFFER_STENCIL].Renderbuffer;
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( GLcontext *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->Attachment[BUFFER_STENCIL].Renderbuffer;
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( GLcontext *ctx, struct sw_span *span, GLuint face )
902 {
903 struct gl_framebuffer *fb = ctx->DrawBuffer;
904 struct gl_renderbuffer *rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
905 const GLuint n = span->end;
906 const GLint *x = span->array->x;
907 const GLint *y = span->array->y;
908 GLubyte *mask = span->array->mask;
909
910 ASSERT(span->arrayMask & SPAN_XY);
911 ASSERT(ctx->Stencil.Enabled);
912 ASSERT(n <= MAX_WIDTH);
913
914 if (!rb->GetPointer(ctx, rb, 0, 0)) {
915 /* No direct access */
916 GLstencil stencil[MAX_WIDTH];
917 GLubyte origMask[MAX_WIDTH];
918
919 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
920 _swrast_get_values(ctx, rb, n, x, y, stencil, sizeof(GLubyte));
921
922 _mesa_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 _swrast_depth_test_span(ctx, span);
932
933 if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
934 GLubyte failmask[MAX_WIDTH];
935 GLuint i;
936 for (i = 0; i < n; i++) {
937 ASSERT(mask[i] == 0 || mask[i] == 1);
938 failmask[i] = origMask[i] & (mask[i] ^ 1);
939 }
940 apply_stencil_op(ctx, ctx->Stencil.ZFailFunc[face], face,
941 n, stencil, failmask);
942 }
943 if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
944 GLubyte passmask[MAX_WIDTH];
945 GLuint i;
946 for (i = 0; i < n; i++) {
947 ASSERT(mask[i] == 0 || mask[i] == 1);
948 passmask[i] = origMask[i] & mask[i];
949 }
950 apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face,
951 n, stencil, passmask);
952 }
953 }
954
955 /* Write updated stencil values into hardware stencil buffer */
956 rb->PutValues(ctx, rb, n, x, y, stencil, origMask);
957
958 return GL_TRUE;
959 }
960 else {
961 /* Direct access to stencil buffer */
962
963 if (stencil_test_pixels(ctx, face, n, x, y, mask) == GL_FALSE) {
964 /* all fragments failed the stencil test, we're done. */
965 return GL_FALSE;
966 }
967
968 if (ctx->Depth.Test==GL_FALSE) {
969 apply_stencil_op_to_pixels(ctx, n, x, y,
970 ctx->Stencil.ZPassFunc[face], face, mask);
971 }
972 else {
973 GLubyte passmask[MAX_WIDTH], failmask[MAX_WIDTH], oldmask[MAX_WIDTH];
974 GLuint i;
975
976 _mesa_memcpy(oldmask, mask, n * sizeof(GLubyte));
977
978 _swrast_depth_test_span(ctx, span);
979
980 for (i=0;i<n;i++) {
981 ASSERT(mask[i] == 0 || mask[i] == 1);
982 passmask[i] = oldmask[i] & mask[i];
983 failmask[i] = oldmask[i] & (mask[i] ^ 1);
984 }
985
986 if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
987 apply_stencil_op_to_pixels(ctx, n, x, y,
988 ctx->Stencil.ZFailFunc[face],
989 face, failmask);
990 }
991 if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
992 apply_stencil_op_to_pixels(ctx, n, x, y,
993 ctx->Stencil.ZPassFunc[face],
994 face, passmask);
995 }
996 }
997
998 return GL_TRUE; /* one or more fragments passed both tests */
999 }
1000 }
1001
1002
1003 /**
1004 * /return GL_TRUE = one or more fragments passed,
1005 * GL_FALSE = all fragments failed.
1006 */
1007 GLboolean
1008 _swrast_stencil_and_ztest_span(GLcontext *ctx, struct sw_span *span)
1009 {
1010 /* span->facing can only be non-zero if using two-sided stencil */
1011 ASSERT(ctx->Stencil._TestTwoSide || span->facing == 0);
1012 if (span->arrayMask & SPAN_XY)
1013 return stencil_and_ztest_pixels(ctx, span, span->facing);
1014 else
1015 return stencil_and_ztest_span(ctx, span, span->facing);
1016 }
1017
1018
1019 #if 0
1020 GLuint
1021 clip_span(GLuint bufferWidth, GLuint bufferHeight,
1022 GLint x, GLint y, GLuint *count)
1023 {
1024 GLuint n = *count;
1025 GLuint skipPixels = 0;
1026
1027 if (y < 0 || y >= bufferHeight || x + n <= 0 || x >= bufferWidth) {
1028 /* totally out of bounds */
1029 n = 0;
1030 }
1031 else {
1032 /* left clip */
1033 if (x < 0) {
1034 skipPixels = -x;
1035 x = 0;
1036 n -= skipPixels;
1037 }
1038 /* right clip */
1039 if (x + n > bufferWidth) {
1040 GLint dx = x + n - bufferWidth;
1041 n -= dx;
1042 }
1043 }
1044
1045 *count = n;
1046
1047 return skipPixels;
1048 }
1049 #endif
1050
1051
1052 /**
1053 * Return a span of stencil values from the stencil buffer.
1054 * Used for glRead/CopyPixels
1055 * Input: n - how many pixels
1056 * x,y - location of first pixel
1057 * Output: stencil - the array of stencil values
1058 */
1059 void
1060 _swrast_read_stencil_span(GLcontext *ctx, struct gl_renderbuffer *rb,
1061 GLint n, GLint x, GLint y, GLstencil stencil[])
1062 {
1063 if (y < 0 || y >= rb->Height || x + n <= 0 || x >= rb->Width) {
1064 /* span is completely outside framebuffer */
1065 return; /* undefined values OK */
1066 }
1067
1068 if (x < 0) {
1069 GLint dx = -x;
1070 x = 0;
1071 n -= dx;
1072 stencil += dx;
1073 }
1074 if (x + n > rb->Width) {
1075 GLint dx = x + n - rb->Width;
1076 n -= dx;
1077 }
1078 if (n <= 0) {
1079 return;
1080 }
1081
1082 rb->GetRow(ctx, rb, n, x, y, stencil);
1083 }
1084
1085
1086
1087 /**
1088 * Write a span of stencil values to the stencil buffer.
1089 * Used for glDraw/CopyPixels
1090 * Input: n - how many pixels
1091 * x, y - location of first pixel
1092 * stencil - the array of stencil values
1093 */
1094 void
1095 _swrast_write_stencil_span(GLcontext *ctx, GLint n, GLint x, GLint y,
1096 const GLstencil stencil[] )
1097 {
1098 struct gl_framebuffer *fb = ctx->DrawBuffer;
1099 struct gl_renderbuffer *rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
1100
1101 if (y < 0 || y >= rb->Height || x + n <= 0 || x >= rb->Width) {
1102 /* span is completely outside framebuffer */
1103 return; /* undefined values OK */
1104 }
1105 if (x < 0) {
1106 GLint dx = -x;
1107 x = 0;
1108 n -= dx;
1109 stencil += dx;
1110 }
1111 if (x + n > rb->Width) {
1112 GLint dx = x + n - rb->Width;
1113 n -= dx;
1114 }
1115 if (n <= 0) {
1116 return;
1117 }
1118
1119 rb->PutRow(ctx, rb, n, x, y, stencil, NULL);
1120 }
1121
1122
1123
1124 /**
1125 * Clear the stencil buffer.
1126 */
1127 void
1128 _swrast_clear_stencil_buffer( GLcontext *ctx, struct gl_renderbuffer *rb )
1129 {
1130 const GLubyte stencilBits = rb->ComponentSizes[0];
1131 const GLuint mask = ctx->Stencil.WriteMask[0];
1132 const GLuint invMask = ~mask;
1133 const GLuint clearVal = (ctx->Stencil.Clear & mask);
1134 const GLuint stencilMax = (1 << stencilBits) - 1;
1135 GLint x, y, width, height;
1136
1137 if (!rb || mask == 0)
1138 return;
1139
1140 ASSERT(rb->DataType == GL_UNSIGNED_BYTE ||
1141 rb->DataType == GL_UNSIGNED_SHORT);
1142
1143 ASSERT(rb->_BaseFormat == GL_STENCIL_INDEX);
1144
1145 /* compute region to clear */
1146 x = ctx->DrawBuffer->_Xmin;
1147 y = ctx->DrawBuffer->_Ymin;
1148 width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
1149 height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
1150
1151 if (rb->GetPointer(ctx, rb, 0, 0)) {
1152 /* Direct buffer access */
1153 if ((mask & stencilMax) != stencilMax) {
1154 /* need to mask the clear */
1155 if (rb->DataType == GL_UNSIGNED_BYTE) {
1156 GLint i, j;
1157 for (i = 0; i < height; i++) {
1158 GLubyte *stencil = rb->GetPointer(ctx, rb, x, y + i);
1159 for (j = 0; j < width; j++) {
1160 stencil[j] = (stencil[j] & invMask) | clearVal;
1161 }
1162 }
1163 }
1164 else {
1165 GLint i, j;
1166 for (i = 0; i < height; i++) {
1167 GLushort *stencil = rb->GetPointer(ctx, rb, x, y + i);
1168 for (j = 0; j < width; j++) {
1169 stencil[j] = (stencil[j] & invMask) | clearVal;
1170 }
1171 }
1172 }
1173 }
1174 else {
1175 /* no bit masking */
1176 if (width == rb->Width && rb->DataType == GL_UNSIGNED_BYTE) {
1177 /* optimized case */
1178 /* XXX bottom-to-op raster assumed! */
1179 GLubyte *stencil = rb->GetPointer(ctx, rb, x, y);
1180 GLuint len = width * height * sizeof(GLubyte);
1181 _mesa_memset(stencil, clearVal, len);
1182 }
1183 else {
1184 /* general case */
1185 GLint i;
1186 for (i = 0; i < height; i++) {
1187 GLvoid *stencil = rb->GetPointer(ctx, rb, x, y + i);
1188 if (rb->DataType == GL_UNSIGNED_BYTE) {
1189 _mesa_memset(stencil, clearVal, width);
1190 }
1191 else {
1192 _mesa_memset16(stencil, clearVal, width);
1193 }
1194 }
1195 }
1196 }
1197 }
1198 else {
1199 /* no direct access */
1200 if ((mask & stencilMax) != stencilMax) {
1201 /* need to mask the clear */
1202 if (rb->DataType == GL_UNSIGNED_BYTE) {
1203 GLint i, j;
1204 for (i = 0; i < height; i++) {
1205 GLubyte stencil[MAX_WIDTH];
1206 rb->GetRow(ctx, rb, width, x, y + i, stencil);
1207 for (j = 0; j < width; j++) {
1208 stencil[j] = (stencil[j] & invMask) | clearVal;
1209 }
1210 rb->PutRow(ctx, rb, width, x, y + i, stencil, NULL);
1211 }
1212 }
1213 else {
1214 GLint i, j;
1215 for (i = 0; i < height; i++) {
1216 GLushort stencil[MAX_WIDTH];
1217 rb->GetRow(ctx, rb, width, x, y + i, stencil);
1218 for (j = 0; j < width; j++) {
1219 stencil[j] = (stencil[j] & invMask) | clearVal;
1220 }
1221 rb->PutRow(ctx, rb, width, x, y + i, stencil, NULL);
1222 }
1223 }
1224 }
1225 else {
1226 /* no bit masking */
1227 const GLubyte clear8 = (GLubyte) clearVal;
1228 const GLushort clear16 = (GLushort) clearVal;
1229 const void *clear;
1230 GLint i;
1231 if (rb->DataType == GL_UNSIGNED_BYTE) {
1232 clear = &clear8;
1233 }
1234 else {
1235 clear = &clear16;
1236 }
1237 for (i = 0; i < height; i++) {
1238 rb->PutMonoRow(ctx, rb, width, x, y + i, clear, NULL);
1239 }
1240 }
1241 }
1242 }