[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