Subversion Repositories shark

Rev

Rev 57 | Details | Compare with Previous | Last modification | View Log | RSS feed

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