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