s_stencil.c revision cdc920a0
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 39IF stencil test fails THEN 40 Apply fail-op to stencil value 41 Don't write the pixel (RGBA,Z) 42ELSE 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 48ENDIF 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 */ 63static void 64apply_stencil_op( const GLcontext *ctx, GLenum oper, GLuint face, 65 GLuint n, GLstencil stencil[], const GLubyte mask[] ) 66{ 67 const GLstencil ref = ctx->Stencil.Ref[face]; 68 const GLstencil wrtmask = ctx->Stencil.WriteMask[face]; 69 const GLstencil invmask = (GLstencil) (~wrtmask); 70 const GLstencil stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1; 71 GLuint i; 72 73 switch (oper) { 74 case GL_KEEP: 75 /* do nothing */ 76 break; 77 case GL_ZERO: 78 if (invmask==0) { 79 for (i=0;i<n;i++) { 80 if (mask[i]) { 81 stencil[i] = 0; 82 } 83 } 84 } 85 else { 86 for (i=0;i<n;i++) { 87 if (mask[i]) { 88 stencil[i] = (GLstencil) (stencil[i] & invmask); 89 } 90 } 91 } 92 break; 93 case GL_REPLACE: 94 if (invmask==0) { 95 for (i=0;i<n;i++) { 96 if (mask[i]) { 97 stencil[i] = ref; 98 } 99 } 100 } 101 else { 102 for (i=0;i<n;i++) { 103 if (mask[i]) { 104 GLstencil s = stencil[i]; 105 stencil[i] = (GLstencil) ((invmask & s ) | (wrtmask & ref)); 106 } 107 } 108 } 109 break; 110 case GL_INCR: 111 if (invmask==0) { 112 for (i=0;i<n;i++) { 113 if (mask[i]) { 114 GLstencil s = stencil[i]; 115 if (s < stencilMax) { 116 stencil[i] = (GLstencil) (s+1); 117 } 118 } 119 } 120 } 121 else { 122 for (i=0;i<n;i++) { 123 if (mask[i]) { 124 /* VERIFY logic of adding 1 to a write-masked value */ 125 GLstencil s = stencil[i]; 126 if (s < stencilMax) { 127 stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s+1))); 128 } 129 } 130 } 131 } 132 break; 133 case GL_DECR: 134 if (invmask==0) { 135 for (i=0;i<n;i++) { 136 if (mask[i]) { 137 GLstencil s = stencil[i]; 138 if (s>0) { 139 stencil[i] = (GLstencil) (s-1); 140 } 141 } 142 } 143 } 144 else { 145 for (i=0;i<n;i++) { 146 if (mask[i]) { 147 /* VERIFY logic of subtracting 1 to a write-masked value */ 148 GLstencil s = stencil[i]; 149 if (s>0) { 150 stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s-1))); 151 } 152 } 153 } 154 } 155 break; 156 case GL_INCR_WRAP_EXT: 157 if (invmask==0) { 158 for (i=0;i<n;i++) { 159 if (mask[i]) { 160 stencil[i]++; 161 } 162 } 163 } 164 else { 165 for (i=0;i<n;i++) { 166 if (mask[i]) { 167 GLstencil s = stencil[i]; 168 stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s+1))); 169 } 170 } 171 } 172 break; 173 case GL_DECR_WRAP_EXT: 174 if (invmask==0) { 175 for (i=0;i<n;i++) { 176 if (mask[i]) { 177 stencil[i]--; 178 } 179 } 180 } 181 else { 182 for (i=0;i<n;i++) { 183 if (mask[i]) { 184 GLstencil s = stencil[i]; 185 stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s-1))); 186 } 187 } 188 } 189 break; 190 case GL_INVERT: 191 if (invmask==0) { 192 for (i=0;i<n;i++) { 193 if (mask[i]) { 194 GLstencil s = stencil[i]; 195 stencil[i] = (GLstencil) ~s; 196 } 197 } 198 } 199 else { 200 for (i=0;i<n;i++) { 201 if (mask[i]) { 202 GLstencil s = stencil[i]; 203 stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & ~s)); 204 } 205 } 206 } 207 break; 208 default: 209 _mesa_problem(ctx, "Bad stencil op in apply_stencil_op"); 210 } 211} 212 213 214 215 216/** 217 * Apply stencil test to an array of stencil values (before depth buffering). 218 * Input: face - 0 or 1 for front or back-face polygons 219 * n - number of pixels in the array 220 * stencil - array of [n] stencil values 221 * mask - array [n] of flag: 0=skip the pixel, 1=stencil the pixel 222 * Output: mask - pixels which fail the stencil test will have their 223 * mask flag set to 0. 224 * stencil - updated stencil values (where the test passed) 225 * Return: GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed. 226 */ 227static GLboolean 228do_stencil_test( GLcontext *ctx, GLuint face, GLuint n, GLstencil stencil[], 229 GLubyte mask[] ) 230{ 231 GLubyte fail[MAX_WIDTH]; 232 GLboolean allfail = GL_FALSE; 233 GLuint i; 234 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 */ 394static INLINE void 395compute_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 */ 420static GLboolean 421stencil_and_ztest_span(GLcontext *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 /* 467 * No depth buffer, just apply zpass stencil function to active pixels. 468 */ 469 apply_stencil_op( ctx, ctx->Stencil.ZPassFunc[face], face, n, stencil, mask ); 470 } 471 else { 472 /* 473 * Perform depth buffering, then apply zpass or zfail stencil function. 474 */ 475 GLubyte passMask[MAX_WIDTH], failMask[MAX_WIDTH], origMask[MAX_WIDTH]; 476 477 /* save the current mask bits */ 478 memcpy(origMask, mask, n * sizeof(GLubyte)); 479 480 /* apply the depth test */ 481 _swrast_depth_test_span(ctx, span); 482 483 compute_pass_fail_masks(n, origMask, mask, passMask, failMask); 484 485 /* apply the pass and fail operations */ 486 if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) { 487 apply_stencil_op( ctx, ctx->Stencil.ZFailFunc[face], face, 488 n, stencil, failMask ); 489 } 490 if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) { 491 apply_stencil_op( ctx, ctx->Stencil.ZPassFunc[face], face, 492 n, stencil, passMask ); 493 } 494 } 495 496 /* 497 * Write updated stencil values back into hardware stencil buffer. 498 */ 499 if (!rb->GetPointer(ctx, rb, 0, 0)) { 500 rb->PutRow(ctx, rb, n, x, y, stencil, NULL); 501 } 502 503 span->writeAll = GL_FALSE; 504 505 return GL_TRUE; /* one or more fragments passed both tests */ 506} 507 508 509 510/* 511 * Return the address of a stencil buffer value given the window coords: 512 */ 513#define STENCIL_ADDRESS(X, Y) (stencilStart + (Y) * stride + (X)) 514 515 516 517/** 518 * Apply the given stencil operator for each pixel in the array whose 519 * mask flag is set. 520 * \note This is for software stencil buffers only. 521 * Input: n - number of pixels in the span 522 * x, y - array of [n] pixels 523 * operator - the stencil buffer operator 524 * mask - array [n] of flag: 1=apply operator, 0=don't apply operator 525 */ 526static void 527apply_stencil_op_to_pixels( GLcontext *ctx, 528 GLuint n, const GLint x[], const GLint y[], 529 GLenum oper, GLuint face, const GLubyte mask[] ) 530{ 531 struct gl_framebuffer *fb = ctx->DrawBuffer; 532 struct gl_renderbuffer *rb = fb->_StencilBuffer; 533 const GLstencil stencilMax = (1 << fb->Visual.stencilBits) - 1; 534 const GLstencil ref = ctx->Stencil.Ref[face]; 535 const GLstencil wrtmask = ctx->Stencil.WriteMask[face]; 536 const GLstencil invmask = (GLstencil) (~wrtmask); 537 GLuint i; 538 GLstencil *stencilStart = (GLubyte *) rb->Data; 539 const GLuint stride = rb->Width; 540 541 ASSERT(rb->GetPointer(ctx, rb, 0, 0)); 542 ASSERT(sizeof(GLstencil) == 1); 543 544 switch (oper) { 545 case GL_KEEP: 546 /* do nothing */ 547 break; 548 case GL_ZERO: 549 if (invmask==0) { 550 for (i=0;i<n;i++) { 551 if (mask[i]) { 552 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 553 *sptr = 0; 554 } 555 } 556 } 557 else { 558 for (i=0;i<n;i++) { 559 if (mask[i]) { 560 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 561 *sptr = (GLstencil) (invmask & *sptr); 562 } 563 } 564 } 565 break; 566 case GL_REPLACE: 567 if (invmask==0) { 568 for (i=0;i<n;i++) { 569 if (mask[i]) { 570 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 571 *sptr = ref; 572 } 573 } 574 } 575 else { 576 for (i=0;i<n;i++) { 577 if (mask[i]) { 578 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 579 *sptr = (GLstencil) ((invmask & *sptr ) | (wrtmask & ref)); 580 } 581 } 582 } 583 break; 584 case GL_INCR: 585 if (invmask==0) { 586 for (i=0;i<n;i++) { 587 if (mask[i]) { 588 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 589 if (*sptr < stencilMax) { 590 *sptr = (GLstencil) (*sptr + 1); 591 } 592 } 593 } 594 } 595 else { 596 for (i=0;i<n;i++) { 597 if (mask[i]) { 598 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 599 if (*sptr < stencilMax) { 600 *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr+1))); 601 } 602 } 603 } 604 } 605 break; 606 case GL_DECR: 607 if (invmask==0) { 608 for (i=0;i<n;i++) { 609 if (mask[i]) { 610 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 611 if (*sptr>0) { 612 *sptr = (GLstencil) (*sptr - 1); 613 } 614 } 615 } 616 } 617 else { 618 for (i=0;i<n;i++) { 619 if (mask[i]) { 620 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 621 if (*sptr>0) { 622 *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr-1))); 623 } 624 } 625 } 626 } 627 break; 628 case GL_INCR_WRAP_EXT: 629 if (invmask==0) { 630 for (i=0;i<n;i++) { 631 if (mask[i]) { 632 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 633 *sptr = (GLstencil) (*sptr + 1); 634 } 635 } 636 } 637 else { 638 for (i=0;i<n;i++) { 639 if (mask[i]) { 640 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 641 *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr+1))); 642 } 643 } 644 } 645 break; 646 case GL_DECR_WRAP_EXT: 647 if (invmask==0) { 648 for (i=0;i<n;i++) { 649 if (mask[i]) { 650 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 651 *sptr = (GLstencil) (*sptr - 1); 652 } 653 } 654 } 655 else { 656 for (i=0;i<n;i++) { 657 if (mask[i]) { 658 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 659 *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr-1))); 660 } 661 } 662 } 663 break; 664 case GL_INVERT: 665 if (invmask==0) { 666 for (i=0;i<n;i++) { 667 if (mask[i]) { 668 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 669 *sptr = (GLstencil) (~*sptr); 670 } 671 } 672 } 673 else { 674 for (i=0;i<n;i++) { 675 if (mask[i]) { 676 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 677 *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & ~*sptr)); 678 } 679 } 680 } 681 break; 682 default: 683 _mesa_problem(ctx, "Bad stencilop in apply_stencil_op_to_pixels"); 684 } 685} 686 687 688 689/** 690 * Apply stencil test to an array of pixels before depth buffering. 691 * 692 * \note Used for software stencil buffer only. 693 * Input: n - number of pixels in the span 694 * x, y - array of [n] pixels to stencil 695 * mask - array [n] of flag: 0=skip the pixel, 1=stencil the pixel 696 * Output: mask - pixels which fail the stencil test will have their 697 * mask flag set to 0. 698 * \return GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed. 699 */ 700static GLboolean 701stencil_test_pixels( GLcontext *ctx, GLuint face, GLuint n, 702 const GLint x[], const GLint y[], GLubyte mask[] ) 703{ 704 const struct gl_framebuffer *fb = ctx->DrawBuffer; 705 struct gl_renderbuffer *rb = fb->_StencilBuffer; 706 GLubyte fail[MAX_WIDTH]; 707 GLstencil r, s; 708 GLuint i; 709 GLboolean allfail = GL_FALSE; 710 const GLuint valueMask = ctx->Stencil.ValueMask[face]; 711 const GLstencil *stencilStart = (GLstencil *) rb->Data; 712 const GLuint stride = rb->Width; 713 714 ASSERT(rb->GetPointer(ctx, rb, 0, 0)); 715 ASSERT(sizeof(GLstencil) == 1); 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 = (GLstencil) (ctx->Stencil.Ref[face] & valueMask); 743 for (i=0;i<n;i++) { 744 if (mask[i]) { 745 const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]); 746 s = (GLstencil) (*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 = (GLstencil) (ctx->Stencil.Ref[face] & valueMask); 763 for (i=0;i<n;i++) { 764 if (mask[i]) { 765 const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]); 766 s = (GLstencil) (*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 = (GLstencil) (ctx->Stencil.Ref[face] & valueMask); 783 for (i=0;i<n;i++) { 784 if (mask[i]) { 785 const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]); 786 s = (GLstencil) (*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 = (GLstencil) (ctx->Stencil.Ref[face] & valueMask); 803 for (i=0;i<n;i++) { 804 if (mask[i]) { 805 const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]); 806 s = (GLstencil) (*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 = (GLstencil) (ctx->Stencil.Ref[face] & valueMask); 823 for (i=0;i<n;i++) { 824 if (mask[i]) { 825 const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]); 826 s = (GLstencil) (*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 = (GLstencil) (ctx->Stencil.Ref[face] & valueMask); 843 for (i=0;i<n;i++) { 844 if (mask[i]) { 845 const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]); 846 s = (GLstencil) (*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 883/** 884 * Apply stencil and depth testing to an array of pixels. 885 * This is used both for software and hardware stencil buffers. 886 * 887 * The comments in this function are a bit sparse but the code is 888 * almost identical to stencil_and_ztest_span(), which is well 889 * commented. 890 * 891 * Input: n - number of pixels in the array 892 * x, y - array of [n] pixel positions 893 * z - array [n] of z values 894 * mask - array [n] of flags (1=test this pixel, 0=skip the pixel) 895 * Output: mask - array [n] of flags (1=stencil and depth test passed) 896 * Return: GL_FALSE - all fragments failed the testing 897 * GL_TRUE - one or more fragments passed the testing 898 */ 899static GLboolean 900stencil_and_ztest_pixels( GLcontext *ctx, SWspan *span, GLuint face ) 901{ 902 GLubyte passMask[MAX_WIDTH], failMask[MAX_WIDTH], origMask[MAX_WIDTH]; 903 struct gl_framebuffer *fb = ctx->DrawBuffer; 904 struct gl_renderbuffer *rb = fb->_StencilBuffer; 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 918 ASSERT(rb->DataType == GL_UNSIGNED_BYTE); 919 _swrast_get_values(ctx, rb, n, x, y, stencil, sizeof(GLubyte)); 920 921 memcpy(origMask, mask, n * sizeof(GLubyte)); 922 923 (void) do_stencil_test(ctx, face, n, stencil, mask); 924 925 if (ctx->Depth.Test == GL_FALSE) { 926 apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face, 927 n, stencil, mask); 928 } 929 else { 930 GLubyte tmpMask[MAX_WIDTH]; 931 memcpy(tmpMask, mask, n * sizeof(GLubyte)); 932 933 _swrast_depth_test_span(ctx, span); 934 935 compute_pass_fail_masks(n, tmpMask, mask, passMask, failMask); 936 937 if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) { 938 apply_stencil_op(ctx, ctx->Stencil.ZFailFunc[face], face, 939 n, stencil, failMask); 940 } 941 if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) { 942 apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face, 943 n, stencil, passMask); 944 } 945 } 946 947 /* Write updated stencil values into hardware stencil buffer */ 948 rb->PutValues(ctx, rb, n, x, y, stencil, origMask); 949 950 return GL_TRUE; 951 } 952 else { 953 /* Direct access to stencil buffer */ 954 955 if (stencil_test_pixels(ctx, face, n, x, y, mask) == GL_FALSE) { 956 /* all fragments failed the stencil test, we're done. */ 957 return GL_FALSE; 958 } 959 960 if (ctx->Depth.Test==GL_FALSE) { 961 apply_stencil_op_to_pixels(ctx, n, x, y, 962 ctx->Stencil.ZPassFunc[face], face, mask); 963 } 964 else { 965 memcpy(origMask, mask, n * sizeof(GLubyte)); 966 967 _swrast_depth_test_span(ctx, span); 968 969 compute_pass_fail_masks(n, origMask, mask, passMask, failMask); 970 971 if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) { 972 apply_stencil_op_to_pixels(ctx, n, x, y, 973 ctx->Stencil.ZFailFunc[face], 974 face, failMask); 975 } 976 if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) { 977 apply_stencil_op_to_pixels(ctx, n, x, y, 978 ctx->Stencil.ZPassFunc[face], 979 face, passMask); 980 } 981 } 982 983 return GL_TRUE; /* one or more fragments passed both tests */ 984 } 985} 986 987 988/** 989 * /return GL_TRUE = one or more fragments passed, 990 * GL_FALSE = all fragments failed. 991 */ 992GLboolean 993_swrast_stencil_and_ztest_span(GLcontext *ctx, SWspan *span) 994{ 995 const GLuint face = (span->facing == 0) ? 0 : ctx->Stencil._BackFace; 996 997 if (span->arrayMask & SPAN_XY) 998 return stencil_and_ztest_pixels(ctx, span, face); 999 else 1000 return stencil_and_ztest_span(ctx, span, face); 1001} 1002 1003 1004#if 0 1005GLuint 1006clip_span(GLuint bufferWidth, GLuint bufferHeight, 1007 GLint x, GLint y, GLuint *count) 1008{ 1009 GLuint n = *count; 1010 GLuint skipPixels = 0; 1011 1012 if (y < 0 || y >= bufferHeight || x + n <= 0 || x >= bufferWidth) { 1013 /* totally out of bounds */ 1014 n = 0; 1015 } 1016 else { 1017 /* left clip */ 1018 if (x < 0) { 1019 skipPixels = -x; 1020 x = 0; 1021 n -= skipPixels; 1022 } 1023 /* right clip */ 1024 if (x + n > bufferWidth) { 1025 GLint dx = x + n - bufferWidth; 1026 n -= dx; 1027 } 1028 } 1029 1030 *count = n; 1031 1032 return skipPixels; 1033} 1034#endif 1035 1036 1037/** 1038 * Return a span of stencil values from the stencil buffer. 1039 * Used for glRead/CopyPixels 1040 * Input: n - how many pixels 1041 * x,y - location of first pixel 1042 * Output: stencil - the array of stencil values 1043 */ 1044void 1045_swrast_read_stencil_span(GLcontext *ctx, struct gl_renderbuffer *rb, 1046 GLint n, GLint x, GLint y, GLstencil stencil[]) 1047{ 1048 if (y < 0 || y >= (GLint) rb->Height || 1049 x + n <= 0 || x >= (GLint) rb->Width) { 1050 /* span is completely outside framebuffer */ 1051 return; /* undefined values OK */ 1052 } 1053 1054 if (x < 0) { 1055 GLint dx = -x; 1056 x = 0; 1057 n -= dx; 1058 stencil += dx; 1059 } 1060 if (x + n > (GLint) rb->Width) { 1061 GLint dx = x + n - rb->Width; 1062 n -= dx; 1063 } 1064 if (n <= 0) { 1065 return; 1066 } 1067 1068 rb->GetRow(ctx, rb, n, x, y, stencil); 1069} 1070 1071 1072 1073/** 1074 * Write a span of stencil values to the stencil buffer. This function 1075 * applies the stencil write mask when needed. 1076 * Used for glDraw/CopyPixels 1077 * Input: n - how many pixels 1078 * x, y - location of first pixel 1079 * stencil - the array of stencil values 1080 */ 1081void 1082_swrast_write_stencil_span(GLcontext *ctx, GLint n, GLint x, GLint y, 1083 const GLstencil stencil[] ) 1084{ 1085 struct gl_framebuffer *fb = ctx->DrawBuffer; 1086 struct gl_renderbuffer *rb = fb->_StencilBuffer; 1087 const GLuint stencilMax = (1 << fb->Visual.stencilBits) - 1; 1088 const GLuint stencilMask = ctx->Stencil.WriteMask[0]; 1089 1090 if (y < 0 || y >= (GLint) rb->Height || 1091 x + n <= 0 || x >= (GLint) rb->Width) { 1092 /* span is completely outside framebuffer */ 1093 return; /* undefined values OK */ 1094 } 1095 if (x < 0) { 1096 GLint dx = -x; 1097 x = 0; 1098 n -= dx; 1099 stencil += dx; 1100 } 1101 if (x + n > (GLint) rb->Width) { 1102 GLint dx = x + n - rb->Width; 1103 n -= dx; 1104 } 1105 if (n <= 0) { 1106 return; 1107 } 1108 1109 if ((stencilMask & stencilMax) != stencilMax) { 1110 /* need to apply writemask */ 1111 GLstencil destVals[MAX_WIDTH], newVals[MAX_WIDTH]; 1112 GLint i; 1113 rb->GetRow(ctx, rb, n, x, y, destVals); 1114 for (i = 0; i < n; i++) { 1115 newVals[i] 1116 = (stencil[i] & stencilMask) | (destVals[i] & ~stencilMask); 1117 } 1118 rb->PutRow(ctx, rb, n, x, y, newVals, NULL); 1119 } 1120 else { 1121 rb->PutRow(ctx, rb, n, x, y, stencil, NULL); 1122 } 1123} 1124 1125 1126 1127/** 1128 * Clear the stencil buffer. 1129 */ 1130void 1131_swrast_clear_stencil_buffer( GLcontext *ctx, struct gl_renderbuffer *rb ) 1132{ 1133 const GLubyte stencilBits = ctx->DrawBuffer->Visual.stencilBits; 1134 const GLuint mask = ctx->Stencil.WriteMask[0]; 1135 const GLuint invMask = ~mask; 1136 const GLuint clearVal = (ctx->Stencil.Clear & mask); 1137 const GLuint stencilMax = (1 << stencilBits) - 1; 1138 GLint x, y, width, height; 1139 1140 if (!rb || mask == 0) 1141 return; 1142 1143 ASSERT(rb->DataType == GL_UNSIGNED_BYTE || 1144 rb->DataType == GL_UNSIGNED_SHORT); 1145 1146 ASSERT(rb->_BaseFormat == GL_STENCIL_INDEX); 1147 1148 /* compute region to clear */ 1149 x = ctx->DrawBuffer->_Xmin; 1150 y = ctx->DrawBuffer->_Ymin; 1151 width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; 1152 height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; 1153 1154 if (rb->GetPointer(ctx, rb, 0, 0)) { 1155 /* Direct buffer access */ 1156 if ((mask & stencilMax) != stencilMax) { 1157 /* need to mask the clear */ 1158 if (rb->DataType == GL_UNSIGNED_BYTE) { 1159 GLint i, j; 1160 for (i = 0; i < height; i++) { 1161 GLubyte *stencil = (GLubyte*) rb->GetPointer(ctx, rb, x, y + i); 1162 for (j = 0; j < width; j++) { 1163 stencil[j] = (stencil[j] & invMask) | clearVal; 1164 } 1165 } 1166 } 1167 else { 1168 GLint i, j; 1169 for (i = 0; i < height; i++) { 1170 GLushort *stencil = (GLushort*) rb->GetPointer(ctx, rb, x, y + i); 1171 for (j = 0; j < width; j++) { 1172 stencil[j] = (stencil[j] & invMask) | clearVal; 1173 } 1174 } 1175 } 1176 } 1177 else { 1178 /* no bit masking */ 1179 if (width == (GLint) rb->Width && rb->DataType == GL_UNSIGNED_BYTE) { 1180 /* optimized case */ 1181 /* Note: bottom-to-top raster assumed! */ 1182 GLubyte *stencil = (GLubyte *) rb->GetPointer(ctx, rb, x, y); 1183 GLuint len = width * height * sizeof(GLubyte); 1184 memset(stencil, clearVal, len); 1185 } 1186 else { 1187 /* general case */ 1188 GLint i; 1189 for (i = 0; i < height; i++) { 1190 GLvoid *stencil = rb->GetPointer(ctx, rb, x, y + i); 1191 if (rb->DataType == GL_UNSIGNED_BYTE) { 1192 memset(stencil, clearVal, width); 1193 } 1194 else { 1195 _mesa_memset16((short unsigned int*) stencil, clearVal, width); 1196 } 1197 } 1198 } 1199 } 1200 } 1201 else { 1202 /* no direct access */ 1203 if ((mask & stencilMax) != stencilMax) { 1204 /* need to mask the clear */ 1205 if (rb->DataType == GL_UNSIGNED_BYTE) { 1206 GLint i, j; 1207 for (i = 0; i < height; i++) { 1208 GLubyte stencil[MAX_WIDTH]; 1209 rb->GetRow(ctx, rb, width, x, y + i, stencil); 1210 for (j = 0; j < width; j++) { 1211 stencil[j] = (stencil[j] & invMask) | clearVal; 1212 } 1213 rb->PutRow(ctx, rb, width, x, y + i, stencil, NULL); 1214 } 1215 } 1216 else { 1217 GLint i, j; 1218 for (i = 0; i < height; i++) { 1219 GLushort stencil[MAX_WIDTH]; 1220 rb->GetRow(ctx, rb, width, x, y + i, stencil); 1221 for (j = 0; j < width; j++) { 1222 stencil[j] = (stencil[j] & invMask) | clearVal; 1223 } 1224 rb->PutRow(ctx, rb, width, x, y + i, stencil, NULL); 1225 } 1226 } 1227 } 1228 else { 1229 /* no bit masking */ 1230 const GLubyte clear8 = (GLubyte) clearVal; 1231 const GLushort clear16 = (GLushort) clearVal; 1232 const void *clear; 1233 GLint i; 1234 if (rb->DataType == GL_UNSIGNED_BYTE) { 1235 clear = &clear8; 1236 } 1237 else { 1238 clear = &clear16; 1239 } 1240 for (i = 0; i < height; i++) { 1241 rb->PutMonoRow(ctx, rb, width, x, y + i, clear, NULL); 1242 } 1243 } 1244 } 1245} 1246