1 /* $Id: pixel.c,v 1.8 1997/07/24 01:23:44 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: pixel.c,v $ 26 * Revision 1.8 1997/07/24 01:23:44 brianp 27 * changed precompiled header symbol from PCH to PC_HEADER 28 * 29 * Revision 1.7 1997/05/28 03:26:02 brianp 30 * added precompiled header (PCH) support 31 * 32 * Revision 1.6 1997/02/09 20:05:03 brianp 33 * new arguments for gl_pixel_addr_in_image() 34 * 35 * Revision 1.5 1997/02/09 18:52:37 brianp 36 * added GL_EXT_texture3D support 37 * 38 * Revision 1.4 1996/11/06 04:09:37 brianp 39 * added a missing return after a gl_error() call 40 * 41 * Revision 1.3 1996/09/26 22:35:10 brianp 42 * fixed a few compiler warnings from IRIX 6 -n32 and -64 compiler 43 * 44 * Revision 1.2 1996/09/15 14:18:55 brianp 45 * now use GLframebuffer and GLvisual 46 * 47 * Revision 1.1 1996/09/13 01:38:16 brianp 48 * Initial revision 49 * 50 */ 51 52 53 /* 54 * glPixelStore, glPixelTransfer, glPixelMap, glPixelZoom, etc. 55 */ 56 57 58 #ifdef PC_HEADER 59 #include "all.h" 60 #else 61 #include <assert.h> 62 #include <stdio.h> 63 #include <stdlib.h> 64 #include <string.h> 65 #include "context.h" 66 #include "dlist.h" 67 #include "macros.h" 68 #include "pixel.h" 69 #include "image.h" 70 #include "span.h" 71 #include "stencil.h" 72 #include "types.h" 73 #endif 74 75 76 77 /* 78 * Determine if we can use the optimized glDrawPixels function. 79 */ 80 static void update_drawpixels_state( GLcontext *ctx ) 81 { 82 if (ctx->Visual->RGBAflag==GL_TRUE && 83 ctx->Visual->EightBitColor && 84 ctx->Pixel.RedBias==0.0 && ctx->Pixel.RedScale==1.0 && 85 ctx->Pixel.GreenBias==0.0 && ctx->Pixel.GreenScale==1.0 && 86 ctx->Pixel.BlueBias==0.0 && ctx->Pixel.BlueScale==1.0 && 87 ctx->Pixel.AlphaBias==0.0 && ctx->Pixel.AlphaScale==1.0 && 88 ctx->Pixel.MapColorFlag==GL_FALSE && 89 ctx->Pixel.ZoomX==1.0 && ctx->Pixel.ZoomY==1.0 && 90 /* ctx->Unpack.Alignment==4 &&*/ 91 ctx->Unpack.RowLength==0 && 92 ctx->Unpack.SkipPixels==0 && 93 ctx->Unpack.SkipRows==0 && 94 ctx->Unpack.SwapBytes==0 && 95 ctx->Unpack.LsbFirst==0) { 96 ctx->FastDrawPixels = GL_TRUE; 97 } 98 else { 99 ctx->FastDrawPixels = GL_FALSE; 100 } 101 } 102 103 104 105 106 /**********************************************************************/ 107 /***** glPixelZoom *****/ 108 /**********************************************************************/ 109 110 111 112 void gl_PixelZoom( GLcontext *ctx, GLfloat xfactor, GLfloat yfactor ) 113 { 114 if (INSIDE_BEGIN_END(ctx)) { 115 gl_error( ctx, GL_INVALID_OPERATION, "glPixelZoom" ); 116 return; 117 } 118 ctx->Pixel.ZoomX = xfactor; 119 ctx->Pixel.ZoomY = yfactor; 120 update_drawpixels_state( ctx ); 121 } 122 123 124 125 126 /* 127 * Write a span of pixels to the frame buffer while applying a pixel zoom. 128 * This is only used by glDrawPixels and glCopyPixels. 129 * Input: n - number of pixels in input row 130 * x, y - destination of the span 131 * z - depth values for the span 132 * red, green, blue, alpha - array of colors 133 * y0 - location of first row in the image we're drawing. 134 */ 135 void 136 gl_write_zoomed_color_span( GLcontext *ctx, 137 GLuint n, GLint x, GLint y, const GLdepth z[], 138 const GLubyte red[], const GLubyte green[], 139 const GLubyte blue[], const GLubyte alpha[], 140 GLint y0 ) 141 { 142 GLint m; 143 GLint r0, r1, row, r; 144 GLint i, j, skipcol; 145 GLubyte zred[MAX_WIDTH], zgreen[MAX_WIDTH]; /* zoomed pixel colors */ 146 GLubyte zblue[MAX_WIDTH], zalpha[MAX_WIDTH]; 147 GLdepth zdepth[MAX_WIDTH]; /* zoomed depth values */ 148 GLint maxwidth = MIN2( ctx->Buffer->Width, MAX_WIDTH ); 149 150 /* compute width of output row */ 151 m = (GLint) ABSF( n * ctx->Pixel.ZoomX ); 152 if (m==0) { 153 return; 154 } 155 if (ctx->Pixel.ZoomX<0.0) { 156 /* adjust x coordinate for left/right mirroring */ 157 x = x - m; 158 } 159 160 /* compute which rows to draw */ 161 row = y-y0; 162 r0 = y0 + (GLint) (row * ctx->Pixel.ZoomY); 163 r1 = y0 + (GLint) ((row+1) * ctx->Pixel.ZoomY); 164 if (r0==r1) { 165 return; 166 } 167 else if (r1<r0) { 168 GLint rtmp = r1; 169 r1 = r0; 170 r0 = rtmp; 171 } 172 173 /* return early if r0...r1 is above or below window */ 174 if (r0<0 && r1<0) { 175 /* below window */ 176 return; 177 } 178 if (r0>=ctx->Buffer->Height && r1>=ctx->Buffer->Height) { 179 /* above window */ 180 return; 181 } 182 183 /* check if left edge is outside window */ 184 skipcol = 0; 185 if (x<0) { 186 skipcol = -x; 187 m += x; 188 } 189 /* make sure span isn't too long or short */ 190 if (m>maxwidth) { 191 m = maxwidth; 192 } 193 else if (m<=0) { 194 return; 195 } 196 197 assert( m <= MAX_WIDTH ); 198 199 /* zoom the span horizontally */ 200 if (ctx->Pixel.ZoomX==-1.0F) { 201 /* n==m */ 202 for (j=0;j<m;j++) { 203 i = n - (j+skipcol) - 1; 204 zred[j] = red[i]; 205 zgreen[j] = green[i]; 206 zblue[j] = blue[i]; 207 zalpha[j] = alpha[i]; 208 zdepth[j] = z[i]; 209 } 210 } 211 else { 212 GLfloat xscale = 1.0F / ctx->Pixel.ZoomX; 213 for (j=0;j<m;j++) { 214 i = (j+skipcol) * xscale; 215 if (i<0) i = n + i - 1; 216 zred[j] = red[i]; 217 zgreen[j] = green[i]; 218 zblue[j] = blue[i]; 219 zalpha[j] = alpha[i]; 220 zdepth[j] = z[i]; 221 } 222 } 223 224 /* write the span */ 225 for (r=r0; r<r1; r++) { 226 gl_write_color_span( ctx, m, x+skipcol, r, zdepth, 227 zred, zgreen, zblue, zalpha, GL_BITMAP ); 228 } 229 } 230 231 232 233 /* 234 * As above, but write CI pixels. 235 */ 236 void 237 gl_write_zoomed_index_span( GLcontext *ctx, 238 GLuint n, GLint x, GLint y, const GLdepth z[], 239 const GLuint indexes[], GLint y0 ) 240 { 241 GLint m; 242 GLint r0, r1, row, r; 243 GLint i, j, skipcol; 244 GLuint zindexes[MAX_WIDTH]; /* zoomed color indexes */ 245 GLdepth zdepth[MAX_WIDTH]; /* zoomed depth values */ 246 GLint maxwidth = MIN2( ctx->Buffer->Width, MAX_WIDTH ); 247 248 /* compute width of output row */ 249 m = (GLint) ABSF( n * ctx->Pixel.ZoomX ); 250 if (m==0) { 251 return; 252 } 253 if (ctx->Pixel.ZoomX<0.0) { 254 /* adjust x coordinate for left/right mirroring */ 255 x = x - m; 256 } 257 258 /* compute which rows to draw */ 259 row = y-y0; 260 r0 = y0 + (GLint) (row * ctx->Pixel.ZoomY); 261 r1 = y0 + (GLint) ((row+1) * ctx->Pixel.ZoomY); 262 if (r0==r1) { 263 return; 264 } 265 else if (r1<r0) { 266 GLint rtmp = r1; 267 r1 = r0; 268 r0 = rtmp; 269 } 270 271 /* return early if r0...r1 is above or below window */ 272 if (r0<0 && r1<0) { 273 /* below window */ 274 return; 275 } 276 if (r0>=ctx->Buffer->Height && r1>=ctx->Buffer->Height) { 277 /* above window */ 278 return; 279 } 280 281 /* check if left edge is outside window */ 282 skipcol = 0; 283 if (x<0) { 284 skipcol = -x; 285 m += x; 286 } 287 /* make sure span isn't too long or short */ 288 if (m>maxwidth) { 289 m = maxwidth; 290 } 291 else if (m<=0) { 292 return; 293 } 294 295 assert( m <= MAX_WIDTH ); 296 297 /* zoom the span horizontally */ 298 if (ctx->Pixel.ZoomX==-1.0F) { 299 /* n==m */ 300 for (j=0;j<m;j++) { 301 i = n - (j+skipcol) - 1; 302 zindexes[j] = indexes[i]; 303 zdepth[j] = z[i]; 304 } 305 } 306 else { 307 GLfloat xscale = 1.0F / ctx->Pixel.ZoomX; 308 for (j=0;j<m;j++) { 309 i = (j+skipcol) * xscale; 310 if (i<0) i = n + i - 1; 311 zindexes[j] = indexes[i]; 312 zdepth[j] = z[i]; 313 } 314 } 315 316 /* write the span */ 317 for (r=r0; r<r1; r++) { 318 gl_write_index_span( ctx, m, x+skipcol, r, zdepth, zindexes, GL_BITMAP ); 319 } 320 } 321 322 323 324 /* 325 * As above, but write stencil values. 326 */ 327 void 328 gl_write_zoomed_stencil_span( GLcontext *ctx, 329 GLuint n, GLint x, GLint y, 330 const GLubyte stencil[], GLint y0 ) 331 { 332 GLint m; 333 GLint r0, r1, row, r; 334 GLint i, j, skipcol; 335 GLubyte zstencil[MAX_WIDTH]; /* zoomed stencil values */ 336 GLint maxwidth = MIN2( ctx->Buffer->Width, MAX_WIDTH ); 337 338 /* compute width of output row */ 339 m = (GLint) ABSF( n * ctx->Pixel.ZoomX ); 340 if (m==0) { 341 return; 342 } 343 if (ctx->Pixel.ZoomX<0.0) { 344 /* adjust x coordinate for left/right mirroring */ 345 x = x - m; 346 } 347 348 /* compute which rows to draw */ 349 row = y-y0; 350 r0 = y0 + (GLint) (row * ctx->Pixel.ZoomY); 351 r1 = y0 + (GLint) ((row+1) * ctx->Pixel.ZoomY); 352 if (r0==r1) { 353 return; 354 } 355 else if (r1<r0) { 356 GLint rtmp = r1; 357 r1 = r0; 358 r0 = rtmp; 359 } 360 361 /* return early if r0...r1 is above or below window */ 362 if (r0<0 && r1<0) { 363 /* below window */ 364 return; 365 } 366 if (r0>=ctx->Buffer->Height && r1>=ctx->Buffer->Height) { 367 /* above window */ 368 return; 369 } 370 371 /* check if left edge is outside window */ 372 skipcol = 0; 373 if (x<0) { 374 skipcol = -x; 375 m += x; 376 } 377 /* make sure span isn't too long or short */ 378 if (m>maxwidth) { 379 m = maxwidth; 380 } 381 else if (m<=0) { 382 return; 383 } 384 385 assert( m <= MAX_WIDTH ); 386 387 /* zoom the span horizontally */ 388 if (ctx->Pixel.ZoomX==-1.0F) { 389 /* n==m */ 390 for (j=0;j<m;j++) { 391 i = n - (j+skipcol) - 1; 392 zstencil[j] = stencil[i]; 393 } 394 } 395 else { 396 GLfloat xscale = 1.0F / ctx->Pixel.ZoomX; 397 for (j=0;j<m;j++) { 398 i = (j+skipcol) * xscale; 399 if (i<0) i = n + i - 1; 400 zstencil[j] = stencil[i]; 401 } 402 } 403 404 /* write the span */ 405 for (r=r0; r<r1; r++) { 406 gl_write_stencil_span( ctx, m, x+skipcol, r, zstencil ); 407 } 408 } 409 410 411 412 413 /**********************************************************************/ 414 /***** glPixelStore *****/ 415 /**********************************************************************/ 416 417 418 void gl_PixelStorei( GLcontext *ctx, GLenum pname, GLint param ) 419 { 420 /* NOTE: this call can't be compiled into the display list */ 421 422 if (INSIDE_BEGIN_END(ctx)) { 423 gl_error( ctx, GL_INVALID_OPERATION, "glPixelStore" ); 424 return; 425 } 426 427 switch (pname) { 428 case GL_PACK_SWAP_BYTES: 429 ctx->Pack.SwapBytes = param ? GL_TRUE : GL_FALSE; 430 break; 431 case GL_PACK_LSB_FIRST: 432 ctx->Pack.LsbFirst = param ? GL_TRUE : GL_FALSE; 433 break; 434 case GL_PACK_ROW_LENGTH: 435 if (param<0) { 436 gl_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); 437 } 438 else { 439 ctx->Pack.RowLength = param; 440 } 441 break; 442 case GL_PACK_SKIP_PIXELS: 443 if (param<0) { 444 gl_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); 445 } 446 else { 447 ctx->Pack.SkipPixels = param; 448 } 449 break; 450 case GL_PACK_SKIP_ROWS: 451 if (param<0) { 452 gl_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); 453 } 454 else { 455 ctx->Pack.SkipRows = param; 456 } 457 break; 458 case GL_PACK_ALIGNMENT: 459 if (param==1 || param==2 || param==4 || param==8) { 460 ctx->Pack.Alignment = param; 461 } 462 else { 463 gl_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); 464 } 465 break; 466 case GL_UNPACK_SWAP_BYTES: 467 ctx->Unpack.SwapBytes = param ? GL_TRUE : GL_FALSE; 468 break; 469 case GL_UNPACK_LSB_FIRST: 470 ctx->Unpack.LsbFirst = param ? GL_TRUE : GL_FALSE; 471 break; 472 case GL_UNPACK_ROW_LENGTH: 473 if (param<0) { 474 gl_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); 475 } 476 else { 477 ctx->Unpack.RowLength = param; 478 } 479 break; 480 case GL_UNPACK_SKIP_PIXELS: 481 if (param<0) { 482 gl_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); 483 } 484 else { 485 ctx->Unpack.SkipPixels = param; 486 } 487 break; 488 case GL_UNPACK_SKIP_ROWS: 489 if (param<0) { 490 gl_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); 491 } 492 else { 493 ctx->Unpack.SkipRows = param; 494 } 495 break; 496 case GL_UNPACK_ALIGNMENT: 497 if (param==1 || param==2 || param==4 || param==8) { 498 ctx->Unpack.Alignment = param; 499 } 500 else { 501 gl_error( ctx, GL_INVALID_VALUE, "glPixelStore" ); 502 } 503 break; 504 default: 505 gl_error( ctx, GL_INVALID_ENUM, "glPixelStore" ); 506 } 507 update_drawpixels_state( ctx ); 508 } 509 510 511 512 513 514 /**********************************************************************/ 515 /***** glPixelMap *****/ 516 /**********************************************************************/ 517 518 519 520 void gl_PixelMapfv( GLcontext *ctx, 521 GLenum map, GLint mapsize, const GLfloat *values ) 522 { 523 GLuint i; 524 525 if (INSIDE_BEGIN_END(ctx)) { 526 gl_error( ctx, GL_INVALID_OPERATION, "glPixelMapfv" ); 527 return; 528 } 529 530 if (mapsize<0 || mapsize>MAX_PIXEL_MAP_TABLE) { 531 gl_error( ctx, GL_INVALID_VALUE, "glPixelMapfv(mapsize)" ); 532 return; 533 } 534 535 if (map>=GL_PIXEL_MAP_S_TO_S && map<=GL_PIXEL_MAP_I_TO_A) { 536 /* test that mapsize is a power of two */ 537 GLuint p; 538 GLboolean ok = GL_FALSE; 539 for (p=1; p<=MAX_PIXEL_MAP_TABLE; p=p<<1) { 540 if ( (p&mapsize) == p ) { 541 ok = GL_TRUE; 542 break; 543 } 544 } 545 if (!ok) { 546 gl_error( ctx, GL_INVALID_VALUE, "glPixelMapfv(mapsize)" ); 547 return; 548 } 549 } 550 551 switch (map) { 552 case GL_PIXEL_MAP_S_TO_S: 553 ctx->Pixel.MapStoSsize = mapsize; 554 for (i=0;i<mapsize;i++) { 555 ctx->Pixel.MapStoS[i] = (GLint) values[i]; 556 } 557 break; 558 case GL_PIXEL_MAP_I_TO_I: 559 ctx->Pixel.MapItoIsize = mapsize; 560 for (i=0;i<mapsize;i++) { 561 ctx->Pixel.MapItoI[i] = (GLint) values[i]; 562 } 563 break; 564 case GL_PIXEL_MAP_I_TO_R: 565 ctx->Pixel.MapItoRsize = mapsize; 566 for (i=0;i<mapsize;i++) { 567 ctx->Pixel.MapItoR[i] = CLAMP( values[i], 0.0, 1.0 ); 568 } 569 break; 570 case GL_PIXEL_MAP_I_TO_G: 571 ctx->Pixel.MapItoGsize = mapsize; 572 for (i=0;i<mapsize;i++) { 573 ctx->Pixel.MapItoG[i] = CLAMP( values[i], 0.0, 1.0 ); 574 } 575 break; 576 case GL_PIXEL_MAP_I_TO_B: 577 ctx->Pixel.MapItoBsize = mapsize; 578 for (i=0;i<mapsize;i++) { 579 ctx->Pixel.MapItoB[i] = CLAMP( values[i], 0.0, 1.0 ); 580 } 581 break; 582 case GL_PIXEL_MAP_I_TO_A: 583 ctx->Pixel.MapItoAsize = mapsize; 584 for (i=0;i<mapsize;i++) { 585 ctx->Pixel.MapItoA[i] = CLAMP( values[i], 0.0, 1.0 ); 586 } 587 break; 588 case GL_PIXEL_MAP_R_TO_R: 589 ctx->Pixel.MapRtoRsize = mapsize; 590 for (i=0;i<mapsize;i++) { 591 ctx->Pixel.MapRtoR[i] = CLAMP( values[i], 0.0, 1.0 ); 592 } 593 break; 594 case GL_PIXEL_MAP_G_TO_G: 595 ctx->Pixel.MapGtoGsize = mapsize; 596 for (i=0;i<mapsize;i++) { 597 ctx->Pixel.MapGtoG[i] = CLAMP( values[i], 0.0, 1.0 ); 598 } 599 break; 600 case GL_PIXEL_MAP_B_TO_B: 601 ctx->Pixel.MapBtoBsize = mapsize; 602 for (i=0;i<mapsize;i++) { 603 ctx->Pixel.MapBtoB[i] = CLAMP( values[i], 0.0, 1.0 ); 604 } 605 break; 606 case GL_PIXEL_MAP_A_TO_A: 607 ctx->Pixel.MapAtoAsize = mapsize; 608 for (i=0;i<mapsize;i++) { 609 ctx->Pixel.MapAtoA[i] = CLAMP( values[i], 0.0, 1.0 ); 610 } 611 break; 612 default: 613 gl_error( ctx, GL_INVALID_ENUM, "glPixelMapfv(map)" ); 614 } 615 } 616 617 618 619 620 621 void gl_GetPixelMapfv( GLcontext *ctx, GLenum map, GLfloat *values ) 622 { 623 GLuint i; 624 625 if (INSIDE_BEGIN_END(ctx)) { 626 gl_error( ctx, GL_INVALID_OPERATION, "glGetPixelMapfv" ); 627 return; 628 } 629 switch (map) { 630 case GL_PIXEL_MAP_I_TO_I: 631 for (i=0;i<ctx->Pixel.MapItoIsize;i++) { 632 values[i] = (GLfloat) ctx->Pixel.MapItoI[i]; 633 } 634 break; 635 case GL_PIXEL_MAP_S_TO_S: 636 for (i=0;i<ctx->Pixel.MapStoSsize;i++) { 637 values[i] = (GLfloat) ctx->Pixel.MapStoS[i]; 638 } 639 break; 640 case GL_PIXEL_MAP_I_TO_R: 641 MEMCPY(values,ctx->Pixel.MapItoR,ctx->Pixel.MapItoRsize*sizeof(GLfloat)); 642 break; 643 case GL_PIXEL_MAP_I_TO_G: 644 MEMCPY(values,ctx->Pixel.MapItoG,ctx->Pixel.MapItoGsize*sizeof(GLfloat)); 645 break; 646 case GL_PIXEL_MAP_I_TO_B: 647 MEMCPY(values,ctx->Pixel.MapItoB,ctx->Pixel.MapItoBsize*sizeof(GLfloat)); 648 break; 649 case GL_PIXEL_MAP_I_TO_A: 650 MEMCPY(values,ctx->Pixel.MapItoA,ctx->Pixel.MapItoAsize*sizeof(GLfloat)); 651 break; 652 case GL_PIXEL_MAP_R_TO_R: 653 MEMCPY(values,ctx->Pixel.MapRtoR,ctx->Pixel.MapRtoRsize*sizeof(GLfloat)); 654 break; 655 case GL_PIXEL_MAP_G_TO_G: 656 MEMCPY(values,ctx->Pixel.MapGtoG,ctx->Pixel.MapGtoGsize*sizeof(GLfloat)); 657 break; 658 case GL_PIXEL_MAP_B_TO_B: 659 MEMCPY(values,ctx->Pixel.MapBtoB,ctx->Pixel.MapBtoBsize*sizeof(GLfloat)); 660 break; 661 case GL_PIXEL_MAP_A_TO_A: 662 MEMCPY(values,ctx->Pixel.MapAtoA,ctx->Pixel.MapAtoAsize*sizeof(GLfloat)); 663 break; 664 default: 665 gl_error( ctx, GL_INVALID_ENUM, "glGetPixelMapfv" ); 666 } 667 } 668 669 670 void gl_GetPixelMapuiv( GLcontext *ctx, GLenum map, GLuint *values ) 671 { 672 GLuint i; 673 674 if (INSIDE_BEGIN_END(ctx)) { 675 gl_error( ctx, GL_INVALID_OPERATION, "glGetPixelMapfv" ); 676 return; 677 } 678 switch (map) { 679 case GL_PIXEL_MAP_I_TO_I: 680 MEMCPY(values, ctx->Pixel.MapItoI, ctx->Pixel.MapItoIsize*sizeof(GLint)); 681 break; 682 case GL_PIXEL_MAP_S_TO_S: 683 MEMCPY(values, ctx->Pixel.MapStoS, ctx->Pixel.MapStoSsize*sizeof(GLint)); 684 break; 685 case GL_PIXEL_MAP_I_TO_R: 686 for (i=0;i<ctx->Pixel.MapItoRsize;i++) { 687 values[i] = FLOAT_TO_UINT( ctx->Pixel.MapItoR[i] ); 688 } 689 break; 690 case GL_PIXEL_MAP_I_TO_G: 691 for (i=0;i<ctx->Pixel.MapItoGsize;i++) { 692 values[i] = FLOAT_TO_UINT( ctx->Pixel.MapItoG[i] ); 693 } 694 break; 695 case GL_PIXEL_MAP_I_TO_B: 696 for (i=0;i<ctx->Pixel.MapItoBsize;i++) { 697 values[i] = FLOAT_TO_UINT( ctx->Pixel.MapItoB[i] ); 698 } 699 break; 700 case GL_PIXEL_MAP_I_TO_A: 701 for (i=0;i<ctx->Pixel.MapItoAsize;i++) { 702 values[i] = FLOAT_TO_UINT( ctx->Pixel.MapItoA[i] ); 703 } 704 break; 705 case GL_PIXEL_MAP_R_TO_R: 706 for (i=0;i<ctx->Pixel.MapRtoRsize;i++) { 707 values[i] = FLOAT_TO_UINT( ctx->Pixel.MapRtoR[i] ); 708 } 709 break; 710 case GL_PIXEL_MAP_G_TO_G: 711 for (i=0;i<ctx->Pixel.MapGtoGsize;i++) { 712 values[i] = FLOAT_TO_UINT( ctx->Pixel.MapGtoG[i] ); 713 } 714 break; 715 case GL_PIXEL_MAP_B_TO_B: 716 for (i=0;i<ctx->Pixel.MapBtoBsize;i++) { 717 values[i] = FLOAT_TO_UINT( ctx->Pixel.MapBtoB[i] ); 718 } 719 break; 720 case GL_PIXEL_MAP_A_TO_A: 721 for (i=0;i<ctx->Pixel.MapAtoAsize;i++) { 722 values[i] = FLOAT_TO_UINT( ctx->Pixel.MapAtoA[i] ); 723 } 724 break; 725 default: 726 gl_error( ctx, GL_INVALID_ENUM, "glGetPixelMapfv" ); 727 } 728 } 729 730 731 void gl_GetPixelMapusv( GLcontext *ctx, GLenum map, GLushort *values ) 732 { 733 GLuint i; 734 735 if (INSIDE_BEGIN_END(ctx)) { 736 gl_error( ctx, GL_INVALID_OPERATION, "glGetPixelMapfv" ); 737 return; 738 } 739 switch (map) { 740 case GL_PIXEL_MAP_I_TO_I: 741 for (i=0;i<ctx->Pixel.MapItoIsize;i++) { 742 values[i] = (GLushort) ctx->Pixel.MapItoI[i]; 743 } 744 break; 745 case GL_PIXEL_MAP_S_TO_S: 746 for (i=0;i<ctx->Pixel.MapStoSsize;i++) { 747 values[i] = (GLushort) ctx->Pixel.MapStoS[i]; 748 } 749 break; 750 case GL_PIXEL_MAP_I_TO_R: 751 for (i=0;i<ctx->Pixel.MapItoRsize;i++) { 752 values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapItoR[i] ); 753 } 754 break; 755 case GL_PIXEL_MAP_I_TO_G: 756 for (i=0;i<ctx->Pixel.MapItoGsize;i++) { 757 values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapItoG[i] ); 758 } 759 break; 760 case GL_PIXEL_MAP_I_TO_B: 761 for (i=0;i<ctx->Pixel.MapItoBsize;i++) { 762 values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapItoB[i] ); 763 } 764 break; 765 case GL_PIXEL_MAP_I_TO_A: 766 for (i=0;i<ctx->Pixel.MapItoAsize;i++) { 767 values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapItoA[i] ); 768 } 769 break; 770 case GL_PIXEL_MAP_R_TO_R: 771 for (i=0;i<ctx->Pixel.MapRtoRsize;i++) { 772 values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapRtoR[i] ); 773 } 774 break; 775 case GL_PIXEL_MAP_G_TO_G: 776 for (i=0;i<ctx->Pixel.MapGtoGsize;i++) { 777 values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapGtoG[i] ); 778 } 779 break; 780 case GL_PIXEL_MAP_B_TO_B: 781 for (i=0;i<ctx->Pixel.MapBtoBsize;i++) { 782 values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapBtoB[i] ); 783 } 784 break; 785 case GL_PIXEL_MAP_A_TO_A: 786 for (i=0;i<ctx->Pixel.MapAtoAsize;i++) { 787 values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapAtoA[i] ); 788 } 789 break; 790 default: 791 gl_error( ctx, GL_INVALID_ENUM, "glGetPixelMapfv" ); 792 } 793 } 794 795 796 797 /**********************************************************************/ 798 /***** glPixelTransfer *****/ 799 /**********************************************************************/ 800 801 802 /* 803 * Implements glPixelTransfer[fi] whether called immediately or from a 804 * display list. 805 */ 806 void gl_PixelTransferf( GLcontext *ctx, GLenum pname, GLfloat param ) 807 { 808 if (INSIDE_BEGIN_END(ctx)) { 809 gl_error( ctx, GL_INVALID_OPERATION, "glPixelTransfer" ); 810 return; 811 } 812 813 switch (pname) { 814 case GL_MAP_COLOR: 815 ctx->Pixel.MapColorFlag = param ? GL_TRUE : GL_FALSE; 816 break; 817 case GL_MAP_STENCIL: 818 ctx->Pixel.MapStencilFlag = param ? GL_TRUE : GL_FALSE; 819 break; 820 case GL_INDEX_SHIFT: 821 ctx->Pixel.IndexShift = (GLint) param; 822 break; 823 case GL_INDEX_OFFSET: 824 ctx->Pixel.IndexOffset = (GLint) param; 825 break; 826 case GL_RED_SCALE: 827 ctx->Pixel.RedScale = param; 828 break; 829 case GL_RED_BIAS: 830 ctx->Pixel.RedBias = param; 831 break; 832 case GL_GREEN_SCALE: 833 ctx->Pixel.GreenScale = param; 834 break; 835 case GL_GREEN_BIAS: 836 ctx->Pixel.GreenBias = param; 837 break; 838 case GL_BLUE_SCALE: 839 ctx->Pixel.BlueScale = param; 840 break; 841 case GL_BLUE_BIAS: 842 ctx->Pixel.BlueBias = param; 843 break; 844 case GL_ALPHA_SCALE: 845 ctx->Pixel.AlphaScale = param; 846 break; 847 case GL_ALPHA_BIAS: 848 ctx->Pixel.AlphaBias = param; 849 break; 850 case GL_DEPTH_SCALE: 851 ctx->Pixel.DepthScale = param; 852 break; 853 case GL_DEPTH_BIAS: 854 ctx->Pixel.DepthBias = param; 855 break; 856 default: 857 gl_error( ctx, GL_INVALID_ENUM, "glPixelTransfer(pname)" ); 858 return; 859 } 860 update_drawpixels_state( ctx ); 861 } 862 863 864 865 866 867 /**********************************************************************/ 868 /***** Pixel packing/unpacking *****/ 869 /**********************************************************************/ 870 871 872 873 /* 874 * Unpack a 2-D pixel array/image. The unpacked format will be con- 875 * tiguous (no "empty" bytes) with byte/bit swapping applied as needed. 876 * Input: same as glDrawPixels 877 * Output: pointer to block of pixel data in same format and type as input 878 * or NULL if error. 879 */ 880 GLvoid *gl_unpack_pixels( GLcontext *ctx, 881 GLsizei width, GLsizei height, 882 GLenum format, GLenum type, 883 const GLvoid *pixels ) 884 { 885 GLint s, n; 886 887 s = gl_sizeof_type( type ); 888 if (s<0) { 889 gl_error( ctx, GL_INVALID_ENUM, "internal error in gl_unpack(type)" ); 890 return NULL; 891 } 892 893 n = gl_components_in_format( format ); 894 if (n<0) { 895 gl_error( ctx, GL_INVALID_ENUM, "gl_unpack_pixels(format)" ); 896 return NULL; 897 } 898 899 if (type==GL_BITMAP) { 900 /* BITMAP data */ 901 GLint bytes, i, width_in_bytes; 902 GLubyte *buffer, *dst; 903 GLvoid *src; 904 905 /* Alloc dest storage */ 906 bytes = CEILING( width * height , 8 ); 907 buffer = (GLubyte *) malloc( bytes ); 908 if (!buffer) { 909 return NULL; 910 } 911 912 /* Copy/unpack pixel data to buffer */ 913 width_in_bytes = CEILING( width, 8 ); 914 dst = buffer; 915 for (i=0;i<height;i++) { 916 src = gl_pixel_addr_in_image( &ctx->Unpack, pixels, width, height, 917 format, type, i); 918 if (!src) { 919 free(buffer); 920 return NULL; 921 } 922 MEMCPY( dst, src, width_in_bytes ); 923 dst += width_in_bytes; 924 } 925 926 /* Bit flipping */ 927 if (ctx->Unpack.LsbFirst) { 928 gl_flip_bytes( buffer, bytes ); 929 } 930 return (GLvoid *) buffer; 931 } 932 else { 933 /* Non-BITMAP data */ 934 GLint width_in_bytes, bytes, i; 935 GLubyte *buffer, *dst; 936 GLvoid *src; 937 938 width_in_bytes = width * n * s; 939 940 /* Alloc dest storage */ 941 bytes = height * width_in_bytes; 942 buffer = (GLubyte *) malloc( bytes ); 943 if (!buffer) { 944 return NULL; 945 } 946 947 /* Copy/unpack pixel data to buffer */ 948 dst = buffer; 949 for (i=0;i<height;i++) { 950 src = gl_pixel_addr_in_image( &ctx->Unpack, pixels, width, height, 951 format, type, i); 952 if (!src) { 953 free(buffer); 954 return NULL; 955 } 956 MEMCPY( dst, src, width_in_bytes ); 957 dst += width_in_bytes; 958 } 959 960 /* Byte swapping */ 961 if (ctx->Unpack.SwapBytes && s>1) { 962 if (s==2) { 963 gl_swap2( (GLushort *) buffer, bytes/2 ); 964 } 965 else if (s==4) { 966 gl_swap4( (GLuint *) buffer, bytes/4 ); 967 } 968 } 969 return (GLvoid *) buffer; 970 } 971 } 972 973 974 975 976 /* 977 if (s>=a) { 978 k = n * l; 979 } 980 else { *s<a* 981 k = (a/s) * ceil( s*n*l / a ); 982 } 983 984 s = size in bytes of a single component 985 a = alignment 986 n = number of components in a pixel 987 l = number of pixels in a row 988 989 k = number of components or indices between first pixel in each row in mem. 990 */ 991 992