drawpix.c revision fa849a0e1622039bf66ef2b7506669aba8d77d91
1/* $Id: drawpix.c,v 1.37 2000/10/05 16:22:23 brianp Exp $ */ 2 3/* 4 * Mesa 3-D graphics library 5 * Version: 3.5 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 "convolve.h" 34#include "drawpix.h" 35#include "feedback.h" 36#include "image.h" 37#include "macros.h" 38#include "mem.h" 39#include "mmath.h" 40#include "pixel.h" 41#include "pixeltex.h" 42#include "span.h" 43#include "state.h" 44#include "stencil.h" 45#include "texture.h" 46#include "types.h" 47#include "zoom.h" 48#endif 49 50 51 52/* 53 * Given the dest position, size and skipPixels and skipRows values 54 * for a glDrawPixels command, perform clipping of the image bounds 55 * so the result lies withing the context's buffer bounds. 56 * Return: GL_TRUE if image is ready for drawing 57 * GL_FALSE if image was completely clipped away (draw nothing) 58 */ 59GLboolean 60_mesa_clip_pixelrect(const GLcontext *ctx, 61 GLint *destX, GLint *destY, 62 GLsizei *width, GLsizei *height, 63 GLint *skipPixels, GLint *skipRows) 64{ 65 const GLframebuffer *buffer = ctx->DrawBuffer; 66 67 /* left clipping */ 68 if (*destX < buffer->Xmin) { 69 *skipPixels += (buffer->Xmin - *destX); 70 *width -= (buffer->Xmin - *destX); 71 *destX = buffer->Xmin; 72 } 73 /* right clipping */ 74 if (*destX + *width > buffer->Xmax) 75 *width -= (*destX + *width - buffer->Xmax); 76 77 if (*width <= 0) 78 return GL_FALSE; 79 80 /* bottom clipping */ 81 if (*destY < buffer->Ymin) { 82 *skipRows += (buffer->Ymin - *destY); 83 *height -= (buffer->Ymin - *destY); 84 *destY = buffer->Ymin; 85 } 86 /* top clipping */ 87 if (*destY + *height > buffer->Ymax) 88 *height -= (*destY + *height - buffer->Ymax); 89 90 if (*height <= 0) 91 return GL_TRUE; 92 93 return GL_TRUE; 94} 95 96 97 98/* 99 * Try to do a fast and simple RGB(a) glDrawPixels. 100 * Return: GL_TRUE if success, GL_FALSE if slow path must be used instead 101 */ 102static GLboolean 103fast_draw_pixels(GLcontext *ctx, GLint x, GLint y, 104 GLsizei width, GLsizei height, 105 GLenum format, GLenum type, const GLvoid *pixels) 106{ 107 const struct gl_pixelstore_attrib *unpack = &ctx->Unpack; 108 GLubyte rgb[MAX_WIDTH][3]; 109 GLubyte rgba[MAX_WIDTH][4]; 110 111 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx, "glDrawPixels", 112 GL_FALSE); 113 114 115 if (!ctx->Current.RasterPosValid) { 116 return GL_TRUE; /* no-op */ 117 } 118 119 if ((ctx->RasterMask&(~(SCISSOR_BIT|WINCLIP_BIT)))==0 120 && ctx->Texture.ReallyEnabled == 0 121 && unpack->Alignment == 1 122 && !unpack->SwapBytes 123 && !unpack->LsbFirst) { 124 125 GLint destX = x; 126 GLint destY = y; 127 GLint drawWidth = width; /* actual width drawn */ 128 GLint drawHeight = height; /* actual height drawn */ 129 GLint skipPixels = unpack->SkipPixels; 130 GLint skipRows = unpack->SkipRows; 131 GLint rowLength; 132 GLdepth zSpan[MAX_WIDTH]; /* only used when zooming */ 133 GLint zoomY0 = 0; 134 135 if (unpack->RowLength > 0) 136 rowLength = unpack->RowLength; 137 else 138 rowLength = width; 139 140 /* If we're not using pixel zoom then do all clipping calculations 141 * now. Otherwise, we'll let the gl_write_zoomed_*_span() functions 142 * handle the clipping. 143 */ 144 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { 145 /* horizontal clipping */ 146 if (destX < ctx->DrawBuffer->Xmin) { 147 skipPixels += (ctx->DrawBuffer->Xmin - destX); 148 drawWidth -= (ctx->DrawBuffer->Xmin - destX); 149 destX = ctx->DrawBuffer->Xmin; 150 } 151 if (destX + drawWidth > ctx->DrawBuffer->Xmax) 152 drawWidth -= (destX + drawWidth - ctx->DrawBuffer->Xmax); 153 if (drawWidth <= 0) 154 return GL_TRUE; 155 156 /* vertical clipping */ 157 if (destY < ctx->DrawBuffer->Ymin) { 158 skipRows += (ctx->DrawBuffer->Ymin - destY); 159 drawHeight -= (ctx->DrawBuffer->Ymin - destY); 160 destY = ctx->DrawBuffer->Ymin; 161 } 162 if (destY + drawHeight > ctx->DrawBuffer->Ymax) 163 drawHeight -= (destY + drawHeight - ctx->DrawBuffer->Ymax); 164 if (drawHeight <= 0) 165 return GL_TRUE; 166 } 167 else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) { 168 /* upside-down image */ 169 /* horizontal clipping */ 170 if (destX < ctx->DrawBuffer->Xmin) { 171 skipPixels += (ctx->DrawBuffer->Xmin - destX); 172 drawWidth -= (ctx->DrawBuffer->Xmin - destX); 173 destX = ctx->DrawBuffer->Xmin; 174 } 175 if (destX + drawWidth > ctx->DrawBuffer->Xmax) 176 drawWidth -= (destX + drawWidth - ctx->DrawBuffer->Xmax); 177 if (drawWidth <= 0) 178 return GL_TRUE; 179 180 /* vertical clipping */ 181 if (destY > ctx->DrawBuffer->Ymax) { 182 skipRows += (destY - ctx->DrawBuffer->Ymax); 183 drawHeight -= (destY - ctx->DrawBuffer->Ymax); 184 destY = ctx->DrawBuffer->Ymax; 185 } 186 if (destY - drawHeight < ctx->DrawBuffer->Ymin) 187 drawHeight -= (ctx->DrawBuffer->Ymin - (destY - drawHeight)); 188 if (drawHeight <= 0) 189 return GL_TRUE; 190 } 191 else { 192 /* setup array of fragment Z value to pass to zoom function */ 193 GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * ctx->Visual.DepthMaxF); 194 GLint i; 195 ASSERT(drawWidth < MAX_WIDTH); 196 for (i=0; i<drawWidth; i++) 197 zSpan[i] = z; 198 199 /* save Y value of first row */ 200 zoomY0 = (GLint) (ctx->Current.RasterPos[1] + 0.5F); 201 } 202 203 204 /* 205 * Ready to draw! 206 * The window region at (destX, destY) of size (drawWidth, drawHeight) 207 * will be written to. 208 * We'll take pixel data from buffer pointed to by "pixels" but we'll 209 * skip "skipRows" rows and skip "skipPixels" pixels/row. 210 */ 211 212 if (format==GL_RGBA && type==GL_UNSIGNED_BYTE 213 && ctx->ImageTransferState==0) { 214 if (ctx->Visual.RGBAflag) { 215 GLubyte *src = (GLubyte *) pixels 216 + (skipRows * rowLength + skipPixels) * 4; 217 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { 218 /* no zooming */ 219 GLint row; 220 for (row=0; row<drawHeight; row++) { 221 (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY, 222 (void *) src, NULL); 223 src += rowLength * 4; 224 destY++; 225 } 226 } 227 else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) { 228 /* upside-down */ 229 GLint row; 230 for (row=0; row<drawHeight; row++) { 231 destY--; 232 (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY, 233 (void *) src, NULL); 234 src += rowLength * 4; 235 } 236 } 237 else { 238 /* with zooming */ 239 GLint row; 240 for (row=0; row<drawHeight; row++) { 241 gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY, 242 zSpan, (void *) src, zoomY0); 243 src += rowLength * 4; 244 destY++; 245 } 246 } 247 } 248 return GL_TRUE; 249 } 250 else if (format==GL_RGB && type==GL_UNSIGNED_BYTE 251 && ctx->ImageTransferState==0) { 252 if (ctx->Visual.RGBAflag) { 253 GLubyte *src = (GLubyte *) pixels 254 + (skipRows * rowLength + skipPixels) * 3; 255 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { 256 GLint row; 257 for (row=0; row<drawHeight; row++) { 258 (*ctx->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY, 259 (void *) src, NULL); 260 src += rowLength * 3; 261 destY++; 262 } 263 } 264 else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) { 265 /* upside-down */ 266 GLint row; 267 for (row=0; row<drawHeight; row++) { 268 destY--; 269 (*ctx->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY, 270 (void *) src, NULL); 271 src += rowLength * 3; 272 } 273 } 274 else { 275 /* with zooming */ 276 GLint row; 277 for (row=0; row<drawHeight; row++) { 278 gl_write_zoomed_rgb_span(ctx, drawWidth, destX, destY, 279 zSpan, (void *) src, zoomY0); 280 src += rowLength * 3; 281 destY++; 282 } 283 } 284 } 285 return GL_TRUE; 286 } 287 else if (format==GL_LUMINANCE && type==GL_UNSIGNED_BYTE 288 && ctx->ImageTransferState==0) { 289 if (ctx->Visual.RGBAflag) { 290 GLubyte *src = (GLubyte *) pixels 291 + (skipRows * rowLength + skipPixels); 292 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { 293 /* no zooming */ 294 GLint row; 295 ASSERT(drawWidth < MAX_WIDTH); 296 for (row=0; row<drawHeight; row++) { 297 GLint i; 298 for (i=0;i<drawWidth;i++) { 299 rgb[i][0] = src[i]; 300 rgb[i][1] = src[i]; 301 rgb[i][2] = src[i]; 302 } 303 (*ctx->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY, 304 (void *) rgb, NULL); 305 src += rowLength; 306 destY++; 307 } 308 } 309 else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) { 310 /* upside-down */ 311 GLint row; 312 ASSERT(drawWidth < MAX_WIDTH); 313 for (row=0; row<drawHeight; row++) { 314 GLint i; 315 for (i=0;i<drawWidth;i++) { 316 rgb[i][0] = src[i]; 317 rgb[i][1] = src[i]; 318 rgb[i][2] = src[i]; 319 } 320 destY--; 321 (*ctx->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY, 322 (void *) rgb, NULL); 323 src += rowLength; 324 } 325 } 326 else { 327 /* with zooming */ 328 GLint row; 329 ASSERT(drawWidth < MAX_WIDTH); 330 for (row=0; row<drawHeight; row++) { 331 GLint i; 332 for (i=0;i<drawWidth;i++) { 333 rgb[i][0] = src[i]; 334 rgb[i][1] = src[i]; 335 rgb[i][2] = src[i]; 336 } 337 gl_write_zoomed_rgb_span(ctx, drawWidth, destX, destY, 338 zSpan, (void *) rgb, zoomY0); 339 src += rowLength; 340 destY++; 341 } 342 } 343 } 344 return GL_TRUE; 345 } 346 else if (format==GL_LUMINANCE_ALPHA && type==GL_UNSIGNED_BYTE 347 && ctx->ImageTransferState==0) { 348 if (ctx->Visual.RGBAflag) { 349 GLubyte *src = (GLubyte *) pixels 350 + (skipRows * rowLength + skipPixels)*2; 351 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { 352 /* no zooming */ 353 GLint row; 354 ASSERT(drawWidth < MAX_WIDTH); 355 for (row=0; row<drawHeight; row++) { 356 GLint i; 357 GLubyte *ptr = src; 358 for (i=0;i<drawWidth;i++) { 359 rgba[i][0] = *ptr; 360 rgba[i][1] = *ptr; 361 rgba[i][2] = *ptr++; 362 rgba[i][3] = *ptr++; 363 } 364 (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY, 365 (void *) rgba, NULL); 366 src += rowLength*2; 367 destY++; 368 } 369 } 370 else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) { 371 /* upside-down */ 372 GLint row; 373 ASSERT(drawWidth < MAX_WIDTH); 374 for (row=0; row<drawHeight; row++) { 375 GLint i; 376 GLubyte *ptr = src; 377 for (i=0;i<drawWidth;i++) { 378 rgba[i][0] = *ptr; 379 rgba[i][1] = *ptr; 380 rgba[i][2] = *ptr++; 381 rgba[i][3] = *ptr++; 382 } 383 destY--; 384 (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY, 385 (void *) rgba, NULL); 386 src += rowLength*2; 387 } 388 } 389 else { 390 /* with zooming */ 391 GLint row; 392 ASSERT(drawWidth < MAX_WIDTH); 393 for (row=0; row<drawHeight; row++) { 394 GLubyte *ptr = src; 395 GLint i; 396 for (i=0;i<drawWidth;i++) { 397 rgba[i][0] = *ptr; 398 rgba[i][1] = *ptr; 399 rgba[i][2] = *ptr++; 400 rgba[i][3] = *ptr++; 401 } 402 gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY, 403 zSpan, (void *) rgba, zoomY0); 404 src += rowLength*2; 405 destY++; 406 } 407 } 408 } 409 return GL_TRUE; 410 } 411 else if (format==GL_COLOR_INDEX && type==GL_UNSIGNED_BYTE) { 412 GLubyte *src = (GLubyte *) pixels + skipRows * rowLength + skipPixels; 413 if (ctx->Visual.RGBAflag 414 && ctx->ImageTransferState==IMAGE_MAP_COLOR_BIT) { 415 /* convert CI data to RGBA */ 416 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { 417 /* no zooming */ 418 GLint row; 419 for (row=0; row<drawHeight; row++) { 420 ASSERT(drawWidth < MAX_WIDTH); 421 _mesa_map_ci8_to_rgba(ctx, drawWidth, src, rgba); 422 (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY, 423 (const GLubyte (*)[4])rgba, 424 NULL); 425 src += rowLength; 426 destY++; 427 } 428 return GL_TRUE; 429 } 430 else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) { 431 /* upside-down */ 432 GLint row; 433 for (row=0; row<drawHeight; row++) { 434 ASSERT(drawWidth < MAX_WIDTH); 435 _mesa_map_ci8_to_rgba(ctx, drawWidth, src, rgba); 436 destY--; 437 (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY, 438 (const GLubyte (*)[4])rgba, 439 NULL); 440 src += rowLength; 441 } 442 return GL_TRUE; 443 } 444 else { 445 /* with zooming */ 446 GLint row; 447 for (row=0; row<drawHeight; row++) { 448 ASSERT(drawWidth < MAX_WIDTH); 449 _mesa_map_ci8_to_rgba(ctx, drawWidth, src, rgba); 450 gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY, 451 zSpan, (void *) rgba, zoomY0); 452 src += rowLength; 453 destY++; 454 } 455 return GL_TRUE; 456 } 457 } 458 else if (ctx->ImageTransferState==0) { 459 /* write CI data to CI frame buffer */ 460 GLint row; 461 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { 462 /* no zooming */ 463 for (row=0; row<drawHeight; row++) { 464 (*ctx->Driver.WriteCI8Span)(ctx, drawWidth, destX, destY, 465 src, NULL); 466 src += rowLength; 467 destY++; 468 } 469 return GL_TRUE; 470 } 471 else { 472 /* with zooming */ 473 return GL_FALSE; 474 } 475 } 476 } 477 else { 478 /* can't handle this pixel format and/or data type here */ 479 return GL_FALSE; 480 } 481 } 482 483 /* can't do a simple draw, have to use slow path */ 484 return GL_FALSE; 485} 486 487 488 489/* 490 * Do glDrawPixels of index pixels. 491 */ 492static void 493draw_index_pixels( GLcontext *ctx, GLint x, GLint y, 494 GLsizei width, GLsizei height, 495 GLenum type, const GLvoid *pixels ) 496{ 497 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0; 498 const GLint desty = y; 499 GLint row, drawWidth; 500 GLdepth zspan[MAX_WIDTH]; 501 502 drawWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width; 503 504 /* Fragment depth values */ 505 if (ctx->Depth.Test || ctx->Fog.Enabled) { 506 GLdepth zval = (GLdepth) (ctx->Current.RasterPos[2] * ctx->Visual.DepthMaxF); 507 GLint i; 508 for (i = 0; i < drawWidth; i++) { 509 zspan[i] = zval; 510 } 511 } 512 513 /* 514 * General solution 515 */ 516 for (row = 0; row < height; row++, y++) { 517 GLuint indexes[MAX_WIDTH]; 518 const GLvoid *source = _mesa_image_address(&ctx->Unpack, 519 pixels, width, height, GL_COLOR_INDEX, type, 0, row, 0); 520 _mesa_unpack_index_span(ctx, drawWidth, GL_UNSIGNED_INT, indexes, 521 type, source, &ctx->Unpack, 522 ctx->ImageTransferState); 523 if (zoom) { 524 gl_write_zoomed_index_span(ctx, drawWidth, x, y, zspan, indexes, desty); 525 } 526 else { 527 gl_write_index_span(ctx, drawWidth, x, y, zspan, indexes, GL_BITMAP); 528 } 529 } 530} 531 532 533 534/* 535 * Do glDrawPixels of stencil image. The image datatype may either 536 * be GLubyte or GLbitmap. 537 */ 538static void 539draw_stencil_pixels( GLcontext *ctx, GLint x, GLint y, 540 GLsizei width, GLsizei height, 541 GLenum type, const GLvoid *pixels ) 542{ 543 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0; 544 const GLint desty = y; 545 GLint row, drawWidth; 546 547 if (type != GL_BYTE && 548 type != GL_UNSIGNED_BYTE && 549 type != GL_SHORT && 550 type != GL_UNSIGNED_SHORT && 551 type != GL_INT && 552 type != GL_UNSIGNED_INT && 553 type != GL_FLOAT && 554 type != GL_BITMAP) { 555 gl_error( ctx, GL_INVALID_ENUM, "glDrawPixels(stencil type)"); 556 return; 557 } 558 559 drawWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width; 560 561 for (row = 0; row < height; row++, y++) { 562 GLstencil values[MAX_WIDTH]; 563 GLenum destType = (sizeof(GLstencil) == sizeof(GLubyte)) 564 ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT; 565 const GLvoid *source = _mesa_image_address(&ctx->Unpack, 566 pixels, width, height, GL_COLOR_INDEX, type, 0, row, 0); 567 _mesa_unpack_index_span(ctx, drawWidth, destType, values, 568 type, source, &ctx->Unpack, 569 ctx->ImageTransferState); 570 if (ctx->ImageTransferState & IMAGE_SHIFT_OFFSET_BIT) { 571 _mesa_shift_and_offset_stencil( ctx, drawWidth, values ); 572 } 573 if (ctx->Pixel.MapStencilFlag) { 574 _mesa_map_stencil( ctx, drawWidth, values ); 575 } 576 577 if (zoom) { 578 gl_write_zoomed_stencil_span( ctx, (GLuint) drawWidth, x, y, 579 values, desty ); 580 } 581 else { 582 _mesa_write_stencil_span( ctx, (GLuint) drawWidth, x, y, values ); 583 } 584 } 585} 586 587 588 589/* 590 * Do a glDrawPixels of depth values. 591 */ 592static void 593draw_depth_pixels( GLcontext *ctx, GLint x, GLint y, 594 GLsizei width, GLsizei height, 595 GLenum type, const GLvoid *pixels ) 596{ 597 const GLboolean bias_or_scale = ctx->Pixel.DepthBias!=0.0 || ctx->Pixel.DepthScale!=1.0; 598 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0; 599 const GLint desty = y; 600 GLubyte rgba[MAX_WIDTH][4]; 601 GLuint ispan[MAX_WIDTH]; 602 GLint drawWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width; 603 604 if (type != GL_BYTE 605 && type != GL_UNSIGNED_BYTE 606 && type != GL_SHORT 607 && type != GL_UNSIGNED_SHORT 608 && type != GL_INT 609 && type != GL_UNSIGNED_INT 610 && type != GL_FLOAT) { 611 gl_error(ctx, GL_INVALID_ENUM, "glDrawPixels(type)"); 612 return; 613 } 614 615 /* Colors or indexes */ 616 if (ctx->Visual.RGBAflag) { 617 GLint r = (GLint) (ctx->Current.RasterColor[0] * 255.0F); 618 GLint g = (GLint) (ctx->Current.RasterColor[1] * 255.0F); 619 GLint b = (GLint) (ctx->Current.RasterColor[2] * 255.0F); 620 GLint a = (GLint) (ctx->Current.RasterColor[3] * 255.0F); 621 GLint i; 622 for (i = 0; i < drawWidth; i++) { 623 rgba[i][RCOMP] = r; 624 rgba[i][GCOMP] = g; 625 rgba[i][BCOMP] = b; 626 rgba[i][ACOMP] = a; 627 } 628 } 629 else { 630 GLint i; 631 for (i = 0; i < drawWidth; i++) { 632 ispan[i] = ctx->Current.RasterIndex; 633 } 634 } 635 636 if (type==GL_UNSIGNED_SHORT && sizeof(GLdepth)==sizeof(GLushort) 637 && !bias_or_scale && !zoom && ctx->Visual.RGBAflag) { 638 /* Special case: directly write 16-bit depth values */ 639 GLint row; 640 for (row = 0; row < height; row++, y++) { 641 GLdepth zspan[MAX_WIDTH]; 642 const GLushort *zptr = _mesa_image_address(&ctx->Unpack, 643 pixels, width, height, GL_DEPTH_COMPONENT, type, 0, row, 0); 644 GLint i; 645 for (i = 0; i < width; i++) 646 zspan[i] = zptr[i]; 647 gl_write_rgba_span( ctx, width, x, y, zspan, rgba, GL_BITMAP ); 648 } 649 } 650 else if (type==GL_UNSIGNED_INT && ctx->Visual.DepthBits == 32 651 && !bias_or_scale && !zoom && ctx->Visual.RGBAflag) { 652 /* Special case: directly write 32-bit depth values */ 653 GLint row; 654 for (row = 0; row < height; row++, y++) { 655 const GLuint *zptr = _mesa_image_address(&ctx->Unpack, 656 pixels, width, height, GL_DEPTH_COMPONENT, type, 0, row, 0); 657 gl_write_rgba_span( ctx, width, x, y, zptr, rgba, GL_BITMAP ); 658 } 659 } 660 else { 661 /* General case */ 662 GLint row; 663 for (row = 0; row < height; row++, y++) { 664 GLdepth zspan[MAX_WIDTH]; 665 const GLvoid *src = _mesa_image_address(&ctx->Unpack, 666 pixels, width, height, GL_DEPTH_COMPONENT, type, 0, row, 0); 667 _mesa_unpack_depth_span( ctx, drawWidth, zspan, type, src, 668 &ctx->Unpack, ctx->ImageTransferState ); 669 if (ctx->Visual.RGBAflag) { 670 if (zoom) { 671 gl_write_zoomed_rgba_span(ctx, width, x, y, zspan, 672 (const GLubyte (*)[4])rgba, desty); 673 } 674 else { 675 gl_write_rgba_span(ctx, width, x, y, zspan, rgba, GL_BITMAP); 676 } 677 } 678 else { 679 if (zoom) { 680 gl_write_zoomed_index_span(ctx, width, x, y, zspan, 681 ispan, GL_BITMAP); 682 } 683 else { 684 gl_write_index_span(ctx, width, x, y, zspan, ispan, GL_BITMAP); 685 } 686 } 687 688 } 689 } 690} 691 692 693/* 694 * Do glDrawPixels of RGBA pixels. 695 */ 696static void 697draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y, 698 GLsizei width, GLsizei height, 699 GLenum format, GLenum type, const GLvoid *pixels ) 700{ 701 const struct gl_pixelstore_attrib *unpack = &ctx->Unpack; 702 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0; 703 const GLint desty = y; 704 GLdepth zspan[MAX_WIDTH]; 705 GLboolean quickDraw; 706 GLfloat *convImage = NULL; 707 GLuint transferOps = ctx->ImageTransferState; 708 709 if (!_mesa_is_legal_format_and_type(format, type)) { 710 gl_error(ctx, GL_INVALID_ENUM, "glDrawPixels(format or type)"); 711 return; 712 } 713 714 /* Try an optimized glDrawPixels first */ 715 if (fast_draw_pixels(ctx, x, y, width, height, format, type, pixels)) 716 return; 717 718 /* Fragment depth values */ 719 if (ctx->Depth.Test || ctx->Fog.Enabled) { 720 /* fill in array of z values */ 721 GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * ctx->Visual.DepthMaxF); 722 GLint i; 723 for (i=0;i<width;i++) { 724 zspan[i] = z; 725 } 726 } 727 728 729 if (ctx->RasterMask == 0 && !zoom && x >= 0 && y >= 0 730 && x + width <= ctx->DrawBuffer->Width 731 && y + height <= ctx->DrawBuffer->Height) { 732 quickDraw = GL_TRUE; 733 } 734 else { 735 quickDraw = GL_FALSE; 736 } 737 738 if (ctx->Pixel.Convolution2DEnabled || ctx->Pixel.Separable2DEnabled) { 739 /* Convolution has to be handled specially. We'll create an 740 * intermediate image, applying all pixel transfer operations 741 * up to convolution. Then we'll convolve the image. Then 742 * we'll proceed with the rest of the transfer operations and 743 * rasterize the image. 744 */ 745 GLint row; 746 GLfloat *dest, *tmpImage; 747 748 tmpImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat)); 749 if (!tmpImage) { 750 gl_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels"); 751 return; 752 } 753 convImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat)); 754 if (!convImage) { 755 FREE(tmpImage); 756 gl_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels"); 757 return; 758 } 759 760 /* Unpack the image and apply transfer ops up to convolution */ 761 dest = tmpImage; 762 for (row = 0; row < height; row++) { 763 const GLvoid *source = _mesa_image_address(unpack, 764 pixels, width, height, format, type, 0, row, 0); 765 _mesa_unpack_float_color_span(ctx, width, GL_RGBA, (void *) dest, 766 format, type, source, unpack, 767 transferOps & IMAGE_PRE_CONVOLUTION_BITS, 768 GL_FALSE); 769 dest += width * 4; 770 } 771 772 /* do convolution */ 773 if (ctx->Pixel.Convolution2DEnabled) { 774 _mesa_convolve_2d_image(ctx, &width, &height, tmpImage, convImage); 775 } 776 else { 777 ASSERT(ctx->Pixel.Separable2DEnabled); 778 _mesa_convolve_sep_image(ctx, &width, &height, tmpImage, convImage); 779 } 780 FREE(tmpImage); 781 782 /* continue transfer ops and draw the convolved image */ 783 unpack = &_mesa_native_packing; 784 pixels = convImage; 785 format = GL_RGBA; 786 type = GL_FLOAT; 787 transferOps &= IMAGE_POST_CONVOLUTION_BITS; 788 } 789 790 /* 791 * General solution 792 */ 793 { 794 GLubyte rgba[MAX_WIDTH][4]; 795 GLint row; 796 if (width > MAX_WIDTH) 797 width = MAX_WIDTH; 798 for (row = 0; row < height; row++, y++) { 799 const GLvoid *source = _mesa_image_address(unpack, 800 pixels, width, height, format, type, 0, row, 0); 801 _mesa_unpack_ubyte_color_span(ctx, width, GL_RGBA, (void*) rgba, 802 format, type, source, unpack, 803 transferOps); 804 if ((ctx->Pixel.MinMaxEnabled && ctx->MinMax.Sink) || 805 (ctx->Pixel.HistogramEnabled && ctx->Histogram.Sink)) 806 continue; 807 808 if (ctx->Texture.ReallyEnabled && ctx->Pixel.PixelTextureEnabled) { 809 GLfloat s[MAX_WIDTH], t[MAX_WIDTH], r[MAX_WIDTH], q[MAX_WIDTH]; 810 GLubyte primary_rgba[MAX_WIDTH][4]; 811 GLuint unit; 812 /* XXX not sure how multitexture is supposed to work here */ 813 814 MEMCPY(primary_rgba, rgba, 4 * width * sizeof(GLubyte)); 815 816 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { 817 if (ctx->Texture.Unit[unit].ReallyEnabled) { 818 _mesa_pixeltexgen(ctx, width, (const GLubyte (*)[4]) rgba, 819 s, t, r, q); 820 gl_texture_pixels(ctx, unit, width, s, t, r, NULL, 821 primary_rgba, rgba); 822 } 823 } 824 } 825 826 if (quickDraw) { 827 (*ctx->Driver.WriteRGBASpan)( ctx, width, x, y, 828 (CONST GLubyte (*)[]) rgba, NULL); 829 } 830 else if (zoom) { 831 gl_write_zoomed_rgba_span( ctx, width, x, y, zspan, 832 (CONST GLubyte (*)[]) rgba, desty ); 833 } 834 else { 835 gl_write_rgba_span( ctx, (GLuint) width, x, y, zspan, rgba, GL_BITMAP); 836 } 837 } 838 } 839 840 if (convImage) { 841 FREE(convImage); 842 } 843} 844 845 846 847/* 848 * Execute glDrawPixels 849 */ 850void 851_mesa_DrawPixels( GLsizei width, GLsizei height, 852 GLenum format, GLenum type, const GLvoid *pixels ) 853{ 854 GET_CURRENT_CONTEXT(ctx); 855 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDrawPixels"); 856 857 if (ctx->RenderMode==GL_RENDER) { 858 GLint x, y; 859 if (!pixels || !ctx->Current.RasterPosValid) { 860 return; 861 } 862 863 if (ctx->NewState) { 864 gl_update_state(ctx); 865 } 866 867 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE) 868 _mesa_update_image_transfer_state(ctx); 869 870 x = (GLint) (ctx->Current.RasterPos[0] + 0.5F); 871 y = (GLint) (ctx->Current.RasterPos[1] + 0.5F); 872 873 ctx->OcclusionResult = GL_TRUE; 874 875 /* see if device driver can do the drawpix */ 876 if (ctx->Driver.DrawPixels 877 && (*ctx->Driver.DrawPixels)(ctx, x, y, width, height, format, type, 878 &ctx->Unpack, pixels)) { 879 return; 880 } 881 882 switch (format) { 883 case GL_STENCIL_INDEX: 884 draw_stencil_pixels( ctx, x, y, width, height, type, pixels ); 885 break; 886 case GL_DEPTH_COMPONENT: 887 draw_depth_pixels( ctx, x, y, width, height, type, pixels ); 888 break; 889 case GL_COLOR_INDEX: 890 if (ctx->Visual.RGBAflag) 891 draw_rgba_pixels(ctx, x,y, width, height, format, type, pixels); 892 else 893 draw_index_pixels(ctx, x, y, width, height, type, pixels); 894 break; 895 case GL_RED: 896 case GL_GREEN: 897 case GL_BLUE: 898 case GL_ALPHA: 899 case GL_LUMINANCE: 900 case GL_LUMINANCE_ALPHA: 901 case GL_RGB: 902 case GL_BGR: 903 case GL_RGBA: 904 case GL_BGRA: 905 case GL_ABGR_EXT: 906 draw_rgba_pixels(ctx, x, y, width, height, format, type, pixels); 907 break; 908 default: 909 gl_error( ctx, GL_INVALID_ENUM, "glDrawPixels(format)" ); 910 return; 911 } 912 } 913 else if (ctx->RenderMode==GL_FEEDBACK) { 914 if (ctx->Current.RasterPosValid) { 915 GLfloat color[4]; 916 GLfloat texcoord[4], invq; 917 UBYTE_RGBA_TO_FLOAT_RGBA(color, ctx->Current.ByteColor); 918 invq = 1.0F / ctx->Current.Texcoord[0][3]; 919 texcoord[0] = ctx->Current.Texcoord[0][0] * invq; 920 texcoord[1] = ctx->Current.Texcoord[0][1] * invq; 921 texcoord[2] = ctx->Current.Texcoord[0][2] * invq; 922 texcoord[3] = ctx->Current.Texcoord[0][3]; 923 FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN ); 924 gl_feedback_vertex( ctx, 925 ctx->Current.RasterPos, 926 color, ctx->Current.Index, texcoord ); 927 } 928 } 929 else if (ctx->RenderMode==GL_SELECT) { 930 if (ctx->Current.RasterPosValid) { 931 gl_update_hitflag( ctx, ctx->Current.RasterPos[2] ); 932 } 933 } 934} 935 936