Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1901 serge 1
/*
2
 * Mesa 3-D graphics library
3
 * Version:  6.5
4
 *
5
 * Copyright (C) 1999-2006  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 "main/glheader.h"
27
#include "main/condrender.h"
28
#include "main/image.h"
29
#include "main/macros.h"
30
#include "s_context.h"
31
 
32
 
33
#define ABS(X)   ((X) < 0 ? -(X) : (X))
34
 
35
 
36
/**
37
 * Generate a row resampler function for GL_NEAREST mode.
38
 */
39
#define RESAMPLE(NAME, PIXELTYPE, SIZE)			\
40
static void						\
41
NAME(GLint srcWidth, GLint dstWidth,			\
42
     const GLvoid *srcBuffer, GLvoid *dstBuffer,	\
43
     GLboolean flip)					\
44
{							\
45
   const PIXELTYPE *src = (const PIXELTYPE *) srcBuffer;\
46
   PIXELTYPE *dst = (PIXELTYPE *) dstBuffer;		\
47
   GLint dstCol;					\
48
							\
49
   if (flip) {						\
50
      for (dstCol = 0; dstCol < dstWidth; dstCol++) {	\
51
         GLint srcCol = (dstCol * srcWidth) / dstWidth;	\
52
         ASSERT(srcCol >= 0);				\
53
         ASSERT(srcCol < srcWidth);			\
54
         srcCol = srcWidth - 1 - srcCol; /* flip */	\
55
         if (SIZE == 1) {				\
56
            dst[dstCol] = src[srcCol];			\
57
         }						\
58
         else if (SIZE == 2) {				\
59
            dst[dstCol*2+0] = src[srcCol*2+0];		\
60
            dst[dstCol*2+1] = src[srcCol*2+1];		\
61
         }						\
62
         else if (SIZE == 4) {				\
63
            dst[dstCol*4+0] = src[srcCol*4+0];		\
64
            dst[dstCol*4+1] = src[srcCol*4+1];		\
65
            dst[dstCol*4+2] = src[srcCol*4+2];		\
66
            dst[dstCol*4+3] = src[srcCol*4+3];		\
67
         }						\
68
      }							\
69
   }							\
70
   else {						\
71
      for (dstCol = 0; dstCol < dstWidth; dstCol++) {	\
72
         GLint srcCol = (dstCol * srcWidth) / dstWidth;	\
73
         ASSERT(srcCol >= 0);				\
74
         ASSERT(srcCol < srcWidth);			\
75
         if (SIZE == 1) {				\
76
            dst[dstCol] = src[srcCol];			\
77
         }						\
78
         else if (SIZE == 2) {				\
79
            dst[dstCol*2+0] = src[srcCol*2+0];		\
80
            dst[dstCol*2+1] = src[srcCol*2+1];		\
81
         }						\
82
         else if (SIZE == 4) {				\
83
            dst[dstCol*4+0] = src[srcCol*4+0];		\
84
            dst[dstCol*4+1] = src[srcCol*4+1];		\
85
            dst[dstCol*4+2] = src[srcCol*4+2];		\
86
            dst[dstCol*4+3] = src[srcCol*4+3];		\
87
         }						\
88
      }							\
89
   }							\
90
}
91
 
92
/**
93
 * Resamplers for 1, 2, 4, 8 and 16-byte pixels.
94
 */
95
RESAMPLE(resample_row_1, GLubyte, 1)
96
RESAMPLE(resample_row_2, GLushort, 1)
97
RESAMPLE(resample_row_4, GLuint, 1)
98
RESAMPLE(resample_row_8, GLuint, 2)
99
RESAMPLE(resample_row_16, GLuint, 4)
100
 
101
 
102
/**
103
 * Blit color, depth or stencil with GL_NEAREST filtering.
104
 */
105
static void
106
blit_nearest(struct gl_context *ctx,
107
             GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
108
             GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
109
             GLbitfield buffer)
110
{
111
   struct gl_renderbuffer *readRb, *drawRb;
112
 
113
   const GLint srcWidth = ABS(srcX1 - srcX0);
114
   const GLint dstWidth = ABS(dstX1 - dstX0);
115
   const GLint srcHeight = ABS(srcY1 - srcY0);
116
   const GLint dstHeight = ABS(dstY1 - dstY0);
117
 
118
   const GLint srcXpos = MIN2(srcX0, srcX1);
119
   const GLint srcYpos = MIN2(srcY0, srcY1);
120
   const GLint dstXpos = MIN2(dstX0, dstX1);
121
   const GLint dstYpos = MIN2(dstY0, dstY1);
122
 
123
   const GLboolean invertX = (srcX1 < srcX0) ^ (dstX1 < dstX0);
124
   const GLboolean invertY = (srcY1 < srcY0) ^ (dstY1 < dstY0);
125
 
126
   GLint dstRow;
127
 
128
   GLint comps, pixelSize;
129
   GLvoid *srcBuffer, *dstBuffer;
130
   GLint prevY = -1;
131
 
132
   typedef void (*resample_func)(GLint srcWidth, GLint dstWidth,
133
                                 const GLvoid *srcBuffer, GLvoid *dstBuffer,
134
                                 GLboolean flip);
135
   resample_func resampleRow;
136
 
137
   switch (buffer) {
138
   case GL_COLOR_BUFFER_BIT:
139
      readRb = ctx->ReadBuffer->_ColorReadBuffer;
140
      drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0];
141
      comps = 4;
142
      break;
143
   case GL_DEPTH_BUFFER_BIT:
144
      readRb = ctx->ReadBuffer->_DepthBuffer;
145
      drawRb = ctx->DrawBuffer->_DepthBuffer;
146
      comps = 1;
147
      break;
148
   case GL_STENCIL_BUFFER_BIT:
149
      readRb = ctx->ReadBuffer->_StencilBuffer;
150
      drawRb = ctx->DrawBuffer->_StencilBuffer;
151
      comps = 1;
152
      break;
153
   default:
154
      _mesa_problem(ctx, "unexpected buffer in blit_nearest()");
155
      return;
156
   }
157
 
158
   switch (readRb->DataType) {
159
   case GL_UNSIGNED_BYTE:
160
      pixelSize = comps * sizeof(GLubyte);
161
      break;
162
   case GL_UNSIGNED_SHORT:
163
      pixelSize = comps * sizeof(GLushort);
164
      break;
165
   case GL_UNSIGNED_INT:
166
      pixelSize = comps * sizeof(GLuint);
167
      break;
168
   case GL_FLOAT:
169
      pixelSize = comps * sizeof(GLfloat);
170
      break;
171
   default:
172
      _mesa_problem(ctx, "unexpected buffer type (0x%x) in blit_nearest",
173
                    readRb->DataType);
174
      return;
175
   }
176
 
177
   /* choose row resampler */
178
   switch (pixelSize) {
179
   case 1:
180
      resampleRow = resample_row_1;
181
      break;
182
   case 2:
183
      resampleRow = resample_row_2;
184
      break;
185
   case 4:
186
      resampleRow = resample_row_4;
187
      break;
188
   case 8:
189
      resampleRow = resample_row_8;
190
      break;
191
   case 16:
192
      resampleRow = resample_row_16;
193
      break;
194
   default:
195
      _mesa_problem(ctx, "unexpected pixel size (%d) in blit_nearest",
196
                    pixelSize);
197
      return;
198
   }
199
 
200
   /* allocate the src/dst row buffers */
201
   srcBuffer = malloc(pixelSize * srcWidth);
202
   if (!srcBuffer) {
203
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
204
      return;
205
   }
206
   dstBuffer = malloc(pixelSize * dstWidth);
207
   if (!dstBuffer) {
208
      free(srcBuffer);
209
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
210
      return;
211
   }
212
 
213
   for (dstRow = 0; dstRow < dstHeight; dstRow++) {
214
      const GLint dstY = dstYpos + dstRow;
215
      GLint srcRow = (dstRow * srcHeight) / dstHeight;
216
      GLint srcY;
217
 
218
      ASSERT(srcRow >= 0);
219
      ASSERT(srcRow < srcHeight);
220
 
221
      if (invertY) {
222
         srcRow = srcHeight - 1 - srcRow;
223
      }
224
 
225
      srcY = srcYpos + srcRow;
226
 
227
      /* get pixel row from source and resample to match dest width */
228
      if (prevY != srcY) {
229
         readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY, srcBuffer);
230
         (*resampleRow)(srcWidth, dstWidth, srcBuffer, dstBuffer, invertX);
231
         prevY = srcY;
232
      }
233
 
234
      /* store pixel row in destination */
235
      drawRb->PutRow(ctx, drawRb, dstWidth, dstXpos, dstY, dstBuffer, NULL);
236
   }
237
 
238
   free(srcBuffer);
239
   free(dstBuffer);
240
}
241
 
242
 
243
 
244
#define LERP(T, A, B)  ( (A) + (T) * ((B) - (A)) )
245
 
246
static INLINE GLfloat
247
lerp_2d(GLfloat a, GLfloat b,
248
        GLfloat v00, GLfloat v10, GLfloat v01, GLfloat v11)
249
{
250
   const GLfloat temp0 = LERP(a, v00, v10);
251
   const GLfloat temp1 = LERP(a, v01, v11);
252
   return LERP(b, temp0, temp1);
253
}
254
 
255
 
256
/**
257
 * Bilinear interpolation of two source rows.
258
 * GLubyte pixels.
259
 */
260
static void
261
resample_linear_row_ub(GLint srcWidth, GLint dstWidth,
262
                       const GLvoid *srcBuffer0, const GLvoid *srcBuffer1,
263
                       GLvoid *dstBuffer, GLboolean flip, GLfloat rowWeight)
264
{
265
   const GLubyte (*srcColor0)[4] = (const GLubyte (*)[4]) srcBuffer0;
266
   const GLubyte (*srcColor1)[4] = (const GLubyte (*)[4]) srcBuffer1;
267
   GLubyte (*dstColor)[4] = (GLubyte (*)[4]) dstBuffer;
268
   const GLfloat dstWidthF = (GLfloat) dstWidth;
269
   GLint dstCol;
270
 
271
   for (dstCol = 0; dstCol < dstWidth; dstCol++) {
272
      const GLfloat srcCol = (dstCol * srcWidth) / dstWidthF;
273
      GLint srcCol0 = IFLOOR(srcCol);
274
      GLint srcCol1 = srcCol0 + 1;
275
      GLfloat colWeight = srcCol - srcCol0; /* fractional part of srcCol */
276
      GLfloat red, green, blue, alpha;
277
 
278
      ASSERT(srcCol0 >= 0);
279
      ASSERT(srcCol0 < srcWidth);
280
      ASSERT(srcCol1 <= srcWidth);
281
 
282
      if (srcCol1 == srcWidth) {
283
         /* last column fudge */
284
         srcCol1--;
285
         colWeight = 0.0;
286
      }
287
 
288
      if (flip) {
289
         srcCol0 = srcWidth - 1 - srcCol0;
290
         srcCol1 = srcWidth - 1 - srcCol1;
291
      }
292
 
293
      red = lerp_2d(colWeight, rowWeight,
294
                    srcColor0[srcCol0][RCOMP], srcColor0[srcCol1][RCOMP],
295
                    srcColor1[srcCol0][RCOMP], srcColor1[srcCol1][RCOMP]);
296
      green = lerp_2d(colWeight, rowWeight,
297
                    srcColor0[srcCol0][GCOMP], srcColor0[srcCol1][GCOMP],
298
                    srcColor1[srcCol0][GCOMP], srcColor1[srcCol1][GCOMP]);
299
      blue = lerp_2d(colWeight, rowWeight,
300
                    srcColor0[srcCol0][BCOMP], srcColor0[srcCol1][BCOMP],
301
                    srcColor1[srcCol0][BCOMP], srcColor1[srcCol1][BCOMP]);
302
      alpha = lerp_2d(colWeight, rowWeight,
303
                    srcColor0[srcCol0][ACOMP], srcColor0[srcCol1][ACOMP],
304
                    srcColor1[srcCol0][ACOMP], srcColor1[srcCol1][ACOMP]);
305
 
306
      dstColor[dstCol][RCOMP] = IFLOOR(red);
307
      dstColor[dstCol][GCOMP] = IFLOOR(green);
308
      dstColor[dstCol][BCOMP] = IFLOOR(blue);
309
      dstColor[dstCol][ACOMP] = IFLOOR(alpha);
310
   }
311
}
312
 
313
 
314
 
315
/**
316
 * Bilinear filtered blit (color only).
317
 */
318
static void
319
blit_linear(struct gl_context *ctx,
320
            GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
321
            GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1)
322
{
323
   struct gl_renderbuffer *readRb = ctx->ReadBuffer->_ColorReadBuffer;
324
   struct gl_renderbuffer *drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0];
325
 
326
   const GLint srcWidth = ABS(srcX1 - srcX0);
327
   const GLint dstWidth = ABS(dstX1 - dstX0);
328
   const GLint srcHeight = ABS(srcY1 - srcY0);
329
   const GLint dstHeight = ABS(dstY1 - dstY0);
330
   const GLfloat dstHeightF = (GLfloat) dstHeight;
331
 
332
   const GLint srcXpos = MIN2(srcX0, srcX1);
333
   const GLint srcYpos = MIN2(srcY0, srcY1);
334
   const GLint dstXpos = MIN2(dstX0, dstX1);
335
   const GLint dstYpos = MIN2(dstY0, dstY1);
336
 
337
   const GLboolean invertX = (srcX1 < srcX0) ^ (dstX1 < dstX0);
338
   const GLboolean invertY = (srcY1 < srcY0) ^ (dstY1 < dstY0);
339
 
340
   GLint dstRow;
341
 
342
   GLint pixelSize;
343
   GLvoid *srcBuffer0, *srcBuffer1;
344
   GLint srcBufferY0 = -1, srcBufferY1 = -1;
345
   GLvoid *dstBuffer;
346
 
347
   switch (readRb->DataType) {
348
   case GL_UNSIGNED_BYTE:
349
      pixelSize = 4 * sizeof(GLubyte);
350
      break;
351
   case GL_UNSIGNED_SHORT:
352
      pixelSize = 4 * sizeof(GLushort);
353
      break;
354
   case GL_UNSIGNED_INT:
355
      pixelSize = 4 * sizeof(GLuint);
356
      break;
357
   case GL_FLOAT:
358
      pixelSize = 4 * sizeof(GLfloat);
359
      break;
360
   default:
361
      _mesa_problem(ctx, "unexpected buffer type (0x%x) in blit_nearest",
362
                    readRb->DataType);
363
      return;
364
   }
365
 
366
   /* Allocate the src/dst row buffers.
367
    * Keep two adjacent src rows around for bilinear sampling.
368
    */
369
   srcBuffer0 = malloc(pixelSize * srcWidth);
370
   if (!srcBuffer0) {
371
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
372
      return;
373
   }
374
   srcBuffer1 = malloc(pixelSize * srcWidth);
375
   if (!srcBuffer1) {
376
      free(srcBuffer0);
377
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
378
      return;
379
   }
380
   dstBuffer = malloc(pixelSize * dstWidth);
381
   if (!dstBuffer) {
382
      free(srcBuffer0);
383
      free(srcBuffer1);
384
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
385
      return;
386
   }
387
 
388
   for (dstRow = 0; dstRow < dstHeight; dstRow++) {
389
      const GLint dstY = dstYpos + dstRow;
390
      const GLfloat srcRow = (dstRow * srcHeight) / dstHeightF;
391
      GLint srcRow0 = IFLOOR(srcRow);
392
      GLint srcRow1 = srcRow0 + 1;
393
      GLfloat rowWeight = srcRow - srcRow0; /* fractional part of srcRow */
394
 
395
      ASSERT(srcRow >= 0);
396
      ASSERT(srcRow < srcHeight);
397
 
398
      if (srcRow1 == srcHeight) {
399
         /* last row fudge */
400
         srcRow1 = srcRow0;
401
         rowWeight = 0.0;
402
      }
403
 
404
      if (invertY) {
405
         srcRow0 = srcHeight - 1 - srcRow0;
406
         srcRow1 = srcHeight - 1 - srcRow1;
407
      }
408
 
409
      srcY0 = srcYpos + srcRow0;
410
      srcY1 = srcYpos + srcRow1;
411
 
412
      /* get the two source rows */
413
      if (srcY0 == srcBufferY0 && srcY1 == srcBufferY1) {
414
         /* use same source row buffers again */
415
      }
416
      else if (srcY0 == srcBufferY1) {
417
         /* move buffer1 into buffer0 by swapping pointers */
418
         GLvoid *tmp = srcBuffer0;
419
         srcBuffer0 = srcBuffer1;
420
         srcBuffer1 = tmp;
421
         /* get y1 row */
422
         readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY1, srcBuffer1);
423
         srcBufferY0 = srcY0;
424
         srcBufferY1 = srcY1;
425
      }
426
      else {
427
         /* get both new rows */
428
         readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY0, srcBuffer0);
429
         readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY1, srcBuffer1);
430
         srcBufferY0 = srcY0;
431
         srcBufferY1 = srcY1;
432
      }
433
 
434
      if (readRb->DataType == GL_UNSIGNED_BYTE) {
435
         resample_linear_row_ub(srcWidth, dstWidth, srcBuffer0, srcBuffer1,
436
                                dstBuffer, invertX, rowWeight);
437
      }
438
      else {
439
         _mesa_problem(ctx, "Unsupported color channel type in sw blit");
440
         break;
441
      }
442
 
443
      /* store pixel row in destination */
444
      drawRb->PutRow(ctx, drawRb, dstWidth, dstXpos, dstY, dstBuffer, NULL);
445
   }
446
 
447
   free(srcBuffer0);
448
   free(srcBuffer1);
449
   free(dstBuffer);
450
}
451
 
452
 
453
/**
454
 * Simple case:  Blit color, depth or stencil with no scaling or flipping.
455
 * XXX we could easily support vertical flipping here.
456
 */
457
static void
458
simple_blit(struct gl_context *ctx,
459
            GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
460
            GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
461
            GLbitfield buffer)
462
{
463
   struct gl_renderbuffer *readRb, *drawRb;
464
   const GLint width = srcX1 - srcX0;
465
   const GLint height = srcY1 - srcY0;
466
   GLint row, srcY, dstY, yStep;
467
   GLint comps, bytesPerRow;
468
   void *rowBuffer;
469
 
470
   /* only one buffer */
471
   ASSERT(_mesa_bitcount(buffer) == 1);
472
   /* no flipping checks */
473
   ASSERT(srcX0 < srcX1);
474
   ASSERT(srcY0 < srcY1);
475
   ASSERT(dstX0 < dstX1);
476
   ASSERT(dstY0 < dstY1);
477
   /* size checks */
478
   ASSERT(srcX1 - srcX0 == dstX1 - dstX0);
479
   ASSERT(srcY1 - srcY0 == dstY1 - dstY0);
480
 
481
   /* determine if copy should be bottom-to-top or top-to-bottom */
482
   if (srcY0 > dstY0) {
483
      /* src above dst: copy bottom-to-top */
484
      yStep = 1;
485
      srcY = srcY0;
486
      dstY = dstY0;
487
   }
488
   else {
489
      /* src below dst: copy top-to-bottom */
490
      yStep = -1;
491
      srcY = srcY1 - 1;
492
      dstY = dstY1 - 1;
493
   }
494
 
495
   switch (buffer) {
496
   case GL_COLOR_BUFFER_BIT:
497
      readRb = ctx->ReadBuffer->_ColorReadBuffer;
498
      drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0];
499
      comps = 4;
500
      break;
501
   case GL_DEPTH_BUFFER_BIT:
502
      readRb = ctx->ReadBuffer->_DepthBuffer;
503
      drawRb = ctx->DrawBuffer->_DepthBuffer;
504
      comps = 1;
505
      break;
506
   case GL_STENCIL_BUFFER_BIT:
507
      readRb = ctx->ReadBuffer->_StencilBuffer;
508
      drawRb = ctx->DrawBuffer->_StencilBuffer;
509
      comps = 1;
510
      break;
511
   default:
512
      _mesa_problem(ctx, "unexpected buffer in simple_blit()");
513
      return;
514
   }
515
 
516
   ASSERT(readRb->DataType == drawRb->DataType);
517
 
518
   /* compute bytes per row */
519
   switch (readRb->DataType) {
520
   case GL_UNSIGNED_BYTE:
521
      bytesPerRow = comps * width * sizeof(GLubyte);
522
      break;
523
   case GL_UNSIGNED_SHORT:
524
      bytesPerRow = comps * width * sizeof(GLushort);
525
      break;
526
   case GL_UNSIGNED_INT:
527
      bytesPerRow = comps * width * sizeof(GLuint);
528
      break;
529
   case GL_FLOAT:
530
      bytesPerRow = comps * width * sizeof(GLfloat);
531
      break;
532
   default:
533
      _mesa_problem(ctx, "unexpected buffer type in simple_blit");
534
      return;
535
   }
536
 
537
   /* allocate the row buffer */
538
   rowBuffer = malloc(bytesPerRow);
539
   if (!rowBuffer) {
540
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
541
      return;
542
   }
543
 
544
   for (row = 0; row < height; row++) {
545
      readRb->GetRow(ctx, readRb, width, srcX0, srcY, rowBuffer);
546
      drawRb->PutRow(ctx, drawRb, width, dstX0, dstY, rowBuffer, NULL);
547
      srcY += yStep;
548
      dstY += yStep;
549
   }
550
 
551
   free(rowBuffer);
552
}
553
 
554
 
555
/**
556
 * Software fallback for glBlitFramebufferEXT().
557
 */
558
void
559
_swrast_BlitFramebuffer(struct gl_context *ctx,
560
                        GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
561
                        GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
562
                        GLbitfield mask, GLenum filter)
563
{
564
   static const GLbitfield buffers[3] = {
565
      GL_COLOR_BUFFER_BIT,
566
      GL_DEPTH_BUFFER_BIT,
567
      GL_STENCIL_BUFFER_BIT
568
   };
569
   GLint i;
570
 
571
   if (!_mesa_check_conditional_render(ctx))
572
      return; /* don't clear */
573
 
574
   if (!ctx->DrawBuffer->_NumColorDrawBuffers)
575
      return;
576
 
577
   if (!_mesa_clip_blit(ctx, &srcX0, &srcY0, &srcX1, &srcY1,
578
                        &dstX0, &dstY0, &dstX1, &dstY1)) {
579
      return;
580
   }
581
 
582
   swrast_render_start(ctx);
583
 
584
   if (srcX1 - srcX0 == dstX1 - dstX0 &&
585
       srcY1 - srcY0 == dstY1 - dstY0 &&
586
       srcX0 < srcX1 &&
587
       srcY0 < srcY1 &&
588
       dstX0 < dstX1 &&
589
       dstY0 < dstY1) {
590
      /* no stretching or flipping.
591
       * filter doesn't matter.
592
       */
593
      for (i = 0; i < 3; i++) {
594
         if (mask & buffers[i]) {
595
            simple_blit(ctx, srcX0, srcY0, srcX1, srcY1,
596
                        dstX0, dstY0, dstX1, dstY1, buffers[i]);
597
         }
598
      }
599
   }
600
   else {
601
      if (filter == GL_NEAREST) {
602
         for (i = 0; i < 3; i++) {
603
            if (mask & buffers[i]) {
604
               blit_nearest(ctx,  srcX0, srcY0, srcX1, srcY1,
605
                            dstX0, dstY0, dstX1, dstY1, buffers[i]);
606
            }
607
         }
608
      }
609
      else {
610
         ASSERT(filter == GL_LINEAR);
611
         if (mask & GL_COLOR_BUFFER_BIT) {  /* depth/stencil not allowed */
612
            blit_linear(ctx,  srcX0, srcY0, srcX1, srcY1,
613
                        dstX0, dstY0, dstX1, dstY1);
614
         }
615
      }
616
   }
617
 
618
   swrast_render_finish(ctx);
619
}