1 /* $Id: drawpix.c,v 1.16 1998/02/03 23:45:02 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: drawpix.c,v $ 26 * Revision 1.16 1998/02/03 23:45:02 brianp 27 * added casts to prevent warnings with Amiga StormC compiler 28 * 29 * Revision 1.15 1997/08/26 02:10:11 brianp 30 * another bug fix related to glPixelStore() 31 * 32 * Revision 1.14 1997/08/24 02:31:23 brianp 33 * bug fix: glPixelStore() params weren't ignored during display list execute 34 * 35 * Revision 1.13 1997/07/24 01:25:01 brianp 36 * changed precompiled header symbol from PCH to PC_HEADER 37 * 38 * Revision 1.12 1997/06/20 02:18:23 brianp 39 * replaced Current.IntColor with Current.ByteColor 40 * 41 * Revision 1.11 1997/05/28 03:24:22 brianp 42 * added precompiled header (PCH) support 43 * 44 * Revision 1.10 1997/04/24 00:18:56 brianp 45 * added some missing UNDEFARRAY()s. Reported by Randy Frank. 46 * 47 * Revision 1.9 1997/04/20 20:28:49 brianp 48 * replaced abort() with gl_problem() 49 * 50 * Revision 1.8 1997/04/11 23:24:25 brianp 51 * move call to gl_update_state() into gl_DrawPixels() from drawpixels() 52 * 53 * Revision 1.7 1997/03/18 01:55:47 brianp 54 * only generate feedback/selection if raster position is valid 55 * 56 * Revision 1.6 1997/02/10 20:26:57 brianp 57 * fixed memory leak in quickdraw_rgb() 58 * 59 * Revision 1.5 1997/02/03 20:30:31 brianp 60 * added a few DEFARRAY macros for BeOS 61 * 62 * Revision 1.4 1996/10/16 00:58:53 brianp 63 * renamed gl_drawpixels() to drawpixels() 64 * 65 * Revision 1.3 1996/09/27 01:26:25 brianp 66 * added missing default cases to switches 67 * 68 * Revision 1.2 1996/09/15 14:17:30 brianp 69 * now use GLframebuffer and GLvisual 70 * 71 * Revision 1.1 1996/09/13 01:38:16 brianp 72 * Initial revision 73 * 74 */ 75 76 77 #ifdef PC_HEADER 78 #include "all.h" 79 #else 80 #include <stdlib.h> 81 #include <string.h> 82 #include "context.h" 83 #include "drawpix.h" 84 #include "feedback.h" 85 #include "dlist.h" 86 #include "macros.h" 87 #include "pixel.h" 88 #include "span.h" 89 #include "stencil.h" 90 #include "types.h" 91 #endif 92 93 94 95 /* TODO: apply texture mapping to fragments */ 96 97 98 99 static void draw_index_pixels( GLcontext* ctx, GLsizei width, GLsizei height, 100 GLenum type, const GLvoid *pixels ) 101 { 102 GLint x, y, desty; 103 GLuint i, j; 104 GLdepth zspan[MAX_WIDTH]; 105 GLboolean zoom; 106 107 zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0; 108 109 /* Position, depth of pixels */ 110 x = (GLint) (ctx->Current.RasterPos[0] + 0.5F); 111 y = (GLint) (ctx->Current.RasterPos[1] + 0.5F); 112 desty = y; 113 if (ctx->Depth.Test) { 114 GLdepth zval = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE); 115 for (i=0;i<width;i++) { 116 zspan[i] = zval; 117 } 118 } 119 120 /* process the image row by row */ 121 for (i=0;i<height;i++,y++) { 122 GLuint ispan[MAX_WIDTH]; 123 124 /* convert to uints */ 125 switch (type) { 126 case GL_UNSIGNED_BYTE: 127 { 128 GLubyte *src = (GLubyte *) pixels + i * width; 129 for (j=0;j<width;j++) { 130 ispan[j] = (GLuint) *src++; 131 } 132 } 133 break; 134 case GL_BYTE: 135 { 136 GLbyte *src = (GLbyte *) pixels + i * width; 137 for (j=0;j<width;j++) { 138 ispan[j] = (GLuint) *src++; 139 } 140 } 141 break; 142 case GL_UNSIGNED_SHORT: 143 { 144 GLushort *src = (GLushort *) pixels + i * width; 145 for (j=0;j<width;j++) { 146 ispan[j] = (GLuint) *src++; 147 } 148 } 149 break; 150 case GL_SHORT: 151 { 152 GLshort *src = (GLshort *) pixels + i * width; 153 for (j=0;j<width;j++) { 154 ispan[j] = (GLuint) *src++; 155 } 156 } 157 break; 158 case GL_UNSIGNED_INT: 159 { 160 GLuint *src = (GLuint *) pixels + i * width; 161 for (j=0;j<width;j++) { 162 ispan[j] = *src++; 163 } 164 } 165 break; 166 case GL_INT: 167 { 168 GLint *src = (GLint *) pixels + i * width; 169 for (j=0;j<width;j++) { 170 ispan[j] = (GLuint) *src++; 171 } 172 } 173 break; 174 case GL_BITMAP: 175 /* TODO */ 176 break; 177 case GL_FLOAT: 178 { 179 GLfloat *src = (GLfloat *) pixels + i * width; 180 for (j=0;j<width;j++) { 181 ispan[j] = (GLuint) (GLint) *src++; 182 } 183 } 184 break; 185 default: 186 gl_error( ctx, GL_INVALID_ENUM, "Internal: draw_index_pixels" ); 187 } 188 189 /* apply shift and offset */ 190 if (ctx->Pixel.IndexOffset || ctx->Pixel.IndexShift) { 191 if (ctx->Pixel.IndexShift>=0) { 192 for (j=0;j<width;j++) { 193 ispan[j] = (ispan[j] << ctx->Pixel.IndexShift) 194 + ctx->Pixel.IndexOffset; 195 } 196 } 197 else { 198 for (j=0;j<width;j++) { 199 ispan[j] = (ispan[j] >> -ctx->Pixel.IndexShift) 200 + ctx->Pixel.IndexOffset; 201 } 202 } 203 } 204 205 if (ctx->Visual->RGBAflag) { 206 /* Convert index to RGBA and write to frame buffer */ 207 GLubyte red[MAX_WIDTH], green[MAX_WIDTH]; 208 GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH]; 209 for (j=0;j<width;j++) { 210 red[j] = (GLint) (ctx->Pixel.MapItoR[ispan[j]] * ctx->Visual->RedScale); 211 green[j] = (GLint) (ctx->Pixel.MapItoG[ispan[j]] * ctx->Visual->GreenScale); 212 blue[j] = (GLint) (ctx->Pixel.MapItoB[ispan[j]] * ctx->Visual->BlueScale); 213 alpha[j] = (GLint) (ctx->Pixel.MapItoA[ispan[j]] * ctx->Visual->AlphaScale); 214 } 215 if (zoom) { 216 gl_write_zoomed_color_span( ctx, width, x, y, zspan, 217 red, green, blue, alpha, desty ); 218 } 219 else { 220 gl_write_color_span( ctx, width, x, y, zspan, 221 red, green, blue, alpha, GL_BITMAP ); 222 } 223 } 224 else { 225 /* optionally apply index map then write to frame buffer */ 226 if (ctx->Pixel.MapColorFlag) { 227 for (j=0;j<width;j++) { 228 ispan[j] = ctx->Pixel.MapItoI[ispan[j]]; 229 } 230 } 231 if (zoom) { 232 gl_write_zoomed_index_span( ctx, width, x, y, zspan, ispan, desty ); 233 } 234 else { 235 gl_write_index_span( ctx, width, x, y, zspan, ispan, GL_BITMAP ); 236 } 237 } 238 } 239 240 } 241 242 243 244 static void draw_stencil_pixels( GLcontext* ctx, GLsizei width, GLsizei height, 245 GLenum type, const GLvoid *pixels ) 246 { 247 GLint x, y, desty; 248 GLuint i, j; 249 GLboolean zoom; 250 251 zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0; 252 253 /* Position, depth of pixels */ 254 x = (GLint) (ctx->Current.RasterPos[0] + 0.5F); 255 y = (GLint) (ctx->Current.RasterPos[1] + 0.5F); 256 desty = y; 257 258 /* process the image row by row */ 259 for (i=0;i<height;i++,y++) { 260 GLubyte stencil[MAX_WIDTH]; 261 262 /* convert to ubytes */ 263 switch (type) { 264 case GL_UNSIGNED_BYTE: 265 { 266 GLubyte *src = (GLubyte *) pixels + i * width; 267 MEMCPY( stencil, src, width ); 268 } 269 break; 270 case GL_BYTE: 271 { 272 GLbyte *src = (GLbyte *) pixels + i * width; 273 MEMCPY( stencil, src, width ); 274 } 275 break; 276 case GL_UNSIGNED_SHORT: 277 { 278 GLushort *src = (GLushort *) pixels + i * width; 279 for (j=0;j<width;j++) { 280 stencil[j] = (GLubyte) ((*src++) & 0xff); 281 } 282 } 283 break; 284 case GL_SHORT: 285 { 286 GLshort *src = (GLshort *) pixels + i * width; 287 for (j=0;j<width;j++) { 288 stencil[j] = (GLubyte) ((*src++) & 0xff); 289 } 290 } 291 break; 292 case GL_UNSIGNED_INT: 293 { 294 GLuint *src = (GLuint *) pixels + i * width; 295 for (j=0;j<width;j++) { 296 stencil[j] = (GLubyte) ((*src++) & 0xff); 297 } 298 } 299 break; 300 case GL_INT: 301 { 302 GLint *src = (GLint *) pixels + i * width; 303 for (j=0;j<width;j++) { 304 stencil[j] = (GLubyte) ((*src++) & 0xff); 305 } 306 } 307 break; 308 case GL_BITMAP: 309 /* TODO */ 310 break; 311 case GL_FLOAT: 312 { 313 GLfloat *src = (GLfloat *) pixels + i * width; 314 for (j=0;j<width;j++) { 315 stencil[j] = (GLubyte) (((GLint) *src++) & 0xff); 316 } 317 } 318 break; 319 default: 320 gl_error( ctx, GL_INVALID_ENUM, "Internal: draw_stencil_pixels" ); 321 } 322 323 /* apply shift and offset */ 324 if (ctx->Pixel.IndexOffset || ctx->Pixel.IndexShift) { 325 if (ctx->Pixel.IndexShift>=0) { 326 for (j=0;j<width;j++) { 327 stencil[j] = (stencil[j] << ctx->Pixel.IndexShift) 328 + ctx->Pixel.IndexOffset; 329 } 330 } 331 else { 332 for (j=0;j<width;j++) { 333 stencil[j] = (stencil[j] >> -ctx->Pixel.IndexShift) 334 + ctx->Pixel.IndexOffset; 335 } 336 } 337 } 338 339 /* mapping */ 340 if (ctx->Pixel.MapStencilFlag) { 341 for (j=0;j<width;j++) { 342 stencil[j] = ctx->Pixel.MapStoS[ stencil[j] ]; 343 } 344 } 345 346 /* write stencil values to stencil buffer */ 347 if (zoom) { 348 gl_write_zoomed_stencil_span( ctx, (GLuint) width, x, y, stencil, desty ); 349 } 350 else { 351 gl_write_stencil_span( ctx, (GLuint) width, x, y, stencil ); 352 } 353 } 354 } 355 356 357 358 static void draw_depth_pixels( GLcontext* ctx, GLsizei width, GLsizei height, 359 GLenum type, const GLvoid *pixels ) 360 { 361 GLint x, y, desty; 362 GLubyte red[MAX_WIDTH], green[MAX_WIDTH], blue[MAX_WIDTH], alpha[MAX_WIDTH]; 363 GLuint ispan[MAX_WIDTH]; 364 GLboolean bias_or_scale; 365 GLboolean zoom; 366 367 bias_or_scale = ctx->Pixel.DepthBias!=0.0 || ctx->Pixel.DepthScale!=1.0; 368 zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0; 369 370 /* Position, depth of pixels */ 371 x = (GLint) (ctx->Current.RasterPos[0] + 0.5F); 372 y = (GLint) (ctx->Current.RasterPos[1] + 0.5F); 373 desty = y; 374 375 /* Color or index */ 376 if (ctx->Visual->RGBAflag) { 377 GLint r, g, b, a; 378 r = (GLint) (ctx->Current.RasterColor[0] * ctx->Visual->RedScale); 379 g = (GLint) (ctx->Current.RasterColor[1] * ctx->Visual->GreenScale); 380 b = (GLint) (ctx->Current.RasterColor[2] * ctx->Visual->BlueScale); 381 a = (GLint) (ctx->Current.RasterColor[3] * ctx->Visual->AlphaScale); 382 MEMSET( red, r, width ); 383 MEMSET( green, g, width ); 384 MEMSET( blue, b, width ); 385 MEMSET( alpha, a, width ); 386 } 387 else { 388 GLuint i; 389 for (i=0;i<width;i++) { 390 ispan[i] = ctx->Current.RasterIndex; 391 } 392 } 393 394 if (type==GL_UNSIGNED_INT && !bias_or_scale && !zoom && ctx->Visual->RGBAflag) 395 { 396 /* Special case: directly write 32-bit depth values */ 397 GLuint i, j; 398 /* Compute shift value to scale 32-bit uints down to depth values. */ 399 GLuint shift = 0; 400 GLuint max = MAX_DEPTH; 401 while ((max&0x80000000)==0) { 402 max = max << 1; 403 shift++; 404 } 405 for (j=0;j<height;j++,y++) { 406 GLdepth zspan[MAX_WIDTH]; 407 GLuint *zptr = (GLuint *) pixels + j * width; 408 for (i=0;i<width;i++) { 409 zspan[i] = zptr[i] >> shift; 410 } 411 gl_write_color_span( ctx, width, x, y, zspan, 412 red, green, blue, alpha, GL_BITMAP ); 413 } 414 } 415 else { 416 /* General case (slower) */ 417 GLuint i, j; 418 419 /* process image row by row */ 420 for (i=0;i<height;i++,y++) { 421 GLfloat depth[MAX_WIDTH]; 422 GLdepth zspan[MAX_WIDTH]; 423 424 switch (type) { 425 case GL_UNSIGNED_BYTE: 426 { 427 GLubyte *src = (GLubyte *) pixels + i * width; 428 for (j=0;j<width;j++) { 429 depth[j] = UBYTE_TO_FLOAT( *src++ ); 430 } 431 } 432 break; 433 case GL_BYTE: 434 { 435 GLbyte *src = (GLbyte *) pixels + i * width; 436 for (j=0;j<width;j++) { 437 depth[j] = BYTE_TO_FLOAT( *src++ ); 438 } 439 } 440 break; 441 case GL_UNSIGNED_SHORT: 442 { 443 GLushort *src = (GLushort *) pixels + i * width; 444 for (j=0;j<width;j++) { 445 depth[j] = USHORT_TO_FLOAT( *src++ ); 446 } 447 } 448 break; 449 case GL_SHORT: 450 { 451 GLshort *src = (GLshort *) pixels + i * width; 452 for (j=0;j<width;j++) { 453 depth[j] = SHORT_TO_FLOAT( *src++ ); 454 } 455 } 456 break; 457 case GL_UNSIGNED_INT: 458 { 459 GLuint *src = (GLuint *) pixels + i * width; 460 for (j=0;j<width;j++) { 461 depth[j] = UINT_TO_FLOAT( *src++ ); 462 } 463 } 464 break; 465 case GL_INT: 466 { 467 GLint *src = (GLint *) pixels + i * width; 468 for (j=0;j<width;j++) { 469 depth[j] = INT_TO_FLOAT( *src++ ); 470 } 471 } 472 break; 473 case GL_FLOAT: 474 { 475 GLfloat *src = (GLfloat *) pixels + i * width; 476 for (j=0;j<width;j++) { 477 depth[j] = *src++; 478 } 479 } 480 break; 481 default: 482 gl_problem(ctx, "Bad type in draw_depth_pixels"); 483 return; 484 } 485 486 /* apply depth scale and bias */ 487 if (ctx->Pixel.DepthScale!=1.0 || ctx->Pixel.DepthBias!=0.0) { 488 for (j=0;j<width;j++) { 489 depth[j] = depth[j] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias; 490 } 491 } 492 493 /* clamp depth values to [0,1] and convert from floats to integers */ 494 for (j=0;j<width;j++) { 495 zspan[j] = (GLdepth) (CLAMP( depth[j], 0.0F, 1.0F ) * DEPTH_SCALE); 496 } 497 498 if (ctx->Visual->RGBAflag) { 499 if (zoom) { 500 gl_write_zoomed_color_span( ctx, width, x, y, zspan, 501 red, green, blue, alpha, desty ); 502 } 503 else { 504 gl_write_color_span( ctx, width, x, y, zspan, 505 red, green, blue, alpha, GL_BITMAP ); 506 } 507 } 508 else { 509 if (zoom) { 510 gl_write_zoomed_index_span( ctx, width, x, y, zspan, 511 ispan, GL_BITMAP ); 512 } 513 else { 514 gl_write_index_span( ctx, width, x, y, zspan, ispan, GL_BITMAP ); 515 } 516 } 517 518 } 519 } 520 } 521 522 523 524 static void draw_color_pixels(GLcontext* ctx, GLsizei width, GLsizei height, 525 GLenum format, GLenum type, const GLvoid *pixels) 526 { 527 GLuint i, j; 528 GLint x, y, desty; 529 GLdepth zspan[MAX_WIDTH]; 530 GLboolean scale_or_bias, quick_draw; 531 GLboolean zoom; 532 533 zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0; 534 535 /* Position, depth of pixels */ 536 x = (GLint) (ctx->Current.RasterPos[0] + 0.5F); 537 y = (GLint) (ctx->Current.RasterPos[1] + 0.5F); 538 desty = y; 539 if (ctx->Depth.Test) 540 { 541 /* fill in array of z values */ 542 GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE); 543 for (i = 0; i < width; i++) 544 { 545 zspan[i] = z; 546 } 547 } 548 549 /* Determine if scaling and/or biasing is needed */ 550 if (ctx->Pixel.RedScale != 1.0F || ctx->Pixel.RedBias != 0.0F 551 || ctx->Pixel.GreenScale != 1.0F || ctx->Pixel.GreenBias != 0.0F 552 || ctx->Pixel.BlueScale != 1.0F || ctx->Pixel.BlueBias != 0.0F 553 || ctx->Pixel.AlphaScale != 1.0F || ctx->Pixel.AlphaBias != 0.0F) 554 { 555 scale_or_bias = GL_TRUE; 556 } 557 else 558 { 559 scale_or_bias = GL_FALSE; 560 } 561 562 /* Determine if we can directly call the device driver function */ 563 if (ctx->RasterMask == 0 && !zoom && x >= 0 && y >= 0 564 && x + width <= ctx->Buffer->Width 565 && y + height <= ctx->Buffer->Height) 566 { 567 quick_draw = GL_TRUE; 568 } 569 else 570 { 571 quick_draw = GL_FALSE; 572 } 573 574 /* First check for common cases */ 575 if (type == GL_UNSIGNED_BYTE 576 && (format == GL_RGB || format == GL_LUMINANCE || format == GL_BGR_EXT) 577 && !ctx->Pixel.MapColorFlag 578 && !scale_or_bias && ctx->Visual->EightBitColor) 579 { 580 DEFARRAY(GLubyte, alpha, MAX_WIDTH); 581 GLubyte *src = (GLubyte *) pixels; 582 /* constant alpha */ 583 MEMSET(alpha, (GLint ) ctx->Visual->AlphaScale, width); 584 if (format == GL_RGB) 585 { 586 /* 8-bit RGB pixels */ 587 DEFARRAY(GLubyte, red, MAX_WIDTH); 588 DEFARRAY(GLubyte, green, MAX_WIDTH); 589 DEFARRAY(GLubyte, blue, MAX_WIDTH); 590 for (i = 0; i < height; i++, y++) 591 { 592 for (j = 0; j < width; j++) 593 { 594 red[j] = *src++; 595 green[j] = *src++; 596 blue[j] = *src++; 597 } 598 if (quick_draw) 599 { 600 (*ctx->Driver.WriteColorSpan)(ctx, width, x, y, red, green, 601 blue, alpha, NULL); 602 } 603 else if (zoom) 604 { 605 gl_write_zoomed_color_span(ctx, (GLuint) width, x, y, zspan, 606 red, green, blue, alpha, desty); 607 } 608 else 609 { 610 gl_write_color_span(ctx, (GLuint) width, x, y, zspan, red, 611 green, blue, alpha, GL_BITMAP); 612 } 613 } 614 UNDEFARRAY( red ); 615 UNDEFARRAY( green ); 616 UNDEFARRAY( blue ); 617 } 618 else if (format == GL_BGR_EXT) 619 { 620 /* 8-bit BGR pixels */ 621 DEFARRAY(GLubyte, red, MAX_WIDTH); 622 DEFARRAY(GLubyte, green, MAX_WIDTH); 623 DEFARRAY(GLubyte, blue, MAX_WIDTH); 624 for (i = 0; i < height; i++, y++) 625 { 626 for (j = 0; j < width; j++) 627 { 628 blue[j] = *src++; 629 green[j] = *src++; 630 red[j] = *src++; 631 } 632 if (quick_draw) 633 { 634 (*ctx->Driver.WriteColorSpan)(ctx, width, x, y, red, green, 635 blue, alpha, NULL); 636 } 637 else if (zoom) 638 { 639 gl_write_zoomed_color_span(ctx, (GLuint) width, x, y, zspan, 640 red, green, blue, alpha, desty); 641 } 642 else 643 { 644 gl_write_color_span(ctx, (GLuint) width, x, y, zspan, red, 645 green, blue, alpha, GL_BITMAP); 646 } 647 } 648 UNDEFARRAY( red ); 649 UNDEFARRAY( green ); 650 UNDEFARRAY( blue ); 651 } 652 else 653 { 654 /* 8-bit Luminance pixels */ 655 GLubyte *lum = (GLubyte *) pixels; 656 for (i = 0; i < height; i++, y++, lum += width) 657 { 658 if (quick_draw) 659 { 660 (*ctx->Driver.WriteColorSpan)(ctx, width, x, y, lum, lum, 661 lum, alpha, NULL); 662 } 663 else if (zoom) 664 { 665 gl_write_zoomed_color_span(ctx, (GLuint) width, x, y, zspan, 666 lum, lum, lum, alpha, desty); 667 } 668 else 669 { 670 gl_write_color_span(ctx, (GLuint) width, x, y, zspan, lum, 671 lum, lum, alpha, GL_BITMAP); 672 } 673 } 674 } 675 UNDEFARRAY( alpha ); 676 } 677 else 678 { 679 /* General solution */ 680 GLboolean r_flag, g_flag, b_flag, a_flag, l_flag; 681 GLuint components; 682 GLboolean is_bgr; 683 684 r_flag = g_flag = b_flag = a_flag = l_flag = GL_FALSE; 685 is_bgr = GL_FALSE; 686 switch (format) 687 { 688 case GL_RED: 689 r_flag = GL_TRUE; 690 components = 1; 691 break; 692 case GL_GREEN: 693 g_flag = GL_TRUE; 694 components = 1; 695 break; 696 case GL_BLUE: 697 b_flag = GL_TRUE; 698 components = 1; 699 break; 700 case GL_ALPHA: 701 a_flag = GL_TRUE; 702 components = 1; 703 break; 704 case GL_RGB: 705 r_flag = g_flag = b_flag = GL_TRUE; 706 components = 3; 707 break; 708 case GL_BGR_EXT: 709 is_bgr = GL_TRUE; 710 r_flag = g_flag = b_flag = GL_TRUE; 711 components = 3; 712 break; 713 case GL_LUMINANCE: 714 l_flag = GL_TRUE; 715 components = 1; 716 break; 717 case GL_LUMINANCE_ALPHA: 718 l_flag = a_flag = GL_TRUE; 719 components = 2; 720 break; 721 case GL_RGBA: 722 r_flag = g_flag = b_flag = a_flag = GL_TRUE; 723 components = 4; 724 break; 725 case GL_BGRA_EXT: 726 is_bgr = GL_TRUE; 727 r_flag = g_flag = b_flag = a_flag = GL_TRUE; 728 components = 4; 729 break; 730 default: 731 gl_problem(ctx, "Bad type in draw_color_pixels"); 732 return; 733 } 734 735 /* process the image row by row */ 736 for (i = 0; i < height; i++, y++) 737 { 738 DEFARRAY(GLfloat, rf, MAX_WIDTH); 739 DEFARRAY(GLfloat, gf, MAX_WIDTH); 740 DEFARRAY(GLfloat, bf, MAX_WIDTH); 741 DEFARRAY(GLfloat, af, MAX_WIDTH); 742 DEFARRAY(GLubyte, red, MAX_WIDTH); 743 DEFARRAY(GLubyte, green, MAX_WIDTH); 744 DEFARRAY(GLubyte, blue, MAX_WIDTH); 745 DEFARRAY(GLubyte, alpha, MAX_WIDTH); 746 747 /* convert to floats */ 748 switch (type) 749 { 750 case GL_UNSIGNED_BYTE: 751 { 752 GLubyte *src = (GLubyte *) pixels + i * width * components; 753 for (j = 0; j < width; j++) 754 { 755 if (l_flag) 756 { 757 rf[j] = gf[j] = bf[j] = UBYTE_TO_FLOAT(*src++); 758 } 759 else if (is_bgr) 760 { 761 bf[j] = b_flag ? UBYTE_TO_FLOAT(*src++) : 0.0; 762 gf[j] = g_flag ? UBYTE_TO_FLOAT(*src++) : 0.0; 763 rf[j] = r_flag ? UBYTE_TO_FLOAT(*src++) : 0.0; 764 } 765 else 766 { 767 rf[j] = r_flag ? UBYTE_TO_FLOAT(*src++) : 0.0; 768 gf[j] = g_flag ? UBYTE_TO_FLOAT(*src++) : 0.0; 769 bf[j] = b_flag ? UBYTE_TO_FLOAT(*src++) : 0.0; 770 } 771 af[j] = a_flag ? UBYTE_TO_FLOAT(*src++) : 1.0; 772 } 773 } 774 break; 775 case GL_BYTE: 776 { 777 GLbyte *src = (GLbyte *) pixels + i * width * components; 778 for (j = 0; j < width; j++) 779 { 780 if (l_flag) 781 { 782 rf[j] = gf[j] = bf[j] = BYTE_TO_FLOAT(*src++); 783 } 784 else if (is_bgr) 785 { 786 bf[j] = b_flag ? BYTE_TO_FLOAT(*src++) : 0.0; 787 gf[j] = g_flag ? BYTE_TO_FLOAT(*src++) : 0.0; 788 rf[j] = r_flag ? BYTE_TO_FLOAT(*src++) : 0.0; 789 } 790 else 791 { 792 rf[j] = r_flag ? BYTE_TO_FLOAT(*src++) : 0.0; 793 gf[j] = g_flag ? BYTE_TO_FLOAT(*src++) : 0.0; 794 bf[j] = b_flag ? BYTE_TO_FLOAT(*src++) : 0.0; 795 } 796 af[j] = a_flag ? BYTE_TO_FLOAT(*src++) : 1.0; 797 } 798 } 799 break; 800 case GL_BITMAP: 801 /* special case */ 802 break; 803 case GL_UNSIGNED_SHORT: 804 { 805 GLushort *src = (GLushort *) pixels + i * width * components; 806 for (j = 0; j < width; j++) 807 { 808 if (l_flag) 809 { 810 rf[j] = gf[j] = bf[j] = USHORT_TO_FLOAT(*src++); 811 } 812 else if (is_bgr) 813 { 814 bf[j] = b_flag ? USHORT_TO_FLOAT(*src++) : 0.0; 815 gf[j] = g_flag ? USHORT_TO_FLOAT(*src++) : 0.0; 816 rf[j] = r_flag ? USHORT_TO_FLOAT(*src++) : 0.0; 817 } 818 else 819 { 820 rf[j] = r_flag ? USHORT_TO_FLOAT(*src++) : 0.0; 821 gf[j] = g_flag ? USHORT_TO_FLOAT(*src++) : 0.0; 822 bf[j] = b_flag ? USHORT_TO_FLOAT(*src++) : 0.0; 823 } 824 af[j] = a_flag ? USHORT_TO_FLOAT(*src++) : 1.0; 825 } 826 } 827 break; 828 case GL_SHORT: 829 { 830 GLshort *src = (GLshort *) pixels + i * width * components; 831 for (j = 0; j < width; j++) 832 { 833 if (l_flag) 834 { 835 rf[j] = gf[j] = bf[j] = SHORT_TO_FLOAT(*src++); 836 } 837 else if (is_bgr) 838 { 839 bf[j] = b_flag ? SHORT_TO_FLOAT(*src++) : 0.0; 840 gf[j] = g_flag ? SHORT_TO_FLOAT(*src++) : 0.0; 841 rf[j] = r_flag ? SHORT_TO_FLOAT(*src++) : 0.0; 842 } 843 else 844 { 845 rf[j] = r_flag ? SHORT_TO_FLOAT(*src++) : 0.0; 846 gf[j] = g_flag ? SHORT_TO_FLOAT(*src++) : 0.0; 847 bf[j] = b_flag ? SHORT_TO_FLOAT(*src++) : 0.0; 848 } 849 af[j] = a_flag ? SHORT_TO_FLOAT(*src++) : 1.0; 850 } 851 } 852 break; 853 case GL_UNSIGNED_INT: 854 { 855 GLuint *src = (GLuint *) pixels + i * width * components; 856 for (j = 0; j < width; j++) 857 { 858 if (l_flag) 859 { 860 rf[j] = gf[j] = bf[j] = UINT_TO_FLOAT(*src++); 861 } 862 else if (is_bgr) 863 { 864 bf[j] = b_flag ? UINT_TO_FLOAT(*src++) : 0.0; 865 gf[j] = g_flag ? UINT_TO_FLOAT(*src++) : 0.0; 866 rf[j] = r_flag ? UINT_TO_FLOAT(*src++) : 0.0; 867 } 868 else 869 { 870 rf[j] = r_flag ? UINT_TO_FLOAT(*src++) : 0.0; 871 gf[j] = g_flag ? UINT_TO_FLOAT(*src++) : 0.0; 872 bf[j] = b_flag ? UINT_TO_FLOAT(*src++) : 0.0; 873 } 874 af[j] = a_flag ? UINT_TO_FLOAT(*src++) : 1.0; 875 } 876 } 877 break; 878 case GL_INT: 879 { 880 GLint *src = (GLint *) pixels + i * width * components; 881 for (j = 0; j < width; j++) 882 { 883 if (l_flag) 884 { 885 rf[j] = gf[j] = bf[j] = INT_TO_FLOAT(*src++); 886 } 887 else if (is_bgr) 888 { 889 bf[j] = b_flag ? INT_TO_FLOAT(*src++) : 0.0; 890 gf[j] = g_flag ? INT_TO_FLOAT(*src++) : 0.0; 891 rf[j] = r_flag ? INT_TO_FLOAT(*src++) : 0.0; 892 } 893 else 894 { 895 rf[j] = r_flag ? INT_TO_FLOAT(*src++) : 0.0; 896 gf[j] = g_flag ? INT_TO_FLOAT(*src++) : 0.0; 897 bf[j] = b_flag ? INT_TO_FLOAT(*src++) : 0.0; 898 } 899 af[j] = a_flag ? INT_TO_FLOAT(*src++) : 1.0; 900 } 901 } 902 break; 903 case GL_FLOAT: 904 { 905 GLfloat *src = (GLfloat *) pixels + i * width * components; 906 for (j = 0; j < width; j++) 907 { 908 if (l_flag) 909 { 910 rf[j] = gf[j] = bf[j] = *src++; 911 } 912 else if (is_bgr) 913 { 914 bf[j] = b_flag ? *src++ : 0.0; 915 gf[j] = g_flag ? *src++ : 0.0; 916 rf[j] = r_flag ? *src++ : 0.0; 917 } 918 else 919 { 920 rf[j] = r_flag ? *src++ : 0.0; 921 gf[j] = g_flag ? *src++ : 0.0; 922 bf[j] = b_flag ? *src++ : 0.0; 923 } 924 af[j] = a_flag ? *src++ : 1.0; 925 } 926 } 927 break; 928 default: 929 gl_error(ctx, GL_INVALID_ENUM, "glDrawPixels"); 930 return; 931 } 932 933 /* apply scale and bias */ 934 if (scale_or_bias) 935 { 936 for (j = 0; j < width; j++) 937 { 938 GLfloat r, g, b, a; 939 r = rf[j] * ctx->Pixel.RedScale + ctx->Pixel.RedBias; 940 g = gf[j] * ctx->Pixel.GreenScale + ctx->Pixel.GreenBias; 941 b = bf[j] * ctx->Pixel.BlueScale + ctx->Pixel.BlueBias; 942 a = af[j] * ctx->Pixel.AlphaScale + ctx->Pixel.AlphaBias; 943 rf[j] = CLAMP(r, 0.0, 1.0); 944 gf[j] = CLAMP(g, 0.0, 1.0); 945 bf[j] = CLAMP(b, 0.0, 1.0); 946 af[j] = CLAMP(a, 0.0, 1.0); 947 } 948 } 949 950 /* apply pixel mappings */ 951 if (ctx->Pixel.MapColorFlag) 952 { 953 GLfloat rscale = ctx->Pixel.MapRtoRsize - 1; 954 GLfloat gscale = ctx->Pixel.MapGtoGsize - 1; 955 GLfloat bscale = ctx->Pixel.MapBtoBsize - 1; 956 GLfloat ascale = ctx->Pixel.MapAtoAsize - 1; 957 for (j = 0; j < width; j++) 958 { 959 rf[j] = ctx->Pixel.MapRtoR[(GLint) (rf[j] * rscale)]; 960 gf[j] = ctx->Pixel.MapGtoG[(GLint) (gf[j] * gscale)]; 961 bf[j] = ctx->Pixel.MapBtoB[(GLint) (bf[j] * bscale)]; 962 af[j] = ctx->Pixel.MapAtoA[(GLint) (af[j] * ascale)]; 963 } 964 } 965 966 /* convert to integers */ 967 for (j = 0; j < width; j++) 968 { 969 red[j] = (GLint) (rf[j] * ctx->Visual->RedScale); 970 green[j] = (GLint) (gf[j] * ctx->Visual->GreenScale); 971 blue[j] = (GLint) (bf[j] * ctx->Visual->BlueScale); 972 alpha[j] = (GLint) (af[j] * ctx->Visual->AlphaScale); 973 } 974 975 /* write to frame buffer */ 976 if (quick_draw) 977 { 978 (*ctx->Driver.WriteColorSpan)(ctx, width, x, y, red, green, 979 blue, alpha, NULL); 980 } 981 else if (zoom) 982 { 983 gl_write_zoomed_color_span(ctx, width, x, y, zspan, red, green, 984 blue, alpha, desty); 985 } 986 else 987 { 988 gl_write_color_span(ctx, (GLuint) width, x, y, zspan, red, 989 green, blue, alpha, GL_BITMAP); 990 } 991 992 UNDEFARRAY(rf); 993 UNDEFARRAY(gf); 994 UNDEFARRAY(bf); 995 UNDEFARRAY(af); 996 UNDEFARRAY(red); 997 UNDEFARRAY(green); 998 UNDEFARRAY(blue); 999 UNDEFARRAY(alpha); 1000 } 1001 } 1002 1003 } 1004 1005 1006 1007 /* 1008 * Do a glDrawPixels( w, h, GL_RGB, GL_UNSIGNED_BYTE, pixels ) optimized 1009 * for the case of no pixel mapping, no scale, no bias, no zoom, default 1010 * storage mode, no raster ops, and no pixel clipping. 1011 * Return: GL_TRUE if success 1012 * GL_FALSE if conditions weren't met for optimized drawing 1013 */ 1014 static GLboolean quickdraw_rgb( GLcontext* ctx, GLsizei width, GLsizei height, 1015 const void *pixels ) 1016 { 1017 DEFARRAY( GLubyte, red, MAX_WIDTH ); 1018 DEFARRAY( GLubyte, green, MAX_WIDTH ); 1019 DEFARRAY( GLubyte, blue, MAX_WIDTH ); 1020 DEFARRAY( GLubyte, alpha, MAX_WIDTH ); 1021 GLint i, j; 1022 GLint x, y; 1023 GLint bytes_per_row; 1024 GLboolean result; 1025 1026 bytes_per_row = width * 3 + (width % ctx->Unpack.Alignment); 1027 1028 if (!ctx->Current.RasterPosValid) { 1029 /* This is success, actually. */ 1030 result = GL_TRUE; 1031 } 1032 else { 1033 x = (GLint) (ctx->Current.RasterPos[0] + 0.5F); 1034 y = (GLint) (ctx->Current.RasterPos[1] + 0.5F); 1035 1036 if (x<0 || y<0 1037 || x+width>ctx->Buffer->Width || y+height>ctx->Buffer->Height) { 1038 result = GL_FALSE; /* can't handle this situation */ 1039 } 1040 else { 1041 /* constant alpha */ 1042 for (j=0;j<width;j++) { 1043 alpha[j] = (GLint) ctx->Visual->AlphaScale; 1044 } 1045 1046 /* write directly to device driver */ 1047 for (i=0;i<height;i++) { 1048 /* each row of pixel data starts at 4-byte boundary */ 1049 GLubyte *src = (GLubyte *) pixels + i * bytes_per_row; 1050 for (j=0;j<width;j++) { 1051 red[j] = *src++; 1052 green[j] = *src++; 1053 blue[j] = *src++; 1054 } 1055 (*ctx->Driver.WriteColorSpan)( ctx, width, x, y+i, 1056 red, green, blue, alpha, NULL); 1057 } 1058 result = GL_TRUE; 1059 } 1060 } 1061 1062 UNDEFARRAY( red ); 1063 UNDEFARRAY( green ); 1064 UNDEFARRAY( blue ); 1065 UNDEFARRAY( alpha ); 1066 1067 return result; 1068 } 1069 1070 1071 1072 /* 1073 * Implements general glDrawPixels operation. 1074 */ 1075 static void drawpixels( GLcontext* ctx, GLsizei width, GLsizei height, 1076 GLenum format, GLenum type, const GLvoid *pixels ) 1077 { 1078 if (INSIDE_BEGIN_END(ctx)) { 1079 gl_error( ctx, GL_INVALID_OPERATION, "glDrawPixels" ); 1080 return; 1081 } 1082 1083 if (ctx->RenderMode==GL_RENDER) { 1084 if (!ctx->Current.RasterPosValid) { 1085 return; 1086 } 1087 switch (format) { 1088 case GL_COLOR_INDEX: 1089 draw_index_pixels( ctx, width, height, type, pixels ); 1090 break; 1091 case GL_STENCIL_INDEX: 1092 draw_stencil_pixels( ctx, width, height, type, pixels ); 1093 break; 1094 case GL_DEPTH_COMPONENT: 1095 draw_depth_pixels( ctx, width, height, type, pixels ); 1096 break; 1097 case GL_RED: 1098 case GL_GREEN: 1099 case GL_BLUE: 1100 case GL_ALPHA: 1101 case GL_RGB: 1102 case GL_BGR_EXT: 1103 case GL_LUMINANCE: 1104 case GL_LUMINANCE_ALPHA: 1105 case GL_RGBA: 1106 case GL_BGRA_EXT: 1107 draw_color_pixels( ctx, width, height, format, type, pixels ); 1108 break; 1109 default: 1110 gl_error( ctx, GL_INVALID_ENUM, "glDrawPixels" ); 1111 } 1112 } 1113 else if (ctx->RenderMode==GL_FEEDBACK) { 1114 if (ctx->Current.RasterPosValid) { 1115 GLfloat color[4], texcoord[4], invq; 1116 color[0] = ctx->Current.ByteColor[0] * ctx->Visual->InvRedScale; 1117 color[1] = ctx->Current.ByteColor[1] * ctx->Visual->InvGreenScale; 1118 color[2] = ctx->Current.ByteColor[2] * ctx->Visual->InvBlueScale; 1119 color[3] = ctx->Current.ByteColor[3] * ctx->Visual->InvAlphaScale; 1120 invq = 1.0F / ctx->Current.TexCoord[3]; 1121 texcoord[0] = ctx->Current.TexCoord[0] * invq; 1122 texcoord[1] = ctx->Current.TexCoord[1] * invq; 1123 texcoord[2] = ctx->Current.TexCoord[2] * invq; 1124 texcoord[3] = ctx->Current.TexCoord[3]; 1125 FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN ); 1126 gl_feedback_vertex( ctx, ctx->Current.RasterPos[0], 1127 ctx->Current.RasterPos[1], 1128 ctx->Current.RasterPos[2], 1129 ctx->Current.RasterPos[3], 1130 color, ctx->Current.Index, texcoord ); 1131 } 1132 } 1133 else if (ctx->RenderMode==GL_SELECT) { 1134 if (ctx->Current.RasterPosValid) { 1135 gl_update_hitflag( ctx, ctx->Current.RasterPos[2] ); 1136 } 1137 } 1138 } 1139 1140 1141 1142 /* 1143 * Compile OR Execute a glDrawPixels! 1144 */ 1145 void gl_DrawPixels( GLcontext* ctx, GLsizei width, GLsizei height, 1146 GLenum format, GLenum type, const GLvoid *pixels ) 1147 { 1148 GLvoid *image; 1149 1150 if (width<0 || height<0) { 1151 gl_error( ctx, GL_INVALID_VALUE, "glDrawPixels" ); 1152 return; 1153 } 1154 1155 if (ctx->NewState) { 1156 gl_update_state(ctx); 1157 } 1158 1159 /* Let the device driver take a crack at glDrawPixels */ 1160 if (!ctx->CompileFlag && ctx->Driver.DrawPixels) { 1161 GLint x = (GLint) (ctx->Current.RasterPos[0] + 0.5F); 1162 GLint y = (GLint) (ctx->Current.RasterPos[1] + 0.5F); 1163 if ((*ctx->Driver.DrawPixels)( ctx, x, y, width, height, 1164 format, type, GL_FALSE, pixels )) { 1165 /* Device driver did the job */ 1166 return; 1167 } 1168 } 1169 1170 if (format==GL_RGB && type==GL_UNSIGNED_BYTE && ctx->FastDrawPixels 1171 && !ctx->CompileFlag && ctx->RenderMode==GL_RENDER 1172 && ctx->RasterMask==0 && ctx->CallDepth==0) { 1173 /* optimized path */ 1174 if (quickdraw_rgb( ctx, width, height, pixels )) { 1175 /* success */ 1176 return; 1177 } 1178 } 1179 1180 /* take the general path */ 1181 1182 /* THIS IS A REAL HACK - FIX IN MESA 2.5 1183 * If we're inside glCallList then we don't have to unpack the pixels again. 1184 */ 1185 if (ctx->CallDepth == 0) { 1186 image = gl_unpack_pixels( ctx, width, height, format, type, pixels ); 1187 if (!image) { 1188 gl_error( ctx, GL_OUT_OF_MEMORY, "glDrawPixels" ); 1189 return; 1190 } 1191 } 1192 else { 1193 image = (GLvoid *) pixels; 1194 } 1195 1196 if (ctx->CompileFlag) { 1197 gl_save_DrawPixels( ctx, width, height, format, type, image ); 1198 } 1199 if (ctx->ExecuteFlag) { 1200 drawpixels( ctx, width, height, format, type, image ); 1201 if (!ctx->CompileFlag) { 1202 /* may discard unpacked image now */ 1203 if (image!=pixels) 1204 free( image ); 1205 } 1206 } 1207 } 1208