vulkan/wsi: include builddir for generated headers
[mesa.git] / src / mesa / swrast / s_blit.c
index 08ec5e2d0e0cde8d16d0194b10e7aeaa59310dfa..3e838a41d44b08149d0ee261a28fa8201d70ce1b 100644 (file)
@@ -1,6 +1,5 @@
 /*
  * Mesa 3-D graphics library
 /*
  * Mesa 3-D graphics library
- * Version:  6.5
  *
  * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
  *
  *
  * 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
  * 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/macros.h"
 #include "main/format_unpack.h"
 #include "main/format_pack.h"
+#include "main/condrender.h"
 #include "s_context.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;        \
    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];                 \
          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;        \
    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];                 \
          }                                             \
          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,
  */
 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)
 {
              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;
 
    GLuint numDrawBuffers = 0;
    GLuint i;
 
@@ -135,12 +136,12 @@ blit_nearest(struct gl_context *ctx,
       UNPACK_Z_FLOAT,
       UNPACK_Z_INT,
       UNPACK_S,
       UNPACK_Z_FLOAT,
       UNPACK_Z_INT,
       UNPACK_S,
-   } mode;
+   } mode = DIRECT;
    GLubyte *srcMap, *dstMap;
    GLint srcRowStride, dstRowStride;
    GLint dstRow;
 
    GLubyte *srcMap, *dstMap;
    GLint srcRowStride, dstRowStride;
    GLint dstRow;
 
-   GLint pixelSize;
+   GLint pixelSize = 0;
    GLvoid *srcBuffer, *dstBuffer;
    GLint prevY = -1;
 
    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.
        */
        * 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;
         mode = UNPACK_Z_FLOAT;
       } else {
         mode = UNPACK_Z_INT;
@@ -188,6 +189,12 @@ blit_nearest(struct gl_context *ctx,
       return;
    }
 
       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) {
    /* Blit to all the draw buffers */
    for (i = 0; i < numDrawBuffers; i++) {
       if (buffer == GL_COLOR_BUFFER_BIT) {
@@ -229,7 +236,7 @@ blit_nearest(struct gl_context *ctx,
       default:
          _mesa_problem(ctx, "unexpected pixel size (%d) in blit_nearest",
                        pixelSize);
       default:
          _mesa_problem(ctx, "unexpected pixel size (%d) in blit_nearest",
                        pixelSize);
-         return;
+         goto fail;
       }
 
       if ((readRb == drawRb) ||
       }
 
       if ((readRb == drawRb) ||
@@ -248,8 +255,7 @@ blit_nearest(struct gl_context *ctx,
                                      GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
                                      &map, &rowStride);
          if (!map) {
                                      GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
                                      &map, &rowStride);
          if (!map) {
-            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer");
-            return;
+            goto fail_no_memory;
          }
 
          srcMap = map + srcYpos * rowStride + srcXpos * formatSize;
          }
 
          srcMap = map + srcYpos * rowStride + srcXpos * formatSize;
@@ -276,8 +282,7 @@ blit_nearest(struct gl_context *ctx,
                                      srcWidth, srcHeight,
                                      GL_MAP_READ_BIT, &srcMap, &srcRowStride);
          if (!srcMap) {
                                      srcWidth, srcHeight,
                                      GL_MAP_READ_BIT, &srcMap, &srcRowStride);
          if (!srcMap) {
-            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer");
-            return;
+            goto fail_no_memory;
          }
          ctx->Driver.MapRenderbuffer(ctx, drawRb,
                                      dstXpos, dstYpos,
          }
          ctx->Driver.MapRenderbuffer(ctx, drawRb,
                                      dstXpos, dstYpos,
@@ -285,30 +290,17 @@ blit_nearest(struct gl_context *ctx,
                                      GL_MAP_WRITE_BIT, &dstMap, &dstRowStride);
          if (!dstMap) {
             ctx->Driver.UnmapRenderbuffer(ctx, readRb);
                                      GL_MAP_WRITE_BIT, &dstMap, &dstRowStride);
          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++) {
       for (dstRow = 0; dstRow < dstHeight; dstRow++) {
-         GLint srcRow = (dstRow * srcHeight) / dstHeight;
+         GLfloat srcRowF = (dstRow + 0.5F) / dstHeight * srcHeight - 0.5F;
+         GLint srcRow = IROUND(srcRowF);
          GLubyte *dstRowStart = dstMap + dstRowStride * dstRow;
 
          GLubyte *dstRowStart = dstMap + dstRowStride * dstRow;
 
-         ASSERT(srcRow >= 0);
-         ASSERT(srcRow < srcHeight);
+         assert(srcRow >= 0);
+         assert(srcRow < srcHeight);
 
          if (invertY) {
             srcRow = srcHeight - 1 - srcRow;
 
          if (invertY) {
             srcRow = srcHeight - 1 - srcRow;
@@ -368,14 +360,21 @@ blit_nearest(struct gl_context *ctx,
          }
       }
 
          }
       }
 
-      free(srcBuffer);
-      free(dstBuffer);
-
       ctx->Driver.UnmapRenderbuffer(ctx, readRb);
       if (drawRb != readRb) {
          ctx->Driver.UnmapRenderbuffer(ctx, drawRb);
       }
    }
       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 +403,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 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++) {
    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, IFLOOR(srcCol));
       GLint srcCol1 = srcCol0 + 1;
       GLfloat colWeight = srcCol - srcCol0; /* fractional part of srcCol */
       GLfloat red, green, blue, alpha;
 
       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 */
 
       if (srcCol1 == srcWidth) {
          /* last column fudge */
@@ -461,19 +458,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 (*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++) {
    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, IFLOOR(srcCol));
       GLint srcCol1 = srcCol0 + 1;
       GLfloat colWeight = srcCol - srcCol0; /* fractional part of srcCol */
       GLfloat red, green, blue, alpha;
 
       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 */
 
       if (srcCol1 == srcWidth) {
          /* last column fudge */
@@ -513,11 +508,11 @@ resample_linear_row_float(GLint srcWidth, GLint dstWidth,
  */
 static void
 blit_linear(struct gl_context *ctx,
  */
 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)
 {
             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];
    struct gl_renderbuffer *readRb = readFb->_ColorReadBuffer;
    struct gl_renderbuffer_attachment *readAtt =
       &readFb->Attachment[readFb->_ColorReadBufferIndex];
@@ -526,7 +521,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 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);
 
    const GLint srcXpos = MIN2(srcX0, srcX1);
    const GLint srcYpos = MIN2(srcY0, srcY1);
@@ -543,7 +537,7 @@ blit_linear(struct gl_context *ctx,
    GLint srcBufferY0 = -1, srcBufferY1 = -1;
    GLvoid *dstBuffer;
 
    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;
    GLuint bpp = _mesa_get_format_bytes(readFormat);
 
    GLenum pixelType;
@@ -568,29 +562,17 @@ blit_linear(struct gl_context *ctx,
     * Keep two adjacent src rows around for bilinear sampling.
     */
    srcBuffer0 = malloc(pixelSize * srcWidth);
     * 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);
    srcBuffer1 = malloc(pixelSize * srcWidth);
-   if (!srcBuffer1) {
-      free(srcBuffer0);
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
-      return;
-   }
    dstBuffer = malloc(pixelSize * dstWidth);
    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];
       struct gl_renderbuffer_attachment *drawAtt;
       struct gl_renderbuffer *drawRb;
    }
 
    for (i = 0; i < drawFb->_NumColorDrawBuffers; i++) {
       GLint idx = drawFb->_ColorDrawBufferIndexes[i];
       struct gl_renderbuffer_attachment *drawAtt;
       struct gl_renderbuffer *drawRb;
-      gl_format drawFormat;
+      mesa_format drawFormat;
 
       if (idx == -1)
          continue;
 
       if (idx == -1)
          continue;
@@ -614,11 +596,7 @@ blit_linear(struct gl_context *ctx,
                                      GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
                                      &srcMap, &srcRowStride);
          if (!srcMap) {
                                      GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
                                      &srcMap, &srcRowStride);
          if (!srcMap) {
-            free(srcBuffer0);
-            free(srcBuffer1);
-            free(dstBuffer);
-            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer");
-            return;
+            goto fail_no_memory;
          }
 
          dstMap = srcMap;
          }
 
          dstMap = srcMap;
@@ -633,35 +611,24 @@ blit_linear(struct gl_context *ctx,
                                      0, 0, readRb->Width, readRb->Height,
                                      GL_MAP_READ_BIT, &srcMap, &srcRowStride);
          if (!srcMap) {
                                      0, 0, readRb->Width, readRb->Height,
                                      GL_MAP_READ_BIT, &srcMap, &srcRowStride);
          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);
          if (!dstMap) {
             ctx->Driver.UnmapRenderbuffer(ctx, readRb);
          }
          ctx->Driver.MapRenderbuffer(ctx, drawRb,
                                      0, 0, drawRb->Width, drawRb->Height,
                                      GL_MAP_WRITE_BIT, &dstMap, &dstRowStride);
          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;
          }
       }
 
       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, IFLOOR(srcRow));
          GLint srcRow1 = srcRow0 + 1;
          GLfloat rowWeight = srcRow - srcRow0; /* fractional part of 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;
          if (srcRow1 == srcHeight) {
             /* last row fudge */
             srcRow1 = srcRow0;
@@ -741,15 +708,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);
       }
    }
       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 +733,8 @@ blit_linear(struct gl_context *ctx,
  */
 void
 _swrast_BlitFramebuffer(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)
                         GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
                         GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
                         GLbitfield mask, GLenum filter)
@@ -775,7 +751,14 @@ _swrast_BlitFramebuffer(struct gl_context *ctx,
    };
    GLint i;
 
    };
    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;
    }
                         &dstX0, &dstY0, &dstX1, &dstY1)) {
       return;
    }
@@ -794,33 +777,34 @@ _swrast_BlitFramebuffer(struct gl_context *ctx,
        dstY0 < dstY1) {
       for (i = 0; i < 3; i++) {
          if (mask & buffers[i]) {
        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)
       }
 
       if (!mask)
-        return;
+         return;
    }
 
    if (filter == GL_NEAREST) {
       for (i = 0; i < 3; i++) {
    }
 
    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 {
       }
    }
    else {
-      ASSERT(filter == GL_LINEAR);
+      assert(filter == GL_LINEAR);
       if (mask & GL_COLOR_BUFFER_BIT) {  /* depth/stencil not allowed */
       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);
       }
    }
 
       }
    }