swrast: add check for conditional rendering
[mesa.git] / src / mesa / swrast / s_blit.c
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(GLcontext *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 = _mesa_malloc(pixelSize * srcWidth);
202 if (!srcBuffer) {
203 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
204 return;
205 }
206 dstBuffer = _mesa_malloc(pixelSize * dstWidth);
207 if (!dstBuffer) {
208 _mesa_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 _mesa_free(srcBuffer);
239 _mesa_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(GLcontext *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 = _mesa_malloc(pixelSize * srcWidth);
370 if (!srcBuffer0) {
371 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
372 return;
373 }
374 srcBuffer1 = _mesa_malloc(pixelSize * srcWidth);
375 if (!srcBuffer1) {
376 _mesa_free(srcBuffer0);
377 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
378 return;
379 }
380 dstBuffer = _mesa_malloc(pixelSize * dstWidth);
381 if (!dstBuffer) {
382 _mesa_free(srcBuffer0);
383 _mesa_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 _mesa_free(srcBuffer0);
448 _mesa_free(srcBuffer1);
449 _mesa_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(GLcontext *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 = _mesa_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 _mesa_free(rowBuffer);
552 }
553
554
555 /**
556 * Software fallback for glBlitFramebufferEXT().
557 */
558 void
559 _swrast_BlitFramebuffer(GLcontext *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 }