radeonsi: stop using TGSI_PROPERTY_FS_DEPTH_LAYOUT
[mesa.git] / src / mesa / swrast / s_blit.c
index 3a4e7eec001001dc1e5b408dca35f4ddf0bc3868..6b7e5e4533381a077be10248ee7917716460a77e 100644 (file)
@@ -1,6 +1,5 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.5
  *
  * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
  *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
  */
 
 
@@ -29,6 +29,7 @@
 #include "main/macros.h"
 #include "main/format_unpack.h"
 #include "main/format_pack.h"
+#include "main/condrender.h"
 #include "s_context.h"
 
 
@@ -51,8 +52,8 @@ NAME(GLint srcWidth, GLint dstWidth,                  \
    if (flip) {                                         \
       for (dstCol = 0; dstCol < dstWidth; dstCol++) {  \
          GLint srcCol = (dstCol * srcWidth) / dstWidth;        \
-         ASSERT(srcCol >= 0);                          \
-         ASSERT(srcCol < srcWidth);                    \
+         assert(srcCol >= 0);                          \
+         assert(srcCol < srcWidth);                    \
          srcCol = srcWidth - 1 - srcCol; /* flip */    \
          if (SIZE == 1) {                              \
             dst[dstCol] = src[srcCol];                 \
@@ -72,8 +73,8 @@ NAME(GLint srcWidth, GLint dstWidth,                  \
    else {                                              \
       for (dstCol = 0; dstCol < dstWidth; dstCol++) {  \
          GLint srcCol = (dstCol * srcWidth) / dstWidth;        \
-         ASSERT(srcCol >= 0);                          \
-         ASSERT(srcCol < srcWidth);                    \
+         assert(srcCol >= 0);                          \
+         assert(srcCol < srcWidth);                    \
          if (SIZE == 1) {                              \
             dst[dstCol] = src[srcCol];                 \
          }                                             \
@@ -106,14 +107,14 @@ RESAMPLE(resample_row_16, GLuint, 4)
  */
 static void
 blit_nearest(struct gl_context *ctx,
+             struct gl_framebuffer *readFb,
+             struct gl_framebuffer *drawFb,
              GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
              GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
              GLbitfield buffer)
 {
-   struct gl_renderbuffer *readRb, *drawRb;
-   struct gl_renderbuffer_attachment *readAtt, *drawAtt;
-   struct gl_framebuffer *readFb = ctx->ReadBuffer;
-   struct gl_framebuffer *drawFb = ctx->DrawBuffer;
+   struct gl_renderbuffer *readRb, *drawRb = NULL;
+   struct gl_renderbuffer_attachment *readAtt = NULL, *drawAtt = NULL;
    GLuint numDrawBuffers = 0;
    GLuint i;
 
@@ -135,12 +136,12 @@ blit_nearest(struct gl_context *ctx,
       UNPACK_Z_FLOAT,
       UNPACK_Z_INT,
       UNPACK_S,
-   } mode;
+   } mode = DIRECT;
    GLubyte *srcMap, *dstMap;
    GLint srcRowStride, dstRowStride;
    GLint dstRow;
 
-   GLint pixelSize;
+   GLint pixelSize = 0;
    GLvoid *srcBuffer, *dstBuffer;
    GLint prevY = -1;
 
@@ -166,8 +167,8 @@ blit_nearest(struct gl_context *ctx,
        * using the core helpers for pack/unpack, we avoid needing to handle
        * masking for things like DEPTH copies of Z24S8.
        */
-      if (readRb->Format == MESA_FORMAT_Z32_FLOAT ||
-         readRb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) {
+      if (readRb->Format == MESA_FORMAT_Z_FLOAT32 ||
+         readRb->Format == MESA_FORMAT_Z32_FLOAT_S8X24_UINT) {
         mode = UNPACK_Z_FLOAT;
       } else {
         mode = UNPACK_Z_INT;
@@ -188,34 +189,17 @@ blit_nearest(struct gl_context *ctx,
       return;
    }
 
-   /* choose row resampler */
-   switch (pixelSize) {
-   case 1:
-      resampleRow = resample_row_1;
-      break;
-   case 2:
-      resampleRow = resample_row_2;
-      break;
-   case 4:
-      resampleRow = resample_row_4;
-      break;
-   case 8:
-      resampleRow = resample_row_8;
-      break;
-   case 16:
-      resampleRow = resample_row_16;
-      break;
-   default:
-      _mesa_problem(ctx, "unexpected pixel size (%d) in blit_nearest",
-                    pixelSize);
-      return;
-   }
+   /* allocate the src/dst row buffers */
+   srcBuffer = malloc(MAX_PIXEL_BYTES * srcWidth);
+   dstBuffer = malloc(MAX_PIXEL_BYTES * dstWidth);
+   if (!srcBuffer || !dstBuffer)
+      goto fail_no_memory;
 
    /* Blit to all the draw buffers */
    for (i = 0; i < numDrawBuffers; i++) {
       if (buffer == GL_COLOR_BUFFER_BIT) {
-         int idx = drawFb->_ColorDrawBufferIndexes[i];
-         if (idx == -1)
+         gl_buffer_index idx = drawFb->_ColorDrawBufferIndexes[i];
+         if (idx == BUFFER_NONE)
             continue;
          drawAtt = &drawFb->Attachment[idx];
          drawRb = drawAtt->Renderbuffer;
@@ -232,6 +216,29 @@ blit_nearest(struct gl_context *ctx,
          }
       }
 
+      /* choose row resampler */
+      switch (pixelSize) {
+      case 1:
+         resampleRow = resample_row_1;
+         break;
+      case 2:
+         resampleRow = resample_row_2;
+         break;
+      case 4:
+         resampleRow = resample_row_4;
+         break;
+      case 8:
+         resampleRow = resample_row_8;
+         break;
+      case 16:
+         resampleRow = resample_row_16;
+         break;
+      default:
+         _mesa_problem(ctx, "unexpected pixel size (%d) in blit_nearest",
+                       pixelSize);
+         goto fail;
+      }
+
       if ((readRb == drawRb) ||
           (readAtt->Texture && drawAtt->Texture &&
            (readAtt->Texture == drawAtt->Texture))) {
@@ -246,10 +253,9 @@ blit_nearest(struct gl_context *ctx,
          ctx->Driver.MapRenderbuffer(ctx, readRb, 0, 0,
                                      readRb->Width, readRb->Height,
                                      GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
-                                     &map, &rowStride);
+                                     &map, &rowStride, readFb->FlipY);
          if (!map) {
-            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer");
-            return;
+            goto fail_no_memory;
          }
 
          srcMap = map + srcYpos * rowStride + srcXpos * formatSize;
@@ -274,41 +280,29 @@ blit_nearest(struct gl_context *ctx,
          ctx->Driver.MapRenderbuffer(ctx, readRb,
                                      srcXpos, srcYpos,
                                      srcWidth, srcHeight,
-                                     GL_MAP_READ_BIT, &srcMap, &srcRowStride);
+                                     GL_MAP_READ_BIT, &srcMap, &srcRowStride,
+                                     readFb->FlipY);
          if (!srcMap) {
-            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer");
-            return;
+            goto fail_no_memory;
          }
          ctx->Driver.MapRenderbuffer(ctx, drawRb,
                                      dstXpos, dstYpos,
                                      dstWidth, dstHeight,
-                                     GL_MAP_WRITE_BIT, &dstMap, &dstRowStride);
+                                     GL_MAP_WRITE_BIT, &dstMap, &dstRowStride,
+                                     drawFb->FlipY);
          if (!dstMap) {
             ctx->Driver.UnmapRenderbuffer(ctx, readRb);
-            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer");
-            return;
+            goto fail_no_memory;
          }
       }
 
-      /* allocate the src/dst row buffers */
-      srcBuffer = malloc(pixelSize * srcWidth);
-      if (!srcBuffer) {
-         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
-         return;
-      }
-      dstBuffer = malloc(pixelSize * dstWidth);
-      if (!dstBuffer) {
-         free(srcBuffer);
-         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
-         return;
-      }
-
       for (dstRow = 0; dstRow < dstHeight; dstRow++) {
-         GLint srcRow = (dstRow * srcHeight) / dstHeight;
+         GLfloat srcRowF = (dstRow + 0.5F) / dstHeight * srcHeight - 0.5F;
+         GLint srcRow = lroundf(srcRowF);
          GLubyte *dstRowStart = dstMap + dstRowStride * dstRow;
 
-         ASSERT(srcRow >= 0);
-         ASSERT(srcRow < srcHeight);
+         assert(srcRow >= 0);
+         assert(srcRow < srcHeight);
 
          if (invertY) {
             srcRow = srcHeight - 1 - srcRow;
@@ -340,14 +334,14 @@ blit_nearest(struct gl_context *ctx,
                break;
             }
 
-            (*resampleRow)(srcWidth, dstWidth, srcBuffer, dstBuffer, invertX);
+            resampleRow(srcWidth, dstWidth, srcBuffer, dstBuffer, invertX);
             prevY = srcRow;
          }
 
          /* store pixel row in destination */
          switch (mode) {
          case DIRECT:
-            memcpy(dstRowStart, dstBuffer, pixelSize * srcWidth);
+            memcpy(dstRowStart, dstBuffer, pixelSize * dstWidth);
             break;
          case UNPACK_RGBA_FLOAT:
             _mesa_pack_float_rgba_row(drawRb->Format, dstWidth, dstBuffer,
@@ -368,14 +362,21 @@ blit_nearest(struct gl_context *ctx,
          }
       }
 
-      free(srcBuffer);
-      free(dstBuffer);
-
       ctx->Driver.UnmapRenderbuffer(ctx, readRb);
       if (drawRb != readRb) {
          ctx->Driver.UnmapRenderbuffer(ctx, drawRb);
       }
    }
+
+fail:
+   free(srcBuffer);
+   free(dstBuffer);
+   return;
+
+fail_no_memory:
+   free(srcBuffer);
+   free(dstBuffer);
+   _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBuffer");
 }
 
 
@@ -404,19 +405,17 @@ resample_linear_row_ub(GLint srcWidth, GLint dstWidth,
    const GLubyte (*srcColor0)[4] = (const GLubyte (*)[4]) srcBuffer0;
    const GLubyte (*srcColor1)[4] = (const GLubyte (*)[4]) srcBuffer1;
    GLubyte (*dstColor)[4] = (GLubyte (*)[4]) dstBuffer;
-   const GLfloat dstWidthF = (GLfloat) dstWidth;
    GLint dstCol;
 
    for (dstCol = 0; dstCol < dstWidth; dstCol++) {
-      const GLfloat srcCol = (dstCol * srcWidth) / dstWidthF;
-      GLint srcCol0 = IFLOOR(srcCol);
+      const GLfloat srcCol = (dstCol + 0.5F) / dstWidth * srcWidth - 0.5F;
+      GLint srcCol0 = MAX2(0, util_ifloor(srcCol));
       GLint srcCol1 = srcCol0 + 1;
       GLfloat colWeight = srcCol - srcCol0; /* fractional part of srcCol */
       GLfloat red, green, blue, alpha;
 
-      ASSERT(srcCol0 >= 0);
-      ASSERT(srcCol0 < srcWidth);
-      ASSERT(srcCol1 <= srcWidth);
+      assert(srcCol0 < srcWidth);
+      assert(srcCol1 <= srcWidth);
 
       if (srcCol1 == srcWidth) {
          /* last column fudge */
@@ -441,11 +440,11 @@ resample_linear_row_ub(GLint srcWidth, GLint dstWidth,
       alpha = lerp_2d(colWeight, rowWeight,
                     srcColor0[srcCol0][ACOMP], srcColor0[srcCol1][ACOMP],
                     srcColor1[srcCol0][ACOMP], srcColor1[srcCol1][ACOMP]);
-      
-      dstColor[dstCol][RCOMP] = IFLOOR(red);
-      dstColor[dstCol][GCOMP] = IFLOOR(green);
-      dstColor[dstCol][BCOMP] = IFLOOR(blue);
-      dstColor[dstCol][ACOMP] = IFLOOR(alpha);
+
+      dstColor[dstCol][RCOMP] = util_ifloor(red);
+      dstColor[dstCol][GCOMP] = util_ifloor(green);
+      dstColor[dstCol][BCOMP] = util_ifloor(blue);
+      dstColor[dstCol][ACOMP] = util_ifloor(alpha);
    }
 }
 
@@ -461,19 +460,17 @@ resample_linear_row_float(GLint srcWidth, GLint dstWidth,
    const GLfloat (*srcColor0)[4] = (const GLfloat (*)[4]) srcBuffer0;
    const GLfloat (*srcColor1)[4] = (const GLfloat (*)[4]) srcBuffer1;
    GLfloat (*dstColor)[4] = (GLfloat (*)[4]) dstBuffer;
-   const GLfloat dstWidthF = (GLfloat) dstWidth;
    GLint dstCol;
 
    for (dstCol = 0; dstCol < dstWidth; dstCol++) {
-      const GLfloat srcCol = (dstCol * srcWidth) / dstWidthF;
-      GLint srcCol0 = IFLOOR(srcCol);
+      const GLfloat srcCol = (dstCol + 0.5F) / dstWidth * srcWidth - 0.5F;
+      GLint srcCol0 = MAX2(0, util_ifloor(srcCol));
       GLint srcCol1 = srcCol0 + 1;
       GLfloat colWeight = srcCol - srcCol0; /* fractional part of srcCol */
       GLfloat red, green, blue, alpha;
 
-      ASSERT(srcCol0 >= 0);
-      ASSERT(srcCol0 < srcWidth);
-      ASSERT(srcCol1 <= srcWidth);
+      assert(srcCol0 < srcWidth);
+      assert(srcCol1 <= srcWidth);
 
       if (srcCol1 == srcWidth) {
          /* last column fudge */
@@ -498,7 +495,7 @@ resample_linear_row_float(GLint srcWidth, GLint dstWidth,
       alpha = lerp_2d(colWeight, rowWeight,
                     srcColor0[srcCol0][ACOMP], srcColor0[srcCol1][ACOMP],
                     srcColor1[srcCol0][ACOMP], srcColor1[srcCol1][ACOMP]);
-      
+
       dstColor[dstCol][RCOMP] = red;
       dstColor[dstCol][GCOMP] = green;
       dstColor[dstCol][BCOMP] = blue;
@@ -513,11 +510,11 @@ resample_linear_row_float(GLint srcWidth, GLint dstWidth,
  */
 static void
 blit_linear(struct gl_context *ctx,
+            struct gl_framebuffer *readFb,
+            struct gl_framebuffer *drawFb,
             GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
             GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1)
 {
-   struct gl_framebuffer *drawFb = ctx->DrawBuffer;
-   struct gl_framebuffer *readFb = ctx->ReadBuffer;
    struct gl_renderbuffer *readRb = readFb->_ColorReadBuffer;
    struct gl_renderbuffer_attachment *readAtt =
       &readFb->Attachment[readFb->_ColorReadBufferIndex];
@@ -526,7 +523,6 @@ blit_linear(struct gl_context *ctx,
    const GLint dstWidth = ABS(dstX1 - dstX0);
    const GLint srcHeight = ABS(srcY1 - srcY0);
    const GLint dstHeight = ABS(dstY1 - dstY0);
-   const GLfloat dstHeightF = (GLfloat) dstHeight;
 
    const GLint srcXpos = MIN2(srcX0, srcX1);
    const GLint srcYpos = MIN2(srcY0, srcY1);
@@ -543,7 +539,7 @@ blit_linear(struct gl_context *ctx,
    GLint srcBufferY0 = -1, srcBufferY1 = -1;
    GLvoid *dstBuffer;
 
-   gl_format readFormat = _mesa_get_srgb_format_linear(readRb->Format);
+   mesa_format readFormat = _mesa_get_srgb_format_linear(readRb->Format);
    GLuint bpp = _mesa_get_format_bytes(readFormat);
 
    GLenum pixelType;
@@ -568,31 +564,19 @@ blit_linear(struct gl_context *ctx,
     * Keep two adjacent src rows around for bilinear sampling.
     */
    srcBuffer0 = malloc(pixelSize * srcWidth);
-   if (!srcBuffer0) {
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
-      return;
-   }
    srcBuffer1 = malloc(pixelSize * srcWidth);
-   if (!srcBuffer1) {
-      free(srcBuffer0);
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
-      return;
-   }
    dstBuffer = malloc(pixelSize * dstWidth);
-   if (!dstBuffer) {
-      free(srcBuffer0);
-      free(srcBuffer1);
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
-      return;
+   if (!srcBuffer0 || !srcBuffer1 || !dstBuffer) {
+      goto fail_no_memory;
    }
 
    for (i = 0; i < drawFb->_NumColorDrawBuffers; i++) {
-      GLint idx = drawFb->_ColorDrawBufferIndexes[i];
+      gl_buffer_index idx = drawFb->_ColorDrawBufferIndexes[i];
       struct gl_renderbuffer_attachment *drawAtt;
       struct gl_renderbuffer *drawRb;
-      gl_format drawFormat;
+      mesa_format drawFormat;
 
-      if (idx == -1)
+      if (idx == BUFFER_NONE)
          continue;
 
       drawAtt = &drawFb->Attachment[idx];
@@ -612,13 +596,10 @@ blit_linear(struct gl_context *ctx,
          ctx->Driver.MapRenderbuffer(ctx, readRb,
                                      0, 0, readRb->Width, readRb->Height,
                                      GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
-                                     &srcMap, &srcRowStride);
+                                     &srcMap, &srcRowStride,
+                                     readFb->FlipY);
          if (!srcMap) {
-            free(srcBuffer0);
-            free(srcBuffer1);
-            free(dstBuffer);
-            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer");
-            return;
+            goto fail_no_memory;
          }
 
          dstMap = srcMap;
@@ -631,37 +612,28 @@ blit_linear(struct gl_context *ctx,
           */
          ctx->Driver.MapRenderbuffer(ctx, readRb,
                                      0, 0, readRb->Width, readRb->Height,
-                                     GL_MAP_READ_BIT, &srcMap, &srcRowStride);
+                                     GL_MAP_READ_BIT, &srcMap, &srcRowStride,
+                                     readFb->FlipY);
          if (!srcMap) {
-            free(srcBuffer0);
-            free(srcBuffer1);
-            free(dstBuffer);
-            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer");
-            return;
+            goto fail_no_memory;
          }
          ctx->Driver.MapRenderbuffer(ctx, drawRb,
                                      0, 0, drawRb->Width, drawRb->Height,
-                                     GL_MAP_WRITE_BIT, &dstMap, &dstRowStride);
+                                     GL_MAP_WRITE_BIT, &dstMap, &dstRowStride,
+                                     drawFb->FlipY);
          if (!dstMap) {
             ctx->Driver.UnmapRenderbuffer(ctx, readRb);
-            free(srcBuffer0);
-            free(srcBuffer1);
-            free(dstBuffer);
-            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer");
-            return;
+            goto fail_no_memory;
          }
       }
 
       for (dstRow = 0; dstRow < dstHeight; dstRow++) {
          const GLint dstY = dstYpos + dstRow;
-         const GLfloat srcRow = (dstRow * srcHeight) / dstHeightF;
-         GLint srcRow0 = IFLOOR(srcRow);
+         GLfloat srcRow = (dstRow + 0.5F) / dstHeight * srcHeight - 0.5F;
+         GLint srcRow0 = MAX2(0, util_ifloor(srcRow));
          GLint srcRow1 = srcRow0 + 1;
          GLfloat rowWeight = srcRow - srcRow0; /* fractional part of srcRow */
 
-         ASSERT(srcRow >= 0);
-         ASSERT(srcRow < srcHeight);
-
          if (srcRow1 == srcHeight) {
             /* last row fudge */
             srcRow1 = srcRow0;
@@ -741,15 +713,22 @@ blit_linear(struct gl_context *ctx,
          }
       }
 
-      free(srcBuffer0);
-      free(srcBuffer1);
-      free(dstBuffer);
-
       ctx->Driver.UnmapRenderbuffer(ctx, readRb);
       if (drawRb != readRb) {
          ctx->Driver.UnmapRenderbuffer(ctx, drawRb);
       }
    }
+
+   free(srcBuffer0);
+   free(srcBuffer1);
+   free(dstBuffer);
+   return;
+
+fail_no_memory:
+   free(srcBuffer0);
+   free(srcBuffer1);
+   free(dstBuffer);
+   _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer");
 }
 
 
@@ -759,6 +738,8 @@ blit_linear(struct gl_context *ctx,
  */
 void
 _swrast_BlitFramebuffer(struct gl_context *ctx,
+                        struct gl_framebuffer *readFb,
+                        struct gl_framebuffer *drawFb,
                         GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
                         GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
                         GLbitfield mask, GLenum filter)
@@ -775,7 +756,14 @@ _swrast_BlitFramebuffer(struct gl_context *ctx,
    };
    GLint i;
 
-   if (!_mesa_clip_blit(ctx, &srcX0, &srcY0, &srcX1, &srcY1,
+   /* Page 679 of OpenGL 4.4 spec says:
+    *    "Added BlitFramebuffer to commands affected by conditional rendering in
+    *     section 10.10 (Bug 9562)."
+    */
+   if (!_mesa_check_conditional_render(ctx))
+      return; /* Do not blit */
+
+   if (!_mesa_clip_blit(ctx, readFb, drawFb, &srcX0, &srcY0, &srcX1, &srcY1,
                         &dstX0, &dstY0, &dstX1, &dstY1)) {
       return;
    }
@@ -794,33 +782,34 @@ _swrast_BlitFramebuffer(struct gl_context *ctx,
        dstY0 < dstY1) {
       for (i = 0; i < 3; i++) {
          if (mask & buffers[i]) {
-           if (swrast_fast_copy_pixels(ctx,
-                                       srcX0, srcY0,
-                                       srcX1 - srcX0, srcY1 - srcY0,
-                                       dstX0, dstY0,
-                                       buffer_enums[i])) {
-              mask &= ~buffers[i];
-           }
-        }
+            if (swrast_fast_copy_pixels(ctx,
+                                        readFb, drawFb,
+                                        srcX0, srcY0,
+                                        srcX1 - srcX0, srcY1 - srcY0,
+                                        dstX0, dstY0,
+                                        buffer_enums[i])) {
+               mask &= ~buffers[i];
+            }
+         }
       }
 
       if (!mask)
-        return;
+         return;
    }
 
    if (filter == GL_NEAREST) {
       for (i = 0; i < 3; i++) {
-        if (mask & buffers[i]) {
-           blit_nearest(ctx,  srcX0, srcY0, srcX1, srcY1,
-                        dstX0, dstY0, dstX1, dstY1, buffers[i]);
-        }
+          if (mask & buffers[i]) {
+             blit_nearest(ctx, readFb, drawFb, srcX0, srcY0, srcX1, srcY1,
+                          dstX0, dstY0, dstX1, dstY1, buffers[i]);
+          }
       }
    }
    else {
-      ASSERT(filter == GL_LINEAR);
+      assert(filter == GL_LINEAR);
       if (mask & GL_COLOR_BUFFER_BIT) {  /* depth/stencil not allowed */
-        blit_linear(ctx,  srcX0, srcY0, srcX1, srcY1,
-                    dstX0, dstY0, dstX1, dstY1);
+         blit_linear(ctx, readFb, drawFb, srcX0, srcY0, srcX1, srcY1,
+                     dstX0, dstY0, dstX1, dstY1);
       }
    }