drawpix.c revision c29714dccb664562958cf36cdedee9c4377585d2
1/* $Id: drawpix.c,v 1.25 2000/06/30 22:09:47 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.PostConvolutionColorTableEnabled 126 && !ctx->Pixel.MinMaxEnabled 127 && !ctx->Pixel.HistogramEnabled 128 && ctx->Pixel.IndexShift==0 && ctx->Pixel.IndexOffset==0 129 && ctx->Pixel.MapColorFlag==0 130 && ctx->Texture.ReallyEnabled == 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->DrawBuffer->Xmin) { 157 skipPixels += (ctx->DrawBuffer->Xmin - destX); 158 drawWidth -= (ctx->DrawBuffer->Xmin - destX); 159 destX = ctx->DrawBuffer->Xmin; 160 } 161 if (destX + drawWidth > ctx->DrawBuffer->Xmax) 162 drawWidth -= (destX + drawWidth - ctx->DrawBuffer->Xmax - 1); 163 if (drawWidth <= 0) 164 return GL_TRUE; 165 166 /* vertical clipping */ 167 if (destY < ctx->DrawBuffer->Ymin) { 168 skipRows += (ctx->DrawBuffer->Ymin - destY); 169 drawHeight -= (ctx->DrawBuffer->Ymin - destY); 170 destY = ctx->DrawBuffer->Ymin; 171 } 172 if (destY + drawHeight > ctx->DrawBuffer->Ymax) 173 drawHeight -= (destY + drawHeight - ctx->DrawBuffer->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] * ctx->Visual->DepthMaxF); 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 _mesa_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 _mesa_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 || ctx->Fog.Enabled) { 419 GLdepth zval = (GLdepth) (ctx->Current.RasterPos[2] * ctx->Visual->DepthMaxF); 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 = _mesa_image_address(&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 GLboolean shift_or_offset = ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset; 457 const GLint desty = y; 458 GLint row, drawWidth; 459 460 if (type != GL_BYTE && 461 type != GL_UNSIGNED_BYTE && 462 type != GL_SHORT && 463 type != GL_UNSIGNED_SHORT && 464 type != GL_INT && 465 type != GL_UNSIGNED_INT && 466 type != GL_FLOAT && 467 type != GL_BITMAP) { 468 gl_error( ctx, GL_INVALID_ENUM, "glDrawPixels(stencil type)"); 469 return; 470 } 471 472 drawWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width; 473 474 for (row = 0; row < height; row++, y++) { 475 GLstencil values[MAX_WIDTH]; 476 GLenum destType = (sizeof(GLstencil) == sizeof(GLubyte)) 477 ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT; 478 const GLvoid *source = _mesa_image_address(&ctx->Unpack, 479 pixels, width, height, GL_COLOR_INDEX, type, 0, row, 0); 480 _mesa_unpack_index_span(ctx, drawWidth, destType, values, 481 type, source, &ctx->Unpack, GL_FALSE); 482 if (shift_or_offset) { 483 _mesa_shift_and_offset_stencil( ctx, drawWidth, values ); 484 } 485 if (ctx->Pixel.MapStencilFlag) { 486 _mesa_map_stencil( ctx, drawWidth, values ); 487 } 488 489 if (zoom) { 490 gl_write_zoomed_stencil_span( ctx, (GLuint) drawWidth, x, y, 491 values, desty ); 492 } 493 else { 494 _mesa_write_stencil_span( ctx, (GLuint) drawWidth, x, y, values ); 495 } 496 } 497} 498 499 500 501/* 502 * Do a glDrawPixels of depth values. 503 */ 504static void 505draw_depth_pixels( GLcontext *ctx, GLint x, GLint y, 506 GLsizei width, GLsizei height, 507 GLenum type, const GLvoid *pixels ) 508{ 509 const GLboolean bias_or_scale = ctx->Pixel.DepthBias!=0.0 || ctx->Pixel.DepthScale!=1.0; 510 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0; 511 const GLint desty = y; 512 GLubyte rgba[MAX_WIDTH][4]; 513 GLuint ispan[MAX_WIDTH]; 514 GLint drawWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width; 515 516 if (type != GL_BYTE 517 && type != GL_UNSIGNED_BYTE 518 && type != GL_SHORT 519 && type != GL_UNSIGNED_SHORT 520 && type != GL_INT 521 && type != GL_UNSIGNED_INT 522 && type != GL_FLOAT) { 523 gl_error(ctx, GL_INVALID_ENUM, "glDrawPixels(type)"); 524 return; 525 } 526 527 /* Colors or indexes */ 528 if (ctx->Visual->RGBAflag) { 529 GLint r = (GLint) (ctx->Current.RasterColor[0] * 255.0F); 530 GLint g = (GLint) (ctx->Current.RasterColor[1] * 255.0F); 531 GLint b = (GLint) (ctx->Current.RasterColor[2] * 255.0F); 532 GLint a = (GLint) (ctx->Current.RasterColor[3] * 255.0F); 533 GLint i; 534 for (i = 0; i < drawWidth; i++) { 535 rgba[i][RCOMP] = r; 536 rgba[i][GCOMP] = g; 537 rgba[i][BCOMP] = b; 538 rgba[i][ACOMP] = a; 539 } 540 } 541 else { 542 GLint i; 543 for (i = 0; i < drawWidth; i++) { 544 ispan[i] = ctx->Current.RasterIndex; 545 } 546 } 547 548 if (type==GL_UNSIGNED_SHORT && sizeof(GLdepth)==sizeof(GLushort) 549 && !bias_or_scale && !zoom && ctx->Visual->RGBAflag) { 550 /* Special case: directly write 16-bit depth values */ 551 GLint row; 552 for (row = 0; row < height; row++, y++) { 553 GLdepth zspan[MAX_WIDTH]; 554 const GLushort *zptr = _mesa_image_address(&ctx->Unpack, 555 pixels, width, height, GL_DEPTH_COMPONENT, type, 0, row, 0); 556 GLint i; 557 for (i = 0; i < width; i++) 558 zspan[i] = zptr[i]; 559 gl_write_rgba_span( ctx, width, x, y, zspan, rgba, GL_BITMAP ); 560 } 561 } 562 else if (type==GL_UNSIGNED_INT && ctx->Visual->DepthBits == 32 563 && !bias_or_scale && !zoom && ctx->Visual->RGBAflag) { 564 /* Special case: directly write 32-bit depth values */ 565 GLint row; 566 for (row = 0; row < height; row++, y++) { 567 const GLuint *zptr = _mesa_image_address(&ctx->Unpack, 568 pixels, width, height, GL_DEPTH_COMPONENT, type, 0, row, 0); 569 gl_write_rgba_span( ctx, width, x, y, zptr, 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 = _mesa_image_address(&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 || ctx->Fog.Enabled) { 625 /* fill in array of z values */ 626 GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * ctx->Visual->DepthMaxF); 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->DrawBuffer->Width 637 && y + height <= ctx->DrawBuffer->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 = _mesa_image_address(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 if (ctx->Pixel.MinMaxEnabled && ctx->MinMax.Sink) 658 continue; 659 660 if (ctx->Texture.ReallyEnabled && ctx->Pixel.PixelTextureEnabled) { 661 GLfloat s[MAX_WIDTH], t[MAX_WIDTH], r[MAX_WIDTH], q[MAX_WIDTH]; 662 GLubyte primary_rgba[MAX_WIDTH][4]; 663 GLuint unit; 664 /* XXX not sure how multitexture is supposed to work here */ 665 666 MEMCPY(primary_rgba, rgba, 4 * width * sizeof(GLubyte)); 667 668 for (unit = 0; unit < MAX_TEXTURE_UNITS; unit++) { 669 _mesa_pixeltexgen(ctx, width, (const GLubyte (*)[4]) rgba, 670 s, t, r, q); 671 gl_texture_pixels(ctx, unit, width, s, t, r, NULL, 672 primary_rgba, rgba); 673 } 674 } 675 676 if (quickDraw) { 677 (*ctx->Driver.WriteRGBASpan)( ctx, width, x, y, 678 (CONST GLubyte (*)[]) rgba, NULL); 679 } 680 else if (zoom) { 681 gl_write_zoomed_rgba_span( ctx, width, x, y, zspan, 682 (CONST GLubyte (*)[]) rgba, desty ); 683 } 684 else { 685 gl_write_rgba_span( ctx, (GLuint) width, x, y, zspan, rgba, GL_BITMAP); 686 } 687 } 688 } 689} 690 691 692 693/* 694 * Execute glDrawPixels 695 */ 696void 697_mesa_DrawPixels( GLsizei width, GLsizei height, 698 GLenum format, GLenum type, const GLvoid *pixels ) 699{ 700 GET_CURRENT_CONTEXT(ctx); 701 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDrawPixels"); 702 703 if (ctx->RenderMode==GL_RENDER) { 704 GLint x, y; 705 if (!pixels || !ctx->Current.RasterPosValid) { 706 return; 707 } 708 709 if (ctx->NewState) { 710 gl_update_state(ctx); 711 } 712 713 x = (GLint) (ctx->Current.RasterPos[0] + 0.5F); 714 y = (GLint) (ctx->Current.RasterPos[1] + 0.5F); 715 716 ctx->OcclusionResult = GL_TRUE; 717 718 /* see if device driver can do the drawpix */ 719 if (ctx->Driver.DrawPixels 720 && (*ctx->Driver.DrawPixels)(ctx, x, y, width, height, format, type, 721 &ctx->Unpack, pixels)) { 722 return; 723 } 724 725 switch (format) { 726 case GL_STENCIL_INDEX: 727 draw_stencil_pixels( ctx, x, y, width, height, type, pixels ); 728 break; 729 case GL_DEPTH_COMPONENT: 730 draw_depth_pixels( ctx, x, y, width, height, type, pixels ); 731 break; 732 case GL_COLOR_INDEX: 733 if (ctx->Visual->RGBAflag) 734 draw_rgba_pixels(ctx, x,y, width, height, format, type, pixels); 735 else 736 draw_index_pixels(ctx, x, y, width, height, type, pixels); 737 break; 738 case GL_RED: 739 case GL_GREEN: 740 case GL_BLUE: 741 case GL_ALPHA: 742 case GL_LUMINANCE: 743 case GL_LUMINANCE_ALPHA: 744 case GL_RGB: 745 case GL_BGR: 746 case GL_RGBA: 747 case GL_BGRA: 748 case GL_ABGR_EXT: 749 draw_rgba_pixels(ctx, x, y, width, height, format, type, pixels); 750 break; 751 default: 752 gl_error( ctx, GL_INVALID_ENUM, "glDrawPixels(format)" ); 753 return; 754 } 755 } 756 else if (ctx->RenderMode==GL_FEEDBACK) { 757 if (ctx->Current.RasterPosValid) { 758 GLfloat color[4]; 759 GLfloat texcoord[4], invq; 760 UBYTE_RGBA_TO_FLOAT_RGBA(color, ctx->Current.ByteColor); 761 invq = 1.0F / ctx->Current.Texcoord[0][3]; 762 texcoord[0] = ctx->Current.Texcoord[0][0] * invq; 763 texcoord[1] = ctx->Current.Texcoord[0][1] * invq; 764 texcoord[2] = ctx->Current.Texcoord[0][2] * invq; 765 texcoord[3] = ctx->Current.Texcoord[0][3]; 766 FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN ); 767 gl_feedback_vertex( ctx, 768 ctx->Current.RasterPos, 769 color, ctx->Current.Index, texcoord ); 770 } 771 } 772 else if (ctx->RenderMode==GL_SELECT) { 773 if (ctx->Current.RasterPosValid) { 774 gl_update_hitflag( ctx, ctx->Current.RasterPos[2] ); 775 } 776 } 777} 778 779