fixup vertex building code ..
[mesa.git] / src / mesa / swrast / s_copypix.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 5.1
4 *
5 * Copyright (C) 1999-2003 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 "convolve.h"
29 #include "histogram.h"
30 #include "macros.h"
31 #include "imports.h"
32 #include "pixel.h"
33
34 #include "s_context.h"
35 #include "s_depth.h"
36 #include "s_pixeltex.h"
37 #include "s_span.h"
38 #include "s_stencil.h"
39 #include "s_texture.h"
40 #include "s_zoom.h"
41
42
43
44 /*
45 * Determine if there's overlap in an image copy.
46 * This test also compensates for the fact that copies are done from
47 * bottom to top and overlaps can sometimes be handled correctly
48 * without making a temporary image copy.
49 */
50 static GLboolean
51 regions_overlap(GLint srcx, GLint srcy,
52 GLint dstx, GLint dsty,
53 GLint width, GLint height,
54 GLfloat zoomX, GLfloat zoomY)
55 {
56 if (zoomX == 1.0 && zoomY == 1.0) {
57 /* no zoom */
58 if (srcx >= dstx + width || (srcx + width <= dstx)) {
59 return GL_FALSE;
60 }
61 else if (srcy < dsty) { /* this is OK */
62 return GL_FALSE;
63 }
64 else if (srcy > dsty + height) {
65 return GL_FALSE;
66 }
67 else {
68 return GL_TRUE;
69 }
70 }
71 else {
72 /* add one pixel of slop when zooming, just to be safe */
73 if ((srcx > dstx + (width * zoomX) + 1) || (srcx + width + 1 < dstx)) {
74 return GL_FALSE;
75 }
76 else if ((srcy < dsty) && (srcy + height < dsty + (height * zoomY))) {
77 return GL_FALSE;
78 }
79 else if ((srcy > dsty) && (srcy + height > dsty + (height * zoomY))) {
80 return GL_FALSE;
81 }
82 else {
83 return GL_TRUE;
84 }
85 }
86 }
87
88
89
90 /*
91 * RGBA copypixels with convolution.
92 */
93 static void
94 copy_conv_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
95 GLint width, GLint height, GLint destx, GLint desty)
96 {
97 SWcontext *swrast = SWRAST_CONTEXT(ctx);
98 GLboolean quick_draw;
99 GLint row;
100 GLboolean changeBuffer;
101 const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
102 const GLuint transferOps = ctx->_ImageTransferState;
103 GLfloat *dest, *tmpImage, *convImage;
104 struct sw_span span;
105
106 INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_RGBA);
107
108 if (ctx->Depth.Test)
109 _swrast_span_default_z(ctx, &span);
110 if (ctx->Fog.Enabled)
111 _swrast_span_default_fog(ctx, &span);
112
113
114 if (SWRAST_CONTEXT(ctx)->_RasterMask == 0
115 && !zoom
116 && destx >= 0
117 && destx + width <= (GLint) ctx->DrawBuffer->Width) {
118 quick_draw = GL_TRUE;
119 }
120 else {
121 quick_draw = GL_FALSE;
122 }
123
124 /* If read and draw buffer are different we must do buffer switching */
125 changeBuffer = ctx->Pixel.ReadBuffer != ctx->Color.DrawBuffer
126 || ctx->DrawBuffer != ctx->ReadBuffer;
127
128
129 /* allocate space for GLfloat image */
130 tmpImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
131 if (!tmpImage) {
132 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels");
133 return;
134 }
135 convImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
136 if (!convImage) {
137 FREE(tmpImage);
138 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels");
139 return;
140 }
141
142 dest = tmpImage;
143
144 if (changeBuffer) {
145 /* choose the read buffer */
146 _swrast_use_read_buffer(ctx);
147 }
148
149 /* read source image */
150 dest = tmpImage;
151 for (row = 0; row < height; row++) {
152 GLchan rgba[MAX_WIDTH][4];
153 GLint i;
154 _swrast_read_rgba_span(ctx, ctx->ReadBuffer, width, srcx, srcy + row, rgba);
155 /* convert GLchan to GLfloat */
156 for (i = 0; i < width; i++) {
157 *dest++ = (GLfloat) rgba[i][RCOMP] * (1.0F / CHAN_MAXF);
158 *dest++ = (GLfloat) rgba[i][GCOMP] * (1.0F / CHAN_MAXF);
159 *dest++ = (GLfloat) rgba[i][BCOMP] * (1.0F / CHAN_MAXF);
160 *dest++ = (GLfloat) rgba[i][ACOMP] * (1.0F / CHAN_MAXF);
161 }
162 }
163
164 if (changeBuffer) {
165 /* restore default src/dst buffer */
166 _swrast_use_draw_buffer(ctx);
167 }
168
169 /* do image transfer ops up until convolution */
170 for (row = 0; row < height; row++) {
171 GLfloat (*rgba)[4] = (GLfloat (*)[4]) (tmpImage + row * width * 4);
172
173 /* scale & bias */
174 if (transferOps & IMAGE_SCALE_BIAS_BIT) {
175 _mesa_scale_and_bias_rgba(ctx, width, rgba,
176 ctx->Pixel.RedScale, ctx->Pixel.GreenScale,
177 ctx->Pixel.BlueScale, ctx->Pixel.AlphaScale,
178 ctx->Pixel.RedBias, ctx->Pixel.GreenBias,
179 ctx->Pixel.BlueBias, ctx->Pixel.AlphaBias);
180 }
181 /* color map lookup */
182 if (transferOps & IMAGE_MAP_COLOR_BIT) {
183 _mesa_map_rgba(ctx, width, rgba);
184 }
185 /* GL_COLOR_TABLE lookup */
186 if (transferOps & IMAGE_COLOR_TABLE_BIT) {
187 _mesa_lookup_rgba(&ctx->ColorTable, width, rgba);
188 }
189 }
190
191 /* do convolution */
192 if (ctx->Pixel.Convolution2DEnabled) {
193 _mesa_convolve_2d_image(ctx, &width, &height, tmpImage, convImage);
194 }
195 else {
196 ASSERT(ctx->Pixel.Separable2DEnabled);
197 _mesa_convolve_sep_image(ctx, &width, &height, tmpImage, convImage);
198 }
199 FREE(tmpImage);
200
201 /* do remaining image transfer ops */
202 for (row = 0; row < height; row++) {
203 GLfloat (*rgba)[4] = (GLfloat (*)[4]) (convImage + row * width * 4);
204
205 /* GL_POST_CONVOLUTION_COLOR_TABLE lookup */
206 if (transferOps & IMAGE_POST_CONVOLUTION_COLOR_TABLE_BIT) {
207 _mesa_lookup_rgba(&ctx->PostConvolutionColorTable, width, rgba);
208 }
209 /* color matrix */
210 if (transferOps & IMAGE_COLOR_MATRIX_BIT) {
211 _mesa_transform_rgba(ctx, width, rgba);
212 }
213 /* GL_POST_COLOR_MATRIX_COLOR_TABLE lookup */
214 if (transferOps & IMAGE_POST_COLOR_MATRIX_COLOR_TABLE_BIT) {
215 _mesa_lookup_rgba(&ctx->PostColorMatrixColorTable, width, rgba);
216 }
217 /* update histogram count */
218 if (transferOps & IMAGE_HISTOGRAM_BIT) {
219 _mesa_update_histogram(ctx, width, (CONST GLfloat (*)[4]) rgba);
220 }
221 /* update min/max */
222 if (transferOps & IMAGE_MIN_MAX_BIT) {
223 _mesa_update_minmax(ctx, width, (CONST GLfloat (*)[4]) rgba);
224 }
225 }
226
227 for (row = 0; row < height; row++) {
228 const GLfloat *src = convImage + row * width * 4;
229 GLint i, dy;
230
231 /* clamp to [0,1] and convert float back to chan */
232 for (i = 0; i < width; i++) {
233 GLint r = (GLint) (src[i * 4 + RCOMP] * CHAN_MAXF);
234 GLint g = (GLint) (src[i * 4 + GCOMP] * CHAN_MAXF);
235 GLint b = (GLint) (src[i * 4 + BCOMP] * CHAN_MAXF);
236 GLint a = (GLint) (src[i * 4 + ACOMP] * CHAN_MAXF);
237 span.array->rgba[i][RCOMP] = (GLchan) CLAMP(r, 0, CHAN_MAX);
238 span.array->rgba[i][GCOMP] = (GLchan) CLAMP(g, 0, CHAN_MAX);
239 span.array->rgba[i][BCOMP] = (GLchan) CLAMP(b, 0, CHAN_MAX);
240 span.array->rgba[i][ACOMP] = (GLchan) CLAMP(a, 0, CHAN_MAX);
241 }
242
243 if (ctx->Pixel.PixelTextureEnabled && ctx->Texture._EnabledUnits) {
244 span.end = width;
245 _swrast_pixel_texture(ctx, &span);
246 }
247
248 /* write row to framebuffer */
249
250 dy = desty + row;
251 if (quick_draw && dy >= 0 && dy < (GLint) ctx->DrawBuffer->Height) {
252 (*swrast->Driver.WriteRGBASpan)( ctx, width, destx, dy,
253 (const GLchan (*)[4])span.array->rgba, NULL );
254 }
255 else if (zoom) {
256 span.x = destx;
257 span.y = dy;
258 span.end = width;
259 _swrast_write_zoomed_rgba_span(ctx, &span,
260 (CONST GLchan (*)[4])span.array->rgba,
261 desty, 0);
262 }
263 else {
264 span.x = destx;
265 span.y = dy;
266 span.end = width;
267 _swrast_write_rgba_span(ctx, &span);
268 }
269 }
270
271 FREE(convImage);
272 }
273
274
275 /*
276 * RGBA copypixels
277 */
278 static void
279 copy_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
280 GLint width, GLint height, GLint destx, GLint desty)
281 {
282 SWcontext *swrast = SWRAST_CONTEXT(ctx);
283 GLchan *tmpImage,*p;
284 GLboolean quick_draw;
285 GLint sy, dy, stepy, j;
286 GLboolean changeBuffer;
287 const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
288 GLint overlapping;
289 const GLuint transferOps = ctx->_ImageTransferState;
290 struct sw_span span;
291
292 INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_RGBA);
293
294 if (ctx->Pixel.Convolution2DEnabled || ctx->Pixel.Separable2DEnabled) {
295 copy_conv_rgba_pixels(ctx, srcx, srcy, width, height, destx, desty);
296 return;
297 }
298
299 /* Determine if copy should be done bottom-to-top or top-to-bottom */
300 if (srcy < desty) {
301 /* top-down max-to-min */
302 sy = srcy + height - 1;
303 dy = desty + height - 1;
304 stepy = -1;
305 }
306 else {
307 /* bottom-up min-to-max */
308 sy = srcy;
309 dy = desty;
310 stepy = 1;
311 }
312
313 if (ctx->DrawBuffer == ctx->ReadBuffer) {
314 overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
315 ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
316 }
317 else {
318 overlapping = GL_FALSE;
319 }
320
321 if (ctx->Depth.Test)
322 _swrast_span_default_z(ctx, &span);
323 if (ctx->Fog.Enabled)
324 _swrast_span_default_fog(ctx, &span);
325
326 if (SWRAST_CONTEXT(ctx)->_RasterMask == 0
327 && !zoom
328 && destx >= 0
329 && destx + width <= (GLint) ctx->DrawBuffer->Width) {
330 quick_draw = GL_TRUE;
331 }
332 else {
333 quick_draw = GL_FALSE;
334 }
335
336 /* If read and draw buffer are different we must do buffer switching */
337 changeBuffer = ctx->Pixel.ReadBuffer != ctx->Color.DrawBuffer
338 || ctx->DrawBuffer != ctx->ReadBuffer;
339
340 if (overlapping) {
341 GLint ssy = sy;
342 tmpImage = (GLchan *) MALLOC(width * height * sizeof(GLchan) * 4);
343 if (!tmpImage) {
344 _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" );
345 return;
346 }
347 /* setup source */
348 if (changeBuffer)
349 _swrast_use_read_buffer(ctx);
350 /* read the source image */
351 p = tmpImage;
352 for (j = 0; j < height; j++, ssy += stepy) {
353 _swrast_read_rgba_span( ctx, ctx->ReadBuffer, width, srcx, ssy,
354 (GLchan (*)[4]) p );
355 p += width * 4;
356 }
357 p = tmpImage;
358 /* restore dest */
359 if (changeBuffer) {
360 _swrast_use_draw_buffer(ctx);
361 changeBuffer = GL_FALSE;
362 }
363 }
364 else {
365 tmpImage = NULL; /* silence compiler warnings */
366 p = NULL;
367 }
368
369 for (j = 0; j < height; j++, sy += stepy, dy += stepy) {
370 /* Get source pixels */
371 if (overlapping) {
372 /* get from buffered image */
373 ASSERT(width < MAX_WIDTH);
374 MEMCPY(span.array->rgba, p, width * sizeof(GLchan) * 4);
375 p += width * 4;
376 }
377 else {
378 /* get from framebuffer */
379 if (changeBuffer)
380 _swrast_use_read_buffer(ctx);
381 ASSERT(width < MAX_WIDTH);
382 _swrast_read_rgba_span( ctx, ctx->ReadBuffer, width, srcx, sy,
383 span.array->rgba );
384 if (changeBuffer)
385 _swrast_use_draw_buffer(ctx);
386 }
387
388 if (transferOps) {
389 const GLfloat scale = (1.0F / CHAN_MAXF);
390 GLint k;
391 DEFMARRAY(GLfloat, rgbaFloat, MAX_WIDTH, 4); /* mac 32k limitation */
392 CHECKARRAY(rgbaFloat, return);
393
394 /* convert chan to float */
395 for (k = 0; k < width; k++) {
396 rgbaFloat[k][RCOMP] = (GLfloat) span.array->rgba[k][RCOMP] * scale;
397 rgbaFloat[k][GCOMP] = (GLfloat) span.array->rgba[k][GCOMP] * scale;
398 rgbaFloat[k][BCOMP] = (GLfloat) span.array->rgba[k][BCOMP] * scale;
399 rgbaFloat[k][ACOMP] = (GLfloat) span.array->rgba[k][ACOMP] * scale;
400 }
401 /* scale & bias */
402 if (transferOps & IMAGE_SCALE_BIAS_BIT) {
403 _mesa_scale_and_bias_rgba(ctx, width, rgbaFloat,
404 ctx->Pixel.RedScale, ctx->Pixel.GreenScale,
405 ctx->Pixel.BlueScale, ctx->Pixel.AlphaScale,
406 ctx->Pixel.RedBias, ctx->Pixel.GreenBias,
407 ctx->Pixel.BlueBias, ctx->Pixel.AlphaBias);
408 }
409 /* color map lookup */
410 if (transferOps & IMAGE_MAP_COLOR_BIT) {
411 _mesa_map_rgba(ctx, width, rgbaFloat);
412 }
413 /* GL_COLOR_TABLE lookup */
414 if (transferOps & IMAGE_COLOR_TABLE_BIT) {
415 _mesa_lookup_rgba(&ctx->ColorTable, width, rgbaFloat);
416 }
417 /* convolution */
418 if (transferOps & IMAGE_CONVOLUTION_BIT) {
419 _mesa_problem(ctx, "Convolution should not be enabled in copy_rgba_pixels()");
420 return;
421 }
422 /* GL_POST_CONVOLUTION_RED/GREEN/BLUE/ALPHA_SCALE/BIAS */
423 if (transferOps & IMAGE_POST_CONVOLUTION_SCALE_BIAS) {
424 _mesa_scale_and_bias_rgba(ctx, width, rgbaFloat,
425 ctx->Pixel.PostConvolutionScale[RCOMP],
426 ctx->Pixel.PostConvolutionScale[GCOMP],
427 ctx->Pixel.PostConvolutionScale[BCOMP],
428 ctx->Pixel.PostConvolutionScale[ACOMP],
429 ctx->Pixel.PostConvolutionBias[RCOMP],
430 ctx->Pixel.PostConvolutionBias[GCOMP],
431 ctx->Pixel.PostConvolutionBias[BCOMP],
432 ctx->Pixel.PostConvolutionBias[ACOMP]);
433 }
434 /* GL_POST_CONVOLUTION_COLOR_TABLE lookup */
435 if (transferOps & IMAGE_POST_CONVOLUTION_COLOR_TABLE_BIT) {
436 _mesa_lookup_rgba(&ctx->PostConvolutionColorTable, width, rgbaFloat);
437 }
438 /* color matrix */
439 if (transferOps & IMAGE_COLOR_MATRIX_BIT) {
440 _mesa_transform_rgba(ctx, width, rgbaFloat);
441 }
442 /* GL_POST_COLOR_MATRIX_COLOR_TABLE lookup */
443 if (transferOps & IMAGE_POST_COLOR_MATRIX_COLOR_TABLE_BIT) {
444 _mesa_lookup_rgba(&ctx->PostColorMatrixColorTable, width, rgbaFloat);
445 }
446 /* update histogram count */
447 if (transferOps & IMAGE_HISTOGRAM_BIT) {
448 _mesa_update_histogram(ctx, width, (CONST GLfloat (*)[4]) rgbaFloat);
449 }
450 /* update min/max */
451 if (transferOps & IMAGE_MIN_MAX_BIT) {
452 _mesa_update_minmax(ctx, width, (CONST GLfloat (*)[4]) rgbaFloat);
453 }
454 /* clamp to [0,1] and convert float back to chan */
455 for (k = 0; k < width; k++) {
456 GLint r = (GLint) (rgbaFloat[k][RCOMP] * CHAN_MAXF);
457 GLint g = (GLint) (rgbaFloat[k][GCOMP] * CHAN_MAXF);
458 GLint b = (GLint) (rgbaFloat[k][BCOMP] * CHAN_MAXF);
459 GLint a = (GLint) (rgbaFloat[k][ACOMP] * CHAN_MAXF);
460 span.array->rgba[k][RCOMP] = (GLchan) CLAMP(r, 0, CHAN_MAX);
461 span.array->rgba[k][GCOMP] = (GLchan) CLAMP(g, 0, CHAN_MAX);
462 span.array->rgba[k][BCOMP] = (GLchan) CLAMP(b, 0, CHAN_MAX);
463 span.array->rgba[k][ACOMP] = (GLchan) CLAMP(a, 0, CHAN_MAX);
464 }
465 UNDEFARRAY(rgbaFloat); /* mac 32k limitation */
466 }
467
468 if (ctx->Pixel.PixelTextureEnabled && ctx->Texture._EnabledUnits) {
469 span.end = width;
470 _swrast_pixel_texture(ctx, &span);
471 }
472
473 /* Write color span */
474 if (quick_draw && dy >= 0 && dy < (GLint) ctx->DrawBuffer->Height) {
475 (*swrast->Driver.WriteRGBASpan)( ctx, width, destx, dy,
476 (const GLchan (*)[4])span.array->rgba, NULL );
477 }
478 else if (zoom) {
479 span.x = destx;
480 span.y = dy;
481 span.end = width;
482 _swrast_write_zoomed_rgba_span(ctx, &span,
483 (CONST GLchan (*)[4]) span.array->rgba,
484 desty, 0);
485 }
486 else {
487 span.x = destx;
488 span.y = dy;
489 span.end = width;
490 _swrast_write_rgba_span(ctx, &span);
491 }
492 }
493
494 if (overlapping)
495 FREE(tmpImage);
496 }
497
498
499 static void
500 copy_ci_pixels( GLcontext *ctx, GLint srcx, GLint srcy,
501 GLint width, GLint height,
502 GLint destx, GLint desty )
503 {
504 GLuint *tmpImage,*p;
505 GLint sy, dy, stepy;
506 GLint j;
507 GLboolean changeBuffer;
508 const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
509 const GLboolean shift_or_offset = ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset;
510 GLint overlapping;
511 struct sw_span span;
512
513 INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_INDEX);
514
515 /* Determine if copy should be bottom-to-top or top-to-bottom */
516 if (srcy<desty) {
517 /* top-down max-to-min */
518 sy = srcy + height - 1;
519 dy = desty + height - 1;
520 stepy = -1;
521 }
522 else {
523 /* bottom-up min-to-max */
524 sy = srcy;
525 dy = desty;
526 stepy = 1;
527 }
528
529 if (ctx->DrawBuffer == ctx->ReadBuffer) {
530 overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
531 ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
532 }
533 else {
534 overlapping = GL_FALSE;
535 }
536
537 if (ctx->Depth.Test)
538 _swrast_span_default_z(ctx, &span);
539 if (ctx->Fog.Enabled)
540 _swrast_span_default_fog(ctx, &span);
541
542 /* If read and draw buffer are different we must do buffer switching */
543 changeBuffer = ctx->Pixel.ReadBuffer != ctx->Color.DrawBuffer
544 || ctx->DrawBuffer != ctx->ReadBuffer;
545
546 if (overlapping) {
547 GLint ssy = sy;
548 tmpImage = (GLuint *) MALLOC(width * height * sizeof(GLuint));
549 if (!tmpImage) {
550 _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" );
551 return;
552 }
553 /* setup source */
554 if (changeBuffer)
555 _swrast_use_read_buffer(ctx);
556 /* read the image */
557 p = tmpImage;
558 for (j = 0; j < height; j++, ssy += stepy) {
559 _swrast_read_index_span( ctx, ctx->ReadBuffer, width, srcx, ssy, p );
560 p += width;
561 }
562 p = tmpImage;
563 /* restore to draw buffer */
564 if (changeBuffer) {
565 _swrast_use_draw_buffer(ctx);
566 changeBuffer = GL_FALSE;
567 }
568 }
569 else {
570 tmpImage = NULL; /* silence compiler warning */
571 p = NULL;
572 }
573
574 for (j = 0; j < height; j++, sy += stepy, dy += stepy) {
575 /* Get color indexes */
576 if (overlapping) {
577 MEMCPY(span.array->index, p, width * sizeof(GLuint));
578 p += width;
579 }
580 else {
581 if (changeBuffer)
582 _swrast_use_read_buffer(ctx);
583 _swrast_read_index_span( ctx, ctx->ReadBuffer, width, srcx, sy,
584 span.array->index );
585 if (changeBuffer)
586 _swrast_use_draw_buffer(ctx);
587 }
588
589 /* Apply shift, offset, look-up table */
590 if (shift_or_offset) {
591 _mesa_shift_and_offset_ci( ctx, width, span.array->index );
592 }
593 if (ctx->Pixel.MapColorFlag) {
594 _mesa_map_ci( ctx, width, span.array->index );
595 }
596
597 /* write color indexes */
598 span.x = destx;
599 span.y = dy;
600 span.end = width;
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 if (overlapping)
608 FREE(tmpImage);
609 }
610
611
612
613 /*
614 * TODO: Optimize!!!!
615 */
616 static void
617 copy_depth_pixels( GLcontext *ctx, GLint srcx, GLint srcy,
618 GLint width, GLint height,
619 GLint destx, GLint desty )
620 {
621 GLfloat *p, *tmpImage;
622 GLint sy, dy, stepy;
623 GLint i, j;
624 const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
625 GLint overlapping;
626 struct sw_span span;
627
628 INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_Z);
629
630 if (!ctx->Visual.depthBits) {
631 _mesa_error( ctx, GL_INVALID_OPERATION, "glCopyPixels" );
632 return;
633 }
634
635 /* Determine if copy should be bottom-to-top or top-to-bottom */
636 if (srcy<desty) {
637 /* top-down max-to-min */
638 sy = srcy + height - 1;
639 dy = desty + height - 1;
640 stepy = -1;
641 }
642 else {
643 /* bottom-up min-to-max */
644 sy = srcy;
645 dy = desty;
646 stepy = 1;
647 }
648
649 if (ctx->DrawBuffer == ctx->ReadBuffer) {
650 overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
651 ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
652 }
653 else {
654 overlapping = GL_FALSE;
655 }
656
657 _swrast_span_default_color(ctx, &span);
658 if (ctx->Fog.Enabled)
659 _swrast_span_default_fog(ctx, &span);
660
661 if (overlapping) {
662 GLint ssy = sy;
663 tmpImage = (GLfloat *) MALLOC(width * height * sizeof(GLfloat));
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_depth_span_float(ctx, 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 GLfloat depth[MAX_WIDTH];
682
683 /* get depth values */
684 if (overlapping) {
685 MEMCPY(depth, p, width * sizeof(GLfloat));
686 p += width;
687 }
688 else {
689 _swrast_read_depth_span_float(ctx, width, srcx, sy, depth);
690 }
691
692 /* apply scale and bias */
693 for (i = 0; i < width; i++) {
694 GLfloat d = depth[i] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias;
695 span.array->z[i] = (GLdepth) (CLAMP(d, 0.0F, 1.0F) * ctx->DepthMax);
696 }
697
698 /* write depth values */
699 span.x = destx;
700 span.y = dy;
701 span.end = width;
702 if (ctx->Visual.rgbMode) {
703 if (zoom)
704 _swrast_write_zoomed_rgba_span( ctx, &span,
705 (const GLchan (*)[4])span.array->rgba, desty, 0 );
706 else
707 _swrast_write_rgba_span(ctx, &span);
708 }
709 else {
710 if (zoom)
711 _swrast_write_zoomed_index_span( ctx, &span, desty, 0 );
712 else
713 _swrast_write_index_span(ctx, &span);
714 }
715 }
716
717 if (overlapping)
718 FREE(tmpImage);
719 }
720
721
722
723 static void
724 copy_stencil_pixels( GLcontext *ctx, GLint srcx, GLint srcy,
725 GLint width, GLint height,
726 GLint destx, GLint desty )
727 {
728 GLint sy, dy, stepy;
729 GLint j;
730 GLstencil *p, *tmpImage;
731 const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
732 const GLboolean shift_or_offset = ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset;
733 GLint overlapping;
734
735 if (!ctx->Visual.stencilBits) {
736 _mesa_error( ctx, GL_INVALID_OPERATION, "glCopyPixels" );
737 return;
738 }
739
740 /* Determine if copy should be bottom-to-top or top-to-bottom */
741 if (srcy < desty) {
742 /* top-down max-to-min */
743 sy = srcy + height - 1;
744 dy = desty + height - 1;
745 stepy = -1;
746 }
747 else {
748 /* bottom-up min-to-max */
749 sy = srcy;
750 dy = desty;
751 stepy = 1;
752 }
753
754 if (ctx->DrawBuffer == ctx->ReadBuffer) {
755 overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
756 ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
757 }
758 else {
759 overlapping = GL_FALSE;
760 }
761
762 if (overlapping) {
763 GLint ssy = sy;
764 tmpImage = (GLstencil *) MALLOC(width * height * sizeof(GLstencil));
765 if (!tmpImage) {
766 _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" );
767 return;
768 }
769 p = tmpImage;
770 for (j = 0; j < height; j++, ssy += stepy) {
771 _swrast_read_stencil_span( ctx, width, srcx, ssy, p );
772 p += width;
773 }
774 p = tmpImage;
775 }
776 else {
777 tmpImage = NULL; /* silence compiler warning */
778 p = NULL;
779 }
780
781 for (j = 0; j < height; j++, sy += stepy, dy += stepy) {
782 GLstencil stencil[MAX_WIDTH];
783
784 /* Get stencil values */
785 if (overlapping) {
786 MEMCPY(stencil, p, width * sizeof(GLstencil));
787 p += width;
788 }
789 else {
790 _swrast_read_stencil_span( ctx, width, srcx, sy, stencil );
791 }
792
793 /* Apply shift, offset, look-up table */
794 if (shift_or_offset) {
795 _mesa_shift_and_offset_stencil( ctx, width, stencil );
796 }
797 if (ctx->Pixel.MapStencilFlag) {
798 _mesa_map_stencil( ctx, width, stencil );
799 }
800
801 /* Write stencil values */
802 if (zoom) {
803 _swrast_write_zoomed_stencil_span( ctx, width, destx, dy,
804 stencil, desty, 0 );
805 }
806 else {
807 _swrast_write_stencil_span( ctx, width, destx, dy, stencil );
808 }
809 }
810
811 if (overlapping)
812 FREE(tmpImage);
813 }
814
815
816
817 void
818 _swrast_CopyPixels( GLcontext *ctx,
819 GLint srcx, GLint srcy, GLsizei width, GLsizei height,
820 GLint destx, GLint desty,
821 GLenum type )
822 {
823 SWcontext *swrast = SWRAST_CONTEXT(ctx);
824 RENDER_START(swrast,ctx);
825
826 if (swrast->NewState)
827 _swrast_validate_derived( ctx );
828
829 if (type == GL_COLOR && ctx->Visual.rgbMode) {
830 copy_rgba_pixels( ctx, srcx, srcy, width, height, destx, desty );
831 }
832 else if (type == GL_COLOR && !ctx->Visual.rgbMode) {
833 copy_ci_pixels( ctx, srcx, srcy, width, height, destx, desty );
834 }
835 else if (type == GL_DEPTH) {
836 copy_depth_pixels( ctx, srcx, srcy, width, height, destx, desty );
837 }
838 else if (type == GL_STENCIL) {
839 copy_stencil_pixels( ctx, srcx, srcy, width, height, destx, desty );
840 }
841 else {
842 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyPixels" );
843 }
844
845 RENDER_FINISH(swrast,ctx);
846 }