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