drawpix.c revision 485f04074151686fa24d40e3eeb83029d3d8c425
1/* $Id: drawpix.c,v 1.3 1999/10/08 09:27:10 keithw 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 assert(image); 491 assert(image->Format == GL_STENCIL_INDEX); 492 assert(image->Type == GL_UNSIGNED_BYTE || image->Type == GL_BITMAP); 493 494 if (image->Type == GL_UNSIGNED_BYTE) 495 widthInBytes = image->Width; 496 else 497 widthInBytes = (image->Width + 7) / 8; 498 width = image->Width; 499 height = image->Height; 500 501 /* process the image row by row */ 502 for (i=0;i<height;i++,y++) { 503 GLstencil *src = (GLstencil*)image->Data + i * widthInBytes; 504 GLstencil *stencilValues; 505 GLstencil stencilCopy[MAX_WIDTH]; 506 507 if (image->Type == GL_BITMAP) { 508 /* convert bitmap data to GLubyte (0 or 1) data */ 509 GLint j; 510 for (j = 0; j < width; j++) { 511 stencilCopy[j] = ( src[j >> 3] >> (7 - (j & 0x7)) ) & 1; 512 } 513 src = stencilCopy; 514 } 515 516 if (ctx->Pixel.IndexOffset || ctx->Pixel.IndexShift 517 || ctx->Pixel.MapStencilFlag) { 518 519 /* make copy of stencil values */ 520 if (src != stencilCopy) 521 MEMCPY( stencilCopy, src, width * sizeof(GLstencil)); 522 523 /* apply shift and offset */ 524 if (ctx->Pixel.IndexOffset || ctx->Pixel.IndexShift) { 525 gl_shift_and_offset_stencil( ctx, width, stencilCopy ); 526 } 527 528 /* mapping */ 529 if (ctx->Pixel.MapStencilFlag) { 530 gl_map_stencil( ctx, width, stencilCopy ); 531 } 532 533 stencilValues = stencilCopy; 534 } 535 else { 536 /* use stencil values in-place */ 537 stencilValues = src; 538 } 539 540 /* write stencil values to stencil buffer */ 541 if (zoom) { 542 gl_write_zoomed_stencil_span( ctx, (GLuint) width, x, y, 543 stencilValues, desty ); 544 } 545 else { 546 gl_write_stencil_span( ctx, (GLuint) width, x, y, stencilValues ); 547 } 548 } 549} 550 551 552 553/* 554 * Do a glDrawPixels of depth values. 555 */ 556static void draw_depth_pixels( GLcontext *ctx, GLint x, GLint y, 557 const struct gl_image *image ) 558{ 559 GLint width, height; 560 const GLint desty = y; 561 GLubyte rgba[MAX_WIDTH][4]; 562 GLuint ispan[MAX_WIDTH]; 563 const GLboolean bias_or_scale = ctx->Pixel.DepthBias!=0.0 || ctx->Pixel.DepthScale!=1.0; 564 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0; 565 566 assert(image); 567 assert(image->Format == GL_DEPTH_COMPONENT); 568 569 width = image->Width; 570 height = image->Height; 571 572 /* Color or index */ 573 if (ctx->Visual->RGBAflag) { 574 GLint r = (GLint) (ctx->Current.RasterColor[0] * 255.0F); 575 GLint g = (GLint) (ctx->Current.RasterColor[1] * 255.0F); 576 GLint b = (GLint) (ctx->Current.RasterColor[2] * 255.0F); 577 GLint a = (GLint) (ctx->Current.RasterColor[3] * 255.0F); 578 GLint i; 579 for (i=0; i<width; i++) { 580 rgba[i][RCOMP] = r; 581 rgba[i][GCOMP] = g; 582 rgba[i][BCOMP] = b; 583 rgba[i][ACOMP] = a; 584 } 585 } 586 else { 587 GLint i; 588 for (i=0;i<width;i++) { 589 ispan[i] = ctx->Current.RasterIndex; 590 } 591 } 592 593 if (image->Type==GL_UNSIGNED_SHORT && sizeof(GLdepth)==sizeof(GLushort) 594 && !bias_or_scale && !zoom && ctx->Visual->RGBAflag) { 595 /* Special case: directly write 16-bit depth values */ 596 GLint j; 597 for (j=0;j<height;j++,y++) { 598 GLdepth *zptr = (GLdepth *) image->Data + j * width; 599 gl_write_rgba_span( ctx, width, x, y, zptr, rgba, GL_BITMAP ); 600 } 601 } 602 else if (image->Type==GL_UNSIGNED_INT && sizeof(GLdepth)==sizeof(GLuint) 603 && !bias_or_scale && !zoom && ctx->Visual->RGBAflag) { 604 /* Special case: directly write 32-bit depth values */ 605 GLint i, j; 606 /* Compute shift value to scale 32-bit uints down to depth values. */ 607 GLuint shift = 0; 608 GLuint max = MAX_DEPTH; 609 while ((max&0x80000000)==0) { 610 max = max << 1; 611 shift++; 612 } 613 for (j=0;j<height;j++,y++) { 614 GLdepth zspan[MAX_WIDTH]; 615 GLuint *zptr = (GLuint *) image->Data + j * width; 616 for (i=0;i<width;i++) { 617 zspan[i] = zptr[i] >> shift; 618 } 619 gl_write_rgba_span( ctx, width, x, y, zspan, rgba, GL_BITMAP ); 620 } 621 } 622 else { 623 /* General case (slower) */ 624 GLint i, j; 625 626 /* process image row by row */ 627 for (i=0;i<height;i++,y++) { 628 GLfloat depth[MAX_WIDTH]; 629 GLdepth zspan[MAX_WIDTH]; 630 631 switch (image->Type) { 632 case GL_UNSIGNED_SHORT: 633 { 634 GLushort *src = (GLushort *) image->Data + i * width; 635 for (j=0;j<width;j++) { 636 depth[j] = USHORT_TO_FLOAT( *src++ ); 637 } 638 } 639 break; 640 case GL_UNSIGNED_INT: 641 { 642 GLuint *src = (GLuint *) image->Data + i * width; 643 for (j=0;j<width;j++) { 644 depth[j] = UINT_TO_FLOAT( *src++ ); 645 } 646 } 647 break; 648 case GL_FLOAT: 649 { 650 GLfloat *src = (GLfloat *) image->Data + i * width; 651 for (j=0;j<width;j++) { 652 depth[j] = *src++; 653 } 654 } 655 break; 656 default: 657 gl_problem(ctx, "Bad type in draw_depth_pixels"); 658 return; 659 } 660 661 /* apply depth scale and bias */ 662 if (ctx->Pixel.DepthScale!=1.0 || ctx->Pixel.DepthBias!=0.0) { 663 for (j=0;j<width;j++) { 664 depth[j] = depth[j] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias; 665 } 666 } 667 668 /* clamp depth values to [0,1] and convert from floats to integers */ 669 for (j=0;j<width;j++) { 670 zspan[j] = (GLdepth) (CLAMP( depth[j], 0.0F, 1.0F ) * DEPTH_SCALE); 671 } 672 673 if (ctx->Visual->RGBAflag) { 674 if (zoom) { 675 gl_write_zoomed_rgba_span( ctx, width, x, y, zspan, 676 (const GLubyte (*)[4])rgba, desty ); 677 } 678 else { 679 gl_write_rgba_span( ctx, width, x, y, zspan, rgba, GL_BITMAP ); 680 } 681 } 682 else { 683 if (zoom) { 684 gl_write_zoomed_index_span( ctx, width, x, y, zspan, 685 ispan, GL_BITMAP ); 686 } 687 else { 688 gl_write_index_span( ctx, width, x, y, zspan, ispan, GL_BITMAP ); 689 } 690 } 691 692 } 693 } 694} 695 696 697 698/* Simple unpacking parameters: */ 699static struct gl_pixelstore_attrib NoUnpack = { 700 1, /* Alignment */ 701 0, /* RowLength */ 702 0, /* SkipPixels */ 703 0, /* SkipRows */ 704 0, /* ImageHeight */ 705 0, /* SkipImages */ 706 GL_FALSE, /* SwapBytes */ 707 GL_FALSE /* LsbFirst */ 708}; 709 710 711/* 712 * Do glDrawPixels of RGBA pixels. 713 */ 714static void draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y, 715 const struct gl_image *image ) 716{ 717 GLint width, height; 718 GLint i, j; 719 const GLint desty = y; 720 GLdepth zspan[MAX_WIDTH]; 721 GLboolean quickDraw; 722 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0; 723 724 assert(image); 725 726 /* Try an optimized glDrawPixels first */ 727 if (gl_direct_DrawPixels(ctx, &NoUnpack, image->Width, image->Height, 728 image->Format, image->Type, image->Data )) 729 return; 730 731 width = image->Width; 732 height = image->Height; 733 734 /* Fragment depth values */ 735 if (ctx->Depth.Test) { 736 /* fill in array of z values */ 737 GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE); 738 for (i=0;i<width;i++) { 739 zspan[i] = z; 740 } 741 } 742 743 if (ctx->RasterMask==0 && !zoom && x>=0 && y>=0 744 && x+width<=ctx->Buffer->Width && y+height<=ctx->Buffer->Height) { 745 quickDraw = GL_TRUE; 746 } 747 else { 748 quickDraw = GL_FALSE; 749 } 750 751 { 752 /* General solution */ 753 GLboolean r_flag, g_flag, b_flag, a_flag, l_flag; 754 GLuint components; 755 GLubyte rgba[MAX_WIDTH][4]; 756 GLfloat rf[MAX_WIDTH]; 757 GLfloat gf[MAX_WIDTH]; 758 GLfloat bf[MAX_WIDTH]; 759 DEFARRAY(GLfloat,af,MAX_WIDTH); 760 CHECKARRAY(af,return); 761 762 r_flag = g_flag = b_flag = a_flag = l_flag = GL_FALSE; 763 switch (image->Format) { 764 case GL_RED: 765 r_flag = GL_TRUE; 766 components = 1; 767 break; 768 case GL_GREEN: 769 g_flag = GL_TRUE; 770 components = 1; 771 break; 772 case GL_BLUE: 773 b_flag = GL_TRUE; 774 components = 1; 775 break; 776 case GL_ALPHA: 777 a_flag = GL_TRUE; 778 components = 1; 779 break; 780 case GL_RGB: 781 r_flag = g_flag = b_flag = GL_TRUE; 782 components = 3; 783 break; 784 case GL_LUMINANCE: 785 l_flag = GL_TRUE; 786 components = 1; 787 break; 788 case GL_LUMINANCE_ALPHA: 789 l_flag = a_flag = GL_TRUE; 790 components = 2; 791 break; 792 case GL_RGBA: 793 r_flag = g_flag = b_flag = a_flag = GL_TRUE; 794 components = 4; 795 break; 796 default: 797 gl_problem(ctx, "Bad type in draw_rgba_pixels"); 798 goto cleanup; 799 } 800 801 /* process the image row by row */ 802 for (i=0;i<height;i++,y++) { 803 /* convert to floats */ 804 switch (image->Type) { 805 case GL_UNSIGNED_BYTE: 806 { 807 GLubyte *src = (GLubyte *) image->Data + i * width * components; 808 for (j=0;j<width;j++) { 809 if (l_flag) { 810 rf[j] = gf[j] = bf[j] = UBYTE_TO_FLOAT(*src++); 811 } 812 else { 813 rf[j] = r_flag ? UBYTE_TO_FLOAT(*src++) : 0.0; 814 gf[j] = g_flag ? UBYTE_TO_FLOAT(*src++) : 0.0; 815 bf[j] = b_flag ? UBYTE_TO_FLOAT(*src++) : 0.0; 816 } 817 af[j] = a_flag ? UBYTE_TO_FLOAT(*src++) : 1.0; 818 } 819 } 820 break; 821 case GL_FLOAT: 822 { 823 GLfloat *src = (GLfloat *) image->Data + i * width * components; 824 for (j=0;j<width;j++) { 825 if (l_flag) { 826 rf[j] = gf[j] = bf[j] = *src++; 827 } 828 else { 829 rf[j] = r_flag ? *src++ : 0.0; 830 gf[j] = g_flag ? *src++ : 0.0; 831 bf[j] = b_flag ? *src++ : 0.0; 832 } 833 af[j] = a_flag ? *src++ : 1.0; 834 } 835 } 836 break; 837 default: 838 gl_problem( ctx, "draw_rgba_pixels type" ); 839 goto cleanup; 840 } 841 842 /* apply scale and bias */ 843 if (ctx->Pixel.ScaleOrBiasRGBA) { 844 gl_scale_and_bias_color(ctx, width, rf, gf, bf, af); 845 } 846 847 /* apply pixel mappings */ 848 if (ctx->Pixel.MapColorFlag) { 849 gl_map_color(ctx, width, rf, gf, bf, af); 850 } 851 852 /* convert to integers */ 853 for (j=0;j<width;j++) { 854 rgba[j][RCOMP] = (GLint) (rf[j] * 255.0F); 855 rgba[j][GCOMP] = (GLint) (gf[j] * 255.0F); 856 rgba[j][BCOMP] = (GLint) (bf[j] * 255.0F); 857 rgba[j][ACOMP] = (GLint) (af[j] * 255.0F); 858 } 859 860 /* write to frame buffer */ 861 if (quickDraw) { 862 (*ctx->Driver.WriteRGBASpan)( ctx, width, x, y, 863 (const GLubyte (*)[4])rgba, NULL); 864 } 865 else if (zoom) { 866 gl_write_zoomed_rgba_span( ctx, width, x, y, zspan, 867 (const GLubyte (*)[4])rgba, desty ); 868 } 869 else { 870 gl_write_rgba_span( ctx, (GLuint) width, x, y, zspan, rgba, GL_BITMAP); 871 } 872 } 873cleanup: 874 UNDEFARRAY(af); 875 } 876} 877 878 879 880/* 881 * Execute glDrawPixels 882 */ 883void gl_DrawPixels( GLcontext* ctx, struct gl_image *image ) 884{ 885 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDrawPixels"); 886 887 888 if (gl_image_error_test( ctx, image, "glDrawPixels" )) 889 return; 890 891 if (ctx->RenderMode==GL_RENDER) { 892 GLint x, y; 893 if (!ctx->Current.RasterPosValid) { 894 return; 895 } 896 897 x = (GLint) (ctx->Current.RasterPos[0] + 0.5F); 898 y = (GLint) (ctx->Current.RasterPos[1] + 0.5F); 899 900 switch (image->Format) { 901 case GL_COLOR_INDEX: 902 draw_index_pixels( ctx, x, y, image ); 903 break; 904 case GL_STENCIL_INDEX: 905 draw_stencil_pixels( ctx, x, y, image ); 906 break; 907 case GL_DEPTH_COMPONENT: 908 draw_depth_pixels( ctx, x, y, image ); 909 break; 910 case GL_RED: 911 case GL_GREEN: 912 case GL_BLUE: 913 case GL_ALPHA: 914 case GL_RGB: 915 case GL_LUMINANCE: 916 case GL_LUMINANCE_ALPHA: 917 case GL_RGBA: 918 draw_rgba_pixels( ctx, x, y, image ); 919 break; 920 default: 921 gl_error( ctx, GL_INVALID_ENUM, "glDrawPixels" ); 922 return; 923 } 924 } 925 else if (ctx->RenderMode==GL_FEEDBACK) { 926 if (ctx->Current.RasterPosValid) { 927 GLfloat color[4]; 928 GLfloat texcoord[4], invq; 929 UBYTE_RGBA_TO_FLOAT_RGBA(color, ctx->Current.ByteColor); 930 invq = 1.0F / ctx->Current.Texcoord[0][3]; 931 texcoord[0] = ctx->Current.Texcoord[0][0] * invq; 932 texcoord[1] = ctx->Current.Texcoord[0][1] * invq; 933 texcoord[2] = ctx->Current.Texcoord[0][2] * invq; 934 texcoord[3] = ctx->Current.Texcoord[0][3]; 935 FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN ); 936 gl_feedback_vertex( ctx, 937 ctx->Current.RasterPos, 938 color, ctx->Current.Index, texcoord ); 939 } 940 } 941 else if (ctx->RenderMode==GL_SELECT) { 942 if (ctx->Current.RasterPosValid) { 943 gl_update_hitflag( ctx, ctx->Current.RasterPos[2] ); 944 } 945 } 946} 947 948