drawpix.c revision bc41b08073bd764d1844c4cc32bbd4cd0fc0b850
1/* $Id: drawpix.c,v 1.4 1999/10/19 20:33:57 brianp Exp $ */ 2 3/* 4 * Mesa 3-D graphics library 5 * Version: 3.1 6 * 7 * Copyright (C) 1999 Brian Paul All Rights Reserved. 8 * 9 * Permission is hereby granted, free of charge, to any person obtaining a 10 * copy of this software and associated documentation files (the "Software"), 11 * to deal in the Software without restriction, including without limitation 12 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 * and/or sell copies of the Software, and to permit persons to whom the 14 * Software is furnished to do so, subject to the following conditions: 15 * 16 * The above copyright notice and this permission notice shall be included 17 * in all copies or substantial portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 */ 26 27 28 29 30 31#ifdef PC_HEADER 32#include "all.h" 33#else 34#ifndef XFree86Server 35#include <assert.h> 36#include <stdlib.h> 37#include <string.h> 38#else 39#include "GL/xf86glx.h" 40#endif 41#include "context.h" 42#include "drawpix.h" 43#include "feedback.h" 44#include "image.h" 45#include "macros.h" 46#include "mmath.h" 47#include "pixel.h" 48#include "span.h" 49#include "stencil.h" 50#include "types.h" 51#include "zoom.h" 52#ifdef XFree86Server 53#include "GL/xf86glx.h" 54#endif 55#endif 56 57 58 59/* TODO: apply texture mapping to fragments */ 60 61 62/* 63 * Try to do a fast glDrawPixels. Conditions include: 64 * not using a display list 65 * simple pixel unpacking 66 * no raster ops 67 * etc.... 68 * Return: GL_TRUE if success, GL_FALSE if slow path must be used instead 69 */ 70GLboolean gl_direct_DrawPixels( GLcontext *ctx, 71 const struct gl_pixelstore_attrib *unpack, 72 GLsizei width, GLsizei height, 73 GLenum format, GLenum type, 74 const GLvoid *pixels ) 75{ 76 GLubyte rgb[MAX_WIDTH][3]; 77 GLubyte rgba[MAX_WIDTH][4]; 78 79 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx, "glDrawPixels", 80 GL_FALSE); 81 82 83 if (!ctx->Current.RasterPosValid) { 84 /* no-op */ 85 return GL_TRUE; 86 } 87 88 if (ctx->NewState) { 89 gl_update_state(ctx); 90 } 91 92 /* see if device driver can do the drawpix */ 93 if (ctx->Driver.DrawPixels) { 94 GLint x = (GLint) (ctx->Current.RasterPos[0] + 0.5F); 95 GLint y = (GLint) (ctx->Current.RasterPos[1] + 0.5F); 96 if ((*ctx->Driver.DrawPixels)(ctx, x, y, width, height, format, type, 97 unpack, pixels)) 98 return GL_TRUE; 99 } 100 101 if ((ctx->RasterMask&(~(SCISSOR_BIT|WINCLIP_BIT)))==0 102 && ctx->Pixel.RedBias==0.0 && ctx->Pixel.RedScale==1.0 103 && ctx->Pixel.GreenBias==0.0 && ctx->Pixel.GreenScale==1.0 104 && ctx->Pixel.BlueBias==0.0 && ctx->Pixel.BlueScale==1.0 105 && ctx->Pixel.AlphaBias==0.0 && ctx->Pixel.AlphaScale==1.0 106 && ctx->Pixel.IndexShift==0 && ctx->Pixel.IndexOffset==0 107 && ctx->Pixel.MapColorFlag==0 108 && unpack->Alignment==1 109 && !unpack->SwapBytes 110 && !unpack->LsbFirst) { 111 112 GLint destX = (GLint) (ctx->Current.RasterPos[0] + 0.5F); 113 GLint destY = (GLint) (ctx->Current.RasterPos[1] + 0.5F); 114 GLint drawWidth = width; /* actual width drawn */ 115 GLint drawHeight = height; /* actual height drawn */ 116 GLint skipPixels = unpack->SkipPixels; 117 GLint skipRows = unpack->SkipRows; 118 GLint rowLength; 119 GLdepth zSpan[MAX_WIDTH]; /* only used when zooming */ 120 GLint zoomY0; 121 122 if (unpack->RowLength > 0) 123 rowLength = unpack->RowLength; 124 else 125 rowLength = width; 126 127 /* If we're not using pixel zoom then do all clipping calculations 128 * now. Otherwise, we'll let the gl_write_zoomed_*_span() functions 129 * handle the clipping. 130 */ 131 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { 132 /* horizontal clipping */ 133 if (destX < ctx->Buffer->Xmin) { 134 skipPixels += (ctx->Buffer->Xmin - destX); 135 drawWidth -= (ctx->Buffer->Xmin - destX); 136 destX = ctx->Buffer->Xmin; 137 } 138 if (destX + drawWidth > ctx->Buffer->Xmax) 139 drawWidth -= (destX + drawWidth - ctx->Buffer->Xmax - 1); 140 if (drawWidth <= 0) 141 return GL_TRUE; 142 143 /* vertical clipping */ 144 if (destY < ctx->Buffer->Ymin) { 145 skipRows += (ctx->Buffer->Ymin - destY); 146 drawHeight -= (ctx->Buffer->Ymin - destY); 147 destY = ctx->Buffer->Ymin; 148 } 149 if (destY + drawHeight > ctx->Buffer->Ymax) 150 drawHeight -= (destY + drawHeight - ctx->Buffer->Ymax - 1); 151 if (drawHeight <= 0) 152 return GL_TRUE; 153 } 154 else { 155 /* setup array of fragment Z value to pass to zoom function */ 156 GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE); 157 GLint i; 158 assert(drawWidth < MAX_WIDTH); 159 for (i=0; i<drawWidth; i++) 160 zSpan[i] = z; 161 162 /* save Y value of first row */ 163 zoomY0 = (GLint) (ctx->Current.RasterPos[1] + 0.5F); 164 } 165 166 167 /* 168 * Ready to draw! 169 * The window region at (destX, destY) of size (drawWidth, drawHeight) 170 * will be written to. 171 * We'll take pixel data from buffer pointed to by "pixels" but we'll 172 * skip "skipRows" rows and skip "skipPixels" pixels/row. 173 */ 174 175 if (format==GL_RGBA && type==GL_UNSIGNED_BYTE) { 176 if (ctx->Visual->RGBAflag) { 177 GLubyte *src = (GLubyte *) pixels 178 + (skipRows * rowLength + skipPixels) * 4; 179 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { 180 /* no zooming */ 181 GLint row; 182 for (row=0; row<drawHeight; row++) { 183 (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY, 184 (void *) src, NULL); 185 src += rowLength * 4; 186 destY++; 187 } 188 } 189 else { 190 /* with zooming */ 191 GLint row; 192 for (row=0; row<drawHeight; row++) { 193 gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY, 194 zSpan, (void *) src, zoomY0); 195 src += rowLength * 4; 196 destY++; 197 } 198 } 199 } 200 return GL_TRUE; 201 } 202 else if (format==GL_RGB && type==GL_UNSIGNED_BYTE) { 203 if (ctx->Visual->RGBAflag) { 204 GLubyte *src = (GLubyte *) pixels 205 + (skipRows * rowLength + skipPixels) * 3; 206 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { 207 GLint row; 208 for (row=0; row<drawHeight; row++) { 209 (*ctx->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY, 210 (void *) src, NULL); 211 src += rowLength * 3; 212 destY++; 213 } 214 } 215 else { 216 /* with zooming */ 217 GLint row; 218 for (row=0; row<drawHeight; row++) { 219 gl_write_zoomed_rgb_span(ctx, drawWidth, destX, destY, 220 zSpan, (void *) src, zoomY0); 221 src += rowLength * 3; 222 destY++; 223 } 224 } 225 } 226 return GL_TRUE; 227 } 228 else if (format==GL_LUMINANCE && type==GL_UNSIGNED_BYTE) { 229 if (ctx->Visual->RGBAflag) { 230 GLubyte *src = (GLubyte *) pixels 231 + (skipRows * rowLength + skipPixels); 232 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { 233 /* no zooming */ 234 GLint row; 235 assert(drawWidth < MAX_WIDTH); 236 for (row=0; row<drawHeight; row++) { 237 GLint i; 238 for (i=0;i<drawWidth;i++) { 239 rgb[i][0] = src[i]; 240 rgb[i][1] = src[i]; 241 rgb[i][2] = src[i]; 242 } 243 (*ctx->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY, 244 (void *) rgb, NULL); 245 src += rowLength; 246 destY++; 247 } 248 } 249 else { 250 /* with zooming */ 251 GLint row; 252 assert(drawWidth < MAX_WIDTH); 253 for (row=0; row<drawHeight; row++) { 254 GLint i; 255 for (i=0;i<drawWidth;i++) { 256 rgb[i][0] = src[i]; 257 rgb[i][1] = src[i]; 258 rgb[i][2] = src[i]; 259 } 260 gl_write_zoomed_rgb_span(ctx, drawWidth, destX, destY, 261 zSpan, (void *) rgb, zoomY0); 262 src += rowLength; 263 destY++; 264 } 265 } 266 } 267 return GL_TRUE; 268 } 269 else if (format==GL_LUMINANCE_ALPHA && type==GL_UNSIGNED_BYTE) { 270 if (ctx->Visual->RGBAflag) { 271 GLubyte *src = (GLubyte *) pixels 272 + (skipRows * rowLength + skipPixels)*2; 273 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { 274 /* no zooming */ 275 GLint row; 276 assert(drawWidth < MAX_WIDTH); 277 for (row=0; row<drawHeight; row++) { 278 GLint i; 279 GLubyte *ptr = src; 280 for (i=0;i<drawWidth;i++) { 281 rgba[i][0] = *ptr; 282 rgba[i][1] = *ptr; 283 rgba[i][2] = *ptr++; 284 rgba[i][3] = *ptr++; 285 } 286 (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY, 287 (void *) rgba, NULL); 288 src += rowLength*2; 289 destY++; 290 } 291 } 292 else { 293 /* with zooming */ 294 GLint row; 295 assert(drawWidth < MAX_WIDTH); 296 for (row=0; row<drawHeight; row++) { 297 GLubyte *ptr = src; 298 GLint i; 299 for (i=0;i<drawWidth;i++) { 300 rgba[i][0] = *ptr; 301 rgba[i][1] = *ptr; 302 rgba[i][2] = *ptr++; 303 rgba[i][3] = *ptr++; 304 } 305 gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY, 306 zSpan, (void *) rgba, zoomY0); 307 src += rowLength*2; 308 destY++; 309 } 310 } 311 } 312 return GL_TRUE; 313 } 314 else if (format==GL_COLOR_INDEX && type==GL_UNSIGNED_BYTE) { 315 GLubyte *src = (GLubyte *) pixels + skipRows * rowLength + skipPixels; 316 if (ctx->Visual->RGBAflag) { 317 /* convert CI data to RGBA */ 318 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { 319 /* no zooming */ 320 GLint row; 321 for (row=0; row<drawHeight; row++) { 322 assert(drawWidth < MAX_WIDTH); 323 gl_map_ci8_to_rgba(ctx, drawWidth, src, rgba); 324 (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY, 325 (const GLubyte (*)[4])rgba, 326 NULL); 327 src += rowLength; 328 destY++; 329 } 330 return GL_TRUE; 331 } 332 else { 333 /* with zooming */ 334 GLint row; 335 for (row=0; row<drawHeight; row++) { 336 assert(drawWidth < MAX_WIDTH); 337 gl_map_ci8_to_rgba(ctx, drawWidth, src, rgba); 338 gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY, 339 zSpan, (void *) rgba, zoomY0); 340 src += rowLength; 341 destY++; 342 } 343 return GL_TRUE; 344 } 345 } 346 else { 347 /* write CI data to CI frame buffer */ 348 GLint row; 349 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { 350 /* no zooming */ 351 for (row=0; row<drawHeight; row++) { 352 (*ctx->Driver.WriteCI8Span)(ctx, drawWidth, destX, destY, 353 src, NULL); 354 src += rowLength; 355 destY++; 356 } 357 return GL_TRUE; 358 } 359 else { 360 /* with zooming */ 361 return GL_FALSE; 362 } 363 } 364 } 365 else { 366 /* can't handle this pixel format and/or data type here */ 367 return GL_FALSE; 368 } 369 } 370 else { 371 /* can't do direct render, have to use slow path */ 372 return GL_FALSE; 373 } 374} 375 376 377 378/* 379 * Do glDrawPixels of index pixels. 380 */ 381static void draw_index_pixels( GLcontext *ctx, GLint x, GLint y, 382 const struct gl_image *image ) 383{ 384 GLint width, height, widthInBytes; 385 const GLint desty = y; 386 GLint i, j; 387 GLdepth zspan[MAX_WIDTH]; 388 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0; 389 390 assert(image); 391 assert(image->Format == GL_COLOR_INDEX); 392 393 width = image->Width; 394 height = image->Height; 395 if (image->Type == GL_BITMAP) 396 widthInBytes = (width + 7) / 8; 397 else 398 widthInBytes = width; 399 400 /* Fragment depth values */ 401 if (ctx->Depth.Test) { 402 GLdepth zval = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE); 403 for (i=0;i<width;i++) { 404 zspan[i] = zval; 405 } 406 } 407 408 /* process the image row by row */ 409 for (i=0;i<height;i++,y++) { 410 GLuint ispan[MAX_WIDTH]; 411 412 /* convert to uints */ 413 switch (image->Type) { 414 case GL_UNSIGNED_BYTE: 415 { 416 GLubyte *src = (GLubyte *) image->Data + i * width; 417 for (j=0;j<width;j++) { 418 ispan[j] = (GLuint) *src++; 419 } 420 } 421 break; 422 case GL_FLOAT: 423 { 424 GLfloat *src = (GLfloat *) image->Data + i * width; 425 for (j=0;j<width;j++) { 426 ispan[j] = (GLuint) (GLint) *src++; 427 } 428 } 429 break; 430 case GL_BITMAP: 431 { 432 GLubyte *src = (GLubyte *) image->Data + i * widthInBytes; 433 for (j=0;j<width;j++) { 434 ispan[j] = ( src[j >> 3] >> (7 - (j & 0x7)) ) & 1; 435 } 436 } 437 break; 438 default: 439 gl_problem( ctx, "draw_index_pixels type" ); 440 return; 441 } 442 443 /* apply shift and offset */ 444 if (ctx->Pixel.IndexOffset || ctx->Pixel.IndexShift) { 445 gl_shift_and_offset_ci( ctx, width, ispan ); 446 } 447 448 if (ctx->Visual->RGBAflag) { 449 /* Convert index to RGBA and write to frame buffer */ 450 GLubyte rgba[MAX_WIDTH][4]; 451 gl_map_ci_to_rgba( ctx, width, ispan, rgba ); 452 if (zoom) { 453 gl_write_zoomed_rgba_span( ctx, width, x, y, zspan, 454 (const GLubyte (*)[4])rgba, desty ); 455 } 456 else { 457 gl_write_rgba_span( ctx, width, x, y, zspan, rgba, GL_BITMAP ); 458 } 459 } 460 else { 461 /* optionally apply index map then write to frame buffer */ 462 if (ctx->Pixel.MapColorFlag) { 463 gl_map_ci(ctx, width, ispan); 464 } 465 if (zoom) { 466 gl_write_zoomed_index_span( ctx, width, x, y, zspan, ispan, desty ); 467 } 468 else { 469 gl_write_index_span( ctx, width, x, y, zspan, ispan, GL_BITMAP ); 470 } 471 } 472 } 473 474} 475 476 477 478/* 479 * Do glDrawPixels of stencil image. The image datatype may either 480 * be GLubyte or GLbitmap. 481 */ 482static void draw_stencil_pixels( GLcontext *ctx, GLint x, GLint y, 483 const struct gl_image *image ) 484{ 485 GLint widthInBytes, width, height; 486 const GLint desty = y; 487 GLint i; 488 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0; 489 490 if (image->Type != GL_BYTE && 491 image->Type != GL_UNSIGNED_BYTE && 492 image->Type != GL_SHORT && 493 image->Type != GL_UNSIGNED_SHORT && 494 image->Type != GL_INT && 495 image->Type != GL_UNSIGNED_INT && 496 image->Type != GL_FLOAT && 497 image->Type != GL_BITMAP) { 498 gl_error( ctx, GL_INVALID_OPERATION, "glDrawPixels(stencil type)"); 499 return; 500 } 501 502 assert(image); 503 assert(image->Format == GL_STENCIL_INDEX); 504 assert(image->Type == GL_UNSIGNED_BYTE || image->Type == GL_BITMAP); 505 506 if (image->Type == GL_UNSIGNED_BYTE) 507 widthInBytes = image->Width; 508 else 509 widthInBytes = (image->Width + 7) / 8; 510 width = image->Width; 511 height = image->Height; 512 513 /* process the image row by row */ 514 for (i=0;i<height;i++,y++) { 515 GLstencil *src = (GLstencil*)image->Data + i * widthInBytes; 516 GLstencil *stencilValues; 517 GLstencil stencilCopy[MAX_WIDTH]; 518 519 if (image->Type == GL_BITMAP) { 520 /* convert bitmap data to GLubyte (0 or 1) data */ 521 GLint j; 522 for (j = 0; j < width; j++) { 523 stencilCopy[j] = ( src[j >> 3] >> (7 - (j & 0x7)) ) & 1; 524 } 525 src = stencilCopy; 526 } 527 528 if (ctx->Pixel.IndexOffset || ctx->Pixel.IndexShift 529 || ctx->Pixel.MapStencilFlag) { 530 531 /* make copy of stencil values */ 532 if (src != stencilCopy) 533 MEMCPY( stencilCopy, src, width * sizeof(GLstencil)); 534 535 /* apply shift and offset */ 536 if (ctx->Pixel.IndexOffset || ctx->Pixel.IndexShift) { 537 gl_shift_and_offset_stencil( ctx, width, stencilCopy ); 538 } 539 540 /* mapping */ 541 if (ctx->Pixel.MapStencilFlag) { 542 gl_map_stencil( ctx, width, stencilCopy ); 543 } 544 545 stencilValues = stencilCopy; 546 } 547 else { 548 /* use stencil values in-place */ 549 stencilValues = src; 550 } 551 552 /* write stencil values to stencil buffer */ 553 if (zoom) { 554 gl_write_zoomed_stencil_span( ctx, (GLuint) width, x, y, 555 stencilValues, desty ); 556 } 557 else { 558 gl_write_stencil_span( ctx, (GLuint) width, x, y, stencilValues ); 559 } 560 } 561} 562 563 564 565/* 566 * Do a glDrawPixels of depth values. 567 */ 568static void draw_depth_pixels( GLcontext *ctx, GLint x, GLint y, 569 const struct gl_image *image ) 570{ 571 GLint width, height; 572 const GLint desty = y; 573 GLubyte rgba[MAX_WIDTH][4]; 574 GLuint ispan[MAX_WIDTH]; 575 const GLboolean bias_or_scale = ctx->Pixel.DepthBias!=0.0 || ctx->Pixel.DepthScale!=1.0; 576 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0; 577 578 assert(image); 579 assert(image->Format == GL_DEPTH_COMPONENT); 580 581 width = image->Width; 582 height = image->Height; 583 584 /* Color or index */ 585 if (ctx->Visual->RGBAflag) { 586 GLint r = (GLint) (ctx->Current.RasterColor[0] * 255.0F); 587 GLint g = (GLint) (ctx->Current.RasterColor[1] * 255.0F); 588 GLint b = (GLint) (ctx->Current.RasterColor[2] * 255.0F); 589 GLint a = (GLint) (ctx->Current.RasterColor[3] * 255.0F); 590 GLint i; 591 for (i=0; i<width; i++) { 592 rgba[i][RCOMP] = r; 593 rgba[i][GCOMP] = g; 594 rgba[i][BCOMP] = b; 595 rgba[i][ACOMP] = a; 596 } 597 } 598 else { 599 GLint i; 600 for (i=0;i<width;i++) { 601 ispan[i] = ctx->Current.RasterIndex; 602 } 603 } 604 605 if (image->Type==GL_UNSIGNED_SHORT && sizeof(GLdepth)==sizeof(GLushort) 606 && !bias_or_scale && !zoom && ctx->Visual->RGBAflag) { 607 /* Special case: directly write 16-bit depth values */ 608 GLint j; 609 for (j=0;j<height;j++,y++) { 610 GLdepth *zptr = (GLdepth *) image->Data + j * width; 611 gl_write_rgba_span( ctx, width, x, y, zptr, rgba, GL_BITMAP ); 612 } 613 } 614 else if (image->Type==GL_UNSIGNED_INT && sizeof(GLdepth)==sizeof(GLuint) 615 && !bias_or_scale && !zoom && ctx->Visual->RGBAflag) { 616 /* Special case: directly write 32-bit depth values */ 617 GLint i, j; 618 /* Compute shift value to scale 32-bit uints down to depth values. */ 619 GLuint shift = 0; 620 GLuint max = MAX_DEPTH; 621 while ((max&0x80000000)==0) { 622 max = max << 1; 623 shift++; 624 } 625 for (j=0;j<height;j++,y++) { 626 GLdepth zspan[MAX_WIDTH]; 627 GLuint *zptr = (GLuint *) image->Data + j * width; 628 for (i=0;i<width;i++) { 629 zspan[i] = zptr[i] >> shift; 630 } 631 gl_write_rgba_span( ctx, width, x, y, zspan, rgba, GL_BITMAP ); 632 } 633 } 634 else { 635 /* General case (slower) */ 636 GLint i, j; 637 638 /* process image row by row */ 639 for (i=0;i<height;i++,y++) { 640 GLfloat depth[MAX_WIDTH]; 641 GLdepth zspan[MAX_WIDTH]; 642 643 switch (image->Type) { 644 case GL_UNSIGNED_SHORT: 645 { 646 GLushort *src = (GLushort *) image->Data + i * width; 647 for (j=0;j<width;j++) { 648 depth[j] = USHORT_TO_FLOAT( *src++ ); 649 } 650 } 651 break; 652 case GL_UNSIGNED_INT: 653 { 654 GLuint *src = (GLuint *) image->Data + i * width; 655 for (j=0;j<width;j++) { 656 depth[j] = UINT_TO_FLOAT( *src++ ); 657 } 658 } 659 break; 660 case GL_FLOAT: 661 { 662 GLfloat *src = (GLfloat *) image->Data + i * width; 663 for (j=0;j<width;j++) { 664 depth[j] = *src++; 665 } 666 } 667 break; 668 default: 669 gl_problem(ctx, "Bad type in draw_depth_pixels"); 670 return; 671 } 672 673 /* apply depth scale and bias */ 674 if (ctx->Pixel.DepthScale!=1.0 || ctx->Pixel.DepthBias!=0.0) { 675 for (j=0;j<width;j++) { 676 depth[j] = depth[j] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias; 677 } 678 } 679 680 /* clamp depth values to [0,1] and convert from floats to integers */ 681 for (j=0;j<width;j++) { 682 zspan[j] = (GLdepth) (CLAMP( depth[j], 0.0F, 1.0F ) * DEPTH_SCALE); 683 } 684 685 if (ctx->Visual->RGBAflag) { 686 if (zoom) { 687 gl_write_zoomed_rgba_span( ctx, width, x, y, zspan, 688 (const GLubyte (*)[4])rgba, desty ); 689 } 690 else { 691 gl_write_rgba_span( ctx, width, x, y, zspan, rgba, GL_BITMAP ); 692 } 693 } 694 else { 695 if (zoom) { 696 gl_write_zoomed_index_span( ctx, width, x, y, zspan, 697 ispan, GL_BITMAP ); 698 } 699 else { 700 gl_write_index_span( ctx, width, x, y, zspan, ispan, GL_BITMAP ); 701 } 702 } 703 704 } 705 } 706} 707 708 709 710/* Simple unpacking parameters: */ 711static struct gl_pixelstore_attrib NoUnpack = { 712 1, /* Alignment */ 713 0, /* RowLength */ 714 0, /* SkipPixels */ 715 0, /* SkipRows */ 716 0, /* ImageHeight */ 717 0, /* SkipImages */ 718 GL_FALSE, /* SwapBytes */ 719 GL_FALSE /* LsbFirst */ 720}; 721 722 723/* 724 * Do glDrawPixels of RGBA pixels. 725 */ 726static void draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y, 727 const struct gl_image *image ) 728{ 729 GLint width, height; 730 GLint i, j; 731 const GLint desty = y; 732 GLdepth zspan[MAX_WIDTH]; 733 GLboolean quickDraw; 734 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0; 735 736 assert(image); 737 738 /* Try an optimized glDrawPixels first */ 739 if (gl_direct_DrawPixels(ctx, &NoUnpack, image->Width, image->Height, 740 image->Format, image->Type, image->Data )) 741 return; 742 743 width = image->Width; 744 height = image->Height; 745 746 /* Fragment depth values */ 747 if (ctx->Depth.Test) { 748 /* fill in array of z values */ 749 GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE); 750 for (i=0;i<width;i++) { 751 zspan[i] = z; 752 } 753 } 754 755 if (ctx->RasterMask==0 && !zoom && x>=0 && y>=0 756 && x+width<=ctx->Buffer->Width && y+height<=ctx->Buffer->Height) { 757 quickDraw = GL_TRUE; 758 } 759 else { 760 quickDraw = GL_FALSE; 761 } 762 763 { 764 /* General solution */ 765 GLboolean r_flag, g_flag, b_flag, a_flag, l_flag; 766 GLuint components; 767 GLubyte rgba[MAX_WIDTH][4]; 768 GLfloat rf[MAX_WIDTH]; 769 GLfloat gf[MAX_WIDTH]; 770 GLfloat bf[MAX_WIDTH]; 771 DEFARRAY(GLfloat,af,MAX_WIDTH); 772 CHECKARRAY(af,return); 773 774 r_flag = g_flag = b_flag = a_flag = l_flag = GL_FALSE; 775 switch (image->Format) { 776 case GL_RED: 777 r_flag = GL_TRUE; 778 components = 1; 779 break; 780 case GL_GREEN: 781 g_flag = GL_TRUE; 782 components = 1; 783 break; 784 case GL_BLUE: 785 b_flag = GL_TRUE; 786 components = 1; 787 break; 788 case GL_ALPHA: 789 a_flag = GL_TRUE; 790 components = 1; 791 break; 792 case GL_RGB: 793 r_flag = g_flag = b_flag = GL_TRUE; 794 components = 3; 795 break; 796 case GL_LUMINANCE: 797 l_flag = GL_TRUE; 798 components = 1; 799 break; 800 case GL_LUMINANCE_ALPHA: 801 l_flag = a_flag = GL_TRUE; 802 components = 2; 803 break; 804 case GL_RGBA: 805 r_flag = g_flag = b_flag = a_flag = GL_TRUE; 806 components = 4; 807 break; 808 default: 809 gl_problem(ctx, "Bad type in draw_rgba_pixels"); 810 goto cleanup; 811 } 812 813 /* process the image row by row */ 814 for (i=0;i<height;i++,y++) { 815 /* convert to floats */ 816 switch (image->Type) { 817 case GL_UNSIGNED_BYTE: 818 { 819 GLubyte *src = (GLubyte *) image->Data + i * width * components; 820 for (j=0;j<width;j++) { 821 if (l_flag) { 822 rf[j] = gf[j] = bf[j] = UBYTE_TO_FLOAT(*src++); 823 } 824 else { 825 rf[j] = r_flag ? UBYTE_TO_FLOAT(*src++) : 0.0; 826 gf[j] = g_flag ? UBYTE_TO_FLOAT(*src++) : 0.0; 827 bf[j] = b_flag ? UBYTE_TO_FLOAT(*src++) : 0.0; 828 } 829 af[j] = a_flag ? UBYTE_TO_FLOAT(*src++) : 1.0; 830 } 831 } 832 break; 833 case GL_FLOAT: 834 { 835 GLfloat *src = (GLfloat *) image->Data + i * width * components; 836 for (j=0;j<width;j++) { 837 if (l_flag) { 838 rf[j] = gf[j] = bf[j] = *src++; 839 } 840 else { 841 rf[j] = r_flag ? *src++ : 0.0; 842 gf[j] = g_flag ? *src++ : 0.0; 843 bf[j] = b_flag ? *src++ : 0.0; 844 } 845 af[j] = a_flag ? *src++ : 1.0; 846 } 847 } 848 break; 849 default: 850 gl_problem( ctx, "draw_rgba_pixels type" ); 851 goto cleanup; 852 } 853 854 /* apply scale and bias */ 855 if (ctx->Pixel.ScaleOrBiasRGBA) { 856 gl_scale_and_bias_color(ctx, width, rf, gf, bf, af); 857 } 858 859 /* apply pixel mappings */ 860 if (ctx->Pixel.MapColorFlag) { 861 gl_map_color(ctx, width, rf, gf, bf, af); 862 } 863 864 /* convert to integers */ 865 for (j=0;j<width;j++) { 866 rgba[j][RCOMP] = (GLint) (rf[j] * 255.0F); 867 rgba[j][GCOMP] = (GLint) (gf[j] * 255.0F); 868 rgba[j][BCOMP] = (GLint) (bf[j] * 255.0F); 869 rgba[j][ACOMP] = (GLint) (af[j] * 255.0F); 870 } 871 872 /* write to frame buffer */ 873 if (quickDraw) { 874 (*ctx->Driver.WriteRGBASpan)( ctx, width, x, y, 875 (const GLubyte (*)[4])rgba, NULL); 876 } 877 else if (zoom) { 878 gl_write_zoomed_rgba_span( ctx, width, x, y, zspan, 879 (const GLubyte (*)[4])rgba, desty ); 880 } 881 else { 882 gl_write_rgba_span( ctx, (GLuint) width, x, y, zspan, rgba, GL_BITMAP); 883 } 884 } 885cleanup: 886 UNDEFARRAY(af); 887 } 888} 889 890 891 892/* 893 * Execute glDrawPixels 894 */ 895void gl_DrawPixels( GLcontext* ctx, struct gl_image *image ) 896{ 897 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDrawPixels"); 898 899 900 if (gl_image_error_test( ctx, image, "glDrawPixels" )) 901 return; 902 903 if (ctx->RenderMode==GL_RENDER) { 904 GLint x, y; 905 if (!ctx->Current.RasterPosValid) { 906 return; 907 } 908 909 x = (GLint) (ctx->Current.RasterPos[0] + 0.5F); 910 y = (GLint) (ctx->Current.RasterPos[1] + 0.5F); 911 912 switch (image->Format) { 913 case GL_COLOR_INDEX: 914 draw_index_pixels( ctx, x, y, image ); 915 break; 916 case GL_STENCIL_INDEX: 917 draw_stencil_pixels( ctx, x, y, image ); 918 break; 919 case GL_DEPTH_COMPONENT: 920 draw_depth_pixels( ctx, x, y, image ); 921 break; 922 case GL_RED: 923 case GL_GREEN: 924 case GL_BLUE: 925 case GL_ALPHA: 926 case GL_RGB: 927 case GL_LUMINANCE: 928 case GL_LUMINANCE_ALPHA: 929 case GL_RGBA: 930 draw_rgba_pixels( ctx, x, y, image ); 931 break; 932 default: 933 gl_error( ctx, GL_INVALID_ENUM, "glDrawPixels" ); 934 return; 935 } 936 } 937 else if (ctx->RenderMode==GL_FEEDBACK) { 938 if (ctx->Current.RasterPosValid) { 939 GLfloat color[4]; 940 GLfloat texcoord[4], invq; 941 UBYTE_RGBA_TO_FLOAT_RGBA(color, ctx->Current.ByteColor); 942 invq = 1.0F / ctx->Current.Texcoord[0][3]; 943 texcoord[0] = ctx->Current.Texcoord[0][0] * invq; 944 texcoord[1] = ctx->Current.Texcoord[0][1] * invq; 945 texcoord[2] = ctx->Current.Texcoord[0][2] * invq; 946 texcoord[3] = ctx->Current.Texcoord[0][3]; 947 FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN ); 948 gl_feedback_vertex( ctx, 949 ctx->Current.RasterPos, 950 color, ctx->Current.Index, texcoord ); 951 } 952 } 953 else if (ctx->RenderMode==GL_SELECT) { 954 if (ctx->Current.RasterPosValid) { 955 gl_update_hitflag( ctx, ctx->Current.RasterPos[2] ); 956 } 957 } 958} 959 960