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

Brian Paul brian.e.paul at gmail.com
Fri Dec 21 13:00:34 PST 2012


On Fri, Dec 21, 2012 at 1:47 PM, Anuj Phogat <anuj.phogat at gmail.com> wrote:
> 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 caused an assertion failure in
> 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.
>
> Signed-off-by: Anuj Phogat <anuj.phogat at gmail.com>
> ---
>  src/mesa/main/fbobject.c |   30 ++-
>  src/mesa/swrast/s_blit.c |  559 ++++++++++++++++++++++++---------------------
>  2 files changed, 320 insertions(+), 269 deletions(-)
>
> diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c
> index 517bf13..fed0d61 100644
> --- a/src/mesa/main/fbobject.c
> +++ b/src/mesa/main/fbobject.c
> @@ -2843,8 +2843,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 +2854,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 (int i = 0; i < numColorDrawBuffers; i++) {

Declaring 'int i' in the loop will not compile with MSVC.  And it
should probably be unsigned.


> +            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..4943be9 100644
> --- a/src/mesa/swrast/s_blit.c
> +++ b/src/mesa/swrast/s_blit.c
> @@ -111,6 +111,10 @@ 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;
>
>     const GLint srcWidth = ABS(srcX1 - srcX0);
>     const GLint dstWidth = ABS(dstX1 - dstX0);
> @@ -146,21 +150,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 +174,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 +210,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 (int i = 0; i < NumDrawBuffers; i++) {

Another declaration inside a loop.


> +      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 +512,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);
> @@ -556,151 +584,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 (int i = 0; i < drawFb->_NumColorDrawBuffers; i++) {

Another.


> +      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
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list