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