s_copypix.c revision 3622f4f27fe51edff0717e4a42623f62e2936e90
1/* 2 * Mesa 3-D graphics library 3 * Version: 6.5 4 * 5 * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included 15 * in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25 26#include "glheader.h" 27#include "context.h" 28#include "colormac.h" 29#include "convolve.h" 30#include "histogram.h" 31#include "image.h" 32#include "macros.h" 33#include "imports.h" 34#include "pixel.h" 35 36#include "s_context.h" 37#include "s_depth.h" 38#include "s_pixeltex.h" 39#include "s_span.h" 40#include "s_stencil.h" 41#include "s_texture.h" 42#include "s_zoom.h" 43 44 45 46/* 47 * Determine if there's overlap in an image copy. 48 * This test also compensates for the fact that copies are done from 49 * bottom to top and overlaps can sometimes be handled correctly 50 * without making a temporary image copy. 51 */ 52static GLboolean 53regions_overlap(GLint srcx, GLint srcy, 54 GLint dstx, GLint dsty, 55 GLint width, GLint height, 56 GLfloat zoomX, GLfloat zoomY) 57{ 58 if (zoomX == 1.0 && zoomY == 1.0) { 59 /* no zoom */ 60 if (srcx >= dstx + width || (srcx + width <= dstx)) { 61 return GL_FALSE; 62 } 63 else if (srcy < dsty) { /* this is OK */ 64 return GL_FALSE; 65 } 66 else if (srcy > dsty + height) { 67 return GL_FALSE; 68 } 69 else { 70 return GL_TRUE; 71 } 72 } 73 else { 74 /* add one pixel of slop when zooming, just to be safe */ 75 if ((srcx > dstx + (width * zoomX) + 1) || (srcx + width + 1 < dstx)) { 76 return GL_FALSE; 77 } 78 else if ((srcy < dsty) && (srcy + height < dsty + (height * zoomY))) { 79 return GL_FALSE; 80 } 81 else if ((srcy > dsty) && (srcy + height > dsty + (height * zoomY))) { 82 return GL_FALSE; 83 } 84 else { 85 return GL_TRUE; 86 } 87 } 88} 89 90 91/** 92 * Convert GLfloat[n][4] colors to GLchan[n][4]. 93 * XXX maybe move into image.c 94 */ 95static void 96float_span_to_chan(GLuint n, CONST GLfloat in[][4], GLchan out[][4]) 97{ 98 GLuint i; 99 for (i = 0; i < n; i++) { 100 UNCLAMPED_FLOAT_TO_CHAN(out[i][RCOMP], in[i][RCOMP]); 101 UNCLAMPED_FLOAT_TO_CHAN(out[i][GCOMP], in[i][GCOMP]); 102 UNCLAMPED_FLOAT_TO_CHAN(out[i][BCOMP], in[i][BCOMP]); 103 UNCLAMPED_FLOAT_TO_CHAN(out[i][ACOMP], in[i][ACOMP]); 104 } 105} 106 107 108/** 109 * Convert GLchan[n][4] colors to GLfloat[n][4]. 110 * XXX maybe move into image.c 111 */ 112static void 113chan_span_to_float(GLuint n, CONST GLchan in[][4], GLfloat out[][4]) 114{ 115 GLuint i; 116 for (i = 0; i < n; i++) { 117 out[i][RCOMP] = CHAN_TO_FLOAT(in[i][RCOMP]); 118 out[i][GCOMP] = CHAN_TO_FLOAT(in[i][GCOMP]); 119 out[i][BCOMP] = CHAN_TO_FLOAT(in[i][BCOMP]); 120 out[i][ACOMP] = CHAN_TO_FLOAT(in[i][ACOMP]); 121 } 122} 123 124 125 126/* 127 * RGBA copypixels with convolution. 128 */ 129static void 130copy_conv_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy, 131 GLint width, GLint height, GLint destx, GLint desty) 132{ 133 struct gl_renderbuffer *drawRb = NULL; 134 GLboolean quick_draw; 135 GLint row; 136 const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F; 137 const GLuint transferOps = ctx->_ImageTransferState; 138 GLfloat *dest, *tmpImage, *convImage; 139 struct sw_span span; 140 141 INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_RGBA); 142 143 if (ctx->Depth.Test) 144 _swrast_span_default_z(ctx, &span); 145 if (ctx->Fog.Enabled) 146 _swrast_span_default_fog(ctx, &span); 147 148 149 if (SWRAST_CONTEXT(ctx)->_RasterMask == 0 150 && !zoom 151 && destx >= 0 152 && destx + width <= (GLint) ctx->DrawBuffer->Width) { 153 quick_draw = GL_TRUE; 154 drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0][0]; 155 } 156 else { 157 quick_draw = GL_FALSE; 158 } 159 160 /* allocate space for GLfloat image */ 161 tmpImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat)); 162 if (!tmpImage) { 163 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels"); 164 return; 165 } 166 convImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat)); 167 if (!convImage) { 168 FREE(tmpImage); 169 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels"); 170 return; 171 } 172 173 /* read source image */ 174 dest = tmpImage; 175 for (row = 0; row < height; row++) { 176 GLchan rgba[MAX_WIDTH][4]; 177 /* Read GLchan and convert to GLfloat */ 178 _swrast_read_rgba_span(ctx, ctx->ReadBuffer->_ColorReadBuffer, 179 width, srcx, srcy + row, rgba); 180 chan_span_to_float(width, (CONST GLchan (*)[4]) rgba, 181 (GLfloat (*)[4]) dest); 182 dest += 4 * width; 183 } 184 185 /* do the image transfer ops which preceed convolution */ 186 for (row = 0; row < height; row++) { 187 GLfloat (*rgba)[4] = (GLfloat (*)[4]) (tmpImage + row * width * 4); 188 _mesa_apply_rgba_transfer_ops(ctx, 189 transferOps & IMAGE_PRE_CONVOLUTION_BITS, 190 width, rgba); 191 } 192 193 /* do convolution */ 194 if (ctx->Pixel.Convolution2DEnabled) { 195 _mesa_convolve_2d_image(ctx, &width, &height, tmpImage, convImage); 196 } 197 else { 198 ASSERT(ctx->Pixel.Separable2DEnabled); 199 _mesa_convolve_sep_image(ctx, &width, &height, tmpImage, convImage); 200 } 201 FREE(tmpImage); 202 203 /* do remaining post-convolution image transfer ops */ 204 for (row = 0; row < height; row++) { 205 GLfloat (*rgba)[4] = (GLfloat (*)[4]) (convImage + row * width * 4); 206 _mesa_apply_rgba_transfer_ops(ctx, 207 transferOps & IMAGE_POST_CONVOLUTION_BITS, 208 width, rgba); 209 } 210 211 /* write the new image */ 212 for (row = 0; row < height; row++) { 213 const GLfloat *src = convImage + row * width * 4; 214 GLint dy; 215 216 /* convert floats back to chan */ 217 float_span_to_chan(width, (const GLfloat (*)[4]) src, span.array->rgba); 218 219 if (ctx->Pixel.PixelTextureEnabled && ctx->Texture._EnabledUnits) { 220 span.end = width; 221 _swrast_pixel_texture(ctx, &span); 222 } 223 224 /* write row to framebuffer */ 225 226 dy = desty + row; 227 if (quick_draw && dy >= 0 && dy < (GLint) ctx->DrawBuffer->Height) { 228 drawRb->PutRow(ctx, drawRb, width, destx, dy, span.array->rgba, NULL); 229 } 230 else if (zoom) { 231 span.x = destx; 232 span.y = dy; 233 span.end = width; 234 _swrast_write_zoomed_rgba_span(ctx, &span, 235 (CONST GLchan (*)[4])span.array->rgba, 236 desty, 0); 237 } 238 else { 239 span.x = destx; 240 span.y = dy; 241 span.end = width; 242 _swrast_write_rgba_span(ctx, &span); 243 } 244 } 245 246 FREE(convImage); 247} 248 249 250/* 251 * RGBA copypixels 252 */ 253static void 254copy_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy, 255 GLint width, GLint height, GLint destx, GLint desty) 256{ 257 struct gl_renderbuffer *drawRb; 258 GLchan *tmpImage,*p; 259 GLboolean quick_draw; 260 GLint sy, dy, stepy, j; 261 const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F; 262 GLint overlapping; 263 const GLuint transferOps = ctx->_ImageTransferState; 264 struct sw_span span; 265 266 if (!ctx->ReadBuffer->_ColorReadBuffer) { 267 /* no readbuffer - OK */ 268 return; 269 } 270 271 INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_RGBA); 272 273 if (ctx->Pixel.Convolution2DEnabled || ctx->Pixel.Separable2DEnabled) { 274 copy_conv_rgba_pixels(ctx, srcx, srcy, width, height, destx, desty); 275 return; 276 } 277 278 /* Determine if copy should be done bottom-to-top or top-to-bottom */ 279 if (srcy < desty) { 280 /* top-down max-to-min */ 281 sy = srcy + height - 1; 282 dy = desty + height - 1; 283 stepy = -1; 284 } 285 else { 286 /* bottom-up min-to-max */ 287 sy = srcy; 288 dy = desty; 289 stepy = 1; 290 } 291 292 if (ctx->DrawBuffer == ctx->ReadBuffer) { 293 overlapping = regions_overlap(srcx, srcy, destx, desty, width, height, 294 ctx->Pixel.ZoomX, ctx->Pixel.ZoomY); 295 } 296 else { 297 overlapping = GL_FALSE; 298 } 299 300 if (ctx->Depth.Test) 301 _swrast_span_default_z(ctx, &span); 302 if (ctx->Fog.Enabled) 303 _swrast_span_default_fog(ctx, &span); 304 305 if (SWRAST_CONTEXT(ctx)->_RasterMask == 0 306 && !zoom 307 && destx >= 0 308 && destx + width <= (GLint) ctx->DrawBuffer->Width) { 309 quick_draw = GL_TRUE; 310 drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0][0]; 311 } 312 else { 313 quick_draw = GL_FALSE; 314 drawRb = NULL; 315 } 316 317 if (overlapping) { 318 GLint ssy = sy; 319 tmpImage = (GLchan *) MALLOC(width * height * sizeof(GLchan) * 4); 320 if (!tmpImage) { 321 _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" ); 322 return; 323 } 324 /* read the source image */ 325 p = tmpImage; 326 for (j = 0; j < height; j++, ssy += stepy) { 327 _swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer, 328 width, srcx, ssy, (GLchan (*)[4]) p ); 329 p += width * 4; 330 } 331 p = tmpImage; 332 } 333 else { 334 tmpImage = NULL; /* silence compiler warnings */ 335 p = NULL; 336 } 337 338 for (j = 0; j < height; j++, sy += stepy, dy += stepy) { 339 /* Get source pixels */ 340 if (overlapping) { 341 /* get from buffered image */ 342 ASSERT(width < MAX_WIDTH); 343 MEMCPY(span.array->rgba, p, width * sizeof(GLchan) * 4); 344 p += width * 4; 345 } 346 else { 347 /* get from framebuffer */ 348 ASSERT(width < MAX_WIDTH); 349 _swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer, 350 width, srcx, sy, span.array->rgba ); 351 } 352 353 if (transferOps) { 354 GLfloat rgbaFloat[MAX_WIDTH][4]; 355 /* convert to float, transfer, convert back to chan */ 356 chan_span_to_float(width, (CONST GLchan (*)[4]) span.array->rgba, 357 rgbaFloat); 358 _mesa_apply_rgba_transfer_ops(ctx, transferOps, width, rgbaFloat); 359 float_span_to_chan(width, (CONST GLfloat (*)[4]) rgbaFloat, 360 span.array->rgba); 361 } 362 363 if (ctx->Pixel.PixelTextureEnabled && ctx->Texture._EnabledUnits) { 364 span.end = width; 365 _swrast_pixel_texture(ctx, &span); 366 } 367 368 /* Write color span */ 369 if (quick_draw && dy >= 0 && dy < (GLint) ctx->DrawBuffer->Height) { 370 drawRb->PutRow(ctx, drawRb, width, destx, dy, span.array->rgba, NULL); 371 } 372 else if (zoom) { 373 span.x = destx; 374 span.y = dy; 375 span.end = width; 376 _swrast_write_zoomed_rgba_span(ctx, &span, 377 (CONST GLchan (*)[4]) span.array->rgba, 378 desty, 0); 379 } 380 else { 381 span.x = destx; 382 span.y = dy; 383 span.end = width; 384 _swrast_write_rgba_span(ctx, &span); 385 } 386 } 387 388 if (overlapping) 389 FREE(tmpImage); 390} 391 392 393static void 394copy_ci_pixels( GLcontext *ctx, GLint srcx, GLint srcy, 395 GLint width, GLint height, 396 GLint destx, GLint desty ) 397{ 398 GLuint *tmpImage,*p; 399 GLint sy, dy, stepy; 400 GLint j; 401 const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F; 402 const GLboolean shift_or_offset = ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset; 403 GLint overlapping; 404 struct sw_span span; 405 406 if (!ctx->ReadBuffer->_ColorReadBuffer) { 407 /* no readbuffer - OK */ 408 return; 409 } 410 411 INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_INDEX); 412 413 /* Determine if copy should be bottom-to-top or top-to-bottom */ 414 if (srcy<desty) { 415 /* top-down max-to-min */ 416 sy = srcy + height - 1; 417 dy = desty + height - 1; 418 stepy = -1; 419 } 420 else { 421 /* bottom-up min-to-max */ 422 sy = srcy; 423 dy = desty; 424 stepy = 1; 425 } 426 427 if (ctx->DrawBuffer == ctx->ReadBuffer) { 428 overlapping = regions_overlap(srcx, srcy, destx, desty, width, height, 429 ctx->Pixel.ZoomX, ctx->Pixel.ZoomY); 430 } 431 else { 432 overlapping = GL_FALSE; 433 } 434 435 if (ctx->Depth.Test) 436 _swrast_span_default_z(ctx, &span); 437 if (ctx->Fog.Enabled) 438 _swrast_span_default_fog(ctx, &span); 439 440 if (overlapping) { 441 GLint ssy = sy; 442 tmpImage = (GLuint *) MALLOC(width * height * sizeof(GLuint)); 443 if (!tmpImage) { 444 _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" ); 445 return; 446 } 447 /* read the image */ 448 p = tmpImage; 449 for (j = 0; j < height; j++, ssy += stepy) { 450 _swrast_read_index_span( ctx, ctx->ReadBuffer->_ColorReadBuffer, 451 width, srcx, ssy, p ); 452 p += width; 453 } 454 p = tmpImage; 455 } 456 else { 457 tmpImage = NULL; /* silence compiler warning */ 458 p = NULL; 459 } 460 461 for (j = 0; j < height; j++, sy += stepy, dy += stepy) { 462 /* Get color indexes */ 463 if (overlapping) { 464 MEMCPY(span.array->index, p, width * sizeof(GLuint)); 465 p += width; 466 } 467 else { 468 _swrast_read_index_span( ctx, ctx->ReadBuffer->_ColorReadBuffer, 469 width, srcx, sy, span.array->index ); 470 } 471 472 /* Apply shift, offset, look-up table */ 473 if (shift_or_offset) { 474 _mesa_shift_and_offset_ci( ctx, width, span.array->index ); 475 } 476 if (ctx->Pixel.MapColorFlag) { 477 _mesa_map_ci( ctx, width, span.array->index ); 478 } 479 480 /* write color indexes */ 481 span.x = destx; 482 span.y = dy; 483 span.end = width; 484 if (zoom) 485 _swrast_write_zoomed_index_span(ctx, &span, desty, 0); 486 else 487 _swrast_write_index_span(ctx, &span); 488 } 489 490 if (overlapping) 491 FREE(tmpImage); 492} 493 494 495 496/* 497 * TODO: Optimize!!!! 498 */ 499static void 500copy_depth_pixels( GLcontext *ctx, GLint srcx, GLint srcy, 501 GLint width, GLint height, 502 GLint destx, GLint desty ) 503{ 504 const GLfloat depthMax = ctx->DrawBuffer->_DepthMaxF; 505 struct gl_renderbuffer *readRb 506 = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; 507 GLfloat *p, *tmpImage; 508 GLint sy, dy, stepy; 509 GLint i, j; 510 const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F; 511 GLint overlapping; 512 struct sw_span span; 513 514 if (!readRb) { 515 /* no readbuffer - OK */ 516 return; 517 } 518 519 INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_Z); 520 521 if (!ctx->Visual.depthBits) { 522 _mesa_error( ctx, GL_INVALID_OPERATION, "glCopyPixels" ); 523 return; 524 } 525 526 /* Determine if copy should be bottom-to-top or top-to-bottom */ 527 if (srcy<desty) { 528 /* top-down max-to-min */ 529 sy = srcy + height - 1; 530 dy = desty + height - 1; 531 stepy = -1; 532 } 533 else { 534 /* bottom-up min-to-max */ 535 sy = srcy; 536 dy = desty; 537 stepy = 1; 538 } 539 540 if (ctx->DrawBuffer == ctx->ReadBuffer) { 541 overlapping = regions_overlap(srcx, srcy, destx, desty, width, height, 542 ctx->Pixel.ZoomX, ctx->Pixel.ZoomY); 543 } 544 else { 545 overlapping = GL_FALSE; 546 } 547 548 _swrast_span_default_color(ctx, &span); 549 if (ctx->Fog.Enabled) 550 _swrast_span_default_fog(ctx, &span); 551 552 if (overlapping) { 553 GLint ssy = sy; 554 tmpImage = (GLfloat *) MALLOC(width * height * sizeof(GLfloat)); 555 if (!tmpImage) { 556 _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" ); 557 return; 558 } 559 p = tmpImage; 560 for (j = 0; j < height; j++, ssy += stepy) { 561 _swrast_read_depth_span_float(ctx, readRb, width, srcx, ssy, p); 562 p += width; 563 } 564 p = tmpImage; 565 } 566 else { 567 tmpImage = NULL; /* silence compiler warning */ 568 p = NULL; 569 } 570 571 for (j = 0; j < height; j++, sy += stepy, dy += stepy) { 572 GLfloat depth[MAX_WIDTH]; 573 float sum = 0; 574 /* get depth values */ 575 if (overlapping) { 576 MEMCPY(depth, p, width * sizeof(GLfloat)); 577 p += width; 578 } 579 else { 580 _swrast_read_depth_span_float(ctx, readRb, width, srcx, sy, depth); 581 } 582 583 /* apply scale and bias */ 584 for (i = 0; i < width; i++) { 585 GLfloat d = depth[i] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias; 586 sum += d; 587 span.array->z[i] = (GLdepth) (CLAMP(d, 0.0F, 1.0F) * depthMax); 588 } 589 590 /* write depth values */ 591 span.x = destx; 592 span.y = dy; 593 span.end = width; 594 if (ctx->Visual.rgbMode) { 595 if (zoom) 596 _swrast_write_zoomed_rgba_span( ctx, &span, 597 (const GLchan (*)[4])span.array->rgba, desty, 0 ); 598 else 599 _swrast_write_rgba_span(ctx, &span); 600 } 601 else { 602 if (zoom) 603 _swrast_write_zoomed_index_span( ctx, &span, desty, 0 ); 604 else 605 _swrast_write_index_span(ctx, &span); 606 } 607 } 608 609 if (overlapping) 610 FREE(tmpImage); 611} 612 613 614 615static void 616copy_stencil_pixels( GLcontext *ctx, GLint srcx, GLint srcy, 617 GLint width, GLint height, 618 GLint destx, GLint desty ) 619{ 620 struct gl_renderbuffer *rb 621 = ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer; 622 GLint sy, dy, stepy; 623 GLint j; 624 GLstencil *p, *tmpImage; 625 const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F; 626 const GLboolean shift_or_offset = ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset; 627 GLint overlapping; 628 629 if (!ctx->Visual.stencilBits) { 630 _mesa_error( ctx, GL_INVALID_OPERATION, "glCopyPixels" ); 631 return; 632 } 633 634 if (!rb) { 635 /* no readbuffer - OK */ 636 return; 637 } 638 639 /* Determine if copy should be bottom-to-top or top-to-bottom */ 640 if (srcy < desty) { 641 /* top-down max-to-min */ 642 sy = srcy + height - 1; 643 dy = desty + height - 1; 644 stepy = -1; 645 } 646 else { 647 /* bottom-up min-to-max */ 648 sy = srcy; 649 dy = desty; 650 stepy = 1; 651 } 652 653 if (ctx->DrawBuffer == ctx->ReadBuffer) { 654 overlapping = regions_overlap(srcx, srcy, destx, desty, width, height, 655 ctx->Pixel.ZoomX, ctx->Pixel.ZoomY); 656 } 657 else { 658 overlapping = GL_FALSE; 659 } 660 661 if (overlapping) { 662 GLint ssy = sy; 663 tmpImage = (GLstencil *) MALLOC(width * height * sizeof(GLstencil)); 664 if (!tmpImage) { 665 _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" ); 666 return; 667 } 668 p = tmpImage; 669 for (j = 0; j < height; j++, ssy += stepy) { 670 _swrast_read_stencil_span( ctx, rb, width, srcx, ssy, p ); 671 p += width; 672 } 673 p = tmpImage; 674 } 675 else { 676 tmpImage = NULL; /* silence compiler warning */ 677 p = NULL; 678 } 679 680 for (j = 0; j < height; j++, sy += stepy, dy += stepy) { 681 GLstencil stencil[MAX_WIDTH]; 682 683 /* Get stencil values */ 684 if (overlapping) { 685 MEMCPY(stencil, p, width * sizeof(GLstencil)); 686 p += width; 687 } 688 else { 689 _swrast_read_stencil_span( ctx, rb, width, srcx, sy, stencil ); 690 } 691 692 /* Apply shift, offset, look-up table */ 693 if (shift_or_offset) { 694 _mesa_shift_and_offset_stencil( ctx, width, stencil ); 695 } 696 if (ctx->Pixel.MapStencilFlag) { 697 _mesa_map_stencil( ctx, width, stencil ); 698 } 699 700 /* Write stencil values */ 701 if (zoom) { 702 _swrast_write_zoomed_stencil_span( ctx, width, destx, dy, 703 stencil, desty, 0 ); 704 } 705 else { 706 _swrast_write_stencil_span( ctx, width, destx, dy, stencil ); 707 } 708 } 709 710 if (overlapping) 711 FREE(tmpImage); 712} 713 714 715 716void 717_swrast_CopyPixels( GLcontext *ctx, 718 GLint srcx, GLint srcy, GLsizei width, GLsizei height, 719 GLint destx, GLint desty, 720 GLenum type ) 721{ 722 SWcontext *swrast = SWRAST_CONTEXT(ctx); 723 RENDER_START(swrast,ctx); 724 725 if (swrast->NewState) 726 _swrast_validate_derived( ctx ); 727 728 if (type == GL_COLOR && ctx->Visual.rgbMode) { 729 copy_rgba_pixels( ctx, srcx, srcy, width, height, destx, desty ); 730 } 731 else if (type == GL_COLOR && !ctx->Visual.rgbMode) { 732 copy_ci_pixels( ctx, srcx, srcy, width, height, destx, desty ); 733 } 734 else if (type == GL_DEPTH) { 735 copy_depth_pixels( ctx, srcx, srcy, width, height, destx, desty ); 736 } 737 else if (type == GL_STENCIL) { 738 copy_stencil_pixels( ctx, srcx, srcy, width, height, destx, desty ); 739 } 740 else { 741 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyPixels" ); 742 } 743 744 RENDER_FINISH(swrast,ctx); 745} 746