drawpix.c revision 4e176ff358956b773ec486a220cc21971ed97495
1/* $Id: drawpix.c,v 1.8 1999/11/22 22:21:38 brianp Exp $ */ 2 3/* 4 * Mesa 3-D graphics library 5 * Version: 3.3 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#ifdef PC_HEADER 29#include "all.h" 30#else 31#include "glheader.h" 32#include "context.h" 33#include "drawpix.h" 34#include "feedback.h" 35#include "image.h" 36#include "macros.h" 37#include "mmath.h" 38#include "pixel.h" 39#include "span.h" 40#include "stencil.h" 41#include "types.h" 42#include "zoom.h" 43#endif 44 45 46 47/* 48 * Given the dest position, size and skipPixels and skipRows values 49 * for a glDrawPixels command, perform clipping of the image bounds 50 * so the result lies withing the context's buffer bounds. 51 * Return: GL_TRUE if image is ready for drawing 52 * GL_FALSE if image was completely clipped away (draw nothing) 53 */ 54GLboolean 55_mesa_clip_pixelrect(const GLcontext *ctx, 56 GLint *destX, GLint *destY, 57 GLsizei *width, GLsizei *height, 58 GLint *skipPixels, GLint *skipRows) 59{ 60 /* left clipping */ 61 if (*destX < ctx->Buffer->Xmin) { 62 *skipPixels += (ctx->Buffer->Xmin - *destX); 63 *width -= (ctx->Buffer->Xmin - *destX); 64 *destX = ctx->Buffer->Xmin; 65 } 66 /* right clipping */ 67 if (*destX + *width > ctx->Buffer->Xmax) 68 *width -= (*destX + *width - ctx->Buffer->Xmax - 1); 69 70 if (*width <= 0) 71 return GL_FALSE; 72 73 /* bottom clipping */ 74 if (*destY < ctx->Buffer->Ymin) { 75 *skipRows += (ctx->Buffer->Ymin - *destY); 76 *height -= (ctx->Buffer->Ymin - *destY); 77 *destY = ctx->Buffer->Ymin; 78 } 79 /* top clipping */ 80 if (*destY + *height > ctx->Buffer->Ymax) 81 *height -= (*destY + *height - ctx->Buffer->Ymax - 1); 82 83 if (*height <= 0) 84 return GL_TRUE; 85 86 return GL_TRUE; 87} 88 89 90 91/* 92 * Try to do a fast and simple RGB(a) glDrawPixels. 93 * Return: GL_TRUE if success, GL_FALSE if slow path must be used instead 94 */ 95static GLboolean 96simple_DrawPixels( GLcontext *ctx, GLint x, GLint y, 97 GLsizei width, GLsizei height, GLenum format, GLenum type, 98 const GLvoid *pixels ) 99{ 100 const struct gl_pixelstore_attrib *unpack = &ctx->Unpack; 101 GLubyte rgb[MAX_WIDTH][3]; 102 GLubyte rgba[MAX_WIDTH][4]; 103 104 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx, "glDrawPixels", 105 GL_FALSE); 106 107 108 if (!ctx->Current.RasterPosValid) { 109 /* no-op */ 110 return GL_TRUE; 111 } 112 113 if (ctx->NewState) { 114 gl_update_state(ctx); 115 } 116 117 /* see if device driver can do the drawpix */ 118 if (ctx->Driver.DrawPixels 119 && (*ctx->Driver.DrawPixels)(ctx, x, y, width, height, format, type, 120 unpack, pixels)) { 121 return GL_TRUE; 122 } 123 124 if ((ctx->RasterMask&(~(SCISSOR_BIT|WINCLIP_BIT)))==0 125 && ctx->Pixel.RedBias==0.0 && ctx->Pixel.RedScale==1.0 126 && ctx->Pixel.GreenBias==0.0 && ctx->Pixel.GreenScale==1.0 127 && ctx->Pixel.BlueBias==0.0 && ctx->Pixel.BlueScale==1.0 128 && ctx->Pixel.AlphaBias==0.0 && ctx->Pixel.AlphaScale==1.0 129 && ctx->Pixel.IndexShift==0 && ctx->Pixel.IndexOffset==0 130 && ctx->Pixel.MapColorFlag==0 131 && unpack->Alignment==1 132 && !unpack->SwapBytes 133 && !unpack->LsbFirst) { 134 135 GLint destX = x; 136 GLint destY = y; 137 GLint drawWidth = width; /* actual width drawn */ 138 GLint drawHeight = height; /* actual height drawn */ 139 GLint skipPixels = unpack->SkipPixels; 140 GLint skipRows = unpack->SkipRows; 141 GLint rowLength; 142 GLdepth zSpan[MAX_WIDTH]; /* only used when zooming */ 143 GLint zoomY0; 144 145 if (unpack->RowLength > 0) 146 rowLength = unpack->RowLength; 147 else 148 rowLength = width; 149 150 /* If we're not using pixel zoom then do all clipping calculations 151 * now. Otherwise, we'll let the gl_write_zoomed_*_span() functions 152 * handle the clipping. 153 */ 154 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { 155 /* horizontal clipping */ 156 if (destX < ctx->Buffer->Xmin) { 157 skipPixels += (ctx->Buffer->Xmin - destX); 158 drawWidth -= (ctx->Buffer->Xmin - destX); 159 destX = ctx->Buffer->Xmin; 160 } 161 if (destX + drawWidth > ctx->Buffer->Xmax) 162 drawWidth -= (destX + drawWidth - ctx->Buffer->Xmax - 1); 163 if (drawWidth <= 0) 164 return GL_TRUE; 165 166 /* vertical clipping */ 167 if (destY < ctx->Buffer->Ymin) { 168 skipRows += (ctx->Buffer->Ymin - destY); 169 drawHeight -= (ctx->Buffer->Ymin - destY); 170 destY = ctx->Buffer->Ymin; 171 } 172 if (destY + drawHeight > ctx->Buffer->Ymax) 173 drawHeight -= (destY + drawHeight - ctx->Buffer->Ymax - 1); 174 if (drawHeight <= 0) 175 return GL_TRUE; 176 177 zoomY0 = 0; /* not used - silence compiler warning */ 178 } 179 else { 180 /* setup array of fragment Z value to pass to zoom function */ 181 GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE); 182 GLint i; 183 assert(drawWidth < MAX_WIDTH); 184 for (i=0; i<drawWidth; i++) 185 zSpan[i] = z; 186 187 /* save Y value of first row */ 188 zoomY0 = (GLint) (ctx->Current.RasterPos[1] + 0.5F); 189 } 190 191 192 /* 193 * Ready to draw! 194 * The window region at (destX, destY) of size (drawWidth, drawHeight) 195 * will be written to. 196 * We'll take pixel data from buffer pointed to by "pixels" but we'll 197 * skip "skipRows" rows and skip "skipPixels" pixels/row. 198 */ 199 200 if (format==GL_RGBA && type==GL_UNSIGNED_BYTE) { 201 if (ctx->Visual->RGBAflag) { 202 GLubyte *src = (GLubyte *) pixels 203 + (skipRows * rowLength + skipPixels) * 4; 204 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { 205 /* no zooming */ 206 GLint row; 207 for (row=0; row<drawHeight; row++) { 208 (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY, 209 (void *) src, NULL); 210 src += rowLength * 4; 211 destY++; 212 } 213 } 214 else { 215 /* with zooming */ 216 GLint row; 217 for (row=0; row<drawHeight; row++) { 218 gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY, 219 zSpan, (void *) src, zoomY0); 220 src += rowLength * 4; 221 destY++; 222 } 223 } 224 } 225 return GL_TRUE; 226 } 227 else if (format==GL_RGB && type==GL_UNSIGNED_BYTE) { 228 if (ctx->Visual->RGBAflag) { 229 GLubyte *src = (GLubyte *) pixels 230 + (skipRows * rowLength + skipPixels) * 3; 231 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { 232 GLint row; 233 for (row=0; row<drawHeight; row++) { 234 (*ctx->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY, 235 (void *) src, NULL); 236 src += rowLength * 3; 237 destY++; 238 } 239 } 240 else { 241 /* with zooming */ 242 GLint row; 243 for (row=0; row<drawHeight; row++) { 244 gl_write_zoomed_rgb_span(ctx, drawWidth, destX, destY, 245 zSpan, (void *) src, zoomY0); 246 src += rowLength * 3; 247 destY++; 248 } 249 } 250 } 251 return GL_TRUE; 252 } 253 else if (format==GL_LUMINANCE && type==GL_UNSIGNED_BYTE) { 254 if (ctx->Visual->RGBAflag) { 255 GLubyte *src = (GLubyte *) pixels 256 + (skipRows * rowLength + skipPixels); 257 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { 258 /* no zooming */ 259 GLint row; 260 assert(drawWidth < MAX_WIDTH); 261 for (row=0; row<drawHeight; row++) { 262 GLint i; 263 for (i=0;i<drawWidth;i++) { 264 rgb[i][0] = src[i]; 265 rgb[i][1] = src[i]; 266 rgb[i][2] = src[i]; 267 } 268 (*ctx->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY, 269 (void *) rgb, NULL); 270 src += rowLength; 271 destY++; 272 } 273 } 274 else { 275 /* with zooming */ 276 GLint row; 277 assert(drawWidth < MAX_WIDTH); 278 for (row=0; row<drawHeight; row++) { 279 GLint i; 280 for (i=0;i<drawWidth;i++) { 281 rgb[i][0] = src[i]; 282 rgb[i][1] = src[i]; 283 rgb[i][2] = src[i]; 284 } 285 gl_write_zoomed_rgb_span(ctx, drawWidth, destX, destY, 286 zSpan, (void *) rgb, zoomY0); 287 src += rowLength; 288 destY++; 289 } 290 } 291 } 292 return GL_TRUE; 293 } 294 else if (format==GL_LUMINANCE_ALPHA && type==GL_UNSIGNED_BYTE) { 295 if (ctx->Visual->RGBAflag) { 296 GLubyte *src = (GLubyte *) pixels 297 + (skipRows * rowLength + skipPixels)*2; 298 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { 299 /* no zooming */ 300 GLint row; 301 assert(drawWidth < MAX_WIDTH); 302 for (row=0; row<drawHeight; row++) { 303 GLint i; 304 GLubyte *ptr = src; 305 for (i=0;i<drawWidth;i++) { 306 rgba[i][0] = *ptr; 307 rgba[i][1] = *ptr; 308 rgba[i][2] = *ptr++; 309 rgba[i][3] = *ptr++; 310 } 311 (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY, 312 (void *) rgba, NULL); 313 src += rowLength*2; 314 destY++; 315 } 316 } 317 else { 318 /* with zooming */ 319 GLint row; 320 assert(drawWidth < MAX_WIDTH); 321 for (row=0; row<drawHeight; row++) { 322 GLubyte *ptr = src; 323 GLint i; 324 for (i=0;i<drawWidth;i++) { 325 rgba[i][0] = *ptr; 326 rgba[i][1] = *ptr; 327 rgba[i][2] = *ptr++; 328 rgba[i][3] = *ptr++; 329 } 330 gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY, 331 zSpan, (void *) rgba, zoomY0); 332 src += rowLength*2; 333 destY++; 334 } 335 } 336 } 337 return GL_TRUE; 338 } 339 else if (format==GL_COLOR_INDEX && type==GL_UNSIGNED_BYTE) { 340 GLubyte *src = (GLubyte *) pixels + skipRows * rowLength + skipPixels; 341 if (ctx->Visual->RGBAflag) { 342 /* convert CI data to RGBA */ 343 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { 344 /* no zooming */ 345 GLint row; 346 for (row=0; row<drawHeight; row++) { 347 assert(drawWidth < MAX_WIDTH); 348 gl_map_ci8_to_rgba(ctx, drawWidth, src, rgba); 349 (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY, 350 (const GLubyte (*)[4])rgba, 351 NULL); 352 src += rowLength; 353 destY++; 354 } 355 return GL_TRUE; 356 } 357 else { 358 /* with zooming */ 359 GLint row; 360 for (row=0; row<drawHeight; row++) { 361 assert(drawWidth < MAX_WIDTH); 362 gl_map_ci8_to_rgba(ctx, drawWidth, src, rgba); 363 gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY, 364 zSpan, (void *) rgba, zoomY0); 365 src += rowLength; 366 destY++; 367 } 368 return GL_TRUE; 369 } 370 } 371 else { 372 /* write CI data to CI frame buffer */ 373 GLint row; 374 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { 375 /* no zooming */ 376 for (row=0; row<drawHeight; row++) { 377 (*ctx->Driver.WriteCI8Span)(ctx, drawWidth, destX, destY, 378 src, NULL); 379 src += rowLength; 380 destY++; 381 } 382 return GL_TRUE; 383 } 384 else { 385 /* with zooming */ 386 return GL_FALSE; 387 } 388 } 389 } 390 else { 391 /* can't handle this pixel format and/or data type here */ 392 return GL_FALSE; 393 } 394 } 395 396 /* can't do a simple draw, have to use slow path */ 397 return GL_FALSE; 398} 399 400 401 402/* 403 * Do glDrawPixels of index pixels. 404 */ 405static void 406draw_index_pixels( GLcontext *ctx, GLint x, GLint y, 407 GLsizei width, GLsizei height, 408 GLenum type, const GLvoid *pixels ) 409{ 410 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0; 411 const GLint desty = y; 412 GLint row, drawWidth; 413 GLdepth zspan[MAX_WIDTH]; 414 415 drawWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width; 416 417 /* Fragment depth values */ 418 if (ctx->Depth.Test) { 419 GLdepth zval = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE); 420 GLint i; 421 for (i = 0; i < drawWidth; i++) { 422 zspan[i] = zval; 423 } 424 } 425 426 /* 427 * General solution 428 */ 429 for (row = 0; row < height; row++, y++) { 430 GLuint indexes[MAX_WIDTH]; 431 const GLvoid *source = gl_pixel_addr_in_image(&ctx->Unpack, 432 pixels, width, height, GL_COLOR_INDEX, type, 0, row, 0); 433 _mesa_unpack_index_span(ctx, drawWidth, GL_UNSIGNED_INT, indexes, 434 type, source, &ctx->Unpack, GL_TRUE); 435 if (zoom) { 436 gl_write_zoomed_index_span(ctx, drawWidth, x, y, zspan, indexes, desty); 437 } 438 else { 439 gl_write_index_span(ctx, drawWidth, x, y, zspan, indexes, GL_BITMAP); 440 } 441 } 442} 443 444 445 446/* 447 * Do glDrawPixels of stencil image. The image datatype may either 448 * be GLubyte or GLbitmap. 449 */ 450static void 451draw_stencil_pixels( GLcontext *ctx, GLint x, GLint y, 452 GLsizei width, GLsizei height, 453 GLenum type, const GLvoid *pixels ) 454{ 455 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0; 456 const GLint desty = y; 457 GLint row, drawWidth; 458 459 if (type != GL_BYTE && 460 type != GL_UNSIGNED_BYTE && 461 type != GL_SHORT && 462 type != GL_UNSIGNED_SHORT && 463 type != GL_INT && 464 type != GL_UNSIGNED_INT && 465 type != GL_FLOAT && 466 type != GL_BITMAP) { 467 gl_error( ctx, GL_INVALID_ENUM, "glDrawPixels(stencil type)"); 468 return; 469 } 470 471 drawWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width; 472 473 for (row = 0; row < height; row++, y++) { 474 GLstencil values[MAX_WIDTH]; 475 GLenum destType = (sizeof(GLstencil) == sizeof(GLubyte)) 476 ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT; 477 const GLvoid *source = gl_pixel_addr_in_image(&ctx->Unpack, 478 pixels, width, height, GL_COLOR_INDEX, type, 0, row, 0); 479 _mesa_unpack_index_span(ctx, drawWidth, destType, values, 480 type, source, &ctx->Unpack, GL_TRUE); 481 482 if (zoom) { 483 gl_write_zoomed_stencil_span( ctx, (GLuint) drawWidth, x, y, 484 values, desty ); 485 } 486 else { 487 gl_write_stencil_span( ctx, (GLuint) drawWidth, x, y, values ); 488 } 489 } 490} 491 492 493 494/* 495 * Do a glDrawPixels of depth values. 496 */ 497static void 498draw_depth_pixels( GLcontext *ctx, GLint x, GLint y, 499 GLsizei width, GLsizei height, 500 GLenum type, const GLvoid *pixels ) 501{ 502 const GLboolean bias_or_scale = ctx->Pixel.DepthBias!=0.0 || ctx->Pixel.DepthScale!=1.0; 503 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0; 504 const GLint desty = y; 505 GLubyte rgba[MAX_WIDTH][4]; 506 GLuint ispan[MAX_WIDTH]; 507 GLint drawWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width; 508 509 if (type != GL_UNSIGNED_BYTE 510 && type != GL_UNSIGNED_BYTE 511 && type != GL_UNSIGNED_SHORT 512 && type != GL_UNSIGNED_SHORT 513 && type != GL_UNSIGNED_INT 514 && type != GL_UNSIGNED_INT 515 && type != GL_FLOAT) { 516 gl_error(ctx, GL_INVALID_ENUM, "glDrawPixels(type)"); 517 return; 518 } 519 520 /* Colors or indexes */ 521 if (ctx->Visual->RGBAflag) { 522 GLint r = (GLint) (ctx->Current.RasterColor[0] * 255.0F); 523 GLint g = (GLint) (ctx->Current.RasterColor[1] * 255.0F); 524 GLint b = (GLint) (ctx->Current.RasterColor[2] * 255.0F); 525 GLint a = (GLint) (ctx->Current.RasterColor[3] * 255.0F); 526 GLint i; 527 for (i = 0; i < drawWidth; i++) { 528 rgba[i][RCOMP] = r; 529 rgba[i][GCOMP] = g; 530 rgba[i][BCOMP] = b; 531 rgba[i][ACOMP] = a; 532 } 533 } 534 else { 535 GLint i; 536 for (i = 0; i < drawWidth; i++) { 537 ispan[i] = ctx->Current.RasterIndex; 538 } 539 } 540 541 if (type==GL_UNSIGNED_SHORT && sizeof(GLdepth)==sizeof(GLushort) 542 && !bias_or_scale && !zoom && ctx->Visual->RGBAflag) { 543 /* Special case: directly write 16-bit depth values */ 544 GLint row; 545 for (row = 0; row < height; row++, y++) { 546 const GLdepth *zptr = gl_pixel_addr_in_image(&ctx->Unpack, 547 pixels, width, height, GL_DEPTH_COMPONENT, type, 0, row, 0); 548 gl_write_rgba_span( ctx, width, x, y, zptr, rgba, GL_BITMAP ); 549 } 550 } 551 else if (type==GL_UNSIGNED_INT && sizeof(GLdepth)==sizeof(GLuint) 552 && !bias_or_scale && !zoom && ctx->Visual->RGBAflag) { 553 /* Special case: directly write 32-bit depth values */ 554 GLint i, row; 555 /* Compute shift value to scale 32-bit uints down to depth values. */ 556 GLuint shift = 0; 557 GLuint max = MAX_DEPTH; 558 while ((max & 0x80000000) == 0) { 559 max = max << 1; 560 shift++; 561 } 562 for (row = 0; row < height; row++, y++) { 563 GLdepth zspan[MAX_WIDTH]; 564 const GLdepth *zptr = gl_pixel_addr_in_image(&ctx->Unpack, 565 pixels, width, height, GL_DEPTH_COMPONENT, type, 0, row, 0); 566 for (i=0;i<width;i++) { 567 zspan[i] = zptr[i] >> shift; 568 } 569 gl_write_rgba_span( ctx, width, x, y, zspan, rgba, GL_BITMAP ); 570 } 571 } 572 else { 573 /* General case */ 574 GLint row; 575 for (row = 0; row < height; row++, y++) { 576 GLdepth zspan[MAX_WIDTH]; 577 const GLvoid *src = gl_pixel_addr_in_image(&ctx->Unpack, 578 pixels, width, height, GL_DEPTH_COMPONENT, type, 0, row, 0); 579 _mesa_unpack_depth_span( ctx, drawWidth, zspan, type, src, 580 &ctx->Unpack, GL_TRUE ); 581 if (ctx->Visual->RGBAflag) { 582 if (zoom) { 583 gl_write_zoomed_rgba_span(ctx, width, x, y, zspan, 584 (const GLubyte (*)[4])rgba, desty); 585 } 586 else { 587 gl_write_rgba_span(ctx, width, x, y, zspan, rgba, GL_BITMAP); 588 } 589 } 590 else { 591 if (zoom) { 592 gl_write_zoomed_index_span(ctx, width, x, y, zspan, 593 ispan, GL_BITMAP); 594 } 595 else { 596 gl_write_index_span(ctx, width, x, y, zspan, ispan, GL_BITMAP); 597 } 598 } 599 600 } 601 } 602} 603 604 605/* 606 * Do glDrawPixels of RGBA pixels. 607 */ 608static void 609draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y, 610 GLsizei width, GLsizei height, 611 GLenum format, GLenum type, const GLvoid *pixels ) 612{ 613 const struct gl_pixelstore_attrib *unpack = &ctx->Unpack; 614 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0; 615 const GLint desty = y; 616 GLdepth zspan[MAX_WIDTH]; 617 GLboolean quickDraw; 618 619 /* Try an optimized glDrawPixels first */ 620 if (simple_DrawPixels(ctx, x, y, width, height, format, type, pixels)) 621 return; 622 623 /* Fragment depth values */ 624 if (ctx->Depth.Test) { 625 /* fill in array of z values */ 626 GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE); 627 GLint i; 628 for (i=0;i<width;i++) { 629 zspan[i] = z; 630 } 631 } 632 633 634 if (ctx->RasterMask == 0 && !zoom 635 && x >= 0 && y >= 0 636 && x + width <= ctx->Buffer->Width 637 && y + height <= ctx->Buffer->Height) { 638 quickDraw = GL_TRUE; 639 } 640 else { 641 quickDraw = GL_FALSE; 642 } 643 644 /* 645 * General solution 646 */ 647 { 648 GLubyte rgba[MAX_WIDTH][4]; 649 GLint row; 650 if (width > MAX_WIDTH) 651 width = MAX_WIDTH; 652 for (row = 0; row < height; row++, y++) { 653 const GLvoid *source = gl_pixel_addr_in_image(unpack, 654 pixels, width, height, format, type, 0, row, 0); 655 _mesa_unpack_ubyte_color_span(ctx, width, GL_RGBA, (void*) rgba, 656 format, type, source, unpack, GL_TRUE); 657 658 if (quickDraw) { 659 (*ctx->Driver.WriteRGBASpan)( ctx, width, x, y, 660 (CONST GLubyte (*)[]) rgba, NULL); 661 } 662 else if (zoom) { 663 gl_write_zoomed_rgba_span( ctx, width, x, y, zspan, 664 (CONST GLubyte (*)[]) rgba, desty ); 665 } 666 else { 667 gl_write_rgba_span( ctx, (GLuint) width, x, y, zspan, rgba, GL_BITMAP); 668 } 669 } 670 } 671} 672 673 674 675/* 676 * Execute glDrawPixels 677 */ 678void 679_mesa_DrawPixels( GLsizei width, GLsizei height, 680 GLenum format, GLenum type, const GLvoid *pixels ) 681{ 682 GET_CURRENT_CONTEXT(ctx); 683 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDrawPixels"); 684 685 if (ctx->RenderMode==GL_RENDER) { 686 GLint x, y; 687 if (!pixels || !ctx->Current.RasterPosValid) { 688 return; 689 } 690 691 x = (GLint) (ctx->Current.RasterPos[0] + 0.5F); 692 y = (GLint) (ctx->Current.RasterPos[1] + 0.5F); 693 694 switch (format) { 695 case GL_STENCIL_INDEX: 696 draw_stencil_pixels( ctx, x, y, width, height, type, pixels ); 697 break; 698 case GL_DEPTH_COMPONENT: 699 draw_depth_pixels( ctx, x, y, width, height, type, pixels ); 700 break; 701 case GL_COLOR_INDEX: 702 if (ctx->Visual->RGBAflag) 703 draw_index_pixels(ctx, x, y, width, height, type, pixels); 704 else 705 draw_rgba_pixels(ctx, x,y, width, height, format, type, pixels); 706 break; 707 case GL_RED: 708 case GL_GREEN: 709 case GL_BLUE: 710 case GL_ALPHA: 711 case GL_LUMINANCE: 712 case GL_LUMINANCE_ALPHA: 713 case GL_RGB: 714 case GL_BGR: 715 case GL_RGBA: 716 case GL_BGRA: 717 case GL_ABGR_EXT: 718 draw_rgba_pixels(ctx, x, y, width, height, format, type, pixels); 719 break; 720 default: 721 gl_error( ctx, GL_INVALID_ENUM, "glDrawPixels(format)" ); 722 return; 723 } 724 } 725 else if (ctx->RenderMode==GL_FEEDBACK) { 726 if (ctx->Current.RasterPosValid) { 727 GLfloat color[4]; 728 GLfloat texcoord[4], invq; 729 UBYTE_RGBA_TO_FLOAT_RGBA(color, ctx->Current.ByteColor); 730 invq = 1.0F / ctx->Current.Texcoord[0][3]; 731 texcoord[0] = ctx->Current.Texcoord[0][0] * invq; 732 texcoord[1] = ctx->Current.Texcoord[0][1] * invq; 733 texcoord[2] = ctx->Current.Texcoord[0][2] * invq; 734 texcoord[3] = ctx->Current.Texcoord[0][3]; 735 FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN ); 736 gl_feedback_vertex( ctx, 737 ctx->Current.RasterPos, 738 color, ctx->Current.Index, texcoord ); 739 } 740 } 741 else if (ctx->RenderMode==GL_SELECT) { 742 if (ctx->Current.RasterPosValid) { 743 gl_update_hitflag( ctx, ctx->Current.RasterPos[2] ); 744 } 745 } 746} 747 748