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

Anuj Phogat anuj.phogat at gmail.com
Tue Jan 8 03:34:50 PST 2013


On Tue, Jan 8, 2013 at 5:22 AM, Kenneth Graunke <kenneth at whitecape.org> wrote:
> On 01/07/2013 08:16 AM, Anuj Phogat 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.
>
>
> Could you please split this into two patches?
Yes. I'll follow up with splitted patches.
>
>> 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."
>>          */
>
>
> How about:
>
>       if (!colorReadRb || numColorDrawBuffers == 0) {
>          mask &= ~GL_COLOR_BUFFER_BIT;
>       } else {
>          ...your loop and error checking...
>       }
>
> Then, colorReadRb/colorDrawRb don't need to be at global scope, and you
> can...
>
>
>> -      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++) {
>
>
> ...just declare them at the start of this loop (which should be valid even
> in C89):
>
>             const struct gl_renderbuffer *colorDrawRb =
>                ctx->DrawBuffer->_ColorDrawBuffers[i];
>             if (!colorDrawRb)
>                continue;
>
>
Made few changes as per your suggestions.
>> +            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;
>> +            }
>
>
> You also need to move the multisampled compatible_resolve_formats (from
> below) into this loop.  Right here would be good.
right.
>
>> +         }
>> +      }
>> +
>> +      if (colorDrawRb == NULL) {
>> +        colorReadRb = NULL;
>> +        mask &= ~GL_COLOR_BUFFER_BIT;
>>         }
>>      }
>>      else {
>
>
> The debug code at the bottom of the function will break since it still uses
> colorReadRb and colorDrawRb, but given that it's not paying attention to
> MRTs, it's probably already broken.  Maybe just comment it...or add a
> similar loop...
I'll fix the debug code to print all active color draw buffers.
>
>> 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) ||
>
>
> I'm not sure if you need this readRb == drawRb check anymore.  It seems like
> you just want the texture checks below.
>
Checking readRb == drawRb handles the case when read and draw color
attachments are same renderbuffer. Texture checks below handles the
case when read and draw color attachments are same texture.
> Or maybe it needs to be &&...
While debugging blitframebuffer test cases I observed few cases where
readRb != drawRb but readAtt->Texture == drawAtt->Texture. So, the two
conditions should be separated by ||.
>
>> +          (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) ||
>
>
> Ditto.  Otherwise, the swrast changes look okay...
>
>
>> +          (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);
>> -   }
>>   }
>>
>>
>>
>


More information about the mesa-dev mailing list