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