1 /* $Id: span.c,v 1.12 1997/08/14 01:12:37 brianp Exp $ */ 2 3 /* 4 * Mesa 3-D graphics library 5 * Version: 2.4 6 * Copyright (C) 1995-1997 Brian Paul 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Library General Public 10 * License as published by the Free Software Foundation; either 11 * version 2 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Library General Public License for more details. 17 * 18 * You should have received a copy of the GNU Library General Public 19 * License along with this library; if not, write to the Free 20 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21 */ 22 23 24 /* 25 * $Log: span.c,v $ 26 * Revision 1.12 1997/08/14 01:12:37 brianp 27 * replaced a few for loops with MEMSET calls 28 * 29 * Revision 1.11 1997/07/24 01:21:56 brianp 30 * changed precompiled header symbol from PCH to PC_HEADER 31 * 32 * Revision 1.10 1997/05/28 03:26:29 brianp 33 * added precompiled header (PCH) support 34 * 35 * Revision 1.9 1997/05/03 00:51:30 brianp 36 * new texturing function call: gl_texture_pixels() 37 * 38 * Revision 1.8 1997/04/16 23:54:11 brianp 39 * do per-pixel fog if texturing is enabled 40 * 41 * Revision 1.7 1997/02/09 19:53:43 brianp 42 * now use TEXTURE_xD enable constants 43 * 44 * Revision 1.6 1997/02/09 18:43:34 brianp 45 * added GL_EXT_texture3D support 46 * 47 * Revision 1.5 1997/01/28 22:17:44 brianp 48 * new RGBA mode logic op support 49 * 50 * Revision 1.4 1996/09/25 03:22:05 brianp 51 * added NO_DRAW_BIT support 52 * 53 * Revision 1.3 1996/09/15 14:18:55 brianp 54 * now use GLframebuffer and GLvisual 55 * 56 * Revision 1.2 1996/09/15 01:48:58 brianp 57 * removed #define NULL 0 58 * 59 * Revision 1.1 1996/09/13 01:38:16 brianp 60 * Initial revision 61 * 62 */ 63 64 65 /* 66 * pixel span rasterization: 67 * These functions simulate the rasterization pipeline. 68 */ 69 70 71 #ifdef PC_HEADER 72 #include "all.h" 73 #else 74 #include <string.h> 75 #include "alpha.h" 76 #include "alphabuf.h" 77 #include "blend.h" 78 #include "depth.h" 79 #include "fog.h" 80 #include "logic.h" 81 #include "macros.h" 82 #include "masking.h" 83 #include "scissor.h" 84 #include "span.h" 85 #include "stencil.h" 86 #include "texture.h" 87 #include "types.h" 88 #endif 89 90 91 92 93 /* 94 * Apply the current polygon stipple pattern to a span of pixels. 95 */ 96 static void stipple_polygon_span( GLcontext *ctx, 97 GLuint n, GLint x, GLint y, GLubyte mask[] ) 98 { 99 register GLuint i, m, stipple, highbit=0x80000000; 100 101 stipple = ctx->PolygonStipple[y % 32]; 102 m = highbit >> (GLuint) (x % 32); 103 104 for (i=0;i<n;i++) { 105 if ((m & stipple)==0) { 106 mask[i] = 0; 107 } 108 m = m >> 1; 109 if (m==0) { 110 m = 0x80000000; 111 } 112 } 113 } 114 115 116 117 /* 118 * Clip a pixel span to the current buffer/window boundaries. 119 * Return: 0 = all pixels clipped 120 * 1 = at least one pixel is visible 121 */ 122 static GLuint clip_span( GLcontext *ctx, 123 GLint n, GLint x, GLint y, GLubyte mask[] ) 124 { 125 GLint i; 126 127 /* Clip to top and bottom */ 128 if (y<0 || y>=ctx->Buffer->Height) { 129 return 0; 130 } 131 132 /* Clip to left and right */ 133 if (x>=0 && x+n<=ctx->Buffer->Width) { 134 /* no clipping needed */ 135 return 1; 136 } 137 else if (x+n<=0) { 138 /* completely off left side */ 139 return 0; 140 } 141 else if (x>=ctx->Buffer->Width) { 142 /* completely off right side */ 143 return 0; 144 } 145 else { 146 /* clip-test each pixel, this could be done better */ 147 for (i=0;i<n;i++) { 148 if (x+i<0 || x+i>=ctx->Buffer->Width) { 149 mask[i] = 0; 150 } 151 } 152 return 1; 153 } 154 } 155 156 157 158 /* 159 * Write a horizontal span of color index pixels to the frame buffer. 160 * Stenciling, Depth-testing, etc. are done as needed. 161 * Input: n - number of pixels in the span 162 * x, y - location of leftmost pixel in the span 163 * z - array of [n] z-values 164 * index - array of [n] color indexes 165 * primitive - either GL_POINT, GL_LINE, GL_POLYGON, or GL_BITMAP 166 */ 167 void gl_write_index_span( GLcontext *ctx, 168 GLuint n, GLint x, GLint y, GLdepth z[], 169 GLuint index[], GLenum primitive ) 170 { 171 GLubyte mask[MAX_WIDTH]; 172 GLuint index_save[MAX_WIDTH]; 173 174 /* init mask to 1's (all pixels are to be written) */ 175 MEMSET(mask, 1, n); 176 177 if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) { 178 if (clip_span(ctx,n,x,y,mask)==0) { 179 return; 180 } 181 } 182 183 /* Per-pixel fog */ 184 if (ctx->Fog.Enabled 185 && (ctx->Hint.Fog==GL_NICEST || primitive==GL_BITMAP)) { 186 gl_fog_index_pixels( ctx, n, z, index ); 187 } 188 189 /* Do the scissor test */ 190 if (ctx->Scissor.Enabled) { 191 if (gl_scissor_span( ctx, n, x, y, mask )==0) { 192 return; 193 } 194 } 195 196 /* Polygon Stippling */ 197 if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) { 198 stipple_polygon_span( ctx, n, x, y, mask ); 199 } 200 201 if (ctx->Stencil.Enabled) { 202 /* first stencil test */ 203 if (gl_stencil_span( ctx, n, x, y, mask )==0) { 204 return; 205 } 206 /* depth buffering w/ stencil */ 207 gl_depth_stencil_span( ctx, n, x, y, z, mask ); 208 } 209 else if (ctx->Depth.Test) { 210 /* regular depth testing */ 211 if ((*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask )==0) return; 212 } 213 214 if (ctx->RasterMask & NO_DRAW_BIT) { 215 /* write no pixels */ 216 return; 217 } 218 219 if (ctx->RasterMask & FRONT_AND_BACK_BIT) { 220 /* Save a copy of the indexes since LogicOp and IndexMask 221 * may change them 222 */ 223 MEMCPY( index_save, index, n * sizeof(GLuint) ); 224 } 225 226 if (ctx->Color.SWLogicOpEnabled) { 227 gl_logicop_ci_span( ctx, n, x, y, index, mask ); 228 } 229 if (ctx->Color.SWmasking) { 230 gl_mask_index_span( ctx, n, x, y, index ); 231 } 232 233 /* write pixels */ 234 (*ctx->Driver.WriteIndexSpan)( ctx, n, x, y, index, mask ); 235 236 237 if (ctx->RasterMask & FRONT_AND_BACK_BIT) { 238 /*** Also draw to back buffer ***/ 239 (*ctx->Driver.SetBuffer)( ctx, GL_BACK ); 240 MEMCPY( index, index_save, n * sizeof(GLuint) ); 241 if (ctx->Color.SWLogicOpEnabled) { 242 gl_logicop_ci_span( ctx, n, x, y, index, mask ); 243 } 244 if (ctx->Color.SWmasking) { 245 gl_mask_index_span( ctx, n, x, y, index ); 246 } 247 (*ctx->Driver.WriteIndexSpan)( ctx, n, x, y, index, mask ); 248 (*ctx->Driver.SetBuffer)( ctx, GL_FRONT ); 249 } 250 } 251 252 253 254 255 void gl_write_monoindex_span( GLcontext *ctx, 256 GLuint n, GLint x, GLint y, GLdepth z[], 257 GLuint index, GLenum primitive ) 258 { 259 GLuint i; 260 GLubyte mask[MAX_WIDTH]; 261 GLuint index_save[MAX_WIDTH]; 262 263 /* init mask to 1's (all pixels are to be written) */ 264 MEMSET(mask, 1, n); 265 266 if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) 267 { 268 if (clip_span( ctx,n,x,y,mask)==0) { 269 return; 270 } 271 } 272 273 /* Do the scissor test */ 274 if (ctx->Scissor.Enabled) 275 { 276 if (gl_scissor_span( ctx, n, x, y, mask )==0) { 277 return; 278 } 279 } 280 281 /* Polygon Stippling */ 282 if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) 283 { 284 stipple_polygon_span( ctx, n, x, y, mask ); 285 } 286 287 if (ctx->Stencil.Enabled) 288 { 289 /* first stencil test */ 290 if (gl_stencil_span( ctx, n, x, y, mask )==0) 291 { 292 return; 293 } 294 /* depth buffering w/ stencil */ 295 gl_depth_stencil_span( ctx, n, x, y, z, mask ); 296 } 297 else if (ctx->Depth.Test) 298 { 299 /* regular depth testing */ 300 if ((*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask )==0) 301 return; 302 } 303 304 if (ctx->RasterMask & NO_DRAW_BIT) 305 { 306 /* write no pixels */ 307 return; 308 } 309 310 if ((ctx->Fog.Enabled && (ctx->Hint.Fog==GL_NICEST || primitive==GL_BITMAP)) 311 || ctx->Color.SWLogicOpEnabled || ctx->Color.SWmasking) 312 { 313 GLuint ispan[MAX_WIDTH]; 314 /* index may change, replicate single index into an array */ 315 for (i=0;i<n;i++) 316 { 317 ispan[i] = index; 318 } 319 320 if (ctx->Fog.Enabled 321 && (ctx->Hint.Fog==GL_NICEST || primitive==GL_BITMAP)) 322 { 323 gl_fog_index_pixels( ctx, n, z, ispan ); 324 } 325 326 if (ctx->RasterMask & FRONT_AND_BACK_BIT) 327 { 328 MEMCPY( index_save, ispan, n * sizeof(GLuint) ); 329 } 330 331 if (ctx->Color.SWLogicOpEnabled) 332 { 333 gl_logicop_ci_span( ctx, n, x, y, ispan, mask ); 334 } 335 336 if (ctx->Color.SWmasking) 337 { 338 gl_mask_index_span( ctx, n, x, y, ispan ); 339 } 340 341 (*ctx->Driver.WriteIndexSpan)( ctx, n, x, y, ispan, mask ); 342 343 if (ctx->RasterMask & FRONT_AND_BACK_BIT) 344 { 345 /*** Also draw to back buffer ***/ 346 (*ctx->Driver.SetBuffer)( ctx, GL_BACK ); 347 for (i=0;i<n;i++) 348 { 349 ispan[i] = index; 350 } 351 352 if (ctx->Color.SWLogicOpEnabled) { 353 gl_logicop_ci_span( ctx, n, x, y, ispan, mask ); 354 } 355 if (ctx->Color.SWmasking) { 356 gl_mask_index_span( ctx, n, x, y, ispan ); 357 } 358 (*ctx->Driver.WriteIndexSpan)( ctx, n, x, y, ispan, mask ); 359 (*ctx->Driver.SetBuffer)( ctx, GL_FRONT ); 360 } 361 } 362 else 363 { 364 (*ctx->Driver.WriteMonoindexSpan)( ctx, n, x, y, mask ); 365 366 if (ctx->RasterMask & FRONT_AND_BACK_BIT) 367 { 368 /*** Also draw to back buffer ***/ 369 (*ctx->Driver.SetBuffer)( ctx, GL_BACK ); 370 (*ctx->Driver.WriteMonoindexSpan)( ctx, n, x, y, mask ); 371 (*ctx->Driver.SetBuffer)( ctx, GL_FRONT ); 372 } 373 } 374 } 375 376 377 378 void gl_write_color_span( GLcontext *ctx, 379 GLuint n, GLint x, GLint y, GLdepth z[], 380 GLubyte r[], GLubyte g[], 381 GLubyte b[], GLubyte a[], 382 GLenum primitive ) 383 { 384 GLubyte mask[MAX_WIDTH]; 385 GLboolean write_all = GL_TRUE; 386 GLubyte rtmp[MAX_WIDTH], gtmp[MAX_WIDTH], btmp[MAX_WIDTH], atmp[MAX_WIDTH]; 387 GLubyte *red, *green, *blue, *alpha; 388 389 /* init mask to 1's (all pixels are to be written) */ 390 MEMSET(mask, 1, n); 391 392 if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) { 393 if (clip_span( ctx,n,x,y,mask)==0) { 394 return; 395 } 396 write_all = GL_FALSE; 397 } 398 399 if ((primitive==GL_BITMAP && ctx->MutablePixels) 400 || (ctx->RasterMask & FRONT_AND_BACK_BIT)) { 401 /* must make a copy of the colors since they may be modified */ 402 MEMCPY( rtmp, r, n * sizeof(GLubyte) ); 403 MEMCPY( gtmp, g, n * sizeof(GLubyte) ); 404 MEMCPY( btmp, b, n * sizeof(GLubyte) ); 405 MEMCPY( atmp, a, n * sizeof(GLubyte) ); 406 red = rtmp; 407 green = gtmp; 408 blue = btmp; 409 alpha = atmp; 410 } 411 else { 412 red = r; 413 green = g; 414 blue = b; 415 alpha = a; 416 } 417 418 /* Per-pixel fog */ 419 if (ctx->Fog.Enabled && (ctx->Hint.Fog==GL_NICEST || primitive==GL_BITMAP 420 || ctx->Texture.Enabled)) { 421 gl_fog_color_pixels( ctx, n, z, red, green, blue, alpha ); 422 } 423 424 /* Do the scissor test */ 425 if (ctx->Scissor.Enabled) { 426 if (gl_scissor_span( ctx, n, x, y, mask )==0) { 427 return; 428 } 429 write_all = GL_FALSE; 430 } 431 432 /* Polygon Stippling */ 433 if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) { 434 stipple_polygon_span( ctx, n, x, y, mask ); 435 write_all = GL_FALSE; 436 } 437 438 /* Do the alpha test */ 439 if (ctx->Color.AlphaEnabled) { 440 if (gl_alpha_test( ctx, n, alpha, mask )==0) { 441 return; 442 } 443 write_all = GL_FALSE; 444 } 445 446 if (ctx->Stencil.Enabled) { 447 /* first stencil test */ 448 if (gl_stencil_span( ctx, n, x, y, mask )==0) { 449 return; 450 } 451 /* depth buffering w/ stencil */ 452 gl_depth_stencil_span( ctx, n, x, y, z, mask ); 453 write_all = GL_FALSE; 454 } 455 else if (ctx->Depth.Test) { 456 /* regular depth testing */ 457 GLuint m = (*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask ); 458 if (m==0) { 459 return; 460 } 461 if (m<n) { 462 write_all = GL_FALSE; 463 } 464 } 465 466 if (ctx->RasterMask & NO_DRAW_BIT) { 467 /* write no pixels */ 468 return; 469 } 470 471 /* logic op or blending */ 472 if (ctx->Color.SWLogicOpEnabled) { 473 gl_logicop_rgba_span( ctx, n, x, y, red, green, blue, alpha, mask ); 474 } 475 else if (ctx->Color.BlendEnabled) { 476 gl_blend_span( ctx, n, x, y, red, green, blue, alpha, mask ); 477 } 478 479 /* Color component masking */ 480 if (ctx->Color.SWmasking) { 481 gl_mask_color_span( ctx, n, x, y, red, green, blue, alpha ); 482 } 483 484 /* write pixels */ 485 (*ctx->Driver.WriteColorSpan)( ctx, n, x, y, red, green, blue, alpha, 486 write_all ? NULL : mask ); 487 if (ctx->RasterMask & ALPHABUF_BIT) { 488 gl_write_alpha_span( ctx, n, x, y, alpha, write_all ? NULL : mask ); 489 } 490 491 if (ctx->RasterMask & FRONT_AND_BACK_BIT) { 492 /*** Also render to back buffer ***/ 493 MEMCPY( rtmp, r, n * sizeof(GLubyte) ); 494 MEMCPY( gtmp, g, n * sizeof(GLubyte) ); 495 MEMCPY( btmp, b, n * sizeof(GLubyte) ); 496 MEMCPY( atmp, a, n * sizeof(GLubyte) ); 497 (*ctx->Driver.SetBuffer)( ctx, GL_BACK ); 498 if (ctx->Color.SWLogicOpEnabled) { 499 gl_logicop_rgba_span( ctx, n, x, y, red, green, blue, alpha, mask ); 500 } 501 else if (ctx->Color.BlendEnabled) { 502 gl_blend_span( ctx, n, x, y, red, green, blue, alpha, mask ); 503 } 504 if (ctx->Color.SWmasking) { 505 gl_mask_color_span( ctx, n, x, y, red, green, blue, alpha ); 506 } 507 (*ctx->Driver.WriteColorSpan)( ctx, n, x, y, red, green, blue, alpha, 508 write_all ? NULL : mask ); 509 if (ctx->RasterMask & ALPHABUF_BIT) { 510 ctx->Buffer->Alpha = ctx->Buffer->BackAlpha; 511 gl_write_alpha_span( ctx, n, x, y, alpha, write_all ? NULL : mask ); 512 ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha; 513 } 514 (*ctx->Driver.SetBuffer)( ctx, GL_FRONT ); 515 } 516 517 } 518 519 520 521 /* 522 * Write a horizontal span of color pixels to the frame buffer. 523 * The color is initially constant for the whole span. 524 * Alpha-testing, stenciling, depth-testing, and blending are done as needed. 525 * Input: n - number of pixels in the span 526 * x, y - location of leftmost pixel in the span 527 * z - array of [n] z-values 528 * r, g, b, a - the color of the pixels 529 * primitive - either GL_POINT, GL_LINE, GL_POLYGON or GL_BITMAP. 530 */ 531 void gl_write_monocolor_span( GLcontext *ctx, 532 GLuint n, GLint x, GLint y, GLdepth z[], 533 GLint r, GLint g, GLint b, GLint a, 534 GLenum primitive ) 535 { 536 GLuint i; 537 GLubyte mask[MAX_WIDTH]; 538 GLboolean write_all = GL_TRUE; 539 GLubyte red[MAX_WIDTH], green[MAX_WIDTH], blue[MAX_WIDTH], alpha[MAX_WIDTH]; 540 541 /* init mask to 1's (all pixels are to be written) */ 542 MEMSET(mask, 1, n); 543 544 if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) { 545 if (clip_span( ctx,n,x,y,mask)==0) { 546 return; 547 } 548 write_all = GL_FALSE; 549 } 550 551 /* Do the scissor test */ 552 if (ctx->Scissor.Enabled) { 553 if (gl_scissor_span( ctx, n, x, y, mask )==0) { 554 return; 555 } 556 write_all = GL_FALSE; 557 } 558 559 /* Polygon Stippling */ 560 if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) { 561 stipple_polygon_span( ctx, n, x, y, mask ); 562 write_all = GL_FALSE; 563 } 564 565 /* Do the alpha test */ 566 if (ctx->Color.AlphaEnabled) { 567 GLubyte alpha[MAX_WIDTH]; 568 for (i=0;i<n;i++) { 569 alpha[i] = a; 570 } 571 if (gl_alpha_test( ctx, n, alpha, mask )==0) { 572 return; 573 } 574 write_all = GL_FALSE; 575 } 576 577 if (ctx->Stencil.Enabled) { 578 /* first stencil test */ 579 if (gl_stencil_span( ctx, n, x, y, mask )==0) { 580 return; 581 } 582 /* depth buffering w/ stencil */ 583 gl_depth_stencil_span( ctx, n, x, y, z, mask ); 584 write_all = GL_FALSE; 585 } 586 else if (ctx->Depth.Test) { 587 /* regular depth testing */ 588 GLuint m = (*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask ); 589 if (m==0) { 590 return; 591 } 592 if (m<n) { 593 write_all = GL_FALSE; 594 } 595 } 596 597 if (ctx->RasterMask & NO_DRAW_BIT) { 598 /* write no pixels */ 599 return; 600 } 601 602 if (ctx->Color.BlendEnabled || ctx->Color.SWLogicOpEnabled 603 || ctx->Color.SWmasking) { 604 /* assign same color to each pixel */ 605 for (i=0;i<n;i++) { 606 if (mask[i]) { 607 red[i] = r; 608 green[i] = g; 609 blue[i] = b; 610 alpha[i] = a; 611 } 612 } 613 614 if (ctx->Color.SWLogicOpEnabled) { 615 gl_logicop_rgba_span( ctx, n, x, y, red, green, blue, alpha, mask ); 616 } 617 else if (ctx->Color.BlendEnabled) { 618 gl_blend_span( ctx, n, x, y, red, green, blue, alpha, mask ); 619 } 620 621 /* Color component masking */ 622 if (ctx->Color.SWmasking) { 623 gl_mask_color_span( ctx, n, x, y, red, green, blue, alpha ); 624 } 625 626 /* write pixels */ 627 (*ctx->Driver.WriteColorSpan)( ctx, n, x, y, red, green, blue, alpha, 628 write_all ? NULL : mask ); 629 if (ctx->RasterMask & ALPHABUF_BIT) { 630 gl_write_alpha_span( ctx, n, x, y, alpha, write_all ? NULL : mask ); 631 } 632 633 if (ctx->RasterMask & FRONT_AND_BACK_BIT) { 634 /*** Also draw to back buffer ***/ 635 for (i=0;i<n;i++) { 636 if (mask[i]) { 637 red[i] = r; 638 green[i] = g; 639 blue[i] = b; 640 alpha[i] = a; 641 } 642 } 643 (*ctx->Driver.SetBuffer)( ctx, GL_BACK ); 644 if (ctx->Color.SWLogicOpEnabled) { 645 gl_logicop_rgba_span( ctx, n, x, y, red, green, blue, alpha, mask); 646 } 647 else if (ctx->Color.BlendEnabled) { 648 gl_blend_span( ctx, n, x, y, red, green, blue, alpha, mask ); 649 } 650 if (ctx->Color.SWmasking) { 651 gl_mask_color_span( ctx, n, x, y, red, green, blue, alpha ); 652 } 653 (*ctx->Driver.WriteColorSpan)( ctx, n, x, y, red, green, blue, alpha, 654 write_all ? NULL : mask ); 655 (*ctx->Driver.SetBuffer)( ctx, GL_FRONT ); 656 if (ctx->RasterMask & ALPHABUF_BIT) { 657 ctx->Buffer->Alpha = ctx->Buffer->BackAlpha; 658 gl_write_alpha_span( ctx, n, x, y, alpha, 659 write_all ? NULL : mask ); 660 ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha; 661 } 662 } 663 } 664 else { 665 (*ctx->Driver.WriteMonocolorSpan)( ctx, n, x, y, mask ); 666 if (ctx->RasterMask & ALPHABUF_BIT) { 667 gl_write_mono_alpha_span( ctx, n, x, y, a, write_all ? NULL : mask ); 668 } 669 if (ctx->RasterMask & FRONT_AND_BACK_BIT) { 670 /* Also draw to back buffer */ 671 (*ctx->Driver.SetBuffer)( ctx, GL_BACK ); 672 (*ctx->Driver.WriteMonocolorSpan)( ctx, n, x, y, mask ); 673 (*ctx->Driver.SetBuffer)( ctx, GL_FRONT ); 674 if (ctx->RasterMask & ALPHABUF_BIT) { 675 ctx->Buffer->Alpha = ctx->Buffer->BackAlpha; 676 gl_write_mono_alpha_span( ctx, n, x, y, a, 677 write_all ? NULL : mask ); 678 ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha; 679 } 680 } 681 } 682 } 683 684 685 686 /* 687 * Write a horizontal span of textured pixels to the frame buffer. 688 * The color of each pixel is different. 689 * Alpha-testing, stenciling, depth-testing, and blending are done 690 * as needed. 691 * Input: n - number of pixels in the span 692 * x, y - location of leftmost pixel in the span 693 * z - array of [n] z-values 694 * s, t - array of (s,t) texture coordinates for each pixel 695 * lambda - array of texture lambda values 696 * red, green, blue, alpha - array of [n] color components 697 * primitive - either GL_POINT, GL_LINE, GL_POLYGON or GL_BITMAP. 698 */ 699 void gl_write_texture_span( GLcontext *ctx, 700 GLuint n, GLint x, GLint y, GLdepth z[], 701 GLfloat s[], GLfloat t[], GLfloat u[], 702 GLfloat lambda[], 703 GLubyte r[], GLubyte g[], 704 GLubyte b[], GLubyte a[], 705 GLenum primitive ) 706 { 707 GLubyte mask[MAX_WIDTH]; 708 GLboolean write_all = GL_TRUE; 709 GLubyte rtmp[MAX_WIDTH], gtmp[MAX_WIDTH], btmp[MAX_WIDTH], atmp[MAX_WIDTH]; 710 GLubyte *red, *green, *blue, *alpha; 711 712 /* init mask to 1's (all pixels are to be written) */ 713 MEMSET(mask, 1, n); 714 715 if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) { 716 if (clip_span( ctx,n,x,y,mask)==0) { 717 return; 718 } 719 write_all = GL_FALSE; 720 } 721 722 723 if (primitive==GL_BITMAP || (ctx->RasterMask & FRONT_AND_BACK_BIT)) { 724 /* must make a copy of the colors since they may be modified */ 725 MEMCPY( rtmp, r, n * sizeof(GLubyte) ); 726 MEMCPY( gtmp, g, n * sizeof(GLubyte) ); 727 MEMCPY( btmp, b, n * sizeof(GLubyte) ); 728 MEMCPY( atmp, a, n * sizeof(GLubyte) ); 729 red = rtmp; 730 green = gtmp; 731 blue = btmp; 732 alpha = atmp; 733 } 734 else { 735 red = r; 736 green = g; 737 blue = b; 738 alpha = a; 739 } 740 741 /* Texture */ 742 ASSERT(ctx->Texture.Enabled); 743 gl_texture_pixels( ctx, n, s, t, u, lambda, red, green, blue, alpha ); 744 745 /* Per-pixel fog */ 746 if (ctx->Fog.Enabled && (ctx->Hint.Fog==GL_NICEST || primitive==GL_BITMAP 747 || ctx->Texture.Enabled)) { 748 gl_fog_color_pixels( ctx, n, z, red, green, blue, alpha ); 749 } 750 751 /* Do the scissor test */ 752 if (ctx->Scissor.Enabled) { 753 if (gl_scissor_span( ctx, n, x, y, mask )==0) { 754 return; 755 } 756 write_all = GL_FALSE; 757 } 758 759 /* Polygon Stippling */ 760 if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) { 761 stipple_polygon_span( ctx, n, x, y, mask ); 762 write_all = GL_FALSE; 763 } 764 765 /* Do the alpha test */ 766 if (ctx->Color.AlphaEnabled) { 767 if (gl_alpha_test( ctx, n, alpha, mask )==0) { 768 return; 769 } 770 write_all = GL_FALSE; 771 } 772 773 if (ctx->Stencil.Enabled) { 774 /* first stencil test */ 775 if (gl_stencil_span( ctx, n, x, y, mask )==0) { 776 return; 777 } 778 /* depth buffering w/ stencil */ 779 gl_depth_stencil_span( ctx, n, x, y, z, mask ); 780 write_all = GL_FALSE; 781 } 782 else if (ctx->Depth.Test) { 783 /* regular depth testing */ 784 GLuint m = (*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask ); 785 if (m==0) { 786 return; 787 } 788 if (m<n) { 789 write_all = GL_FALSE; 790 } 791 } 792 793 if (ctx->RasterMask & NO_DRAW_BIT) { 794 /* write no pixels */ 795 return; 796 } 797 798 /* blending */ 799 if (ctx->Color.SWLogicOpEnabled) { 800 gl_logicop_rgba_span( ctx, n, x, y, red, green, blue, alpha, mask ); 801 } 802 else if (ctx->Color.BlendEnabled) { 803 gl_blend_span( ctx, n, x, y, red, green, blue, alpha, mask ); 804 } 805 806 if (ctx->Color.SWmasking) { 807 gl_mask_color_span( ctx, n, x, y, red, green, blue, alpha ); 808 } 809 810 /* write pixels */ 811 (*ctx->Driver.WriteColorSpan)( ctx, n, x, y, red, green, blue, alpha, 812 write_all ? NULL : mask ); 813 if (ctx->RasterMask & ALPHABUF_BIT) { 814 gl_write_alpha_span( ctx, n, x, y, alpha, write_all ? NULL : mask ); 815 } 816 817 if (ctx->RasterMask & FRONT_AND_BACK_BIT) { 818 /* Also draw to back buffer */ 819 MEMCPY( rtmp, r, n * sizeof(GLubyte) ); 820 MEMCPY( gtmp, g, n * sizeof(GLubyte) ); 821 MEMCPY( btmp, b, n * sizeof(GLubyte) ); 822 MEMCPY( atmp, a, n * sizeof(GLubyte) ); 823 (*ctx->Driver.SetBuffer)( ctx, GL_BACK ); 824 if (ctx->Color.SWLogicOpEnabled) { 825 gl_logicop_rgba_span( ctx, n, x, y, red, green, blue, alpha, mask ); 826 } 827 else if (ctx->Color.BlendEnabled) { 828 gl_blend_span( ctx, n, x, y, red, green, blue, alpha, mask ); 829 } 830 if (ctx->Color.SWmasking) { 831 gl_mask_color_span( ctx, n, x, y, red, green, blue, alpha ); 832 } 833 (*ctx->Driver.WriteColorSpan)( ctx, n, x, y, red, green, blue, alpha, 834 write_all ? NULL : mask ); 835 (*ctx->Driver.SetBuffer)( ctx, GL_FRONT ); 836 if (ctx->RasterMask & ALPHABUF_BIT) { 837 ctx->Buffer->Alpha = ctx->Buffer->BackAlpha; 838 gl_write_alpha_span( ctx, n, x, y, alpha, write_all ? NULL : mask ); 839 ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha; 840 } 841 } 842 } 843 844 845 846 /* 847 * Read RGBA pixels from frame buffer. Clipping will be done to prevent 848 * reading ouside the buffer's boundaries. 849 */ 850 void gl_read_color_span( GLcontext *ctx, 851 GLuint n, GLint x, GLint y, 852 GLubyte red[], GLubyte green[], 853 GLubyte blue[], GLubyte alpha[] ) 854 { 855 register GLuint i; 856 857 if (y<0 || y>=ctx->Buffer->Height || x>=ctx->Buffer->Width) { 858 /* completely above, below, or right */ 859 for (i=0;i<n;i++) { 860 red[i] = green[i] = blue[i] = alpha[i] = 0; 861 } 862 } 863 else { 864 if (x>=0 && x+n<=ctx->Buffer->Width) { 865 /* OK */ 866 (*ctx->Driver.ReadColorSpan)( ctx, n, x, y, red, green, blue, alpha ); 867 if (ctx->RasterMask & ALPHABUF_BIT) { 868 gl_read_alpha_span( ctx, n, x, y, alpha ); 869 } 870 } 871 else { 872 i = 0; 873 if (x<0) { 874 while (x<0 && n>0) { 875 red[i] = green[i] = blue[i] = alpha[i] = 0; 876 x++; 877 n--; 878 i++; 879 } 880 } 881 n = MIN2( n, ctx->Buffer->Width - x ); 882 (*ctx->Driver.ReadColorSpan)( ctx, n, x, y, red+i, green+i, blue+i, alpha+i); 883 if (ctx->RasterMask & ALPHABUF_BIT) { 884 gl_read_alpha_span( ctx, n, x, y, alpha+i ); 885 } 886 } 887 } 888 } 889 890 891 892 893 /* 894 * Read CI pixels from frame buffer. Clipping will be done to prevent 895 * reading ouside the buffer's boundaries. 896 */ 897 void gl_read_index_span( GLcontext *ctx, 898 GLuint n, GLint x, GLint y, GLuint indx[] ) 899 { 900 register GLuint i; 901 902 if (y<0 || y>=ctx->Buffer->Height || x>=ctx->Buffer->Width) { 903 /* completely above, below, or right */ 904 for (i=0;i<n;i++) { 905 indx[i] = 0; 906 } 907 } 908 else { 909 if (x>=0 && x+n<=ctx->Buffer->Width) { 910 /* OK */ 911 (*ctx->Driver.ReadIndexSpan)( ctx, n, x, y, indx ); 912 } 913 else { 914 i = 0; 915 if (x<0) { 916 while (x<0 && n>0) { 917 indx[i] = 0; 918 x++; 919 n--; 920 i++; 921 } 922 } 923 n = MIN2( n, ctx->Buffer->Width - x ); 924 (*ctx->Driver.ReadIndexSpan)( ctx, n, x, y, indx+i ); 925 } 926 } 927 } 928 929 930