drawpix.c revision 193005393d6b1422ad9084f8e71004f4f055b88f
1/* $Id: drawpix.c,v 1.42 2000/10/29 19:02: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 "colormac.h" 33#include "context.h" 34#include "convolve.h" 35#include "drawpix.h" 36#include "feedback.h" 37#include "image.h" 38#include "macros.h" 39#include "mem.h" 40#include "mmath.h" 41#include "pixel.h" 42#include "pixeltex.h" 43#include "span.h" 44#include "state.h" 45#include "stencil.h" 46#include "texture.h" 47#include "types.h" 48#include "zoom.h" 49#endif 50 51 52 53/* 54 * Given the dest position, size and skipPixels and skipRows values 55 * for a glDrawPixels command, perform clipping of the image bounds 56 * so the result lies withing the context's buffer bounds. 57 * Return: GL_TRUE if image is ready for drawing 58 * GL_FALSE if image was completely clipped away (draw nothing) 59 */ 60GLboolean 61_mesa_clip_pixelrect(const GLcontext *ctx, 62 GLint *destX, GLint *destY, 63 GLsizei *width, GLsizei *height, 64 GLint *skipPixels, GLint *skipRows) 65{ 66 const GLframebuffer *buffer = ctx->DrawBuffer; 67 68 /* left clipping */ 69 if (*destX < buffer->Xmin) { 70 *skipPixels += (buffer->Xmin - *destX); 71 *width -= (buffer->Xmin - *destX); 72 *destX = buffer->Xmin; 73 } 74 /* right clipping */ 75 if (*destX + *width > buffer->Xmax) 76 *width -= (*destX + *width - buffer->Xmax); 77 78 if (*width <= 0) 79 return GL_FALSE; 80 81 /* bottom clipping */ 82 if (*destY < buffer->Ymin) { 83 *skipRows += (buffer->Ymin - *destY); 84 *height -= (buffer->Ymin - *destY); 85 *destY = buffer->Ymin; 86 } 87 /* top clipping */ 88 if (*destY + *height > buffer->Ymax) 89 *height -= (*destY + *height - buffer->Ymax); 90 91 if (*height <= 0) 92 return GL_TRUE; 93 94 return GL_TRUE; 95} 96 97 98 99/* 100 * Try to do a fast and simple RGB(a) glDrawPixels. 101 * Return: GL_TRUE if success, GL_FALSE if slow path must be used instead 102 */ 103static GLboolean 104fast_draw_pixels(GLcontext *ctx, GLint x, GLint y, 105 GLsizei width, GLsizei height, 106 GLenum format, GLenum type, const GLvoid *pixels) 107{ 108 const struct gl_pixelstore_attrib *unpack = &ctx->Unpack; 109 GLchan rgb[MAX_WIDTH][3]; 110 GLchan rgba[MAX_WIDTH][4]; 111 112 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx, "glDrawPixels", 113 GL_FALSE); 114 115 116 if (!ctx->Current.RasterPosValid) { 117 return GL_TRUE; /* no-op */ 118 } 119 120 if ((ctx->RasterMask&(~(SCISSOR_BIT|WINCLIP_BIT)))==0 121 && ctx->Texture.ReallyEnabled == 0 122 && unpack->Alignment == 1 123 && !unpack->SwapBytes 124 && !unpack->LsbFirst) { 125 126 GLint destX = x; 127 GLint destY = y; 128 GLint drawWidth = width; /* actual width drawn */ 129 GLint drawHeight = height; /* actual height drawn */ 130 GLint skipPixels = unpack->SkipPixels; 131 GLint skipRows = unpack->SkipRows; 132 GLint rowLength; 133 GLdepth zSpan[MAX_WIDTH]; /* only used when zooming */ 134 GLint zoomY0 = 0; 135 136 if (unpack->RowLength > 0) 137 rowLength = unpack->RowLength; 138 else 139 rowLength = width; 140 141 /* If we're not using pixel zoom then do all clipping calculations 142 * now. Otherwise, we'll let the gl_write_zoomed_*_span() functions 143 * handle the clipping. 144 */ 145 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { 146 /* horizontal clipping */ 147 if (destX < ctx->DrawBuffer->Xmin) { 148 skipPixels += (ctx->DrawBuffer->Xmin - destX); 149 drawWidth -= (ctx->DrawBuffer->Xmin - destX); 150 destX = ctx->DrawBuffer->Xmin; 151 } 152 if (destX + drawWidth > ctx->DrawBuffer->Xmax) 153 drawWidth -= (destX + drawWidth - ctx->DrawBuffer->Xmax); 154 if (drawWidth <= 0) 155 return GL_TRUE; 156 157 /* vertical clipping */ 158 if (destY < ctx->DrawBuffer->Ymin) { 159 skipRows += (ctx->DrawBuffer->Ymin - destY); 160 drawHeight -= (ctx->DrawBuffer->Ymin - destY); 161 destY = ctx->DrawBuffer->Ymin; 162 } 163 if (destY + drawHeight > ctx->DrawBuffer->Ymax) 164 drawHeight -= (destY + drawHeight - ctx->DrawBuffer->Ymax); 165 if (drawHeight <= 0) 166 return GL_TRUE; 167 } 168 else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) { 169 /* upside-down image */ 170 /* horizontal clipping */ 171 if (destX < ctx->DrawBuffer->Xmin) { 172 skipPixels += (ctx->DrawBuffer->Xmin - destX); 173 drawWidth -= (ctx->DrawBuffer->Xmin - destX); 174 destX = ctx->DrawBuffer->Xmin; 175 } 176 if (destX + drawWidth > ctx->DrawBuffer->Xmax) 177 drawWidth -= (destX + drawWidth - ctx->DrawBuffer->Xmax); 178 if (drawWidth <= 0) 179 return GL_TRUE; 180 181 /* vertical clipping */ 182 if (destY > ctx->DrawBuffer->Ymax) { 183 skipRows += (destY - ctx->DrawBuffer->Ymax); 184 drawHeight -= (destY - ctx->DrawBuffer->Ymax); 185 destY = ctx->DrawBuffer->Ymax; 186 } 187 if (destY - drawHeight < ctx->DrawBuffer->Ymin) 188 drawHeight -= (ctx->DrawBuffer->Ymin - (destY - drawHeight)); 189 if (drawHeight <= 0) 190 return GL_TRUE; 191 } 192 else { 193 /* setup array of fragment Z value to pass to zoom function */ 194 GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * ctx->Visual.DepthMaxF); 195 GLint i; 196 ASSERT(drawWidth < MAX_WIDTH); 197 for (i=0; i<drawWidth; i++) 198 zSpan[i] = z; 199 200 /* save Y value of first row */ 201 zoomY0 = (GLint) (ctx->Current.RasterPos[1] + 0.5F); 202 } 203 204 205 /* 206 * Ready to draw! 207 * The window region at (destX, destY) of size (drawWidth, drawHeight) 208 * will be written to. 209 * We'll take pixel data from buffer pointed to by "pixels" but we'll 210 * skip "skipRows" rows and skip "skipPixels" pixels/row. 211 */ 212 213 if (format == GL_RGBA && type == CHAN_TYPE 214 && ctx->ImageTransferState==0) { 215 if (ctx->Visual.RGBAflag) { 216 GLchan *src = (GLchan *) pixels 217 + (skipRows * rowLength + skipPixels) * 4; 218 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { 219 /* no zooming */ 220 GLint row; 221 for (row=0; row<drawHeight; row++) { 222 (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY, 223 (void *) src, NULL); 224 src += rowLength * 4; 225 destY++; 226 } 227 } 228 else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) { 229 /* upside-down */ 230 GLint row; 231 for (row=0; row<drawHeight; row++) { 232 destY--; 233 (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY, 234 (void *) src, NULL); 235 src += rowLength * 4; 236 } 237 } 238 else { 239 /* with zooming */ 240 GLint row; 241 for (row=0; row<drawHeight; row++) { 242 gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY, 243 zSpan, 0, (void *) src, zoomY0); 244 src += rowLength * 4; 245 destY++; 246 } 247 } 248 } 249 return GL_TRUE; 250 } 251 else if (format == GL_RGB && type == CHAN_TYPE 252 && ctx->ImageTransferState == 0) { 253 if (ctx->Visual.RGBAflag) { 254 GLchan *src = (GLchan *) pixels 255 + (skipRows * rowLength + skipPixels) * 3; 256 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { 257 GLint row; 258 for (row=0; row<drawHeight; row++) { 259 (*ctx->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY, 260 (void *) src, NULL); 261 src += rowLength * 3; 262 destY++; 263 } 264 } 265 else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) { 266 /* upside-down */ 267 GLint row; 268 for (row=0; row<drawHeight; row++) { 269 destY--; 270 (*ctx->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY, 271 (void *) src, NULL); 272 src += rowLength * 3; 273 } 274 } 275 else { 276 /* with zooming */ 277 GLint row; 278 for (row=0; row<drawHeight; row++) { 279 gl_write_zoomed_rgb_span(ctx, drawWidth, destX, destY, 280 zSpan, 0, (void *) src, zoomY0); 281 src += rowLength * 3; 282 destY++; 283 } 284 } 285 } 286 return GL_TRUE; 287 } 288 else if (format == GL_LUMINANCE && type == CHAN_TYPE 289 && ctx->ImageTransferState==0) { 290 if (ctx->Visual.RGBAflag) { 291 GLchan *src = (GLchan *) pixels 292 + (skipRows * rowLength + skipPixels); 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 for (i=0;i<drawWidth;i++) { 300 rgb[i][0] = src[i]; 301 rgb[i][1] = src[i]; 302 rgb[i][2] = src[i]; 303 } 304 (*ctx->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY, 305 (void *) rgb, NULL); 306 src += rowLength; 307 destY++; 308 } 309 } 310 else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) { 311 /* upside-down */ 312 GLint row; 313 ASSERT(drawWidth < MAX_WIDTH); 314 for (row=0; row<drawHeight; row++) { 315 GLint i; 316 for (i=0;i<drawWidth;i++) { 317 rgb[i][0] = src[i]; 318 rgb[i][1] = src[i]; 319 rgb[i][2] = src[i]; 320 } 321 destY--; 322 (*ctx->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY, 323 (void *) rgb, NULL); 324 src += rowLength; 325 } 326 } 327 else { 328 /* with zooming */ 329 GLint row; 330 ASSERT(drawWidth < MAX_WIDTH); 331 for (row=0; row<drawHeight; row++) { 332 GLint i; 333 for (i=0;i<drawWidth;i++) { 334 rgb[i][0] = src[i]; 335 rgb[i][1] = src[i]; 336 rgb[i][2] = src[i]; 337 } 338 gl_write_zoomed_rgb_span(ctx, drawWidth, destX, destY, 339 zSpan, 0, (void *) rgb, zoomY0); 340 src += rowLength; 341 destY++; 342 } 343 } 344 } 345 return GL_TRUE; 346 } 347 else if (format == GL_LUMINANCE_ALPHA && type == CHAN_TYPE 348 && ctx->ImageTransferState == 0) { 349 if (ctx->Visual.RGBAflag) { 350 GLchan *src = (GLchan *) pixels 351 + (skipRows * rowLength + skipPixels)*2; 352 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { 353 /* no zooming */ 354 GLint row; 355 ASSERT(drawWidth < MAX_WIDTH); 356 for (row=0; row<drawHeight; row++) { 357 GLint i; 358 GLchan *ptr = src; 359 for (i=0;i<drawWidth;i++) { 360 rgba[i][0] = *ptr; 361 rgba[i][1] = *ptr; 362 rgba[i][2] = *ptr++; 363 rgba[i][3] = *ptr++; 364 } 365 (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY, 366 (void *) rgba, NULL); 367 src += rowLength*2; 368 destY++; 369 } 370 } 371 else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) { 372 /* upside-down */ 373 GLint row; 374 ASSERT(drawWidth < MAX_WIDTH); 375 for (row=0; row<drawHeight; row++) { 376 GLint i; 377 GLchan *ptr = src; 378 for (i=0;i<drawWidth;i++) { 379 rgba[i][0] = *ptr; 380 rgba[i][1] = *ptr; 381 rgba[i][2] = *ptr++; 382 rgba[i][3] = *ptr++; 383 } 384 destY--; 385 (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY, 386 (void *) rgba, NULL); 387 src += rowLength*2; 388 } 389 } 390 else { 391 /* with zooming */ 392 GLint row; 393 ASSERT(drawWidth < MAX_WIDTH); 394 for (row=0; row<drawHeight; row++) { 395 GLchan *ptr = src; 396 GLint i; 397 for (i=0;i<drawWidth;i++) { 398 rgba[i][0] = *ptr; 399 rgba[i][1] = *ptr; 400 rgba[i][2] = *ptr++; 401 rgba[i][3] = *ptr++; 402 } 403 gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY, 404 zSpan, 0, (void *) rgba, zoomY0); 405 src += rowLength*2; 406 destY++; 407 } 408 } 409 } 410 return GL_TRUE; 411 } 412 else if (format==GL_COLOR_INDEX && type==GL_UNSIGNED_BYTE) { 413 GLubyte *src = (GLubyte *) pixels + skipRows * rowLength + skipPixels; 414 if (ctx->Visual.RGBAflag) { 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 GLchan (*)[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 GLchan (*)[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, 0, (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, 0, indexes, desty); 525 } 526 else { 527 gl_write_index_span(ctx, drawWidth, x, y, zspan, 0, 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 GLchan 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 = FLOAT_TO_CHAN(ctx->Current.RasterColor[0]); 618 GLint g = FLOAT_TO_CHAN(ctx->Current.RasterColor[1]); 619 GLint b = FLOAT_TO_CHAN(ctx->Current.RasterColor[2]); 620 GLint a = FLOAT_TO_CHAN(ctx->Current.RasterColor[3]); 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, 0, 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, 0, 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, 0, 672 (const GLchan (*)[4]) rgba, desty); 673 } 674 else { 675 gl_write_rgba_span(ctx, width, x, y, zspan, 0, rgba, GL_BITMAP); 676 } 677 } 678 else { 679 if (zoom) { 680 gl_write_zoomed_index_span(ctx, width, x, y, zspan, 0, 681 ispan, GL_BITMAP); 682 } 683 else { 684 gl_write_index_span(ctx, width, x, y, zspan, 0, 685 ispan, GL_BITMAP); 686 } 687 } 688 689 } 690 } 691} 692 693 694/* 695 * Do glDrawPixels of RGBA pixels. 696 */ 697static void 698draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y, 699 GLsizei width, GLsizei height, 700 GLenum format, GLenum type, const GLvoid *pixels ) 701{ 702 const struct gl_pixelstore_attrib *unpack = &ctx->Unpack; 703 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0; 704 const GLint desty = y; 705 GLdepth zspan[MAX_WIDTH]; 706 GLboolean quickDraw; 707 GLfloat *convImage = NULL; 708 GLuint transferOps = ctx->ImageTransferState; 709 710 if (!_mesa_is_legal_format_and_type(format, type)) { 711 gl_error(ctx, GL_INVALID_ENUM, "glDrawPixels(format or type)"); 712 return; 713 } 714 715 /* Try an optimized glDrawPixels first */ 716 if (fast_draw_pixels(ctx, x, y, width, height, format, type, pixels)) 717 return; 718 719 /* Fragment depth values */ 720 if (ctx->Depth.Test || ctx->Fog.Enabled) { 721 /* fill in array of z values */ 722 GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * ctx->Visual.DepthMaxF); 723 GLint i; 724 for (i=0;i<width;i++) { 725 zspan[i] = z; 726 } 727 } 728 729 730 if (ctx->RasterMask == 0 && !zoom && x >= 0 && y >= 0 731 && x + width <= ctx->DrawBuffer->Width 732 && y + height <= ctx->DrawBuffer->Height) { 733 quickDraw = GL_TRUE; 734 } 735 else { 736 quickDraw = GL_FALSE; 737 } 738 739 if (ctx->Pixel.Convolution2DEnabled || ctx->Pixel.Separable2DEnabled) { 740 /* Convolution has to be handled specially. We'll create an 741 * intermediate image, applying all pixel transfer operations 742 * up to convolution. Then we'll convolve the image. Then 743 * we'll proceed with the rest of the transfer operations and 744 * rasterize the image. 745 */ 746 GLint row; 747 GLfloat *dest, *tmpImage; 748 749 tmpImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat)); 750 if (!tmpImage) { 751 gl_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels"); 752 return; 753 } 754 convImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat)); 755 if (!convImage) { 756 FREE(tmpImage); 757 gl_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels"); 758 return; 759 } 760 761 /* Unpack the image and apply transfer ops up to convolution */ 762 dest = tmpImage; 763 for (row = 0; row < height; row++) { 764 const GLvoid *source = _mesa_image_address(unpack, 765 pixels, width, height, format, type, 0, row, 0); 766 _mesa_unpack_float_color_span(ctx, width, GL_RGBA, (void *) dest, 767 format, type, source, unpack, 768 transferOps & IMAGE_PRE_CONVOLUTION_BITS, 769 GL_FALSE); 770 dest += width * 4; 771 } 772 773 /* do convolution */ 774 if (ctx->Pixel.Convolution2DEnabled) { 775 _mesa_convolve_2d_image(ctx, &width, &height, tmpImage, convImage); 776 } 777 else { 778 ASSERT(ctx->Pixel.Separable2DEnabled); 779 _mesa_convolve_sep_image(ctx, &width, &height, tmpImage, convImage); 780 } 781 FREE(tmpImage); 782 783 /* continue transfer ops and draw the convolved image */ 784 unpack = &_mesa_native_packing; 785 pixels = convImage; 786 format = GL_RGBA; 787 type = GL_FLOAT; 788 transferOps &= IMAGE_POST_CONVOLUTION_BITS; 789 } 790 791 /* 792 * General solution 793 */ 794 { 795 GLchan rgba[MAX_WIDTH][4]; 796 GLint row; 797 if (width > MAX_WIDTH) 798 width = MAX_WIDTH; 799 for (row = 0; row < height; row++, y++) { 800 const GLvoid *source = _mesa_image_address(unpack, 801 pixels, width, height, format, type, 0, row, 0); 802 _mesa_unpack_chan_color_span(ctx, width, GL_RGBA, (void*) rgba, 803 format, type, source, unpack, 804 transferOps); 805 if ((ctx->Pixel.MinMaxEnabled && ctx->MinMax.Sink) || 806 (ctx->Pixel.HistogramEnabled && ctx->Histogram.Sink)) 807 continue; 808 809 if (ctx->Texture.ReallyEnabled && ctx->Pixel.PixelTextureEnabled) { 810 GLfloat s[MAX_WIDTH], t[MAX_WIDTH], r[MAX_WIDTH], q[MAX_WIDTH]; 811 GLchan primary_rgba[MAX_WIDTH][4]; 812 GLuint unit; 813 /* XXX not sure how multitexture is supposed to work here */ 814 815 MEMCPY(primary_rgba, rgba, 4 * width * sizeof(GLchan)); 816 817 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { 818 if (ctx->Texture.Unit[unit].ReallyEnabled) { 819 _mesa_pixeltexgen(ctx, width, (const GLchan (*)[4]) rgba, 820 s, t, r, q); 821 gl_texture_pixels(ctx, unit, width, s, t, r, NULL, 822 primary_rgba, rgba); 823 } 824 } 825 } 826 827 if (quickDraw) { 828 (*ctx->Driver.WriteRGBASpan)( ctx, width, x, y, 829 (CONST GLchan (*)[]) rgba, NULL); 830 } 831 else if (zoom) { 832 gl_write_zoomed_rgba_span( ctx, width, x, y, zspan, 0, 833 (CONST GLchan (*)[]) rgba, desty ); 834 } 835 else { 836 gl_write_rgba_span( ctx, (GLuint) width, x, y, zspan, 0, 837 rgba, GL_BITMAP); 838 } 839 } 840 } 841 842 if (convImage) { 843 FREE(convImage); 844 } 845} 846 847 848 849/* 850 * Execute glDrawPixels 851 */ 852void 853_mesa_DrawPixels( GLsizei width, GLsizei height, 854 GLenum format, GLenum type, const GLvoid *pixels ) 855{ 856 GET_CURRENT_CONTEXT(ctx); 857 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDrawPixels"); 858 859 if (ctx->RenderMode==GL_RENDER) { 860 GLint x, y; 861 if (!pixels || !ctx->Current.RasterPosValid) { 862 return; 863 } 864 865 if (ctx->NewState) { 866 gl_update_state(ctx); 867 } 868 869 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE) 870 _mesa_update_image_transfer_state(ctx); 871 872 x = (GLint) (ctx->Current.RasterPos[0] + 0.5F); 873 y = (GLint) (ctx->Current.RasterPos[1] + 0.5F); 874 875 ctx->OcclusionResult = GL_TRUE; 876 877 /* see if device driver can do the drawpix */ 878 if (ctx->Driver.DrawPixels 879 && (*ctx->Driver.DrawPixels)(ctx, x, y, width, height, format, type, 880 &ctx->Unpack, pixels)) { 881 return; 882 } 883 884 RENDER_START(ctx); 885 switch (format) { 886 case GL_STENCIL_INDEX: 887 draw_stencil_pixels( ctx, x, y, width, height, type, pixels ); 888 break; 889 case GL_DEPTH_COMPONENT: 890 draw_depth_pixels( ctx, x, y, width, height, type, pixels ); 891 break; 892 case GL_COLOR_INDEX: 893 if (ctx->Visual.RGBAflag) 894 draw_rgba_pixels(ctx, x,y, width, height, format, type, pixels); 895 else 896 draw_index_pixels(ctx, x, y, width, height, type, pixels); 897 break; 898 case GL_RED: 899 case GL_GREEN: 900 case GL_BLUE: 901 case GL_ALPHA: 902 case GL_LUMINANCE: 903 case GL_LUMINANCE_ALPHA: 904 case GL_RGB: 905 case GL_BGR: 906 case GL_RGBA: 907 case GL_BGRA: 908 case GL_ABGR_EXT: 909 draw_rgba_pixels(ctx, x, y, width, height, format, type, pixels); 910 break; 911 default: 912 gl_error( ctx, GL_INVALID_ENUM, "glDrawPixels(format)" ); 913 } 914 RENDER_FINISH(ctx); 915 } 916 else if (ctx->RenderMode==GL_FEEDBACK) { 917 if (ctx->Current.RasterPosValid) { 918 GLfloat color[4]; 919 GLfloat texcoord[4], invq; 920 color[0] = CHAN_TO_FLOAT(ctx->Current.Color[0]); 921 color[1] = CHAN_TO_FLOAT(ctx->Current.Color[1]); 922 color[2] = CHAN_TO_FLOAT(ctx->Current.Color[2]); 923 color[3] = CHAN_TO_FLOAT(ctx->Current.Color[3]); 924 invq = 1.0F / ctx->Current.Texcoord[0][3]; 925 texcoord[0] = ctx->Current.Texcoord[0][0] * invq; 926 texcoord[1] = ctx->Current.Texcoord[0][1] * invq; 927 texcoord[2] = ctx->Current.Texcoord[0][2] * invq; 928 texcoord[3] = ctx->Current.Texcoord[0][3]; 929 FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN ); 930 gl_feedback_vertex( ctx, 931 ctx->Current.RasterPos, 932 color, ctx->Current.Index, texcoord ); 933 } 934 } 935 else if (ctx->RenderMode==GL_SELECT) { 936 if (ctx->Current.RasterPosValid) { 937 gl_update_hitflag( ctx, ctx->Current.RasterPos[2] ); 938 } 939 } 940} 941 942