[Mesa-dev] [PATCH 3/3] swrast: convert blit_linear() to Map/UnmapRenderbuffer()

Jose Fonseca jfonseca at vmware.com
Mon Jan 9 10:36:27 PST 2012


Looks good to me.

Jose

----- Original Message -----
> ---
>  src/mesa/swrast/s_blit.c |  183
>  +++++++++++++++++++++++++++++++++++++++------
>  1 files changed, 158 insertions(+), 25 deletions(-)
> 
> diff --git a/src/mesa/swrast/s_blit.c b/src/mesa/swrast/s_blit.c
> index 1063024..34317cc 100644
> --- a/src/mesa/swrast/s_blit.c
> +++ b/src/mesa/swrast/s_blit.c
> @@ -423,9 +423,66 @@ resample_linear_row_ub(GLint srcWidth, GLint
> dstWidth,
>  }
>  
>  
> +/**
> + * Bilinear interpolation of two source rows.  floating point
> pixels.
> + */
> +static void
> +resample_linear_row_float(GLint srcWidth, GLint dstWidth,
> +                          const GLvoid *srcBuffer0, const GLvoid
> *srcBuffer1,
> +                          GLvoid *dstBuffer, GLboolean flip, GLfloat
> rowWeight)
> +{
> +   const GLfloat (*srcColor0)[4] = (const GLfloat (*)[4])
> srcBuffer0;
> +   const GLfloat (*srcColor1)[4] = (const GLfloat (*)[4])
> srcBuffer1;
> +   GLfloat (*dstColor)[4] = (GLfloat (*)[4]) dstBuffer;
> +   const GLfloat dstWidthF = (GLfloat) dstWidth;
> +   GLint dstCol;
> +
> +   for (dstCol = 0; dstCol < dstWidth; dstCol++) {
> +      const GLfloat srcCol = (dstCol * srcWidth) / dstWidthF;
> +      GLint srcCol0 = IFLOOR(srcCol);
> +      GLint srcCol1 = srcCol0 + 1;
> +      GLfloat colWeight = srcCol - srcCol0; /* fractional part of
> srcCol */
> +      GLfloat red, green, blue, alpha;
> +
> +      ASSERT(srcCol0 >= 0);
> +      ASSERT(srcCol0 < srcWidth);
> +      ASSERT(srcCol1 <= srcWidth);
> +
> +      if (srcCol1 == srcWidth) {
> +         /* last column fudge */
> +         srcCol1--;
> +         colWeight = 0.0;
> +      }
> +
> +      if (flip) {
> +         srcCol0 = srcWidth - 1 - srcCol0;
> +         srcCol1 = srcWidth - 1 - srcCol1;
> +      }
> +
> +      red = lerp_2d(colWeight, rowWeight,
> +                    srcColor0[srcCol0][RCOMP],
> srcColor0[srcCol1][RCOMP],
> +                    srcColor1[srcCol0][RCOMP],
> srcColor1[srcCol1][RCOMP]);
> +      green = lerp_2d(colWeight, rowWeight,
> +                    srcColor0[srcCol0][GCOMP],
> srcColor0[srcCol1][GCOMP],
> +                    srcColor1[srcCol0][GCOMP],
> srcColor1[srcCol1][GCOMP]);
> +      blue = lerp_2d(colWeight, rowWeight,
> +                    srcColor0[srcCol0][BCOMP],
> srcColor0[srcCol1][BCOMP],
> +                    srcColor1[srcCol0][BCOMP],
> srcColor1[srcCol1][BCOMP]);
> +      alpha = lerp_2d(colWeight, rowWeight,
> +                    srcColor0[srcCol0][ACOMP],
> srcColor0[srcCol1][ACOMP],
> +                    srcColor1[srcCol0][ACOMP],
> srcColor1[srcCol1][ACOMP]);
> +
> +      dstColor[dstCol][RCOMP] = red;
> +      dstColor[dstCol][GCOMP] = green;
> +      dstColor[dstCol][BCOMP] = blue;
> +      dstColor[dstCol][ACOMP] = alpha;
> +   }
> +}
> +
> +
>  
>  /**
> - * Bilinear filtered blit (color only).
> + * Bilinear filtered blit (color only, non-integer values).
>   */
>  static void
>  blit_linear(struct gl_context *ctx,
> @@ -456,23 +513,25 @@ blit_linear(struct gl_context *ctx,
>     GLint srcBufferY0 = -1, srcBufferY1 = -1;
>     GLvoid *dstBuffer;
>  
> -   switch (readRb->DataType) {
> -   case GL_UNSIGNED_BYTE:
> +   gl_format readFormat = readRb->Format;
> +   gl_format drawFormat = drawRb->Format;
> +   GLuint bpp = _mesa_get_format_bytes(readFormat);
> +
> +   GLenum pixelType;
> +
> +   GLubyte *srcMap, *dstMap;
> +   GLint srcRowStride, dstRowStride;
> +
> +
> +   /* Determine datatype for resampling */
> +   if (_mesa_get_format_max_bits(readFormat) == 8 &&
> +       _mesa_get_format_datatype(readFormat) ==
> GL_UNSIGNED_NORMALIZED) {
> +      pixelType = GL_UNSIGNED_BYTE;
>        pixelSize = 4 * sizeof(GLubyte);
> -      break;
> -   case GL_UNSIGNED_SHORT:
> -      pixelSize = 4 * sizeof(GLushort);
> -      break;
> -   case GL_UNSIGNED_INT:
> -      pixelSize = 4 * sizeof(GLuint);
> -      break;
> -   case GL_FLOAT:
> +   }
> +   else {
> +      pixelType = GL_FLOAT;
>        pixelSize = 4 * sizeof(GLfloat);
> -      break;
> -   default:
> -      _mesa_problem(ctx, "unexpected buffer type (0x%x) in
> blit_nearest",
> -                    readRb->DataType);
> -      return;
>     }
>  
>     /* Allocate the src/dst row buffers.
> @@ -497,6 +556,45 @@ 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) {
> +         _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.
> +       */
> +      ctx->Driver.MapRenderbuffer(ctx, readRb,
> +				  0, 0, readRb->Width, readRb->Height,
> +                                  GL_MAP_READ_BIT, &srcMap,
> &srcRowStride);
> +      if (!srcMap) {
> +         _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);
> +         _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;
> @@ -531,36 +629,73 @@ blit_linear(struct gl_context *ctx,
>           srcBuffer0 = srcBuffer1;
>           srcBuffer1 = tmp;
>           /* get y1 row */
> -         readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY1,
> srcBuffer1);
> +         {
> +            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);
> +            }
> +         }
>           srcBufferY0 = srcY0;
>           srcBufferY1 = srcY1;
>        }
>        else {
>           /* get both new rows */
> -         readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY0,
> srcBuffer0);
> -         readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY1,
> srcBuffer1);
> +         {
> +            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;
>        }
>  
> -      if (readRb->DataType == GL_UNSIGNED_BYTE) {
> +      if (pixelType == GL_UNSIGNED_BYTE) {
>           resample_linear_row_ub(srcWidth, dstWidth, srcBuffer0,
>           srcBuffer1,
>                                  dstBuffer, invertX, rowWeight);
>        }
>        else {
> -         _mesa_problem(ctx, "Unsupported color channel type in sw
> blit");
> -         break;
> +         resample_linear_row_float(srcWidth, dstWidth, srcBuffer0,
> srcBuffer1,
> +                                   dstBuffer, invertX, rowWeight);
>        }
>  
>        /* store pixel row in destination */
> -      drawRb->PutRow(ctx, drawRb, dstWidth, dstXpos, dstY,
> dstBuffer, NULL);
> +      {
> +         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);
> +         }
> +      }
>     }
>  
>     free(srcBuffer0);
>     free(srcBuffer1);
>     free(dstBuffer);
> +
> +   ctx->Driver.UnmapRenderbuffer(ctx, readRb);
> +   if (drawRb != readRb) {
> +      ctx->Driver.UnmapRenderbuffer(ctx, drawRb);
> +   }
>  }
>  
> +
> +
>  /**
>   * Software fallback for glBlitFramebufferEXT().
>   */
> @@ -626,10 +761,8 @@ _swrast_BlitFramebuffer(struct gl_context *ctx,
>     else {
>        ASSERT(filter == GL_LINEAR);
>        if (mask & GL_COLOR_BUFFER_BIT) {  /* depth/stencil not
>        allowed */
> -	 swrast_render_start(ctx);
>  	 blit_linear(ctx,  srcX0, srcY0, srcX1, srcY1,
>  		     dstX0, dstY0, dstX1, dstY1);
> -	 swrast_render_finish(ctx);
>        }
>     }
>  
> --
> 1.7.3.4
> 
> _______________________________________________
> 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