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

Anuj Phogat anuj.phogat at gmail.com
Fri Dec 21 13:48:59 PST 2012


On Fri, Dec 21, 2012 at 1:00 PM, Brian Paul <brian.e.paul at gmail.com> wrote:
>
> 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.
Yeah, I always forget about MSVC compilation issues with such
declarations. I'll take care of them before pushing the patches in
this series.

> > +            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