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