Update includes post-splitting of s_texture.c
[mesa.git] / src / mesa / swrast / s_copypix.c
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 */
51 static GLboolean
52 regions_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 */
94 static void
95 float_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 */
111 static void
112 chan_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 */
128 static void
129 copy_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 */
252 static void
253 copy_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
392 static void
393 copy_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 */
498 static void
499 copy_depth_pixels( GLcontext *ctx, GLint srcx, GLint srcy,
500 GLint width, GLint height,
501 GLint destx, GLint desty )
502 {
503 const GLfloat depthMax = ctx->DrawBuffer->_DepthMaxF;
504 struct gl_renderbuffer *readRb
505 = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
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 (!ctx->Visual.depthBits) {
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 float sum = 0;
573 /* get depth values */
574 if (overlapping) {
575 MEMCPY(depth, p, width * sizeof(GLfloat));
576 p += width;
577 }
578 else {
579 _swrast_read_depth_span_float(ctx, readRb, width, srcx, sy, depth);
580 }
581
582 /* apply scale and bias */
583 for (i = 0; i < width; i++) {
584 GLfloat d = depth[i] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias;
585 sum += d;
586 span.array->z[i] = (GLdepth) (CLAMP(d, 0.0F, 1.0F) * depthMax);
587 }
588
589 /* write depth values */
590 span.x = destx;
591 span.y = dy;
592 span.end = width;
593 if (ctx->Visual.rgbMode) {
594 if (zoom)
595 _swrast_write_zoomed_rgba_span( ctx, &span,
596 (const GLchan (*)[4])span.array->rgba, desty, 0 );
597 else
598 _swrast_write_rgba_span(ctx, &span);
599 }
600 else {
601 if (zoom)
602 _swrast_write_zoomed_index_span( ctx, &span, desty, 0 );
603 else
604 _swrast_write_index_span(ctx, &span);
605 }
606 }
607
608 if (overlapping)
609 FREE(tmpImage);
610 }
611
612
613
614 static void
615 copy_stencil_pixels( GLcontext *ctx, GLint srcx, GLint srcy,
616 GLint width, GLint height,
617 GLint destx, GLint desty )
618 {
619 struct gl_renderbuffer *rb
620 = ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
621 GLint sy, dy, stepy;
622 GLint j;
623 GLstencil *p, *tmpImage;
624 const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
625 const GLboolean shift_or_offset = ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset;
626 GLint overlapping;
627
628 if (!ctx->Visual.stencilBits) {
629 _mesa_error( ctx, GL_INVALID_OPERATION, "glCopyPixels" );
630 return;
631 }
632
633 if (!rb) {
634 /* no readbuffer - OK */
635 return;
636 }
637
638 /* Determine if copy should be bottom-to-top or top-to-bottom */
639 if (srcy < desty) {
640 /* top-down max-to-min */
641 sy = srcy + height - 1;
642 dy = desty + height - 1;
643 stepy = -1;
644 }
645 else {
646 /* bottom-up min-to-max */
647 sy = srcy;
648 dy = desty;
649 stepy = 1;
650 }
651
652 if (ctx->DrawBuffer == ctx->ReadBuffer) {
653 overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
654 ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
655 }
656 else {
657 overlapping = GL_FALSE;
658 }
659
660 if (overlapping) {
661 GLint ssy = sy;
662 tmpImage = (GLstencil *) MALLOC(width * height * sizeof(GLstencil));
663 if (!tmpImage) {
664 _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" );
665 return;
666 }
667 p = tmpImage;
668 for (j = 0; j < height; j++, ssy += stepy) {
669 _swrast_read_stencil_span( ctx, rb, width, srcx, ssy, p );
670 p += width;
671 }
672 p = tmpImage;
673 }
674 else {
675 tmpImage = NULL; /* silence compiler warning */
676 p = NULL;
677 }
678
679 for (j = 0; j < height; j++, sy += stepy, dy += stepy) {
680 GLstencil stencil[MAX_WIDTH];
681
682 /* Get stencil values */
683 if (overlapping) {
684 MEMCPY(stencil, p, width * sizeof(GLstencil));
685 p += width;
686 }
687 else {
688 _swrast_read_stencil_span( ctx, rb, width, srcx, sy, stencil );
689 }
690
691 /* Apply shift, offset, look-up table */
692 if (shift_or_offset) {
693 _mesa_shift_and_offset_stencil( ctx, width, stencil );
694 }
695 if (ctx->Pixel.MapStencilFlag) {
696 _mesa_map_stencil( ctx, width, stencil );
697 }
698
699 /* Write stencil values */
700 if (zoom) {
701 _swrast_write_zoomed_stencil_span( ctx, width, destx, dy,
702 stencil, desty, 0 );
703 }
704 else {
705 _swrast_write_stencil_span( ctx, width, destx, dy, stencil );
706 }
707 }
708
709 if (overlapping)
710 FREE(tmpImage);
711 }
712
713
714
715 void
716 _swrast_CopyPixels( GLcontext *ctx,
717 GLint srcx, GLint srcy, GLsizei width, GLsizei height,
718 GLint destx, GLint desty,
719 GLenum type )
720 {
721 SWcontext *swrast = SWRAST_CONTEXT(ctx);
722 RENDER_START(swrast,ctx);
723
724 if (swrast->NewState)
725 _swrast_validate_derived( ctx );
726
727 if (type == GL_COLOR && ctx->Visual.rgbMode) {
728 copy_rgba_pixels( ctx, srcx, srcy, width, height, destx, desty );
729 }
730 else if (type == GL_COLOR && !ctx->Visual.rgbMode) {
731 copy_ci_pixels( ctx, srcx, srcy, width, height, destx, desty );
732 }
733 else if (type == GL_DEPTH) {
734 copy_depth_pixels( ctx, srcx, srcy, width, height, destx, desty );
735 }
736 else if (type == GL_STENCIL) {
737 copy_stencil_pixels( ctx, srcx, srcy, width, height, destx, desty );
738 }
739 else {
740 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyPixels" );
741 }
742
743 RENDER_FINISH(swrast,ctx);
744 }