1 /* $Id: readpix.c,v 1.10 1997/07/24 01:25:18 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: readpix.c,v $ 26 * Revision 1.10 1997/07/24 01:25:18 brianp 27 * changed precompiled header symbol from PCH to PC_HEADER 28 * 29 * Revision 1.9 1997/05/28 03:26:18 brianp 30 * added precompiled header (PCH) support 31 * 32 * Revision 1.8 1997/05/08 01:43:50 brianp 33 * added error check to gl_ReadPixels() for inside glBegin/glEnd 34 * 35 * Revision 1.7 1997/02/03 20:31:15 brianp 36 * added a few DEFARRAY macros for BeOS 37 * 38 * Revision 1.6 1997/01/16 19:24:05 brianp 39 * replaced a few abort()'s with gl_error() calls 40 * 41 * Revision 1.5 1996/12/20 20:28:04 brianp 42 * use DEF/UNDEFARRAY() macros in read_color_pixels() for Mac compilers 43 * 44 * Revision 1.4 1996/11/01 03:20:47 brianp 45 * reading GL_LUMINANCE pixels weren't clamped 46 * 47 * Revision 1.3 1996/09/27 01:29:47 brianp 48 * added missing default cases to switches 49 * 50 * Revision 1.2 1996/09/15 14:18:37 brianp 51 * now use GLframebuffer and GLvisual 52 * 53 * Revision 1.1 1996/09/13 01:38:16 brianp 54 * Initial revision 55 * 56 */ 57 58 59 #ifdef PC_HEADER 60 #include "all.h" 61 #else 62 #include <math.h> 63 #include <stdlib.h> 64 #include <string.h> 65 #include "alphabuf.h" 66 #include "context.h" 67 #include "depth.h" 68 #include "feedback.h" 69 #include "dlist.h" 70 #include "macros.h" 71 #include "image.h" 72 #include "readpix.h" 73 #include "span.h" 74 #include "stencil.h" 75 #include "types.h" 76 #endif 77 78 79 80 81 /* 82 * Read a block of color index pixels. 83 */ 84 static void read_index_pixels( GLcontext *ctx, 85 GLint x, GLint y, 86 GLsizei width, GLsizei height, 87 GLenum type, GLvoid *pixels ) 88 { 89 GLint i, j; 90 GLuint a, s, k, l, start; 91 92 /* error checking */ 93 if (ctx->Visual->RGBAflag) { 94 gl_error( ctx, GL_INVALID_OPERATION, "glReadPixels" ); 95 return; 96 } 97 98 /* Size of each component */ 99 s = gl_sizeof_type( type ); 100 if (s<=0) { 101 gl_error( ctx, GL_INVALID_ENUM, "glReadPixels(type)" ); 102 return; 103 } 104 105 /* Compute packing parameters */ 106 a = ctx->Pack.Alignment; 107 if (ctx->Pack.RowLength>0) { 108 l = ctx->Pack.RowLength; 109 } 110 else { 111 l = width; 112 } 113 /* k = offset between rows in components */ 114 if (s>=a) { 115 k = l; 116 } 117 else { 118 k = a/s * CEILING( s*l, a ); 119 } 120 121 /* offset to first component returned */ 122 start = ctx->Pack.SkipRows * k + ctx->Pack.SkipPixels; 123 124 /* process image row by row */ 125 for (j=0;j<height;j++,y++) { 126 GLuint index[MAX_WIDTH]; 127 (*ctx->Driver.ReadIndexSpan)( ctx, width, x, y, index ); 128 129 if (ctx->Pixel.IndexShift!=0 || ctx->Pixel.IndexOffset!=0) { 130 GLuint s; 131 if (ctx->Pixel.IndexShift<0) { 132 /* right shift */ 133 s = -ctx->Pixel.IndexShift; 134 for (i=0;i<width;i++) { 135 index[i] = (index[i] >> s) + ctx->Pixel.IndexOffset; 136 } 137 } 138 else { 139 /* left shift */ 140 s = ctx->Pixel.IndexShift; 141 for (i=0;i<width;i++) { 142 index[i] = (index[i] << s) + ctx->Pixel.IndexOffset; 143 } 144 } 145 } 146 147 if (ctx->Pixel.MapColorFlag) { 148 for (i=0;i<width;i++) { 149 index[i] = ctx->Pixel.MapItoI[ index[i] ]; 150 } 151 } 152 153 switch (type) { 154 case GL_UNSIGNED_BYTE: 155 { 156 GLubyte *dst = (GLubyte *) pixels + start + j * k; 157 for (i=0;i<width;i++) { 158 *dst++ = (GLubyte) index[i]; 159 } 160 } 161 break; 162 case GL_BYTE: 163 { 164 GLbyte *dst = (GLbyte *) pixels + start + j * k; 165 for (i=0;i<width;i++) { 166 *dst++ = (GLbyte) index[i]; 167 } 168 } 169 break; 170 case GL_UNSIGNED_SHORT: 171 { 172 GLushort *dst = (GLushort *) pixels + start + j * k; 173 for (i=0;i<width;i++) { 174 *dst++ = (GLushort) index[i]; 175 } 176 if (ctx->Pack.SwapBytes) { 177 gl_swap2( (GLushort *) pixels + start + j * k, width ); 178 } 179 } 180 break; 181 case GL_SHORT: 182 { 183 GLshort *dst = (GLshort *) pixels + start + j * k; 184 for (i=0;i<width;i++) { 185 *dst++ = (GLshort) index[i]; 186 } 187 if (ctx->Pack.SwapBytes) { 188 gl_swap2( (GLushort *) pixels + start + j * k, width ); 189 } 190 } 191 break; 192 case GL_UNSIGNED_INT: 193 { 194 GLuint *dst = (GLuint *) pixels + start + j * k; 195 for (i=0;i<width;i++) { 196 *dst++ = (GLuint) index[i]; 197 } 198 if (ctx->Pack.SwapBytes) { 199 gl_swap4( (GLuint *) pixels + start + j * k, width ); 200 } 201 } 202 break; 203 case GL_INT: 204 { 205 GLint *dst = (GLint *) pixels + start + j * k; 206 for (i=0;i<width;i++) { 207 *dst++ = (GLint) index[i]; 208 } 209 if (ctx->Pack.SwapBytes) { 210 gl_swap4( (GLuint *) pixels + start + j * k, width ); 211 } 212 } 213 break; 214 case GL_FLOAT: 215 { 216 GLfloat *dst = (GLfloat *) pixels + start + j * k; 217 for (i=0;i<width;i++) { 218 *dst++ = (GLfloat) index[i]; 219 } 220 if (ctx->Pack.SwapBytes) { 221 gl_swap4( (GLuint *) pixels + start + j * k, width ); 222 } 223 } 224 break; 225 default: 226 gl_error( ctx, GL_INVALID_ENUM, "glReadPixels(type)" ); 227 } 228 } 229 } 230 231 232 233 static void read_depth_pixels( GLcontext *ctx, 234 GLint x, GLint y, 235 GLsizei width, GLsizei height, 236 GLenum type, GLvoid *pixels ) 237 { 238 GLint i, j; 239 GLuint a, s, k, l, start; 240 GLboolean bias_or_scale; 241 242 /* Error checking */ 243 if (ctx->Visual->DepthBits<=0) { 244 /* No depth buffer */ 245 gl_error( ctx, GL_INVALID_OPERATION, "glReadPixels" ); 246 return; 247 } 248 249 bias_or_scale = ctx->Pixel.DepthBias!=0.0 || ctx->Pixel.DepthScale!=1.0; 250 251 /* Size of each component */ 252 s = gl_sizeof_type( type ); 253 if (s<=0) { 254 gl_error( ctx, GL_INVALID_ENUM, "glReadPixels(type)" ); 255 return; 256 } 257 258 /* Compute packing parameters */ 259 a = ctx->Pack.Alignment; 260 if (ctx->Pack.RowLength>0) { 261 l = ctx->Pack.RowLength; 262 } 263 else { 264 l = width; 265 } 266 /* k = offset between rows in components */ 267 if (s>=a) { 268 k = l; 269 } 270 else { 271 k = a/s * CEILING( s*l, a ); 272 } 273 274 /* offset to first component returned */ 275 start = ctx->Pack.SkipRows * k + ctx->Pack.SkipPixels; 276 277 if (type==GL_UNSIGNED_INT && !bias_or_scale && !ctx->Pack.SwapBytes) { 278 /* Special case: directly read 32-bit unsigned depth values. */ 279 /* Compute shift value to scale depth values up to 32-bit uints. */ 280 GLuint shift = 0; 281 GLuint max = MAX_DEPTH; 282 while ((max&0x80000000)==0) { 283 max = max << 1; 284 shift++; 285 } 286 for (j=0;j<height;j++,y++) { 287 GLuint *dst = (GLuint *) pixels + start + j * k; 288 (*ctx->Driver.ReadDepthSpanInt)( ctx, width, x, y, (GLdepth*) dst); 289 for (i=0;i<width;i++) { 290 dst[i] = dst[i] << shift; 291 } 292 } 293 } 294 else { 295 /* General case (slow) */ 296 for (j=0;j<height;j++,y++) { 297 GLfloat depth[MAX_WIDTH]; 298 299 (*ctx->Driver.ReadDepthSpanFloat)( ctx, width, x, y, depth ); 300 301 if (bias_or_scale) { 302 for (i=0;i<width;i++) { 303 GLfloat d; 304 d = depth[i] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias; 305 depth[i] = CLAMP( d, 0.0, 1.0 ); 306 } 307 } 308 309 switch (type) { 310 case GL_UNSIGNED_BYTE: 311 { 312 GLubyte *dst = (GLubyte *) pixels + start + j * k; 313 for (i=0;i<width;i++) { 314 *dst++ = FLOAT_TO_UBYTE( depth[i] ); 315 } 316 } 317 break; 318 case GL_BYTE: 319 { 320 GLbyte *dst = (GLbyte *) pixels + start + j * k; 321 for (i=0;i<width;i++) { 322 *dst++ = FLOAT_TO_BYTE( depth[i] ); 323 } 324 } 325 break; 326 case GL_UNSIGNED_SHORT: 327 { 328 GLushort *dst = (GLushort *) pixels + start + j * k; 329 for (i=0;i<width;i++) { 330 *dst++ = FLOAT_TO_USHORT( depth[i] ); 331 } 332 if (ctx->Pack.SwapBytes) { 333 gl_swap2( (GLushort *) pixels + start + j * k, width ); 334 } 335 } 336 break; 337 case GL_SHORT: 338 { 339 GLshort *dst = (GLshort *) pixels + start + j * k; 340 for (i=0;i<width;i++) { 341 *dst++ = FLOAT_TO_SHORT( depth[i] ); 342 } 343 if (ctx->Pack.SwapBytes) { 344 gl_swap2( (GLushort *) pixels + start + j * k, width ); 345 } 346 } 347 break; 348 case GL_UNSIGNED_INT: 349 { 350 GLuint *dst = (GLuint *) pixels + start + j * k; 351 for (i=0;i<width;i++) { 352 *dst++ = FLOAT_TO_UINT( depth[i] ); 353 } 354 if (ctx->Pack.SwapBytes) { 355 gl_swap4( (GLuint *) pixels + start + j * k, width ); 356 } 357 } 358 break; 359 case GL_INT: 360 { 361 GLint *dst = (GLint *) pixels + start + j * k; 362 for (i=0;i<width;i++) { 363 *dst++ = FLOAT_TO_INT( depth[i] ); 364 } 365 if (ctx->Pack.SwapBytes) { 366 gl_swap4( (GLuint *) pixels + start + j * k, width ); 367 } 368 } 369 break; 370 case GL_FLOAT: 371 { 372 GLfloat *dst = (GLfloat *) pixels + start + j * k; 373 for (i=0;i<width;i++) { 374 *dst++ = depth[i]; 375 } 376 if (ctx->Pack.SwapBytes) { 377 gl_swap4( (GLuint *) pixels + start + j * k, width ); 378 } 379 } 380 break; 381 default: 382 gl_error( ctx, GL_INVALID_ENUM, "glReadPixels(type)" ); 383 } 384 } 385 } 386 } 387 388 389 390 391 static void read_stencil_pixels( GLcontext *ctx, 392 GLint x, GLint y, 393 GLsizei width, GLsizei height, 394 GLenum type, GLvoid *pixels ) 395 { 396 GLint i, j; 397 GLuint a, s, k, l, start; 398 GLboolean shift_or_offset; 399 400 if (ctx->Visual->StencilBits<=0) { 401 /* No stencil buffer */ 402 gl_error( ctx, GL_INVALID_OPERATION, "glReadPixels" ); 403 return; 404 } 405 406 shift_or_offset = ctx->Pixel.IndexShift!=0 || ctx->Pixel.IndexOffset!=0; 407 408 /* Size of each component */ 409 s = gl_sizeof_type( type ); 410 if (s<=0) { 411 gl_error( ctx, GL_INVALID_ENUM, "glReadPixels(type)" ); 412 return; 413 } 414 415 /* Compute packing parameters */ 416 a = ctx->Pack.Alignment; 417 if (ctx->Pack.RowLength>0) { 418 l = ctx->Pack.RowLength; 419 } 420 else { 421 l = width; 422 } 423 /* k = offset between rows in components */ 424 if (s>=a) { 425 k = l; 426 } 427 else { 428 k = a/s * CEILING( s*l, a ); 429 } 430 431 /* offset to first component returned */ 432 start = ctx->Pack.SkipRows * k + ctx->Pack.SkipPixels; 433 434 /* process image row by row */ 435 for (j=0;j<height;j++,y++) { 436 GLubyte stencil[MAX_WIDTH]; 437 438 gl_read_stencil_span( ctx, width, x, y, stencil ); 439 440 if (shift_or_offset) { 441 GLuint s; 442 if (ctx->Pixel.IndexShift<0) { 443 /* right shift */ 444 s = -ctx->Pixel.IndexShift; 445 for (i=0;i<width;i++) { 446 stencil[i] = (stencil[i] >> s) + ctx->Pixel.IndexOffset; 447 } 448 } 449 else { 450 /* left shift */ 451 s = ctx->Pixel.IndexShift; 452 for (i=0;i<width;i++) { 453 stencil[i] = (stencil[i] << s) + ctx->Pixel.IndexOffset; 454 } 455 } 456 } 457 458 if (ctx->Pixel.MapStencilFlag) { 459 for (i=0;i<width;i++) { 460 stencil[i] = ctx->Pixel.MapStoS[ stencil[i] ]; 461 } 462 } 463 464 switch (type) { 465 case GL_UNSIGNED_BYTE: 466 { 467 GLubyte *dst = (GLubyte *) pixels + start + j * k; 468 MEMCPY( dst, stencil, width ); 469 } 470 break; 471 case GL_BYTE: 472 { 473 GLbyte *dst = (GLbyte *) pixels + start + j * k; 474 MEMCPY( dst, stencil, width ); 475 } 476 break; 477 case GL_UNSIGNED_SHORT: 478 { 479 GLushort *dst = (GLushort *) pixels + start + j * k; 480 for (i=0;i<width;i++) { 481 *dst++ = (GLushort) stencil[i]; 482 } 483 if (ctx->Pack.SwapBytes) { 484 gl_swap2( (GLushort *) pixels + start +j * k, width ); 485 } 486 } 487 break; 488 case GL_SHORT: 489 { 490 GLshort *dst = (GLshort *) pixels + start + j * k; 491 for (i=0;i<width;i++) { 492 *dst++ = (GLshort) stencil[i]; 493 } 494 if (ctx->Pack.SwapBytes) { 495 gl_swap2( (GLushort *) pixels + start +j * k, width ); 496 } 497 } 498 break; 499 case GL_UNSIGNED_INT: 500 { 501 GLuint *dst = (GLuint *) pixels + start + j * k; 502 for (i=0;i<width;i++) { 503 *dst++ = (GLuint) stencil[i]; 504 } 505 if (ctx->Pack.SwapBytes) { 506 gl_swap4( (GLuint *) pixels + start +j * k, width ); 507 } 508 } 509 break; 510 case GL_INT: 511 { 512 GLint *dst = (GLint *) pixels + start + j * k; 513 for (i=0;i<width;i++) { 514 *dst++ = (GLint) stencil[i]; 515 } 516 if (ctx->Pack.SwapBytes) { 517 gl_swap4( (GLuint *) pixels + start +j * k, width ); 518 } 519 } 520 break; 521 case GL_FLOAT: 522 { 523 GLfloat *dst = (GLfloat *) pixels + start + j * k; 524 for (i=0;i<width;i++) { 525 *dst++ = (GLfloat) stencil[i]; 526 } 527 if (ctx->Pack.SwapBytes) { 528 gl_swap4( (GLuint *) pixels + start +j * k, width ); 529 } 530 } 531 break; 532 default: 533 gl_error( ctx, GL_INVALID_ENUM, "glReadPixels(type)" ); 534 } 535 } 536 } 537 538 539 540 /* 541 * Test if scaling or biasing of colors is needed. 542 */ 543 static GLboolean scale_or_bias_rgba( GLcontext *ctx ) 544 { 545 if (ctx->Pixel.RedScale!=1.0F || ctx->Pixel.RedBias!=0.0F || 546 ctx->Pixel.GreenScale!=1.0F || ctx->Pixel.GreenBias!=0.0F || 547 ctx->Pixel.BlueScale!=1.0F || ctx->Pixel.BlueBias!=0.0F || 548 ctx->Pixel.AlphaScale!=1.0F || ctx->Pixel.AlphaBias!=0.0F) { 549 return GL_TRUE; 550 } 551 else { 552 return GL_FALSE; 553 } 554 } 555 556 557 558 /* 559 * Apply scale and bias factors to an array of RGBA pixels. 560 */ 561 static void scale_and_bias_rgba( GLcontext *ctx, 562 GLint n, 563 GLfloat red[], GLfloat green[], 564 GLfloat blue[], GLfloat alpha[] ) 565 { 566 register GLint i; 567 register GLfloat r, g, b, a; 568 569 for (i=0;i<n;i++) { 570 r = red[i] * ctx->Pixel.RedScale + ctx->Pixel.RedBias; 571 g = green[i] * ctx->Pixel.GreenScale + ctx->Pixel.GreenBias; 572 b = blue[i] * ctx->Pixel.BlueScale + ctx->Pixel.BlueBias; 573 a = alpha[i] * ctx->Pixel.AlphaScale + ctx->Pixel.AlphaBias; 574 red[i] = CLAMP( r, 0.0F, 1.0F ); 575 green[i] = CLAMP( g, 0.0F, 1.0F ); 576 blue[i] = CLAMP( b, 0.0F, 1.0F ); 577 alpha[i] = CLAMP( a, 0.0F, 1.0F ); 578 } 579 } 580 581 582 583 /* 584 * Apply pixel mapping to an array of RGBA pixels. 585 */ 586 static void map_rgba( GLcontext *ctx, 587 GLint n, 588 GLfloat red[], GLfloat green[], 589 GLfloat blue[], GLfloat alpha[] ) 590 { 591 GLfloat rscale = ctx->Pixel.MapRtoRsize-1; 592 GLfloat gscale = ctx->Pixel.MapGtoGsize-1; 593 GLfloat bscale = ctx->Pixel.MapBtoBsize-1; 594 GLfloat ascale = ctx->Pixel.MapAtoAsize-1; 595 GLint i; 596 597 for (i=0;i<n;i++) { 598 red[i] = ctx->Pixel.MapRtoR[ (GLint) (red[i] * rscale) ]; 599 green[i] = ctx->Pixel.MapGtoG[ (GLint) (green[i] * gscale) ]; 600 blue[i] = ctx->Pixel.MapBtoB[ (GLint) (blue[i] * bscale) ]; 601 alpha[i] = ctx->Pixel.MapAtoA[ (GLint) (alpha[i] * ascale) ]; 602 } 603 } 604 605 606 607 608 /* 609 * Read R, G, B, A, RGB, L, or LA pixels. 610 */ 611 static void read_color_pixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, 612 GLsizei height, GLenum format, GLenum type, GLvoid *pixels) 613 { 614 GLint i, j, n, a, s, l, k; 615 GLboolean scale_or_bias; 616 DEFARRAY(GLfloat, red, MAX_WIDTH); 617 DEFARRAY(GLfloat, green, MAX_WIDTH); 618 DEFARRAY(GLfloat, blue, MAX_WIDTH); 619 DEFARRAY(GLfloat, alpha, MAX_WIDTH); 620 DEFARRAY(GLfloat, luminance, MAX_WIDTH); 621 GLboolean r_flag, g_flag, b_flag, a_flag, l_flag; 622 GLboolean is_bgr = GL_FALSE; 623 GLuint start; 624 625 scale_or_bias = scale_or_bias_rgba(ctx); 626 627 /* Determine how many / which components to return */ 628 r_flag = g_flag = b_flag = a_flag = l_flag = GL_FALSE; 629 switch (format) 630 { 631 case GL_RED: 632 r_flag = GL_TRUE; 633 n = 1; 634 break; 635 case GL_GREEN: 636 g_flag = GL_TRUE; 637 n = 1; 638 break; 639 case GL_BLUE: 640 b_flag = GL_TRUE; 641 n = 1; 642 break; 643 case GL_ALPHA: 644 a_flag = GL_TRUE; 645 n = 1; 646 break; 647 case GL_LUMINANCE: 648 l_flag = GL_TRUE; 649 n = 1; 650 break; 651 case GL_LUMINANCE_ALPHA: 652 l_flag = a_flag = GL_TRUE; 653 n = 2; 654 break; 655 case GL_RGB: 656 r_flag = g_flag = b_flag = GL_TRUE; 657 n = 3; 658 break; 659 case GL_BGR_EXT: 660 r_flag = g_flag = b_flag = GL_TRUE; 661 n = 3; 662 is_bgr = GL_TRUE; 663 break; 664 case GL_RGBA: 665 r_flag = g_flag = b_flag = a_flag = GL_TRUE; 666 n = 4; 667 break; 668 case GL_BGRA_EXT: 669 r_flag = g_flag = b_flag = a_flag = GL_TRUE; 670 n = 4; 671 is_bgr = GL_TRUE; 672 break; 673 default: 674 gl_error(ctx, GL_INVALID_ENUM, "glReadPixels(format)"); 675 UNDEFARRAY( red ); 676 UNDEFARRAY( green ); 677 UNDEFARRAY( blue ); 678 UNDEFARRAY( alpha ); 679 UNDEFARRAY( luminance ); 680 return; 681 } 682 683 /* Size of each component */ 684 s = gl_sizeof_type(type); 685 if (s <= 0) 686 { 687 gl_error(ctx, GL_INVALID_ENUM, "glReadPixels(type)"); 688 UNDEFARRAY( red ); 689 UNDEFARRAY( green ); 690 UNDEFARRAY( blue ); 691 UNDEFARRAY( alpha ); 692 UNDEFARRAY( luminance ); 693 return; 694 } 695 696 /* Compute packing parameters */ 697 a = ctx->Pack.Alignment; 698 if (ctx->Pack.RowLength > 0) 699 { 700 l = ctx->Pack.RowLength; 701 } 702 else 703 { 704 l = width; 705 } 706 /* k = offset between rows in components */ 707 if (s >= a) 708 { 709 k = n * l; 710 } 711 else 712 { 713 k = a / s * CEILING(s * n * l, a); 714 } 715 716 /* offset to first component returned */ 717 start = ctx->Pack.SkipRows * k + ctx->Pack.SkipPixels * n; 718 719 /* process image row by row */ 720 for (j = 0; j < height; j++, y++) 721 { 722 /* 723 * Read the pixels from frame buffer 724 */ 725 if (ctx->Visual->RGBAflag) 726 { 727 DEFARRAY(GLubyte, r, MAX_WIDTH); 728 DEFARRAY(GLubyte, g, MAX_WIDTH); 729 DEFARRAY(GLubyte, b, MAX_WIDTH); 730 DEFARRAY(GLubyte, a, MAX_WIDTH); 731 GLfloat rscale = 1.0F * ctx->Visual->InvRedScale; 732 GLfloat gscale = 1.0F * ctx->Visual->InvGreenScale; 733 GLfloat bscale = 1.0F * ctx->Visual->InvBlueScale; 734 GLfloat ascale = 1.0F * ctx->Visual->InvAlphaScale; 735 736 /* read colors and convert to floats */ 737 (*ctx->Driver.ReadColorSpan)(ctx, width, x, y, r, g, b, a); 738 if (ctx->RasterMask & ALPHABUF_BIT) 739 { 740 gl_read_alpha_span(ctx, width, x, y, a); 741 } 742 for (i = 0; i < width; i++) 743 { 744 red[i] = r[i] * rscale; 745 green[i] = g[i] * gscale; 746 blue[i] = b[i] * bscale; 747 alpha[i] = a[i] * ascale; 748 } 749 750 if (scale_or_bias) 751 { 752 scale_and_bias_rgba(ctx, width, red, green, blue, alpha); 753 } 754 if (ctx->Pixel.MapColorFlag) 755 { 756 map_rgba(ctx, width, red, green, blue, alpha); 757 } 758 UNDEFARRAY(r); 759 UNDEFARRAY(g); 760 UNDEFARRAY(b); 761 UNDEFARRAY(a); 762 } 763 else 764 { 765 /* convert CI values to RGBA */ 766 GLuint index[MAX_WIDTH]; 767 (*ctx->Driver.ReadIndexSpan)(ctx, width, x, y, index); 768 769 if (ctx->Pixel.IndexShift != 0 || ctx->Pixel.IndexOffset != 0) 770 { 771 GLuint s; 772 if (ctx->Pixel.IndexShift < 0) 773 { 774 /* right shift */ 775 s = -ctx->Pixel.IndexShift; 776 for (i = 0; i < width; i++) 777 { 778 index[i] = (index[i] >> s) + ctx->Pixel.IndexOffset; 779 } 780 } 781 else 782 { 783 /* left shift */ 784 s = ctx->Pixel.IndexShift; 785 for (i = 0; i < width; i++) 786 { 787 index[i] = (index[i] << s) + ctx->Pixel.IndexOffset; 788 } 789 } 790 } 791 792 for (i = 0; i < width; i++) 793 { 794 red[i] = ctx->Pixel.MapItoR[index[i]]; 795 green[i] = ctx->Pixel.MapItoG[index[i]]; 796 blue[i] = ctx->Pixel.MapItoB[index[i]]; 797 alpha[i] = ctx->Pixel.MapItoA[index[i]]; 798 } 799 } 800 801 if (l_flag) 802 { 803 for (i = 0; i < width; i++) 804 { 805 GLfloat sum = red[i] + green[i] + blue[i]; 806 luminance[i] = CLAMP(sum, 0.0F, 1.0F); 807 } 808 } 809 810 /* 811 * Pack/transfer/store the pixels 812 */ 813 814 switch (type) 815 { 816 case GL_UNSIGNED_BYTE: 817 { 818 GLubyte *dst = (GLubyte *) pixels + start + j * k; 819 for (i = 0; i < width; i++) 820 { 821 if (is_bgr) 822 { 823 if (b_flag) 824 *dst++ = FLOAT_TO_UBYTE(blue[i]); 825 if (g_flag) 826 *dst++ = FLOAT_TO_UBYTE(green[i]); 827 if (r_flag) 828 *dst++ = FLOAT_TO_UBYTE(red[i]); 829 } 830 else 831 { 832 if (r_flag) 833 *dst++ = FLOAT_TO_UBYTE(red[i]); 834 if (g_flag) 835 *dst++ = FLOAT_TO_UBYTE(green[i]); 836 if (b_flag) 837 *dst++ = FLOAT_TO_UBYTE(blue[i]); 838 } 839 if (l_flag) 840 *dst++ = FLOAT_TO_UBYTE(luminance[i]); 841 if (a_flag) 842 *dst++ = FLOAT_TO_UBYTE(alpha[i]); 843 } 844 break; 845 } 846 case GL_BYTE: 847 { 848 GLbyte *dst = (GLbyte *) pixels + start + j * k; 849 for (i = 0; i < width; i++) 850 { 851 if (is_bgr) 852 { 853 if (b_flag) 854 *dst++ = FLOAT_TO_BYTE(blue[i]); 855 if (g_flag) 856 *dst++ = FLOAT_TO_BYTE(green[i]); 857 if (r_flag) 858 *dst++ = FLOAT_TO_BYTE(red[i]); 859 } 860 else 861 { 862 if (r_flag) 863 *dst++ = FLOAT_TO_BYTE(red[i]); 864 if (g_flag) 865 *dst++ = FLOAT_TO_BYTE(green[i]); 866 if (b_flag) 867 *dst++ = FLOAT_TO_BYTE(blue[i]); 868 } 869 if (l_flag) 870 *dst++ = FLOAT_TO_BYTE(luminance[i]); 871 if (a_flag) 872 *dst++ = FLOAT_TO_BYTE(alpha[i]); 873 } 874 break; 875 } 876 case GL_UNSIGNED_SHORT: 877 { 878 GLushort *dst = (GLushort *) pixels + start + j * k; 879 for (i = 0; i < width; i++) 880 { 881 if (is_bgr) 882 { 883 if (b_flag) 884 *dst++ = FLOAT_TO_USHORT(blue[i]); 885 if (g_flag) 886 *dst++ = FLOAT_TO_USHORT(green[i]); 887 if (r_flag) 888 *dst++ = FLOAT_TO_USHORT(red[i]); 889 } 890 else 891 { 892 if (r_flag) 893 *dst++ = FLOAT_TO_USHORT(red[i]); 894 if (g_flag) 895 *dst++ = FLOAT_TO_USHORT(green[i]); 896 if (b_flag) 897 *dst++ = FLOAT_TO_USHORT(blue[i]); 898 } 899 if (l_flag) 900 *dst++ = FLOAT_TO_USHORT(luminance[i]); 901 if (a_flag) 902 *dst++ = FLOAT_TO_USHORT(alpha[i]); 903 } 904 if (ctx->Pack.SwapBytes) 905 { 906 gl_swap2((GLushort *) pixels + start + j * k, width * n); 907 } 908 break; 909 } 910 case GL_SHORT: 911 { 912 GLshort *dst = (GLshort *) pixels + start + j * k; 913 for (i = 0; i < width; i++) 914 { 915 if (is_bgr) 916 { 917 if (b_flag) 918 *dst++ = FLOAT_TO_SHORT(blue[i]); 919 if (g_flag) 920 *dst++ = FLOAT_TO_SHORT(green[i]); 921 if (r_flag) 922 *dst++ = FLOAT_TO_SHORT(red[i]); 923 } 924 else 925 { 926 if (r_flag) 927 *dst++ = FLOAT_TO_SHORT(red[i]); 928 if (g_flag) 929 *dst++ = FLOAT_TO_SHORT(green[i]); 930 if (b_flag) 931 *dst++ = FLOAT_TO_SHORT(blue[i]); 932 } 933 if (l_flag) 934 *dst++ = FLOAT_TO_SHORT(luminance[i]); 935 if (a_flag) 936 *dst++ = FLOAT_TO_SHORT(alpha[i]); 937 } 938 if (ctx->Pack.SwapBytes) 939 { 940 gl_swap2((GLushort *) pixels + start + j * k, width * n); 941 } 942 break; 943 } 944 case GL_UNSIGNED_INT: 945 { 946 GLuint *dst = (GLuint *) pixels + start + j * k; 947 for (i = 0; i < width; i++) 948 { 949 if (is_bgr) 950 { 951 if (b_flag) 952 *dst++ = FLOAT_TO_UINT(blue[i]); 953 if (g_flag) 954 *dst++ = FLOAT_TO_UINT(green[i]); 955 if (r_flag) 956 *dst++ = FLOAT_TO_UINT(red[i]); 957 } 958 else 959 { 960 if (r_flag) 961 *dst++ = FLOAT_TO_UINT(red[i]); 962 if (g_flag) 963 *dst++ = FLOAT_TO_UINT(green[i]); 964 if (b_flag) 965 *dst++ = FLOAT_TO_UINT(blue[i]); 966 } 967 if (l_flag) 968 *dst++ = FLOAT_TO_UINT(luminance[i]); 969 if (a_flag) 970 *dst++ = FLOAT_TO_UINT(alpha[i]); 971 } 972 if (ctx->Pack.SwapBytes) 973 { 974 gl_swap4((GLuint *) pixels + start + j * k, width * n); 975 } 976 break; 977 } 978 case GL_INT: 979 { 980 GLint *dst = (GLint *) pixels + start + j * k; 981 for (i = 0; i < width; i++) 982 { 983 if (is_bgr) 984 { 985 if (b_flag) 986 *dst++ = FLOAT_TO_INT(blue[i]); 987 if (g_flag) 988 *dst++ = FLOAT_TO_INT(green[i]); 989 if (r_flag) 990 *dst++ = FLOAT_TO_INT(red[i]); 991 } 992 else 993 { 994 if (r_flag) 995 *dst++ = FLOAT_TO_INT(red[i]); 996 if (g_flag) 997 *dst++ = FLOAT_TO_INT(green[i]); 998 if (b_flag) 999 *dst++ = FLOAT_TO_INT(blue[i]); 1000 } 1001 if (l_flag) 1002 *dst++ = FLOAT_TO_INT(luminance[i]); 1003 if (a_flag) 1004 *dst++ = FLOAT_TO_INT(alpha[i]); 1005 } 1006 if (ctx->Pack.SwapBytes) 1007 { 1008 gl_swap4((GLuint *) pixels + start + j * k, width * n); 1009 } 1010 break; 1011 } 1012 case GL_FLOAT: 1013 { 1014 GLfloat *dst = (GLfloat *) pixels + start + j * k; 1015 for (i = 0; i < width; i++) 1016 { 1017 if (is_bgr) 1018 { 1019 if (b_flag) 1020 *dst++ = blue[i]; 1021 if (g_flag) 1022 *dst++ = green[i]; 1023 if (r_flag) 1024 *dst++ = red[i]; 1025 } 1026 else 1027 { 1028 if (r_flag) 1029 *dst++ = red[i]; 1030 if (g_flag) 1031 *dst++ = green[i]; 1032 if (b_flag) 1033 *dst++ = blue[i]; 1034 } 1035 if (l_flag) 1036 *dst++ = luminance[i]; 1037 if (a_flag) 1038 *dst++ = alpha[i]; 1039 } 1040 if (ctx->Pack.SwapBytes) 1041 { 1042 gl_swap4((GLuint *) pixels + start + j * k, width * n); 1043 } 1044 break; 1045 } 1046 default: 1047 gl_error(ctx, GL_INVALID_ENUM, "glReadPixels(type)"); 1048 } 1049 } 1050 UNDEFARRAY( red ); 1051 UNDEFARRAY( green ); 1052 UNDEFARRAY( blue ); 1053 UNDEFARRAY( alpha ); 1054 UNDEFARRAY( luminance ); 1055 } 1056 1057 1058 1059 void gl_ReadPixels( GLcontext *ctx, 1060 GLint x, GLint y, GLsizei width, GLsizei height, 1061 GLenum format, GLenum type, GLvoid *pixels ) 1062 { 1063 if (INSIDE_BEGIN_END(ctx)) 1064 { 1065 gl_error(ctx, GL_INVALID_OPERATION, "glReadPixels"); 1066 return; 1067 } 1068 1069 (void) (*ctx->Driver.SetBuffer)(ctx, ctx->Pixel.ReadBuffer); 1070 1071 switch (format) 1072 { 1073 case GL_COLOR_INDEX: 1074 read_index_pixels(ctx, x, y, width, height, type, pixels); 1075 break; 1076 case GL_STENCIL_INDEX: 1077 read_stencil_pixels(ctx, x, y, width, height, type, pixels); 1078 break; 1079 case GL_DEPTH_COMPONENT: 1080 read_depth_pixels(ctx, x, y, width, height, type, pixels); 1081 break; 1082 case GL_RED: 1083 case GL_GREEN: 1084 case GL_BLUE: 1085 case GL_ALPHA: 1086 case GL_RGB: 1087 case GL_BGR_EXT: 1088 case GL_LUMINANCE: 1089 case GL_LUMINANCE_ALPHA: 1090 case GL_RGBA: 1091 case GL_BGRA_EXT: 1092 read_color_pixels(ctx, x, y, width, height, format, type, pixels); 1093 break; 1094 default: 1095 gl_error(ctx, GL_INVALID_ENUM, "glReadPixels(format)"); 1096 } 1097 1098 (void) (*ctx->Driver.SetBuffer)(ctx, ctx->Color.DrawBuffer); 1099 } 1100