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