[Mesa-dev] [PATCH 7/7] mesa: Add support to allow blitting to multiple color draw buffers

Anuj Phogat anuj.phogat at gmail.com
Mon Jan 7 08:16:33 PST 2013


Changes in fbobject.c fix a case when blitting to a framebuffer with
renderbuffers/textures attached to GL_COLOR_ATTACHMENT{i} (where i!=0).
Earlier it skips color blitting if nothing is found attached to
GL_COLOR_ATTACHMENT0.

Changes in swrast/s_blit.c fix a blitting case when drawAttachment->Texture
 == readAttachment->Texture. This was causing an assertion failure
intel_miptree_attach_map() with gles3 conformance test case:
framebuffer_blit_functionality_minifying_blit
Number of changes in this file look scary. But most of them are caused by
introducing a big for loop to support rendering to multiple color draw buffers.

V2: Fixed a case when number of draw buffer attachments are zero.
V3: Do compatible_color_datatypes() check for all the  draw renderbuffers
    in fbobject.c. Put a for loop in blit_nearest() and blit_linear()
    functions in swrast/s_blit.c to support blitting to multiple color
    draw buffers.
V4: Remove variable declaration in for loop to avoid MSVC compilation issues.

Signed-off-by: Anuj Phogat <anuj.phogat at gmail.com>
---
 src/mesa/main/fbobject.c |   32 ++-
 src/mesa/swrast/s_blit.c |  561 +++++++++++++++++++++++++---------------------
 2 files changed, 324 insertions(+), 269 deletions(-)

diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c
index 517bf13..e9fd9ca 100644
--- a/src/mesa/main/fbobject.c
+++ b/src/mesa/main/fbobject.c
@@ -2789,6 +2789,8 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
                                      GL_STENCIL_BUFFER_BIT);
    const struct gl_framebuffer *readFb, *drawFb;
    const struct gl_renderbuffer *colorReadRb, *colorDrawRb;
+   GLuint i;
+
    GET_CURRENT_CONTEXT(ctx);
 
    ASSERT_OUTSIDE_BEGIN_END(ctx);
@@ -2843,8 +2845,10 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
 
    /* get color read/draw renderbuffers */
    if (mask & GL_COLOR_BUFFER_BIT) {
+      const  GLuint numColorDrawBuffers =
+         ctx->DrawBuffer->_NumColorDrawBuffers;
       colorReadRb = readFb->_ColorReadBuffer;
-      colorDrawRb = drawFb->_ColorDrawBuffers[0];
+      colorDrawRb = NULL;
 
       /* From the EXT_framebuffer_object spec:
        *
@@ -2852,15 +2856,27 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
        *     the read and draw framebuffers, the corresponding bit is silently
        *     ignored."
        */
-      if ((colorReadRb == NULL) || (colorDrawRb == NULL)) {
-	 colorReadRb = colorDrawRb = NULL;
+      if (colorReadRb == NULL) {
 	 mask &= ~GL_COLOR_BUFFER_BIT;
       }
-      else if (!compatible_color_datatypes(colorReadRb->Format,
-                                           colorDrawRb->Format)) {
-         _mesa_error(ctx, GL_INVALID_OPERATION,
-                     "glBlitFramebufferEXT(color buffer datatypes mismatch)");
-         return;
+      else {
+         for (i = 0; i < numColorDrawBuffers; i++) {
+            if (ctx->DrawBuffer->_ColorDrawBuffers[i] == NULL)
+	       continue;
+	    colorDrawRb = ctx->DrawBuffer->_ColorDrawBuffers[i];
+
+            if (!compatible_color_datatypes(colorReadRb->Format,
+                                            colorDrawRb->Format)) {
+               _mesa_error(ctx, GL_INVALID_OPERATION,
+                           "glBlitFramebufferEXT(color buffer datatypes mismatch)");
+               return;
+            }
+         }
+      }
+
+      if (colorDrawRb == NULL) {
+	 colorReadRb = NULL;
+	 mask &= ~GL_COLOR_BUFFER_BIT;
       }
    }
    else {
diff --git a/src/mesa/swrast/s_blit.c b/src/mesa/swrast/s_blit.c
index b0c56a4..043b578 100644
--- a/src/mesa/swrast/s_blit.c
+++ b/src/mesa/swrast/s_blit.c
@@ -111,6 +111,11 @@ blit_nearest(struct gl_context *ctx,
              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;
+   GLint NumDrawBuffers = 0;
+   GLuint i;
 
    const GLint srcWidth = ABS(srcX1 - srcX0);
    const GLint dstWidth = ABS(dstX1 - dstX0);
@@ -146,21 +151,16 @@ blit_nearest(struct gl_context *ctx,
 
    switch (buffer) {
    case GL_COLOR_BUFFER_BIT:
-      readRb = ctx->ReadBuffer->_ColorReadBuffer;
-      drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0];
-
-      if (readRb->Format == drawRb->Format) {
-	 mode = DIRECT;
-	 pixelSize = _mesa_get_format_bytes(readRb->Format);
-      } else {
-	 mode = UNPACK_RGBA_FLOAT;
-	 pixelSize = 16;
-      }
-
+      readAtt = &readFb->Attachment[readFb->_ColorReadBufferIndex];
+      readRb = readFb->_ColorReadBuffer;
+      NumDrawBuffers = drawFb->_NumColorDrawBuffers;
       break;
    case GL_DEPTH_BUFFER_BIT:
-      readRb = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
-      drawRb = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
+      readAtt = &readFb->Attachment[BUFFER_DEPTH];
+      drawAtt = &drawFb->Attachment[BUFFER_DEPTH];
+      readRb = readAtt->Renderbuffer;
+      drawRb = drawAtt->Renderbuffer;
+      NumDrawBuffers = 1;
 
       /* Note that for depth/stencil, the formats of src/dst must match.  By
        * using the core helpers for pack/unpack, we avoid needing to handle
@@ -175,8 +175,11 @@ blit_nearest(struct gl_context *ctx,
       pixelSize = 4;
       break;
    case GL_STENCIL_BUFFER_BIT:
-      readRb = ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
-      drawRb = ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
+      readAtt = &readFb->Attachment[BUFFER_STENCIL];
+      drawAtt = &drawFb->Attachment[BUFFER_STENCIL];
+      readRb = readAtt->Renderbuffer;
+      drawRb = drawAtt->Renderbuffer;
+      NumDrawBuffers = 1;
       mode = UNPACK_S;
       pixelSize = 1;
       break;
@@ -208,146 +211,167 @@ blit_nearest(struct gl_context *ctx,
       return;
    }
 
-   if (readRb == drawRb) {
-      /* map whole buffer for read/write */
-      /* XXX we could be clever and just map the union region of the
-       * source and dest rects.
-       */
-      GLubyte *map;
-      GLint rowStride;
-      GLint formatSize = _mesa_get_format_bytes(readRb->Format);
-
-      ctx->Driver.MapRenderbuffer(ctx, readRb, 0, 0,
-                                  readRb->Width, readRb->Height,
-                                  GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
-                                  &map, &rowStride);
-      if (!map) {
-         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer");
-         return;
+   /* 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)
+            continue;
+         drawAtt = &drawFb->Attachment[idx];
+         drawRb = drawAtt->Renderbuffer;
+
+         if (readRb->Format == drawRb->Format) {
+            mode = DIRECT;
+            pixelSize = _mesa_get_format_bytes(readRb->Format);
+         } else {
+            mode = UNPACK_RGBA_FLOAT;
+            pixelSize = 16;
+         }
       }
 
-      srcMap = map + srcYpos * rowStride + srcXpos * formatSize;
-      dstMap = map + dstYpos * rowStride + dstXpos * formatSize;
+      if ((readRb == drawRb) ||
+          (readAtt->Texture && drawAtt->Texture &&
+           (readAtt->Texture == drawAtt->Texture))) {
+         /* map whole buffer for read/write */
+         /* XXX we could be clever and just map the union region of the
+          * source and dest rects.
+          */
+         GLubyte *map;
+         GLint rowStride;
+         GLint formatSize = _mesa_get_format_bytes(readRb->Format);
+
+         ctx->Driver.MapRenderbuffer(ctx, readRb, 0, 0,
+                                     readRb->Width, readRb->Height,
+                                     GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
+                                     &map, &rowStride);
+         if (!map) {
+            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer");
+            return;
+         }
+
+         srcMap = map + srcYpos * rowStride + srcXpos * formatSize;
+         dstMap = map + dstYpos * rowStride + dstXpos * formatSize;
 
-      /* this handles overlapping copies */
-      if (srcY0 < dstY0) {
-         /* copy in reverse (top->down) order */
-         srcMap += rowStride * (readRb->Height - 1);
-         dstMap += rowStride * (readRb->Height - 1);
-         srcRowStride = -rowStride;
-         dstRowStride = -rowStride;
+         /* this handles overlapping copies */
+         if (srcY0 < dstY0) {
+            /* copy in reverse (top->down) order */
+            srcMap += rowStride * (readRb->Height - 1);
+            dstMap += rowStride * (readRb->Height - 1);
+            srcRowStride = -rowStride;
+            dstRowStride = -rowStride;
+         }
+         else {
+            /* copy in normal (bottom->up) order */
+            srcRowStride = rowStride;
+            dstRowStride = rowStride;
+         }
       }
       else {
-         /* copy in normal (bottom->up) order */
-         srcRowStride = rowStride;
-         dstRowStride = rowStride;
+         /* different src/dst buffers */
+         ctx->Driver.MapRenderbuffer(ctx, readRb,
+                                     srcXpos, srcYpos,
+                                     srcWidth, srcHeight,
+                                     GL_MAP_READ_BIT, &srcMap, &srcRowStride);
+         if (!srcMap) {
+            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer");
+            return;
+         }
+         ctx->Driver.MapRenderbuffer(ctx, drawRb,
+                                     dstXpos, dstYpos,
+                                     dstWidth, dstHeight,
+                                     GL_MAP_WRITE_BIT, &dstMap, &dstRowStride);
+         if (!dstMap) {
+            ctx->Driver.UnmapRenderbuffer(ctx, readRb);
+            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer");
+            return;
+         }
       }
-   }
-   else {
-      /* different src/dst buffers */
-      ctx->Driver.MapRenderbuffer(ctx, readRb,
-				  srcXpos, srcYpos,
-                                  srcWidth, srcHeight,
-                                  GL_MAP_READ_BIT, &srcMap, &srcRowStride);
-      if (!srcMap) {
-         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer");
+
+      /* allocate the src/dst row buffers */
+      srcBuffer = malloc(pixelSize * srcWidth);
+      if (!srcBuffer) {
+         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
          return;
       }
-      ctx->Driver.MapRenderbuffer(ctx, drawRb,
-				  dstXpos, dstYpos,
-                                  dstWidth, dstHeight,
-                                  GL_MAP_WRITE_BIT, &dstMap, &dstRowStride);
-      if (!dstMap) {
-         ctx->Driver.UnmapRenderbuffer(ctx, readRb);
-         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer");
+      dstBuffer = malloc(pixelSize * dstWidth);
+      if (!dstBuffer) {
+         free(srcBuffer);
+         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
          return;
       }
-   }
 
-   /* 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;
-      GLubyte *dstRowStart = dstMap + dstRowStride * dstRow;
+      for (dstRow = 0; dstRow < dstHeight; dstRow++) {
+         GLint srcRow = (dstRow * srcHeight) / dstHeight;
+         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;
+         }
 
-      /* get pixel row from source and resample to match dest width */
-      if (prevY != srcRow) {
-	 GLubyte *srcRowStart = srcMap + srcRowStride * srcRow;
-
-	 switch (mode) {
-	 case DIRECT:
-	    memcpy(srcBuffer, srcRowStart, pixelSize * srcWidth);
-	    break;
-	 case UNPACK_RGBA_FLOAT:
-	    _mesa_unpack_rgba_row(readRb->Format, srcWidth, srcRowStart,
-				  srcBuffer);
-	    break;
-	 case UNPACK_Z_FLOAT:
-	    _mesa_unpack_float_z_row(readRb->Format, srcWidth, srcRowStart,
-				     srcBuffer);
-	    break;
-	 case UNPACK_Z_INT:
-	    _mesa_unpack_uint_z_row(readRb->Format, srcWidth, srcRowStart,
-				    srcBuffer);
-	    break;
-	 case UNPACK_S:
-	    _mesa_unpack_ubyte_stencil_row(readRb->Format, srcWidth,
-					   srcRowStart, srcBuffer);
-	    break;
-	 }
+         /* get pixel row from source and resample to match dest width */
+         if (prevY != srcRow) {
+            GLubyte *srcRowStart = srcMap + srcRowStride * srcRow;
+
+            switch (mode) {
+            case DIRECT:
+               memcpy(srcBuffer, srcRowStart, pixelSize * srcWidth);
+               break;
+            case UNPACK_RGBA_FLOAT:
+               _mesa_unpack_rgba_row(readRb->Format, srcWidth, srcRowStart,
+                                     srcBuffer);
+               break;
+            case UNPACK_Z_FLOAT:
+               _mesa_unpack_float_z_row(readRb->Format, srcWidth, srcRowStart,
+                                        srcBuffer);
+               break;
+            case UNPACK_Z_INT:
+               _mesa_unpack_uint_z_row(readRb->Format, srcWidth, srcRowStart,
+                                       srcBuffer);
+               break;
+            case UNPACK_S:
+               _mesa_unpack_ubyte_stencil_row(readRb->Format, srcWidth,
+                                              srcRowStart, srcBuffer);
+               break;
+            }
 
-         (*resampleRow)(srcWidth, dstWidth, srcBuffer, dstBuffer, invertX);
-         prevY = srcRow;
-      }
+            (*resampleRow)(srcWidth, dstWidth, srcBuffer, dstBuffer, invertX);
+            prevY = srcRow;
+         }
 
-      /* store pixel row in destination */
-      switch (mode) {
-      case DIRECT:
-	 memcpy(dstRowStart, dstBuffer, pixelSize * srcWidth);
-	 break;
-      case UNPACK_RGBA_FLOAT:
-	 _mesa_pack_float_rgba_row(drawRb->Format, dstWidth, dstBuffer,
-				   dstRowStart);
-	 break;
-      case UNPACK_Z_FLOAT:
-	 _mesa_pack_float_z_row(drawRb->Format, dstWidth, dstBuffer,
-				dstRowStart);
-	 break;
-      case UNPACK_Z_INT:
-	 _mesa_pack_uint_z_row(drawRb->Format, dstWidth, dstBuffer,
-			       dstRowStart);
-	 break;
-      case UNPACK_S:
-	 _mesa_pack_ubyte_stencil_row(drawRb->Format, dstWidth, dstBuffer,
-				      dstRowStart);
-	 break;
+         /* store pixel row in destination */
+         switch (mode) {
+         case DIRECT:
+            memcpy(dstRowStart, dstBuffer, pixelSize * srcWidth);
+            break;
+         case UNPACK_RGBA_FLOAT:
+            _mesa_pack_float_rgba_row(drawRb->Format, dstWidth, dstBuffer,
+                                      dstRowStart);
+            break;
+         case UNPACK_Z_FLOAT:
+            _mesa_pack_float_z_row(drawRb->Format, dstWidth, dstBuffer,
+                                   dstRowStart);
+            break;
+         case UNPACK_Z_INT:
+            _mesa_pack_uint_z_row(drawRb->Format, dstWidth, dstBuffer,
+                                  dstRowStart);
+            break;
+         case UNPACK_S:
+            _mesa_pack_ubyte_stencil_row(drawRb->Format, dstWidth, dstBuffer,
+                                         dstRowStart);
+            break;
+         }
       }
-   }
 
-   free(srcBuffer);
-   free(dstBuffer);
+      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);
+      }
    }
 }
 
@@ -489,8 +513,13 @@ blit_linear(struct gl_context *ctx,
             GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
             GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1)
 {
-   struct gl_renderbuffer *readRb = ctx->ReadBuffer->_ColorReadBuffer;
-   struct gl_renderbuffer *drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0];
+   struct gl_framebuffer *drawFb = ctx->DrawBuffer;
+   struct gl_renderbuffer *drawRb = NULL;
+   struct gl_renderbuffer_attachment *drawAtt = NULL;
+   struct gl_framebuffer *readFb = ctx->ReadBuffer;
+   struct gl_renderbuffer *readRb = readFb->_ColorReadBuffer;
+   struct gl_renderbuffer_attachment *readAtt =
+      &readFb->Attachment[readFb->_ColorReadBufferIndex];
 
    const GLint srcWidth = ABS(srcX1 - srcX0);
    const GLint dstWidth = ABS(dstX1 - dstX0);
@@ -521,6 +550,7 @@ blit_linear(struct gl_context *ctx,
 
    GLubyte *srcMap, *dstMap;
    GLint srcRowStride, dstRowStride;
+   GLuint i;
 
 
    /* Determine datatype for resampling */
@@ -556,151 +586,160 @@ blit_linear(struct gl_context *ctx,
       return;
    }
 
-   /*
-    * Map src / dst renderbuffers
-    */
-   if (readRb == drawRb) {
-      /* map whole buffer for read/write */
-      ctx->Driver.MapRenderbuffer(ctx, readRb,
-                                  0, 0, readRb->Width, readRb->Height,
-                                  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;
-      }
-
-      dstMap = srcMap;
-      dstRowStride = srcRowStride;
-   }
-   else {
-      /* different src/dst buffers */
-      /* XXX with a bit of work we could just map the regions to be
-       * read/written instead of the whole buffers.
+   for (i = 0; i < drawFb->_NumColorDrawBuffers; i++) {
+      int idx = drawFb->_ColorDrawBufferIndexes[i];
+      if (idx == -1)
+         continue;
+      drawAtt = &drawFb->Attachment[idx];
+      drawRb = drawAtt->Renderbuffer;
+      /*
+       * Map src / dst renderbuffers
        */
-      ctx->Driver.MapRenderbuffer(ctx, readRb,
-				  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;
+      if ((readRb == drawRb) ||
+          (readAtt->Texture && drawAtt->Texture &&
+           (readAtt->Texture = drawAtt->Texture))) {
+         /* map whole buffer for read/write */
+         ctx->Driver.MapRenderbuffer(ctx, readRb,
+                                     0, 0, readRb->Width, readRb->Height,
+                                     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;
+         }
+
+         dstMap = srcMap;
+         dstRowStride = srcRowStride;
       }
-      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;
+      else {
+         /* different src/dst buffers */
+         /* XXX with a bit of work we could just map the regions to be
+          * read/written instead of the whole buffers.
+          */
+         ctx->Driver.MapRenderbuffer(ctx, readRb,
+                                     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;
+         }
+         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;
+         }
       }
-   }
 
-   for (dstRow = 0; dstRow < dstHeight; dstRow++) {
-      const GLint dstY = dstYpos + dstRow;
-      const GLfloat srcRow = (dstRow * srcHeight) / dstHeightF;
-      GLint srcRow0 = IFLOOR(srcRow);
-      GLint srcRow1 = srcRow0 + 1;
-      GLfloat rowWeight = srcRow - srcRow0; /* fractional part of srcRow */
+      for (dstRow = 0; dstRow < dstHeight; dstRow++) {
+         const GLint dstY = dstYpos + dstRow;
+         const GLfloat srcRow = (dstRow * srcHeight) / dstHeightF;
+         GLint srcRow0 = IFLOOR(srcRow);
+         GLint srcRow1 = srcRow0 + 1;
+         GLfloat rowWeight = srcRow - srcRow0; /* fractional part of srcRow */
 
-      ASSERT(srcRow >= 0);
-      ASSERT(srcRow < srcHeight);
+         ASSERT(srcRow >= 0);
+         ASSERT(srcRow < srcHeight);
 
-      if (srcRow1 == srcHeight) {
-         /* last row fudge */
-         srcRow1 = srcRow0;
-         rowWeight = 0.0;
-      }
+         if (srcRow1 == srcHeight) {
+            /* last row fudge */
+            srcRow1 = srcRow0;
+            rowWeight = 0.0;
+         }
 
-      if (invertY) {
-         srcRow0 = srcHeight - 1 - srcRow0;
-         srcRow1 = srcHeight - 1 - srcRow1;
-      }
+         if (invertY) {
+            srcRow0 = srcHeight - 1 - srcRow0;
+            srcRow1 = srcHeight - 1 - srcRow1;
+         }
 
-      srcY0 = srcYpos + srcRow0;
-      srcY1 = srcYpos + srcRow1;
+         srcY0 = srcYpos + srcRow0;
+         srcY1 = srcYpos + srcRow1;
 
-      /* get the two source rows */
-      if (srcY0 == srcBufferY0 && srcY1 == srcBufferY1) {
-         /* use same source row buffers again */
-      }
-      else if (srcY0 == srcBufferY1) {
-         /* move buffer1 into buffer0 by swapping pointers */
-         GLvoid *tmp = srcBuffer0;
-         srcBuffer0 = srcBuffer1;
-         srcBuffer1 = tmp;
-         /* get y1 row */
-         {
-            GLubyte *src = srcMap + srcY1 * srcRowStride + srcXpos * bpp;
-            if (pixelType == GL_UNSIGNED_BYTE) {
-               _mesa_unpack_ubyte_rgba_row(readFormat, srcWidth,
-                                           src, srcBuffer1);
+         /* get the two source rows */
+         if (srcY0 == srcBufferY0 && srcY1 == srcBufferY1) {
+            /* use same source row buffers again */
+         }
+         else if (srcY0 == srcBufferY1) {
+            /* move buffer1 into buffer0 by swapping pointers */
+            GLvoid *tmp = srcBuffer0;
+            srcBuffer0 = srcBuffer1;
+            srcBuffer1 = tmp;
+            /* get y1 row */
+            {
+               GLubyte *src = srcMap + srcY1 * srcRowStride + srcXpos * bpp;
+               if (pixelType == GL_UNSIGNED_BYTE) {
+                  _mesa_unpack_ubyte_rgba_row(readFormat, srcWidth,
+                                              src, srcBuffer1);
+               }
+               else {
+                  _mesa_unpack_rgba_row(readFormat, srcWidth,
+                                        src, srcBuffer1);
+               }
             }
-            else {
-               _mesa_unpack_rgba_row(readFormat, srcWidth,
-                                     src, srcBuffer1);
+            srcBufferY0 = srcY0;
+            srcBufferY1 = srcY1;
+         }
+         else {
+            /* get both new rows */
+            {
+               GLubyte *src0 = srcMap + srcY0 * srcRowStride + srcXpos * bpp;
+               GLubyte *src1 = srcMap + srcY1 * srcRowStride + srcXpos * bpp;
+               if (pixelType == GL_UNSIGNED_BYTE) {
+                  _mesa_unpack_ubyte_rgba_row(readFormat, srcWidth,
+                                              src0, srcBuffer0);
+                  _mesa_unpack_ubyte_rgba_row(readFormat, srcWidth,
+                                              src1, srcBuffer1);
+               }
+               else {
+                  _mesa_unpack_rgba_row(readFormat, srcWidth, src0, srcBuffer0);
+                  _mesa_unpack_rgba_row(readFormat, srcWidth, src1, srcBuffer1);
+               }
             }
-         }            
-         srcBufferY0 = srcY0;
-         srcBufferY1 = srcY1;
-      }
-      else {
-         /* get both new rows */
+            srcBufferY0 = srcY0;
+            srcBufferY1 = srcY1;
+         }
+
+         if (pixelType == GL_UNSIGNED_BYTE) {
+            resample_linear_row_ub(srcWidth, dstWidth, srcBuffer0, srcBuffer1,
+                                   dstBuffer, invertX, rowWeight);
+         }
+         else {
+            resample_linear_row_float(srcWidth, dstWidth, srcBuffer0, srcBuffer1,
+                                      dstBuffer, invertX, rowWeight);
+         }
+
+         /* store pixel row in destination */
          {
-            GLubyte *src0 = srcMap + srcY0 * srcRowStride + srcXpos * bpp;
-            GLubyte *src1 = srcMap + srcY1 * srcRowStride + srcXpos * bpp;
+            GLubyte *dst = dstMap + dstY * dstRowStride + dstXpos * bpp;
             if (pixelType == GL_UNSIGNED_BYTE) {
-               _mesa_unpack_ubyte_rgba_row(readFormat, srcWidth,
-                                           src0, srcBuffer0);
-               _mesa_unpack_ubyte_rgba_row(readFormat, srcWidth,
-                                           src1, srcBuffer1);
+               _mesa_pack_ubyte_rgba_row(drawFormat, dstWidth, dstBuffer, dst);
             }
             else {
-               _mesa_unpack_rgba_row(readFormat, srcWidth, src0, srcBuffer0);
-               _mesa_unpack_rgba_row(readFormat, srcWidth, src1, srcBuffer1);
+               _mesa_pack_float_rgba_row(drawFormat, dstWidth, dstBuffer, dst);
             }
          }
-         srcBufferY0 = srcY0;
-         srcBufferY1 = srcY1;
       }
 
-      if (pixelType == GL_UNSIGNED_BYTE) {
-         resample_linear_row_ub(srcWidth, dstWidth, srcBuffer0, srcBuffer1,
-                                dstBuffer, invertX, rowWeight);
-      }
-      else {
-         resample_linear_row_float(srcWidth, dstWidth, srcBuffer0, srcBuffer1,
-                                   dstBuffer, invertX, rowWeight);
-      }
+      free(srcBuffer0);
+      free(srcBuffer1);
+      free(dstBuffer);
 
-      /* store pixel row in destination */
-      {
-         GLubyte *dst = dstMap + dstY * dstRowStride + dstXpos * bpp;
-         if (pixelType == GL_UNSIGNED_BYTE) {
-            _mesa_pack_ubyte_rgba_row(drawFormat, dstWidth, dstBuffer, dst);
-         }
-         else {
-            _mesa_pack_float_rgba_row(drawFormat, dstWidth, dstBuffer, dst);
-         }
+      ctx->Driver.UnmapRenderbuffer(ctx, readRb);
+      if (drawRb != readRb) {
+         ctx->Driver.UnmapRenderbuffer(ctx, drawRb);
       }
    }
-
-   free(srcBuffer0);
-   free(srcBuffer1);
-   free(dstBuffer);
-
-   ctx->Driver.UnmapRenderbuffer(ctx, readRb);
-   if (drawRb != readRb) {
-      ctx->Driver.UnmapRenderbuffer(ctx, drawRb);
-   }
 }
 
 
-- 
1.7.7.6



More information about the mesa-dev mailing list