Changeset 3598 for trunk/src/opengl/mesa/stencil.c
- Timestamp:
- May 23, 2000, 10:41:28 PM (25 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/opengl/mesa/stencil.c
r2962 r3598 1 /* $Id: stencil.c,v 1. 2 2000-03-01 18:49:35jeroen Exp $ */1 /* $Id: stencil.c,v 1.3 2000-05-23 20:40:54 jeroen Exp $ */ 2 2 3 3 /* 4 4 * Mesa 3-D graphics library 5 * Version: 3. 15 * Version: 3.3 6 6 * 7 7 * Copyright (C) 1999 Brian Paul All Rights Reserved. … … 31 31 #include "all.h" 32 32 #else 33 #ifndef XFree86Server 34 #include <stdlib.h> 35 #include <string.h> 36 #else 37 #include "GL/xf86glx.h" 38 #endif 33 #include "glheader.h" 39 34 #include "types.h" 40 35 #include "context.h" … … 43 38 #include "stencil.h" 44 39 #include "enable.h" 40 #include "mem.h" 41 #include "depth.h" 45 42 #endif 46 43 47 44 48 45 49 /* 50 * Return the address of a stencil buffer value given the window coords: 51 */ 52 #define STENCIL_ADDRESS(X,Y) (ctx->Buffer->Stencil + ctx->Buffer->Width * (Y) + (X)) 53 54 55 void gl_ClearStencil( GLcontext *ctx, GLint s ) 56 { 46 void 47 _mesa_ClearStencil( GLint s ) 48 { 49 GET_CURRENT_CONTEXT(ctx); 57 50 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glClearStencil"); 58 51 ctx->Stencil.Clear = (GLstencil) s; … … 65 58 66 59 67 void gl_StencilFunc( GLcontext *ctx, GLenum func, GLint ref, GLuint mask ) 68 { 60 void 61 _mesa_StencilFunc( GLenum func, GLint ref, GLuint mask ) 62 { 63 GET_CURRENT_CONTEXT(ctx); 69 64 GLint maxref; 70 65 … … 98 93 99 94 100 void gl_StencilMask( GLcontext *ctx, GLuint mask ) 101 { 95 void 96 _mesa_StencilMask( GLuint mask ) 97 { 98 GET_CURRENT_CONTEXT(ctx); 102 99 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glStencilMask"); 103 100 ctx->Stencil.WriteMask = (GLstencil) mask; … … 110 107 111 108 112 void gl_StencilOp( GLcontext *ctx, GLenum fail, GLenum zfail, GLenum zpass ) 113 { 109 void 110 _mesa_StencilOp( GLenum fail, GLenum zfail, GLenum zpass ) 111 { 112 GET_CURRENT_CONTEXT(ctx); 114 113 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glStencilOp"); 115 114 switch (fail) { … … 185 184 186 185 /* 186 * Return the address of a stencil buffer value given the window coords: 187 */ 188 #define STENCIL_ADDRESS(X,Y) \ 189 (ctx->DrawBuffer->Stencil + ctx->DrawBuffer->Width * (Y) + (X)) 190 191 192 193 /* 187 194 * Apply the given stencil operator to the array of stencil values. 188 195 * Don't touch stencil[i] if mask[i] is zero. 189 * Input: n - number of pixels in the span196 * Input: n - size of stencil array 190 197 * oper - the stencil buffer operator 191 198 * stencil - array of stencil values 192 199 * mask - array [n] of flag: 1=apply operator, 0=don't apply operator 200 * Output: stencil - modified values 193 201 */ 194 static void apply_stencil_op( GLcontext *ctx, GLenum oper, 195 GLuint n, GLstencil stencil[], GLubyte mask[] ) 202 static void apply_stencil_op( const GLcontext *ctx, GLenum oper, 203 GLuint n, GLstencil stencil[], 204 const GLubyte mask[] ) 196 205 { 197 206 const GLstencil ref = ctx->Stencil.Ref; … … 205 214 break; 206 215 case GL_ZERO: 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 216 if (invmask==0) { 217 for (i=0;i<n;i++) { 218 if (mask[i]) { 219 stencil[i] = 0; 220 } 221 } 222 } 223 else { 224 for (i=0;i<n;i++) { 225 if (mask[i]) { 226 stencil[i] = (GLstencil) (stencil[i] & invmask); 227 } 228 } 229 } 230 break; 222 231 case GL_REPLACE: 223 224 225 232 if (invmask==0) { 233 for (i=0;i<n;i++) { 234 if (mask[i]) { 226 235 stencil[i] = ref; 227 228 229 230 231 232 233 234 235 236 237 238 236 } 237 } 238 } 239 else { 240 for (i=0;i<n;i++) { 241 if (mask[i]) { 242 GLstencil s = stencil[i]; 243 stencil[i] = (GLstencil) ((invmask & s ) | (wrtmask & ref)); 244 } 245 } 246 } 247 break; 239 248 case GL_INCR: 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 249 if (invmask==0) { 250 for (i=0;i<n;i++) { 251 if (mask[i]) { 252 GLstencil s = stencil[i]; 253 if (s < STENCIL_MAX) { 254 stencil[i] = (GLstencil) (s+1); 255 } 256 } 257 } 258 } 259 else { 260 for (i=0;i<n;i++) { 261 if (mask[i]) { 262 /* VERIFY logic of adding 1 to a write-masked value */ 263 GLstencil s = stencil[i]; 264 if (s < STENCIL_MAX) { 265 stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s+1))); 266 } 267 } 268 } 269 } 270 break; 262 271 case GL_DECR: 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 272 if (invmask==0) { 273 for (i=0;i<n;i++) { 274 if (mask[i]) { 275 GLstencil s = stencil[i]; 276 if (s>0) { 277 stencil[i] = (GLstencil) (s-1); 278 } 279 } 280 } 281 } 282 else { 283 for (i=0;i<n;i++) { 284 if (mask[i]) { 285 /* VERIFY logic of subtracting 1 to a write-masked value */ 286 GLstencil s = stencil[i]; 287 if (s>0) { 288 stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s-1))); 289 } 290 } 291 } 292 } 293 break; 285 294 case GL_INCR_WRAP_EXT: 286 287 288 295 if (invmask==0) { 296 for (i=0;i<n;i++) { 297 if (mask[i]) { 289 298 stencil[i]++; 290 291 292 293 294 295 299 } 300 } 301 } 302 else { 303 for (i=0;i<n;i++) { 304 if (mask[i]) { 296 305 GLstencil s = stencil[i]; 297 stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s tencil[i]+1)));298 299 300 301 306 stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s+1))); 307 } 308 } 309 } 310 break; 302 311 case GL_DECR_WRAP_EXT: 303 304 305 306 307 308 309 310 311 312 312 if (invmask==0) { 313 for (i=0;i<n;i++) { 314 if (mask[i]) { 315 stencil[i]--; 316 } 317 } 318 } 319 else { 320 for (i=0;i<n;i++) { 321 if (mask[i]) { 313 322 GLstencil s = stencil[i]; 314 stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s tencil[i]-1)));315 316 317 318 323 stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s-1))); 324 } 325 } 326 } 327 break; 319 328 case GL_INVERT: 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 329 if (invmask==0) { 330 for (i=0;i<n;i++) { 331 if (mask[i]) { 332 GLstencil s = stencil[i]; 333 stencil[i] = (GLstencil) ~s; 334 } 335 } 336 } 337 else { 338 for (i=0;i<n;i++) { 339 if (mask[i]) { 340 GLstencil s = stencil[i]; 341 stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & ~s)); 342 } 343 } 344 } 345 break; 337 346 default: 338 347 gl_problem(ctx, "Bad stencil op in apply_stencil_op"); … … 342 351 343 352 344 345 353 /* 346 * Apply stencil test to a span of pixels before depth buffering.347 * Input: n - number of pixels in the span348 * x, y - coordinate of left-most pixel in the span354 * Apply stencil test to an array of stencil values (before depth buffering). 355 * Input: n - number of pixels in the array 356 * stencil - array of [n] stencil values 349 357 * mask - array [n] of flag: 0=skip the pixel, 1=stencil the pixel 350 358 * Output: mask - pixels which fail the stencil test will have their 351 359 * mask flag set to 0. 352 * Return: 0 = all pixels failed, 1 = zero or more pixels passed. 360 * stencil - updated stencil values (where the test passed) 361 * Return: GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed. 353 362 */ 354 GLint gl_stencil_span( GLcontext *ctx, 355 GLuint n, GLint x, GLint y, GLubyte mask[] ) 356 { 357 GLubyte fail[MAX_WIDTH]; 358 GLint allfail = 0; 363 static GLboolean 364 do_stencil_test( GLcontext *ctx, GLuint n, GLstencil stencil[], 365 GLubyte mask[] ) 366 { 367 GLubyte fail[PB_SIZE]; 368 GLboolean allfail = GL_FALSE; 359 369 GLuint i; 360 370 GLstencil r, s; 361 GLstencil *stencil; 362 363 stencil = STENCIL_ADDRESS( x, y ); 371 372 ASSERT(n <= PB_SIZE); 364 373 365 374 /* … … 376 385 /* always fail */ 377 386 for (i=0;i<n;i++) { 378 379 380 381 382 383 384 385 386 allfail = 1;387 387 if (mask[i]) { 388 mask[i] = 0; 389 fail[i] = 1; 390 } 391 else { 392 fail[i] = 0; 393 } 394 } 395 allfail = GL_TRUE; 396 break; 388 397 case GL_LESS: 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 398 r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask); 399 for (i=0;i<n;i++) { 400 if (mask[i]) { 401 s = (GLstencil) (stencil[i] & ctx->Stencil.ValueMask); 402 if (r < s) { 403 /* passed */ 404 fail[i] = 0; 405 } 406 else { 407 fail[i] = 1; 408 mask[i] = 0; 409 } 410 } 411 else { 412 fail[i] = 0; 413 } 414 } 415 break; 407 416 case GL_LEQUAL: 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 417 r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask); 418 for (i=0;i<n;i++) { 419 if (mask[i]) { 420 s = (GLstencil) (stencil[i] & ctx->Stencil.ValueMask); 421 if (r <= s) { 422 /* pass */ 423 fail[i] = 0; 424 } 425 else { 426 fail[i] = 1; 427 mask[i] = 0; 428 } 429 } 430 else { 431 fail[i] = 0; 432 } 433 } 434 break; 426 435 case GL_GREATER: 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 436 r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask); 437 for (i=0;i<n;i++) { 438 if (mask[i]) { 439 s = (GLstencil) (stencil[i] & ctx->Stencil.ValueMask); 440 if (r > s) { 441 /* passed */ 442 fail[i] = 0; 443 } 444 else { 445 fail[i] = 1; 446 mask[i] = 0; 447 } 448 } 449 else { 450 fail[i] = 0; 451 } 452 } 453 break; 445 454 case GL_GEQUAL: 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 455 r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask); 456 for (i=0;i<n;i++) { 457 if (mask[i]) { 458 s = (GLstencil) (stencil[i] & ctx->Stencil.ValueMask); 459 if (r >= s) { 460 /* passed */ 461 fail[i] = 0; 462 } 463 else { 464 fail[i] = 1; 465 mask[i] = 0; 466 } 467 } 468 else { 469 fail[i] = 0; 470 } 471 } 472 break; 464 473 case GL_EQUAL: 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 474 r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask); 475 for (i=0;i<n;i++) { 476 if (mask[i]) { 477 s = (GLstencil) (stencil[i] & ctx->Stencil.ValueMask); 478 if (r == s) { 479 /* passed */ 480 fail[i] = 0; 481 } 482 else { 483 fail[i] = 1; 484 mask[i] = 0; 485 } 486 } 487 else { 488 fail[i] = 0; 489 } 490 } 491 break; 483 492 case GL_NOTEQUAL: 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 493 r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask); 494 for (i=0;i<n;i++) { 495 if (mask[i]) { 496 s = (GLstencil) (stencil[i] & ctx->Stencil.ValueMask); 497 if (r != s) { 498 /* passed */ 499 fail[i] = 0; 500 } 501 else { 502 fail[i] = 1; 503 mask[i] = 0; 504 } 505 } 506 else { 507 fail[i] = 0; 508 } 509 } 510 break; 502 511 case GL_ALWAYS: 503 504 505 506 507 512 /* always pass */ 513 for (i=0;i<n;i++) { 514 fail[i] = 0; 515 } 516 break; 508 517 default: 509 518 gl_problem(ctx, "Bad stencil func in gl_stencil_span"); … … 515 524 } 516 525 517 return (allfail) ? 0 : 1;526 return !allfail; 518 527 } 519 528 … … 522 531 523 532 /* 524 * Apply the combination depth-buffer/stencil operator to a span of pixels. 533 * Apply stencil and depth testing to an array of pixels. 534 * Hardware or software stencil buffer acceptable. 525 535 * Input: n - number of pixels in the span 526 * x, y - location of leftmost pixel in span527 536 * z - array [n] of z values 528 * Input: mask - array [n] of flags (1=test this pixel, 0=skip the pixel) 529 * Output: mask - array [n] of flags (1=depth test passed, 0=failed) 537 * stencil - array [n] of stencil values 538 * mask - array [n] of flags (1=test this pixel, 0=skip the pixel) 539 * Output: stencil - modified stencil values 540 * mask - array [n] of flags (1=stencil and depth test passed) 541 * Return: GL_TRUE - all fragments failed the testing 542 * GL_FALSE - one or more fragments passed the testing 543 * 530 544 */ 531 void gl_depth_stencil_span( GLcontext *ctx, 532 GLuint n, GLint x, GLint y, const GLdepth z[], 533 GLubyte mask[] ) 534 { 535 GLstencil *stencil = STENCIL_ADDRESS(x, y); 536 545 static GLboolean 546 stencil_and_depth_test_span( GLcontext *ctx, GLuint n, GLint x, GLint y, 547 const GLdepth z[], GLstencil stencil[], 548 GLubyte mask[] ) 549 { 550 ASSERT(ctx->Stencil.Enabled); 551 ASSERT(n <= PB_SIZE); 552 553 /* 554 * Apply the stencil test to the fragments. 555 * failMask[i] is 1 if the stencil test failed. 556 */ 557 if (do_stencil_test( ctx, n, stencil, mask ) == GL_FALSE) { 558 /* all fragments failed the stencil test, we're done. */ 559 return GL_FALSE; 560 } 561 562 563 /* 564 * Some fragments passed the stencil test, apply depth test to them 565 * and apply Zpass and Zfail stencil ops. 566 */ 537 567 if (ctx->Depth.Test==GL_FALSE) { 538 568 /* … … 552 582 553 583 /* apply the depth test */ 554 if (ctx->Driver.DepthTestSpan) 555 (*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask ); 584 _mesa_depth_test_span(ctx, n, x, y, z, mask); 556 585 557 586 /* Set the stencil pass/fail flags according to result of depth testing. … … 561 590 * Depth test passed 562 591 * else 563 * assert(oldmask[i] && !newmask[i])592 * ASSERT(oldmask[i] && !newmask[i]) 564 593 * Depth test failed 565 594 * endif … … 579 608 } 580 609 } 610 611 return GL_TRUE; /* one or more fragments passed both tests */ 612 } 613 614 615 616 /* 617 * Apply stencil and depth testing to the span of pixels. 618 * Both software and hardware stencil buffers are acceptable. 619 * Input: n - number of pixels in the span 620 * x, y - location of leftmost pixel in span 621 * z - array [n] of z values 622 * mask - array [n] of flags (1=test this pixel, 0=skip the pixel) 623 * Output: mask - array [n] of flags (1=stencil and depth test passed) 624 * Return: GL_TRUE - all fragments failed the testing 625 * GL_FALSE - one or more fragments passed the testing 626 * 627 */ 628 GLboolean 629 gl_stencil_and_depth_test_span( GLcontext *ctx, GLuint n, GLint x, GLint y, 630 const GLdepth z[], GLubyte mask[] ) 631 { 632 GLstencil stencilRow[MAX_WIDTH]; 633 GLstencil *stencil; 634 GLboolean result; 635 636 ASSERT(ctx->Stencil.Enabled); 637 ASSERT(n <= MAX_WIDTH); 638 639 /* Get initial stencil values */ 640 if (ctx->Driver.WriteStencilSpan) { 641 ASSERT(ctx->Driver.ReadStencilSpan); 642 /* Get stencil values from the hardware stencil buffer */ 643 (*ctx->Driver.ReadStencilSpan)(ctx, n, x, y, stencilRow); 644 stencil = stencilRow; 645 } 646 else { 647 /* software stencil buffer */ 648 stencil = STENCIL_ADDRESS(x, y); 649 } 650 651 /* do all the stencil/depth testing/updating */ 652 result = stencil_and_depth_test_span( ctx, n, x, y, z, stencil, mask ); 653 654 if (ctx->Driver.WriteStencilSpan) { 655 /* Write updated stencil values into hardware stencil buffer */ 656 (ctx->Driver.WriteStencilSpan)(ctx, n, x, y, stencil, mask ); 657 } 658 659 return result; 581 660 } 582 661 … … 586 665 /* 587 666 * Apply the given stencil operator for each pixel in the array whose 588 * mask flag is set. 667 * mask flag is set. This is for software stencil buffers only. 589 668 * Input: n - number of pixels in the span 590 669 * x, y - array of [n] pixels … … 592 671 * mask - array [n] of flag: 1=apply operator, 0=don't apply operator 593 672 */ 594 static void apply_stencil_op_to_pixels( GLcontext *ctx, 595 GLuint n, const GLint x[], 596 const GLint y[], 597 GLenum oper, GLubyte mask[] ) 598 { 673 static void 674 apply_stencil_op_to_pixels( const GLcontext *ctx, 675 GLuint n, const GLint x[], const GLint y[], 676 GLenum oper, const GLubyte mask[] ) 677 { 678 const GLstencil ref = ctx->Stencil.Ref; 679 const GLstencil wrtmask = ctx->Stencil.WriteMask; 680 const GLstencil invmask = (GLstencil) (~ctx->Stencil.WriteMask); 599 681 GLuint i; 600 GLstencil ref; 601 GLstencil wrtmask, invmask; 602 603 wrtmask = ctx->Stencil.WriteMask; 604 invmask = (GLstencil) (~ctx->Stencil.WriteMask); 605 606 ref = ctx->Stencil.Ref; 682 683 ASSERT(!ctx->Driver.WriteStencilSpan); /* software stencil buffer only! */ 607 684 608 685 switch (oper) { … … 611 688 break; 612 689 case GL_ZERO: 613 614 615 690 if (invmask==0) { 691 for (i=0;i<n;i++) { 692 if (mask[i]) { 616 693 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 617 694 *sptr = 0; 618 619 620 621 622 623 695 } 696 } 697 } 698 else { 699 for (i=0;i<n;i++) { 700 if (mask[i]) { 624 701 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 625 626 627 628 629 702 *sptr = (GLstencil) (invmask & *sptr); 703 } 704 } 705 } 706 break; 630 707 case GL_REPLACE: 631 632 633 708 if (invmask==0) { 709 for (i=0;i<n;i++) { 710 if (mask[i]) { 634 711 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 635 712 *sptr = ref; 636 637 638 639 640 641 713 } 714 } 715 } 716 else { 717 for (i=0;i<n;i++) { 718 if (mask[i]) { 642 719 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 643 644 645 646 647 720 *sptr = (GLstencil) ((invmask & *sptr ) | (wrtmask & ref)); 721 } 722 } 723 } 724 break; 648 725 case GL_INCR: 649 650 651 726 if (invmask==0) { 727 for (i=0;i<n;i++) { 728 if (mask[i]) { 652 729 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 653 654 655 656 657 658 659 660 661 730 if (*sptr < STENCIL_MAX) { 731 *sptr = (GLstencil) (*sptr + 1); 732 } 733 } 734 } 735 } 736 else { 737 for (i=0;i<n;i++) { 738 if (mask[i]) { 662 739 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 663 664 665 666 667 668 669 740 if (*sptr < STENCIL_MAX) { 741 *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr+1))); 742 } 743 } 744 } 745 } 746 break; 670 747 case GL_DECR: 671 672 673 748 if (invmask==0) { 749 for (i=0;i<n;i++) { 750 if (mask[i]) { 674 751 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 675 676 677 678 679 680 681 682 683 752 if (*sptr>0) { 753 *sptr = (GLstencil) (*sptr - 1); 754 } 755 } 756 } 757 } 758 else { 759 for (i=0;i<n;i++) { 760 if (mask[i]) { 684 761 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 685 686 687 688 689 690 691 762 if (*sptr>0) { 763 *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr-1))); 764 } 765 } 766 } 767 } 768 break; 692 769 case GL_INCR_WRAP_EXT: 693 694 695 770 if (invmask==0) { 771 for (i=0;i<n;i++) { 772 if (mask[i]) { 696 773 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 697 774 *sptr = (GLstencil) (*sptr + 1); 698 699 700 701 702 703 775 } 776 } 777 } 778 else { 779 for (i=0;i<n;i++) { 780 if (mask[i]) { 704 781 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 705 782 *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr+1))); 706 707 708 709 783 } 784 } 785 } 786 break; 710 787 case GL_DECR_WRAP_EXT: 711 712 713 788 if (invmask==0) { 789 for (i=0;i<n;i++) { 790 if (mask[i]) { 714 791 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 715 792 *sptr = (GLstencil) (*sptr - 1); 716 717 718 719 720 721 793 } 794 } 795 } 796 else { 797 for (i=0;i<n;i++) { 798 if (mask[i]) { 722 799 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 723 800 *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr-1))); 724 725 726 727 801 } 802 } 803 } 804 break; 728 805 case GL_INVERT: 729 730 731 806 if (invmask==0) { 807 for (i=0;i<n;i++) { 808 if (mask[i]) { 732 809 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 733 810 *sptr = (GLstencil) (~*sptr); 734 735 736 737 738 739 811 } 812 } 813 } 814 else { 815 for (i=0;i<n;i++) { 816 if (mask[i]) { 740 817 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 741 818 *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & ~*sptr)); 742 743 744 745 819 } 820 } 821 } 822 break; 746 823 default: 747 824 gl_problem(ctx, "Bad stencilop in apply_stencil_op_to_pixels"); … … 753 830 /* 754 831 * Apply stencil test to an array of pixels before depth buffering. 832 * Used for software stencil buffer only. 755 833 * Input: n - number of pixels in the span 756 834 * x, y - array of [n] pixels to stencil … … 760 838 * Return: 0 = all pixels failed, 1 = zero or more pixels passed. 761 839 */ 762 GLint gl_stencil_pixels( GLcontext *ctx, 763 GLuint n, const GLint x[], const GLint y[],764 840 static GLboolean 841 stencil_test_pixels( GLcontext *ctx, GLuint n, 842 const GLint x[], const GLint y[], GLubyte mask[] ) 765 843 { 766 844 GLubyte fail[PB_SIZE]; 767 845 GLstencil r, s; 768 846 GLuint i; 769 GLint allfail = 0; 847 GLboolean allfail = GL_FALSE; 848 849 ASSERT(!ctx->Driver.WriteStencilSpan); /* software stencil buffer only! */ 770 850 771 851 /* … … 783 863 /* always fail */ 784 864 for (i=0;i<n;i++) { 785 786 787 788 789 790 791 792 793 allfail = 1;794 865 if (mask[i]) { 866 mask[i] = 0; 867 fail[i] = 1; 868 } 869 else { 870 fail[i] = 0; 871 } 872 } 873 allfail = GL_TRUE; 874 break; 795 875 case GL_LESS: 796 797 798 876 r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask); 877 for (i=0;i<n;i++) { 878 if (mask[i]) { 799 879 GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]); 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 880 s = (GLstencil) (*sptr & ctx->Stencil.ValueMask); 881 if (r < s) { 882 /* passed */ 883 fail[i] = 0; 884 } 885 else { 886 fail[i] = 1; 887 mask[i] = 0; 888 } 889 } 890 else { 891 fail[i] = 0; 892 } 893 } 894 break; 815 895 case GL_LEQUAL: 816 817 818 896 r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask); 897 for (i=0;i<n;i++) { 898 if (mask[i]) { 819 899 GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]); 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 900 s = (GLstencil) (*sptr & ctx->Stencil.ValueMask); 901 if (r <= s) { 902 /* pass */ 903 fail[i] = 0; 904 } 905 else { 906 fail[i] = 1; 907 mask[i] = 0; 908 } 909 } 910 else { 911 fail[i] = 0; 912 } 913 } 914 break; 835 915 case GL_GREATER: 836 837 838 916 r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask); 917 for (i=0;i<n;i++) { 918 if (mask[i]) { 839 919 GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]); 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 920 s = (GLstencil) (*sptr & ctx->Stencil.ValueMask); 921 if (r > s) { 922 /* passed */ 923 fail[i] = 0; 924 } 925 else { 926 fail[i] = 1; 927 mask[i] = 0; 928 } 929 } 930 else { 931 fail[i] = 0; 932 } 933 } 934 break; 855 935 case GL_GEQUAL: 856 857 858 936 r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask); 937 for (i=0;i<n;i++) { 938 if (mask[i]) { 859 939 GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]); 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 940 s = (GLstencil) (*sptr & ctx->Stencil.ValueMask); 941 if (r >= s) { 942 /* passed */ 943 fail[i] = 0; 944 } 945 else { 946 fail[i] = 1; 947 mask[i] = 0; 948 } 949 } 950 else { 951 fail[i] = 0; 952 } 953 } 954 break; 875 955 case GL_EQUAL: 876 877 878 956 r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask); 957 for (i=0;i<n;i++) { 958 if (mask[i]) { 879 959 GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]); 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 960 s = (GLstencil) (*sptr & ctx->Stencil.ValueMask); 961 if (r == s) { 962 /* passed */ 963 fail[i] = 0; 964 } 965 else { 966 fail[i] = 1; 967 mask[i] = 0; 968 } 969 } 970 else { 971 fail[i] = 0; 972 } 973 } 974 break; 895 975 case GL_NOTEQUAL: 896 897 898 976 r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask); 977 for (i=0;i<n;i++) { 978 if (mask[i]) { 899 979 GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]); 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 980 s = (GLstencil) (*sptr & ctx->Stencil.ValueMask); 981 if (r != s) { 982 /* passed */ 983 fail[i] = 0; 984 } 985 else { 986 fail[i] = 1; 987 mask[i] = 0; 988 } 989 } 990 else { 991 fail[i] = 0; 992 } 993 } 994 break; 915 995 case GL_ALWAYS: 916 917 918 919 920 996 /* always pass */ 997 for (i=0;i<n;i++) { 998 fail[i] = 0; 999 } 1000 break; 921 1001 default: 922 1002 gl_problem(ctx, "Bad stencil func in gl_stencil_pixels"); … … 924 1004 } 925 1005 926 apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.FailFunc, fail ); 927 928 return (allfail) ? 0 : 1; 1006 if (ctx->Stencil.FailFunc != GL_KEEP) { 1007 apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.FailFunc, fail ); 1008 } 1009 1010 return !allfail; 929 1011 } 930 1012 … … 933 1015 934 1016 /* 935 * Apply the combination depth-buffer/stencil operator to a span of pixels. 936 * Input: n - number of pixels in the span 937 * x, y - array of [n] pixels to stencil 1017 * Apply stencil and depth testing to an array of pixels. 1018 * This is used both for software and hardware stencil buffers. 1019 * 1020 * The comments in this function are a bit sparse but the code is 1021 * almost identical to stencil_and_depth_test_span(), which is well 1022 * commented. 1023 * 1024 * Input: n - number of pixels in the array 1025 * x, y - array of [n] pixel positions 938 1026 * z - array [n] of z values 939 * Input: mask - array [n] of flags (1=test this pixel, 0=skip the pixel) 940 * Output: mask - array [n] of flags (1=depth test passed, 0=failed) 1027 * mask - array [n] of flags (1=test this pixel, 0=skip the pixel) 1028 * Output: mask - array [n] of flags (1=stencil and depth test passed) 1029 * Return: GL_TRUE - all fragments failed the testing 1030 * GL_FALSE - one or more fragments passed the testing 941 1031 */ 942 void gl_depth_stencil_pixels( GLcontext *ctx, 943 GLuint n, const GLint x[], const GLint y[], 944 const GLdepth z[], GLubyte mask[] ) 945 { 946 if (ctx->Depth.Test==GL_FALSE) { 947 /* 948 * No depth buffer, just apply zpass stencil function to active pixels. 949 */ 950 apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.ZPassFunc, mask ); 1032 GLboolean 1033 gl_stencil_and_depth_test_pixels( GLcontext *ctx, 1034 GLuint n, const GLint x[], const GLint y[], 1035 const GLdepth z[], GLubyte mask[] ) 1036 { 1037 ASSERT(ctx->Stencil.Enabled); 1038 ASSERT(n <= PB_SIZE); 1039 1040 if (ctx->Driver.WriteStencilPixels) { 1041 /*** Hardware stencil buffer ***/ 1042 GLstencil stencil[PB_SIZE]; 1043 GLubyte mask[PB_SIZE]; 1044 1045 ASSERT(ctx->Driver.ReadStencilPixels); 1046 (*ctx->Driver.ReadStencilPixels)(ctx, n, x, y, stencil); 1047 1048 1049 if (do_stencil_test( ctx, n, stencil, mask ) == GL_FALSE) { 1050 /* all fragments failed the stencil test, we're done. */ 1051 return GL_FALSE; 1052 } 1053 1054 if (ctx->Depth.Test == GL_FALSE) { 1055 apply_stencil_op( ctx, ctx->Stencil.ZPassFunc, n, stencil, mask ); 1056 } 1057 else { 1058 GLubyte passmask[PB_SIZE], failmask[PB_SIZE], oldmask[PB_SIZE]; 1059 GLuint i; 1060 1061 MEMCPY(oldmask, mask, n * sizeof(GLubyte)); 1062 1063 _mesa_depth_test_pixels(ctx, n, x, y, z, mask); 1064 1065 for (i=0;i<n;i++) { 1066 ASSERT(mask[i] == 0 || mask[i] == 1); 1067 passmask[i] = oldmask[i] & mask[i]; 1068 failmask[i] = oldmask[i] & (mask[i] ^ 1); 1069 } 1070 1071 if (ctx->Stencil.ZFailFunc != GL_KEEP) { 1072 apply_stencil_op( ctx, ctx->Stencil.ZFailFunc, n, stencil, failmask ); 1073 } 1074 if (ctx->Stencil.ZPassFunc != GL_KEEP) { 1075 apply_stencil_op( ctx, ctx->Stencil.ZPassFunc, n, stencil, passmask ); 1076 } 1077 } 1078 1079 /* Write updated stencil values into hardware stencil buffer */ 1080 (ctx->Driver.WriteStencilPixels)(ctx, n, x, y, stencil, mask ); 1081 1082 return GL_TRUE; 1083 951 1084 } 952 1085 else { 953 /* 954 * Perform depth buffering, then apply zpass or zfail stencil function. 955 */ 956 GLubyte passmask[PB_SIZE], failmask[PB_SIZE], oldmask[PB_SIZE]; 957 GLuint i; 958 959 /* save the current mask bits */ 960 MEMCPY(oldmask, mask, n * sizeof(GLubyte)); 961 962 /* apply the depth test */ 963 if (ctx->Driver.DepthTestPixels) 964 (*ctx->Driver.DepthTestPixels)( ctx, n, x, y, z, mask ); 965 966 /* Set the stencil pass/fail flags according to result of depth testing. 967 * if oldmask[i] == 0 then 968 * Don't touch the stencil value 969 * else if oldmask[i] and newmask[i] then 970 * Depth test passed 971 * else 972 * assert(oldmask[i] && !newmask[i]) 973 * Depth test failed 974 * endif 975 */ 976 for (i=0;i<n;i++) { 977 ASSERT(mask[i] == 0 || mask[i] == 1); 978 passmask[i] = oldmask[i] & mask[i]; 979 failmask[i] = oldmask[i] & (mask[i] ^ 1); 980 } 981 982 /* apply the pass and fail operations */ 983 apply_stencil_op_to_pixels( ctx, n, x, y, 984 ctx->Stencil.ZFailFunc, failmask ); 985 apply_stencil_op_to_pixels( ctx, n, x, y, 986 ctx->Stencil.ZPassFunc, passmask ); 987 } 988 1086 /*** Software stencil buffer ***/ 1087 1088 if (stencil_test_pixels(ctx, n, x, y, mask) == GL_FALSE) { 1089 /* all fragments failed the stencil test, we're done. */ 1090 return GL_FALSE; 1091 } 1092 1093 1094 if (ctx->Depth.Test==GL_FALSE) { 1095 apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.ZPassFunc, mask ); 1096 } 1097 else { 1098 GLubyte passmask[PB_SIZE], failmask[PB_SIZE], oldmask[PB_SIZE]; 1099 GLuint i; 1100 1101 MEMCPY(oldmask, mask, n * sizeof(GLubyte)); 1102 1103 _mesa_depth_test_pixels(ctx, n, x, y, z, mask); 1104 1105 for (i=0;i<n;i++) { 1106 ASSERT(mask[i] == 0 || mask[i] == 1); 1107 passmask[i] = oldmask[i] & mask[i]; 1108 failmask[i] = oldmask[i] & (mask[i] ^ 1); 1109 } 1110 1111 if (ctx->Stencil.ZFailFunc != GL_KEEP) { 1112 apply_stencil_op_to_pixels( ctx, n, x, y, 1113 ctx->Stencil.ZFailFunc, failmask ); 1114 } 1115 if (ctx->Stencil.ZPassFunc != GL_KEEP) { 1116 apply_stencil_op_to_pixels( ctx, n, x, y, 1117 ctx->Stencil.ZPassFunc, passmask ); 1118 } 1119 } 1120 1121 return GL_TRUE; /* one or more fragments passed both tests */ 1122 } 989 1123 } 990 1124 … … 993 1127 /* 994 1128 * Return a span of stencil values from the stencil buffer. 1129 * Used for glRead/CopyPixels 995 1130 * Input: n - how many pixels 996 1131 * x,y - location of first pixel … … 998 1133 */ 999 1134 void gl_read_stencil_span( GLcontext *ctx, 1000 GLuint n, GLint x, GLint y, GLstencil stencil[] ) 1001 { 1002 if (ctx->Buffer->Stencil) { 1003 const GLstencil *s = STENCIL_ADDRESS( x, y ); 1135 GLint n, GLint x, GLint y, GLstencil stencil[] ) 1136 { 1137 ASSERT(n >= 0); 1138 if (ctx->DrawBuffer->Stencil) { 1139 if (ctx->Driver.ReadStencilSpan) { 1140 (*ctx->Driver.ReadStencilSpan)( ctx, (GLuint) n, x, y, stencil ); 1141 } 1142 else { 1143 const GLstencil *s = STENCIL_ADDRESS( x, y ); 1004 1144 #if STENCIL_BITS == 8 1005 MEMCPY( stencil, s, n * sizeof(GLstencil) );1145 MEMCPY( stencil, s, n * sizeof(GLstencil) ); 1006 1146 #else 1007 GLuint i;1008 for (i=0;i<n;i++)1009 stencil[i] = s[i];1147 GLuint i; 1148 for (i=0;i<n;i++) 1149 stencil[i] = s[i]; 1010 1150 #endif 1151 } 1011 1152 } 1012 1153 } … … 1016 1157 /* 1017 1158 * Write a span of stencil values to the stencil buffer. 1159 * Used for glDraw/CopyPixels 1018 1160 * Input: n - how many pixels 1019 * x, y - location of first pixel1161 * x, y - location of first pixel 1020 1162 * stencil - the array of stencil values 1021 1163 */ 1022 1164 void gl_write_stencil_span( GLcontext *ctx, 1023 GLuint n, GLint x, GLint y, 1024 const GLstencil stencil[] ) 1025 { 1026 if (ctx->Buffer->Stencil) { 1027 GLstencil *s = STENCIL_ADDRESS( x, y ); 1165 GLint n, GLint x, GLint y, 1166 const GLstencil stencil[] ) 1167 { 1168 ASSERT(n >= 0); 1169 if (ctx->DrawBuffer->Stencil) { 1170 /* do clipping */ 1171 if (y < ctx->DrawBuffer->Ymin || y > ctx->DrawBuffer->Ymax) 1172 return; 1173 if (x < ctx->DrawBuffer->Xmin) { 1174 GLint diff = ctx->DrawBuffer->Xmin - x; 1175 n -= diff; 1176 stencil += diff; 1177 x = ctx->DrawBuffer->Xmin; 1178 } 1179 if (x + n > ctx->DrawBuffer->Xmax) { 1180 GLint diff = x + n - ctx->DrawBuffer->Xmax; 1181 n -= diff; 1182 } 1183 1184 ASSERT( n >= 0); 1185 1186 if (ctx->Driver.WriteStencilSpan) { 1187 (*ctx->Driver.WriteStencilSpan)( ctx, n, x, y, stencil, NULL ); 1188 } 1189 else { 1190 GLstencil *s = STENCIL_ADDRESS( x, y ); 1028 1191 #if STENCIL_BITS == 8 1029 MEMCPY( s, stencil, n * sizeof(GLstencil) );1192 MEMCPY( s, stencil, n * sizeof(GLstencil) ); 1030 1193 #else 1031 GLuint i;1032 for (i=0;i<n;i++)1033 s[i] = stencil[i];1194 GLuint i; 1195 for (i=0;i<n;i++) 1196 s[i] = stencil[i]; 1034 1197 #endif 1198 } 1035 1199 } 1036 1200 } … … 1044 1208 void gl_alloc_stencil_buffer( GLcontext *ctx ) 1045 1209 { 1046 GLuint buffersize = ctx-> Buffer->Width * ctx->Buffer->Height;1210 GLuint buffersize = ctx->DrawBuffer->Width * ctx->DrawBuffer->Height; 1047 1211 1048 1212 /* deallocate current stencil buffer if present */ 1049 if (ctx-> Buffer->Stencil) {1050 FREE(ctx-> Buffer->Stencil);1051 ctx-> Buffer->Stencil = NULL;1213 if (ctx->DrawBuffer->Stencil) { 1214 FREE(ctx->DrawBuffer->Stencil); 1215 ctx->DrawBuffer->Stencil = NULL; 1052 1216 } 1053 1217 1054 1218 /* allocate new stencil buffer */ 1055 ctx-> Buffer->Stencil = (GLstencil *) MALLOC(buffersize * sizeof(GLstencil));1056 if (!ctx-> Buffer->Stencil) {1219 ctx->DrawBuffer->Stencil = (GLstencil *) MALLOC(buffersize * sizeof(GLstencil)); 1220 if (!ctx->DrawBuffer->Stencil) { 1057 1221 /* out of memory */ 1058 gl_set_enable( ctx, GL_STENCIL_TEST, GL_FALSE );1222 _mesa_set_enable( ctx, GL_STENCIL_TEST, GL_FALSE ); 1059 1223 gl_error( ctx, GL_OUT_OF_MEMORY, "gl_alloc_stencil_buffer" ); 1060 1224 } … … 1063 1227 1064 1228 1065 1066 1229 /* 1067 * Clear the stencil buffer. If the stencil buffer doesn't exist yet we'll 1068 * allocate it now. 1230 * Clear the software (malloc'd) stencil buffer. 1069 1231 */ 1070 void gl_clear_stencil_buffer( GLcontext *ctx ) 1071 { 1072 if (ctx->Visual->StencilBits==0 || !ctx->Buffer->Stencil) { 1232 static void 1233 clear_software_stencil_buffer( GLcontext *ctx ) 1234 { 1235 if (ctx->Visual->StencilBits==0 || !ctx->DrawBuffer->Stencil) { 1073 1236 /* no stencil buffer */ 1074 1237 return; … … 1077 1240 if (ctx->Scissor.Enabled) { 1078 1241 /* clear scissor region only */ 1079 const GLint width = ctx-> Buffer->Xmax - ctx->Buffer->Xmin + 1;1242 const GLint width = ctx->DrawBuffer->Xmax - ctx->DrawBuffer->Xmin + 1; 1080 1243 if (ctx->Stencil.WriteMask != STENCIL_MAX) { 1081 1244 /* must apply mask to the clear */ 1082 1245 GLint y; 1083 for (y=ctx->Buffer->Ymin; y<=ctx->Buffer->Ymax; y++) { 1084 GLstencil *ptr = STENCIL_ADDRESS( ctx->Buffer->Xmin, y ); 1085 GLint x; 1246 for (y = ctx->DrawBuffer->Ymin; y <= ctx->DrawBuffer->Ymax; y++) { 1086 1247 const GLstencil mask = ctx->Stencil.WriteMask; 1087 1248 const GLstencil invMask = ~mask; 1088 1249 const GLstencil clearVal = (ctx->Stencil.Clear & mask); 1089 for (x = 0; x < width; x++) { 1090 ptr[x] = (ptr[x] & invMask) | clearVal; 1250 GLstencil *stencil = STENCIL_ADDRESS( ctx->DrawBuffer->Xmin, y ); 1251 GLint i; 1252 for (i = 0; i < width; i++) { 1253 stencil[i] = (stencil[i] & invMask) | clearVal; 1091 1254 } 1092 1255 } … … 1095 1258 /* no masking */ 1096 1259 GLint y; 1097 for (y =ctx->Buffer->Ymin; y<=ctx->Buffer->Ymax; y++) {1098 GLstencil * ptr = STENCIL_ADDRESS( ctx->Buffer->Xmin, y );1260 for (y = ctx->DrawBuffer->Ymin; y <= ctx->DrawBuffer->Ymax; y++) { 1261 GLstencil *stencil = STENCIL_ADDRESS( ctx->DrawBuffer->Xmin, y ); 1099 1262 #if STENCIL_BITS==8 1100 MEMSET( ptr, ctx->Stencil.Clear, width * sizeof(GLstencil) );1263 MEMSET( stencil, ctx->Stencil.Clear, width * sizeof(GLstencil) ); 1101 1264 #else 1102 GLint x;1103 for ( x = 0; x < width; x++)1104 ptr[x] = ctx->Stencil.Clear;1265 GLint i; 1266 for (i = 0; i < width; i++) 1267 stencil[x] = ctx->Stencil.Clear; 1105 1268 #endif 1106 1269 } … … 1111 1274 if (ctx->Stencil.WriteMask != STENCIL_MAX) { 1112 1275 /* must apply mask to the clear */ 1113 const GLuint n = ctx-> Buffer->Width * ctx->Buffer->Height;1114 GLstencil * buffer = ctx->Buffer->Stencil;1276 const GLuint n = ctx->DrawBuffer->Width * ctx->DrawBuffer->Height; 1277 GLstencil *stencil = ctx->DrawBuffer->Stencil; 1115 1278 const GLstencil mask = ctx->Stencil.WriteMask; 1116 1279 const GLstencil invMask = ~mask; … … 1118 1281 GLuint i; 1119 1282 for (i = 0; i < n; i++) { 1120 buffer[i] = (buffer[i] & invMask) | clearVal;1283 stencil[i] = (stencil[i] & invMask) | clearVal; 1121 1284 } 1122 1285 } 1123 1286 else { 1124 1287 /* clear whole buffer without masking */ 1125 const GLuint n = ctx-> Buffer->Width * ctx->Buffer->Height;1126 GLstencil * buffer = ctx->Buffer->Stencil;1288 const GLuint n = ctx->DrawBuffer->Width * ctx->DrawBuffer->Height; 1289 GLstencil *stencil = ctx->DrawBuffer->Stencil; 1127 1290 1128 1291 #if STENCIL_BITS==8 1129 MEMSET( buffer, ctx->Stencil.Clear, n * sizeof(GLstencil) );1292 MEMSET(stencil, ctx->Stencil.Clear, n * sizeof(GLstencil) ); 1130 1293 #else 1131 1294 GLuint i; 1132 1295 for (i = 0; i < n; i++) { 1133 buffer[i] = ctx->Stencil.Clear;1296 stencil[i] = ctx->Stencil.Clear; 1134 1297 } 1135 1298 #endif … … 1137 1300 } 1138 1301 } 1302 1303 1304 1305 /* 1306 * Clear the hardware (in graphics card) stencil buffer. 1307 * This is done with the Driver.WriteStencilSpan() and Driver.ReadStencilSpan() 1308 * functions. 1309 * Actually, if there is a hardware stencil buffer it really should have 1310 * been cleared in Driver.Clear()! However, if the hardware does not 1311 * support scissored clears or masked clears (i.e. glStencilMask) then 1312 * we have to use the span-based functions. 1313 */ 1314 static void 1315 clear_hardware_stencil_buffer( GLcontext *ctx ) 1316 { 1317 ASSERT(ctx->Driver.WriteStencilSpan); 1318 ASSERT(ctx->Driver.ReadStencilSpan); 1319 1320 if (ctx->Scissor.Enabled) { 1321 /* clear scissor region only */ 1322 const GLint x = ctx->DrawBuffer->Xmin; 1323 const GLint width = ctx->DrawBuffer->Xmax - ctx->DrawBuffer->Xmin + 1; 1324 if (ctx->Stencil.WriteMask != STENCIL_MAX) { 1325 /* must apply mask to the clear */ 1326 GLint y; 1327 for (y = ctx->DrawBuffer->Ymin; y <= ctx->DrawBuffer->Ymax; y++) { 1328 const GLstencil mask = ctx->Stencil.WriteMask; 1329 const GLstencil invMask = ~mask; 1330 const GLstencil clearVal = (ctx->Stencil.Clear & mask); 1331 GLstencil stencil[MAX_WIDTH]; 1332 GLint i; 1333 (*ctx->Driver.ReadStencilSpan)(ctx, x, y, width, stencil); 1334 for (i = 0; i < width; i++) { 1335 stencil[i] = (stencil[i] & invMask) | clearVal; 1336 } 1337 (*ctx->Driver.WriteStencilSpan)(ctx, x, y, width, stencil, NULL); 1338 } 1339 } 1340 else { 1341 /* no masking */ 1342 GLstencil stencil[MAX_WIDTH]; 1343 GLint y, i; 1344 for (i = 0; i < width; i++) { 1345 stencil[i] = ctx->Stencil.Clear; 1346 } 1347 for (y = ctx->DrawBuffer->Ymin; y <= ctx->DrawBuffer->Ymax; y++) { 1348 (*ctx->Driver.WriteStencilSpan)(ctx, x, y, width, stencil, NULL); 1349 } 1350 } 1351 } 1352 else { 1353 /* clear whole stencil buffer */ 1354 if (ctx->Stencil.WriteMask != STENCIL_MAX) { 1355 /* must apply mask to the clear */ 1356 const GLstencil mask = ctx->Stencil.WriteMask; 1357 const GLstencil invMask = ~mask; 1358 const GLstencil clearVal = (ctx->Stencil.Clear & mask); 1359 const GLint width = ctx->DrawBuffer->Width; 1360 const GLint height = ctx->DrawBuffer->Height; 1361 const GLint x = ctx->DrawBuffer->Xmin; 1362 GLint y; 1363 for (y = 0; y < height; y++) { 1364 GLstencil stencil[MAX_WIDTH]; 1365 GLuint i; 1366 (*ctx->Driver.ReadStencilSpan)(ctx, x, y, width, stencil); 1367 for (i = 0; i < width; i++) { 1368 stencil[i] = (stencil[i] & invMask) | clearVal; 1369 } 1370 (*ctx->Driver.WriteStencilSpan)(ctx, x, y, width, stencil, NULL); 1371 } 1372 } 1373 else { 1374 /* clear whole buffer without masking */ 1375 const GLint width = ctx->DrawBuffer->Width; 1376 const GLint height = ctx->DrawBuffer->Width; 1377 const GLint x = ctx->DrawBuffer->Xmin; 1378 GLstencil stencil[MAX_WIDTH]; 1379 GLint y, i; 1380 for (i = 0; i < width; i++) { 1381 stencil[i] = ctx->Stencil.Clear; 1382 } 1383 for (y = 0; y < height; y++) { 1384 (*ctx->Driver.WriteStencilSpan)(ctx, x, y, width, stencil, NULL); 1385 } 1386 } 1387 } 1388 } 1389 1390 1391 1392 /* 1393 * Clear the stencil buffer. 1394 */ 1395 void gl_clear_stencil_buffer( GLcontext *ctx ) 1396 { 1397 if (ctx->Driver.WriteStencilSpan) { 1398 ASSERT(ctx->Driver.ReadStencilSpan); 1399 clear_hardware_stencil_buffer(ctx); 1400 } 1401 else { 1402 clear_software_stencil_buffer(ctx); 1403 } 1404 } 1405
Note:
See TracChangeset
for help on using the changeset viewer.