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