swrast: stop using _swrast_get_values() in stencil code
[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 #include "main/format_unpack.h"
30
31 #include "s_context.h"
32 #include "s_depth.h"
33 #include "s_stencil.h"
34 #include "s_span.h"
35
36
37
38 /* Stencil Logic:
39
40 IF stencil test fails THEN
41 Apply fail-op to stencil value
42 Don't write the pixel (RGBA,Z)
43 ELSE
44 IF doing depth test && depth test fails THEN
45 Apply zfail-op to stencil value
46 Write RGBA and Z to appropriate buffers
47 ELSE
48 Apply zpass-op to stencil value
49 ENDIF
50
51 */
52
53
54 /**
55 * Apply the given stencil operator to the array of stencil values.
56 * Don't touch stencil[i] if mask[i] is zero.
57 * Input: n - size of stencil array
58 * oper - the stencil buffer operator
59 * face - 0 or 1 for front or back face operation
60 * stencil - array of stencil values
61 * mask - array [n] of flag: 1=apply operator, 0=don't apply operator
62 * Output: stencil - modified values
63 */
64 static void
65 apply_stencil_op( const struct gl_context *ctx, GLenum oper, GLuint face,
66 GLuint n, GLubyte stencil[], const GLubyte mask[] )
67 {
68 const GLubyte ref = ctx->Stencil.Ref[face];
69 const GLubyte wrtmask = ctx->Stencil.WriteMask[face];
70 const GLubyte invmask = (GLubyte) (~wrtmask);
71 const GLubyte stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1;
72 GLuint i;
73
74 switch (oper) {
75 case GL_KEEP:
76 /* do nothing */
77 break;
78 case GL_ZERO:
79 if (invmask==0) {
80 for (i=0;i<n;i++) {
81 if (mask[i]) {
82 stencil[i] = 0;
83 }
84 }
85 }
86 else {
87 for (i=0;i<n;i++) {
88 if (mask[i]) {
89 stencil[i] = (GLubyte) (stencil[i] & invmask);
90 }
91 }
92 }
93 break;
94 case GL_REPLACE:
95 if (invmask==0) {
96 for (i=0;i<n;i++) {
97 if (mask[i]) {
98 stencil[i] = ref;
99 }
100 }
101 }
102 else {
103 for (i=0;i<n;i++) {
104 if (mask[i]) {
105 GLubyte s = stencil[i];
106 stencil[i] = (GLubyte) ((invmask & s ) | (wrtmask & ref));
107 }
108 }
109 }
110 break;
111 case GL_INCR:
112 if (invmask==0) {
113 for (i=0;i<n;i++) {
114 if (mask[i]) {
115 GLubyte s = stencil[i];
116 if (s < stencilMax) {
117 stencil[i] = (GLubyte) (s+1);
118 }
119 }
120 }
121 }
122 else {
123 for (i=0;i<n;i++) {
124 if (mask[i]) {
125 /* VERIFY logic of adding 1 to a write-masked value */
126 GLubyte s = stencil[i];
127 if (s < stencilMax) {
128 stencil[i] = (GLubyte) ((invmask & s) | (wrtmask & (s+1)));
129 }
130 }
131 }
132 }
133 break;
134 case GL_DECR:
135 if (invmask==0) {
136 for (i=0;i<n;i++) {
137 if (mask[i]) {
138 GLubyte s = stencil[i];
139 if (s>0) {
140 stencil[i] = (GLubyte) (s-1);
141 }
142 }
143 }
144 }
145 else {
146 for (i=0;i<n;i++) {
147 if (mask[i]) {
148 /* VERIFY logic of subtracting 1 to a write-masked value */
149 GLubyte s = stencil[i];
150 if (s>0) {
151 stencil[i] = (GLubyte) ((invmask & s) | (wrtmask & (s-1)));
152 }
153 }
154 }
155 }
156 break;
157 case GL_INCR_WRAP_EXT:
158 if (invmask==0) {
159 for (i=0;i<n;i++) {
160 if (mask[i]) {
161 stencil[i]++;
162 }
163 }
164 }
165 else {
166 for (i=0;i<n;i++) {
167 if (mask[i]) {
168 GLubyte s = stencil[i];
169 stencil[i] = (GLubyte) ((invmask & s) | (wrtmask & (s+1)));
170 }
171 }
172 }
173 break;
174 case GL_DECR_WRAP_EXT:
175 if (invmask==0) {
176 for (i=0;i<n;i++) {
177 if (mask[i]) {
178 stencil[i]--;
179 }
180 }
181 }
182 else {
183 for (i=0;i<n;i++) {
184 if (mask[i]) {
185 GLubyte s = stencil[i];
186 stencil[i] = (GLubyte) ((invmask & s) | (wrtmask & (s-1)));
187 }
188 }
189 }
190 break;
191 case GL_INVERT:
192 if (invmask==0) {
193 for (i=0;i<n;i++) {
194 if (mask[i]) {
195 GLubyte s = stencil[i];
196 stencil[i] = (GLubyte) ~s;
197 }
198 }
199 }
200 else {
201 for (i=0;i<n;i++) {
202 if (mask[i]) {
203 GLubyte s = stencil[i];
204 stencil[i] = (GLubyte) ((invmask & s) | (wrtmask & ~s));
205 }
206 }
207 }
208 break;
209 default:
210 _mesa_problem(ctx, "Bad stencil op in apply_stencil_op");
211 }
212 }
213
214
215
216
217 /**
218 * Apply stencil test to an array of stencil values (before depth buffering).
219 * Input: face - 0 or 1 for front or back-face polygons
220 * n - number of pixels in the array
221 * stencil - array of [n] stencil values
222 * mask - array [n] of flag: 0=skip the pixel, 1=stencil the pixel
223 * Output: mask - pixels which fail the stencil test will have their
224 * mask flag set to 0.
225 * stencil - updated stencil values (where the test passed)
226 * Return: GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed.
227 */
228 static GLboolean
229 do_stencil_test( struct gl_context *ctx, GLuint face, GLuint n, GLubyte stencil[],
230 GLubyte mask[] )
231 {
232 GLubyte fail[MAX_WIDTH];
233 GLboolean allfail = GL_FALSE;
234 GLuint i;
235 const GLuint valueMask = ctx->Stencil.ValueMask[face];
236 const GLubyte r = (GLubyte) (ctx->Stencil.Ref[face] & valueMask);
237 GLubyte s;
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 for (i=0;i<n;i++) {
266 if (mask[i]) {
267 s = (GLubyte) (stencil[i] & valueMask);
268 if (r < s) {
269 /* passed */
270 fail[i] = 0;
271 }
272 else {
273 fail[i] = 1;
274 mask[i] = 0;
275 }
276 }
277 else {
278 fail[i] = 0;
279 }
280 }
281 break;
282 case GL_LEQUAL:
283 for (i=0;i<n;i++) {
284 if (mask[i]) {
285 s = (GLubyte) (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 for (i=0;i<n;i++) {
302 if (mask[i]) {
303 s = (GLubyte) (stencil[i] & valueMask);
304 if (r > s) {
305 /* passed */
306 fail[i] = 0;
307 }
308 else {
309 fail[i] = 1;
310 mask[i] = 0;
311 }
312 }
313 else {
314 fail[i] = 0;
315 }
316 }
317 break;
318 case GL_GEQUAL:
319 for (i=0;i<n;i++) {
320 if (mask[i]) {
321 s = (GLubyte) (stencil[i] & valueMask);
322 if (r >= s) {
323 /* passed */
324 fail[i] = 0;
325 }
326 else {
327 fail[i] = 1;
328 mask[i] = 0;
329 }
330 }
331 else {
332 fail[i] = 0;
333 }
334 }
335 break;
336 case GL_EQUAL:
337 for (i=0;i<n;i++) {
338 if (mask[i]) {
339 s = (GLubyte) (stencil[i] & valueMask);
340 if (r == s) {
341 /* passed */
342 fail[i] = 0;
343 }
344 else {
345 fail[i] = 1;
346 mask[i] = 0;
347 }
348 }
349 else {
350 fail[i] = 0;
351 }
352 }
353 break;
354 case GL_NOTEQUAL:
355 for (i=0;i<n;i++) {
356 if (mask[i]) {
357 s = (GLubyte) (stencil[i] & valueMask);
358 if (r != s) {
359 /* passed */
360 fail[i] = 0;
361 }
362 else {
363 fail[i] = 1;
364 mask[i] = 0;
365 }
366 }
367 else {
368 fail[i] = 0;
369 }
370 }
371 break;
372 case GL_ALWAYS:
373 /* always pass */
374 for (i=0;i<n;i++) {
375 fail[i] = 0;
376 }
377 break;
378 default:
379 _mesa_problem(ctx, "Bad stencil func in gl_stencil_span");
380 return 0;
381 }
382
383 if (ctx->Stencil.FailFunc[face] != GL_KEEP) {
384 apply_stencil_op( ctx, ctx->Stencil.FailFunc[face], face, n, stencil, fail );
385 }
386
387 return !allfail;
388 }
389
390
391 /**
392 * Compute the zpass/zfail masks by comparing the pre- and post-depth test
393 * masks.
394 */
395 static inline void
396 compute_pass_fail_masks(GLuint n, const GLubyte origMask[],
397 const GLubyte newMask[],
398 GLubyte passMask[], GLubyte failMask[])
399 {
400 GLuint i;
401 for (i = 0; i < n; i++) {
402 ASSERT(newMask[i] == 0 || newMask[i] == 1);
403 passMask[i] = origMask[i] & newMask[i];
404 failMask[i] = origMask[i] & (newMask[i] ^ 1);
405 }
406 }
407
408
409 /**
410 * Apply stencil and depth testing to the span of pixels.
411 * Both software and hardware stencil buffers are acceptable.
412 * Input: n - number of pixels in the span
413 * x, y - location of leftmost pixel in span
414 * z - array [n] of z values
415 * mask - array [n] of flags (1=test this pixel, 0=skip the pixel)
416 * Output: mask - array [n] of flags (1=stencil and depth test passed)
417 * Return: GL_FALSE - all fragments failed the testing
418 * GL_TRUE - one or more fragments passed the testing
419 *
420 */
421 static GLboolean
422 stencil_and_ztest_span(struct gl_context *ctx, SWspan *span, GLuint face)
423 {
424 struct gl_framebuffer *fb = ctx->DrawBuffer;
425 struct gl_renderbuffer *rb = fb->_StencilBuffer;
426 GLubyte stencilRow[MAX_WIDTH];
427 GLubyte *stencil;
428 const GLuint n = span->end;
429 const GLint x = span->x;
430 const GLint y = span->y;
431 GLubyte *mask = span->array->mask;
432
433 ASSERT((span->arrayMask & SPAN_XY) == 0);
434 ASSERT(ctx->Stencil.Enabled);
435 ASSERT(n <= MAX_WIDTH);
436 #ifdef DEBUG
437 if (ctx->Depth.Test) {
438 ASSERT(span->arrayMask & SPAN_Z);
439 }
440 #endif
441
442 stencil = (GLubyte *) rb->GetPointer(ctx, rb, x, y);
443 if (!stencil) {
444 rb->GetRow(ctx, rb, n, x, y, stencilRow);
445 stencil = stencilRow;
446 }
447
448 /*
449 * Apply the stencil test to the fragments.
450 * failMask[i] is 1 if the stencil test failed.
451 */
452 if (do_stencil_test( ctx, face, n, stencil, mask ) == GL_FALSE) {
453 /* all fragments failed the stencil test, we're done. */
454 span->writeAll = GL_FALSE;
455 if (!rb->GetPointer(ctx, rb, 0, 0)) {
456 /* put updated stencil values into buffer */
457 rb->PutRow(ctx, rb, n, x, y, stencil, NULL);
458 }
459 return GL_FALSE;
460 }
461
462 /*
463 * Some fragments passed the stencil test, apply depth test to them
464 * and apply Zpass and Zfail stencil ops.
465 */
466 if (ctx->Depth.Test == GL_FALSE ||
467 ctx->DrawBuffer->_DepthBuffer == NULL) {
468 /*
469 * No depth buffer, just apply zpass stencil function to active pixels.
470 */
471 apply_stencil_op( ctx, ctx->Stencil.ZPassFunc[face], face, n, stencil, mask );
472 }
473 else {
474 /*
475 * Perform depth buffering, then apply zpass or zfail stencil function.
476 */
477 GLubyte passMask[MAX_WIDTH], failMask[MAX_WIDTH], origMask[MAX_WIDTH];
478
479 /* save the current mask bits */
480 memcpy(origMask, mask, n * sizeof(GLubyte));
481
482 /* apply the depth test */
483 _swrast_depth_test_span(ctx, span);
484
485 compute_pass_fail_masks(n, origMask, mask, passMask, failMask);
486
487 /* apply the pass and fail operations */
488 if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
489 apply_stencil_op( ctx, ctx->Stencil.ZFailFunc[face], face,
490 n, stencil, failMask );
491 }
492 if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
493 apply_stencil_op( ctx, ctx->Stencil.ZPassFunc[face], face,
494 n, stencil, passMask );
495 }
496 }
497
498 /*
499 * Write updated stencil values back into hardware stencil buffer.
500 */
501 if (!rb->GetPointer(ctx, rb, 0, 0)) {
502 rb->PutRow(ctx, rb, n, x, y, stencil, NULL);
503 }
504
505 span->writeAll = GL_FALSE;
506
507 return GL_TRUE; /* one or more fragments passed both tests */
508 }
509
510
511
512 /*
513 * Return the address of a stencil buffer value given the window coords:
514 */
515 #define STENCIL_ADDRESS(X, Y) (stencilStart + (Y) * stride + (X))
516
517
518
519 /**
520 * Apply the given stencil operator for each pixel in the array whose
521 * mask flag is set.
522 * \note This is for software stencil buffers only.
523 * Input: n - number of pixels in the span
524 * x, y - array of [n] pixels
525 * operator - the stencil buffer operator
526 * mask - array [n] of flag: 1=apply operator, 0=don't apply operator
527 */
528 static void
529 apply_stencil_op_to_pixels( struct gl_context *ctx,
530 GLuint n, const GLint x[], const GLint y[],
531 GLenum oper, GLuint face, const GLubyte mask[] )
532 {
533 struct gl_framebuffer *fb = ctx->DrawBuffer;
534 struct gl_renderbuffer *rb = fb->_StencilBuffer;
535 const GLubyte stencilMax = (1 << fb->Visual.stencilBits) - 1;
536 const GLubyte ref = ctx->Stencil.Ref[face];
537 const GLubyte wrtmask = ctx->Stencil.WriteMask[face];
538 const GLubyte invmask = (GLubyte) (~wrtmask);
539 GLuint i;
540 GLubyte *stencilStart = (GLubyte *) rb->Data;
541 const GLuint stride = rb->Width;
542
543 ASSERT(rb->GetPointer(ctx, rb, 0, 0));
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 GLubyte *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 GLubyte *sptr = STENCIL_ADDRESS( x[i], y[i] );
562 *sptr = (GLubyte) (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 GLubyte *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 GLubyte *sptr = STENCIL_ADDRESS( x[i], y[i] );
580 *sptr = (GLubyte) ((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 GLubyte *sptr = STENCIL_ADDRESS( x[i], y[i] );
590 if (*sptr < stencilMax) {
591 *sptr = (GLubyte) (*sptr + 1);
592 }
593 }
594 }
595 }
596 else {
597 for (i=0;i<n;i++) {
598 if (mask[i]) {
599 GLubyte *sptr = STENCIL_ADDRESS( x[i], y[i] );
600 if (*sptr < stencilMax) {
601 *sptr = (GLubyte) ((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 GLubyte *sptr = STENCIL_ADDRESS( x[i], y[i] );
612 if (*sptr>0) {
613 *sptr = (GLubyte) (*sptr - 1);
614 }
615 }
616 }
617 }
618 else {
619 for (i=0;i<n;i++) {
620 if (mask[i]) {
621 GLubyte *sptr = STENCIL_ADDRESS( x[i], y[i] );
622 if (*sptr>0) {
623 *sptr = (GLubyte) ((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 GLubyte *sptr = STENCIL_ADDRESS( x[i], y[i] );
634 *sptr = (GLubyte) (*sptr + 1);
635 }
636 }
637 }
638 else {
639 for (i=0;i<n;i++) {
640 if (mask[i]) {
641 GLubyte *sptr = STENCIL_ADDRESS( x[i], y[i] );
642 *sptr = (GLubyte) ((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 GLubyte *sptr = STENCIL_ADDRESS( x[i], y[i] );
652 *sptr = (GLubyte) (*sptr - 1);
653 }
654 }
655 }
656 else {
657 for (i=0;i<n;i++) {
658 if (mask[i]) {
659 GLubyte *sptr = STENCIL_ADDRESS( x[i], y[i] );
660 *sptr = (GLubyte) ((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 GLubyte *sptr = STENCIL_ADDRESS( x[i], y[i] );
670 *sptr = (GLubyte) (~*sptr);
671 }
672 }
673 }
674 else {
675 for (i=0;i<n;i++) {
676 if (mask[i]) {
677 GLubyte *sptr = STENCIL_ADDRESS( x[i], y[i] );
678 *sptr = (GLubyte) ((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 GLubyte r, s;
709 GLuint i;
710 GLboolean allfail = GL_FALSE;
711 const GLuint valueMask = ctx->Stencil.ValueMask[face];
712 const GLubyte *stencilStart = (GLubyte *) rb->Data;
713 const GLuint stride = rb->Width;
714
715 ASSERT(rb->GetPointer(ctx, rb, 0, 0));
716
717 /*
718 * Perform stencil test. The results of this operation are stored
719 * in the fail[] array:
720 * IF fail[i] is non-zero THEN
721 * the stencil fail operator is to be applied
722 * ELSE
723 * the stencil fail operator is not to be applied
724 * ENDIF
725 */
726
727 switch (ctx->Stencil.Function[face]) {
728 case GL_NEVER:
729 /* always fail */
730 for (i=0;i<n;i++) {
731 if (mask[i]) {
732 mask[i] = 0;
733 fail[i] = 1;
734 }
735 else {
736 fail[i] = 0;
737 }
738 }
739 allfail = GL_TRUE;
740 break;
741 case GL_LESS:
742 r = (GLubyte) (ctx->Stencil.Ref[face] & valueMask);
743 for (i=0;i<n;i++) {
744 if (mask[i]) {
745 const GLubyte *sptr = STENCIL_ADDRESS(x[i],y[i]);
746 s = (GLubyte) (*sptr & valueMask);
747 if (r < s) {
748 /* passed */
749 fail[i] = 0;
750 }
751 else {
752 fail[i] = 1;
753 mask[i] = 0;
754 }
755 }
756 else {
757 fail[i] = 0;
758 }
759 }
760 break;
761 case GL_LEQUAL:
762 r = (GLubyte) (ctx->Stencil.Ref[face] & valueMask);
763 for (i=0;i<n;i++) {
764 if (mask[i]) {
765 const GLubyte *sptr = STENCIL_ADDRESS(x[i],y[i]);
766 s = (GLubyte) (*sptr & valueMask);
767 if (r <= s) {
768 /* pass */
769 fail[i] = 0;
770 }
771 else {
772 fail[i] = 1;
773 mask[i] = 0;
774 }
775 }
776 else {
777 fail[i] = 0;
778 }
779 }
780 break;
781 case GL_GREATER:
782 r = (GLubyte) (ctx->Stencil.Ref[face] & valueMask);
783 for (i=0;i<n;i++) {
784 if (mask[i]) {
785 const GLubyte *sptr = STENCIL_ADDRESS(x[i],y[i]);
786 s = (GLubyte) (*sptr & valueMask);
787 if (r > s) {
788 /* passed */
789 fail[i] = 0;
790 }
791 else {
792 fail[i] = 1;
793 mask[i] = 0;
794 }
795 }
796 else {
797 fail[i] = 0;
798 }
799 }
800 break;
801 case GL_GEQUAL:
802 r = (GLubyte) (ctx->Stencil.Ref[face] & valueMask);
803 for (i=0;i<n;i++) {
804 if (mask[i]) {
805 const GLubyte *sptr = STENCIL_ADDRESS(x[i],y[i]);
806 s = (GLubyte) (*sptr & valueMask);
807 if (r >= s) {
808 /* passed */
809 fail[i] = 0;
810 }
811 else {
812 fail[i] = 1;
813 mask[i] = 0;
814 }
815 }
816 else {
817 fail[i] = 0;
818 }
819 }
820 break;
821 case GL_EQUAL:
822 r = (GLubyte) (ctx->Stencil.Ref[face] & valueMask);
823 for (i=0;i<n;i++) {
824 if (mask[i]) {
825 const GLubyte *sptr = STENCIL_ADDRESS(x[i],y[i]);
826 s = (GLubyte) (*sptr & valueMask);
827 if (r == s) {
828 /* passed */
829 fail[i] = 0;
830 }
831 else {
832 fail[i] = 1;
833 mask[i] = 0;
834 }
835 }
836 else {
837 fail[i] = 0;
838 }
839 }
840 break;
841 case GL_NOTEQUAL:
842 r = (GLubyte) (ctx->Stencil.Ref[face] & valueMask);
843 for (i=0;i<n;i++) {
844 if (mask[i]) {
845 const GLubyte *sptr = STENCIL_ADDRESS(x[i],y[i]);
846 s = (GLubyte) (*sptr & valueMask);
847 if (r != s) {
848 /* passed */
849 fail[i] = 0;
850 }
851 else {
852 fail[i] = 1;
853 mask[i] = 0;
854 }
855 }
856 else {
857 fail[i] = 0;
858 }
859 }
860 break;
861 case GL_ALWAYS:
862 /* always pass */
863 for (i=0;i<n;i++) {
864 fail[i] = 0;
865 }
866 break;
867 default:
868 _mesa_problem(ctx, "Bad stencil func in gl_stencil_pixels");
869 return 0;
870 }
871
872 if (ctx->Stencil.FailFunc[face] != GL_KEEP) {
873 apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.FailFunc[face],
874 face, fail );
875 }
876
877 return !allfail;
878 }
879
880
881
882 static void
883 get_s8_values(struct gl_context *ctx, struct gl_renderbuffer *rb,
884 GLuint count, const GLint x[], const GLint y[],
885 GLubyte stencil[])
886 {
887 const GLint w = rb->Width, h = rb->Height;
888 const GLubyte *map = (const GLubyte *) rb->Data;
889 GLuint i;
890
891 if (rb->Format == MESA_FORMAT_S8) {
892 const GLuint rowStride = rb->RowStride;
893 for (i = 0; i < count; i++) {
894 if (x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) {
895 stencil[i] = *(map + y[i] * rowStride + x[i]);
896 }
897 }
898 }
899 else {
900 const GLuint bpp = _mesa_get_format_bytes(rb->Format);
901 const GLuint rowStride = rb->RowStride * bpp;
902 for (i = 0; i < count; i++) {
903 if (x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) {
904 const GLubyte *src = map + y[i] * rowStride + x[i] * bpp;
905 _mesa_unpack_ubyte_stencil_row(rb->Format, 1, src, &stencil[i]);
906 }
907 }
908 }
909 }
910
911
912 /**
913 * Apply stencil and depth testing to an array of pixels.
914 * This is used both for software and hardware stencil buffers.
915 *
916 * The comments in this function are a bit sparse but the code is
917 * almost identical to stencil_and_ztest_span(), which is well
918 * commented.
919 *
920 * Input: n - number of pixels in the array
921 * x, y - array of [n] pixel positions
922 * z - array [n] of z values
923 * mask - array [n] of flags (1=test this pixel, 0=skip the pixel)
924 * Output: mask - array [n] of flags (1=stencil and depth test passed)
925 * Return: GL_FALSE - all fragments failed the testing
926 * GL_TRUE - one or more fragments passed the testing
927 */
928 static GLboolean
929 stencil_and_ztest_pixels( struct gl_context *ctx, SWspan *span, GLuint face )
930 {
931 GLubyte passMask[MAX_WIDTH], failMask[MAX_WIDTH], origMask[MAX_WIDTH];
932 struct gl_framebuffer *fb = ctx->DrawBuffer;
933 struct gl_renderbuffer *rb = fb->_StencilBuffer;
934 const GLuint n = span->end;
935 const GLint *x = span->array->x;
936 const GLint *y = span->array->y;
937 GLubyte *mask = span->array->mask;
938
939 ASSERT(span->arrayMask & SPAN_XY);
940 ASSERT(ctx->Stencil.Enabled);
941 ASSERT(n <= MAX_WIDTH);
942
943 if (!rb->GetPointer(ctx, rb, 0, 0)) {
944 /* No direct access */
945 GLubyte stencil[MAX_WIDTH];
946
947 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
948 get_s8_values(ctx, rb, n, x, y, stencil);
949
950 memcpy(origMask, mask, n * sizeof(GLubyte));
951
952 (void) do_stencil_test(ctx, face, n, stencil, mask);
953
954 if (ctx->Depth.Test == GL_FALSE) {
955 apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face,
956 n, stencil, mask);
957 }
958 else {
959 GLubyte tmpMask[MAX_WIDTH];
960 memcpy(tmpMask, mask, n * sizeof(GLubyte));
961
962 _swrast_depth_test_span(ctx, span);
963
964 compute_pass_fail_masks(n, tmpMask, mask, passMask, failMask);
965
966 if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
967 apply_stencil_op(ctx, ctx->Stencil.ZFailFunc[face], face,
968 n, stencil, failMask);
969 }
970 if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
971 apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face,
972 n, stencil, passMask);
973 }
974 }
975
976 /* Write updated stencil values into hardware stencil buffer */
977 rb->PutValues(ctx, rb, n, x, y, stencil, origMask);
978
979 return GL_TRUE;
980 }
981 else {
982 /* Direct access to stencil buffer */
983
984 if (stencil_test_pixels(ctx, face, n, x, y, mask) == GL_FALSE) {
985 /* all fragments failed the stencil test, we're done. */
986 return GL_FALSE;
987 }
988
989 if (ctx->Depth.Test==GL_FALSE) {
990 apply_stencil_op_to_pixels(ctx, n, x, y,
991 ctx->Stencil.ZPassFunc[face], face, mask);
992 }
993 else {
994 memcpy(origMask, mask, n * sizeof(GLubyte));
995
996 _swrast_depth_test_span(ctx, span);
997
998 compute_pass_fail_masks(n, origMask, mask, passMask, failMask);
999
1000 if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
1001 apply_stencil_op_to_pixels(ctx, n, x, y,
1002 ctx->Stencil.ZFailFunc[face],
1003 face, failMask);
1004 }
1005 if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
1006 apply_stencil_op_to_pixels(ctx, n, x, y,
1007 ctx->Stencil.ZPassFunc[face],
1008 face, passMask);
1009 }
1010 }
1011
1012 return GL_TRUE; /* one or more fragments passed both tests */
1013 }
1014 }
1015
1016
1017 /**
1018 * /return GL_TRUE = one or more fragments passed,
1019 * GL_FALSE = all fragments failed.
1020 */
1021 GLboolean
1022 _swrast_stencil_and_ztest_span(struct gl_context *ctx, SWspan *span)
1023 {
1024 const GLuint face = (span->facing == 0) ? 0 : ctx->Stencil._BackFace;
1025
1026 if (span->arrayMask & SPAN_XY)
1027 return stencil_and_ztest_pixels(ctx, span, face);
1028 else
1029 return stencil_and_ztest_span(ctx, span, face);
1030 }
1031
1032
1033 #if 0
1034 GLuint
1035 clip_span(GLuint bufferWidth, GLuint bufferHeight,
1036 GLint x, GLint y, GLuint *count)
1037 {
1038 GLuint n = *count;
1039 GLuint skipPixels = 0;
1040
1041 if (y < 0 || y >= bufferHeight || x + n <= 0 || x >= bufferWidth) {
1042 /* totally out of bounds */
1043 n = 0;
1044 }
1045 else {
1046 /* left clip */
1047 if (x < 0) {
1048 skipPixels = -x;
1049 x = 0;
1050 n -= skipPixels;
1051 }
1052 /* right clip */
1053 if (x + n > bufferWidth) {
1054 GLint dx = x + n - bufferWidth;
1055 n -= dx;
1056 }
1057 }
1058
1059 *count = n;
1060
1061 return skipPixels;
1062 }
1063 #endif
1064
1065
1066 /**
1067 * Return a span of stencil values from the stencil buffer.
1068 * Used for glRead/CopyPixels
1069 * Input: n - how many pixels
1070 * x,y - location of first pixel
1071 * Output: stencil - the array of stencil values
1072 */
1073 void
1074 _swrast_read_stencil_span(struct gl_context *ctx, struct gl_renderbuffer *rb,
1075 GLint n, GLint x, GLint y, GLubyte stencil[])
1076 {
1077 GLubyte *src;
1078
1079 if (y < 0 || y >= (GLint) rb->Height ||
1080 x + n <= 0 || x >= (GLint) rb->Width) {
1081 /* span is completely outside framebuffer */
1082 return; /* undefined values OK */
1083 }
1084
1085 if (x < 0) {
1086 GLint dx = -x;
1087 x = 0;
1088 n -= dx;
1089 stencil += dx;
1090 }
1091 if (x + n > (GLint) rb->Width) {
1092 GLint dx = x + n - rb->Width;
1093 n -= dx;
1094 }
1095 if (n <= 0) {
1096 return;
1097 }
1098
1099 src = (GLubyte *) rb->Data + y * rb->RowStride +x;
1100 _mesa_unpack_ubyte_stencil_row(rb->Format, n, src, stencil);
1101 }
1102
1103
1104
1105 /**
1106 * Write a span of stencil values to the stencil buffer. This function
1107 * applies the stencil write mask when needed.
1108 * Used for glDraw/CopyPixels
1109 * Input: n - how many pixels
1110 * x, y - location of first pixel
1111 * stencil - the array of stencil values
1112 */
1113 void
1114 _swrast_write_stencil_span(struct gl_context *ctx, GLint n, GLint x, GLint y,
1115 const GLubyte stencil[] )
1116 {
1117 struct gl_framebuffer *fb = ctx->DrawBuffer;
1118 struct gl_renderbuffer *rb = fb->_StencilBuffer;
1119 const GLuint stencilMax = (1 << fb->Visual.stencilBits) - 1;
1120 const GLuint stencilMask = ctx->Stencil.WriteMask[0];
1121
1122 if (y < 0 || y >= (GLint) rb->Height ||
1123 x + n <= 0 || x >= (GLint) rb->Width) {
1124 /* span is completely outside framebuffer */
1125 return; /* undefined values OK */
1126 }
1127 if (x < 0) {
1128 GLint dx = -x;
1129 x = 0;
1130 n -= dx;
1131 stencil += dx;
1132 }
1133 if (x + n > (GLint) rb->Width) {
1134 GLint dx = x + n - rb->Width;
1135 n -= dx;
1136 }
1137 if (n <= 0) {
1138 return;
1139 }
1140
1141 if ((stencilMask & stencilMax) != stencilMax) {
1142 /* need to apply writemask */
1143 GLubyte destVals[MAX_WIDTH], newVals[MAX_WIDTH];
1144 GLint i;
1145 rb->GetRow(ctx, rb, n, x, y, destVals);
1146 for (i = 0; i < n; i++) {
1147 newVals[i]
1148 = (stencil[i] & stencilMask) | (destVals[i] & ~stencilMask);
1149 }
1150 rb->PutRow(ctx, rb, n, x, y, newVals, NULL);
1151 }
1152 else {
1153 rb->PutRow(ctx, rb, n, x, y, stencil, NULL);
1154 }
1155 }
1156
1157
1158
1159 /**
1160 * Clear the stencil buffer. If the buffer is a combined
1161 * depth+stencil buffer, only the stencil bits will be touched.
1162 */
1163 void
1164 _swrast_clear_stencil_buffer(struct gl_context *ctx)
1165 {
1166 struct gl_renderbuffer *rb =
1167 ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
1168 const GLubyte stencilBits = ctx->DrawBuffer->Visual.stencilBits;
1169 const GLuint writeMask = ctx->Stencil.WriteMask[0];
1170 const GLuint stencilMax = (1 << stencilBits) - 1;
1171 GLint x, y, width, height;
1172 GLubyte *map;
1173 GLint rowStride, i, j;
1174 GLbitfield mapMode;
1175
1176 if (!rb || writeMask == 0)
1177 return;
1178
1179 /* compute region to clear */
1180 x = ctx->DrawBuffer->_Xmin;
1181 y = ctx->DrawBuffer->_Ymin;
1182 width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
1183 height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
1184
1185 mapMode = GL_MAP_WRITE_BIT;
1186 if ((writeMask & stencilMax) != stencilMax) {
1187 /* need to mask stencil values */
1188 mapMode |= GL_MAP_READ_BIT;
1189 }
1190 else if (_mesa_get_format_bits(rb->Format, GL_DEPTH_BITS) > 0) {
1191 /* combined depth+stencil, need to mask Z values */
1192 mapMode |= GL_MAP_READ_BIT;
1193 }
1194
1195 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
1196 mapMode, &map, &rowStride);
1197 if (!map) {
1198 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear(stencil)");
1199 return;
1200 }
1201
1202 switch (rb->Format) {
1203 case MESA_FORMAT_S8:
1204 {
1205 GLubyte clear = ctx->Stencil.Clear & writeMask & 0xff;
1206 GLubyte mask = (~writeMask) & 0xff;
1207 if (mask != 0) {
1208 /* masked clear */
1209 for (i = 0; i < height; i++) {
1210 GLubyte *row = map;
1211 for (j = 0; j < width; j++) {
1212 row[j] = (row[j] & mask) | clear;
1213 }
1214 map += rowStride;
1215 }
1216 }
1217 else if (rowStride == width) {
1218 /* clear whole buffer */
1219 memset(map, clear, width * height);
1220 }
1221 else {
1222 /* clear scissored */
1223 for (i = 0; i < height; i++) {
1224 memset(map, clear, width);
1225 map += rowStride;
1226 }
1227 }
1228 }
1229 break;
1230 case MESA_FORMAT_S8_Z24:
1231 {
1232 GLuint clear = (ctx->Stencil.Clear & writeMask & 0xff) << 24;
1233 GLuint mask = (((~writeMask) & 0xff) << 24) | 0xffffff;
1234 for (i = 0; i < height; i++) {
1235 GLuint *row = (GLuint *) map;
1236 for (j = 0; j < width; j++) {
1237 row[j] = (row[j] & mask) | clear;
1238 }
1239 map += rowStride;
1240 }
1241 }
1242 break;
1243 case MESA_FORMAT_Z24_S8:
1244 {
1245 GLuint clear = ctx->Stencil.Clear & writeMask & 0xff;
1246 GLuint mask = 0xffffff00 | ((~writeMask) & 0xff);
1247 for (i = 0; i < height; i++) {
1248 GLuint *row = (GLuint *) map;
1249 for (j = 0; j < width; j++) {
1250 row[j] = (row[j] & mask) | clear;
1251 }
1252 map += rowStride;
1253 }
1254 }
1255 break;
1256 default:
1257 _mesa_problem(ctx, "Unexpected stencil buffer format %s"
1258 " in _swrast_clear_stencil_buffer()",
1259 _mesa_get_format_name(rb->Format));
1260 }
1261
1262 ctx->Driver.UnmapRenderbuffer(ctx, rb);
1263 }