diff options
Diffstat (limited to 'mesalib/src/mesa/swrast')
-rw-r--r-- | mesalib/src/mesa/swrast/s_blit.c | 352 | ||||
-rw-r--r-- | mesalib/src/mesa/swrast/s_copypix.c | 27 | ||||
-rw-r--r-- | mesalib/src/mesa/swrast/s_depth.c | 9 | ||||
-rw-r--r-- | mesalib/src/mesa/swrast/s_span.c | 2 | ||||
-rw-r--r-- | mesalib/src/mesa/swrast/swrast.h | 5 |
5 files changed, 200 insertions, 195 deletions
diff --git a/mesalib/src/mesa/swrast/s_blit.c b/mesalib/src/mesa/swrast/s_blit.c index 803ad2e89..1063024fb 100644 --- a/mesalib/src/mesa/swrast/s_blit.c +++ b/mesalib/src/mesa/swrast/s_blit.c @@ -27,6 +27,8 @@ #include "main/condrender.h" #include "main/image.h" #include "main/macros.h" +#include "main/format_unpack.h" +#include "main/format_pack.h" #include "s_context.h" @@ -122,10 +124,18 @@ blit_nearest(struct gl_context *ctx, const GLboolean invertX = (srcX1 < srcX0) ^ (dstX1 < dstX0); const GLboolean invertY = (srcY1 < srcY0) ^ (dstY1 < dstY0); - + enum mode { + DIRECT, + UNPACK_RGBA_FLOAT, + UNPACK_Z_FLOAT, + UNPACK_Z_INT, + UNPACK_S, + } mode; + GLubyte *srcMap, *dstMap; + GLint srcRowStride, dstRowStride; GLint dstRow; - GLint comps, pixelSize; + GLint pixelSize; GLvoid *srcBuffer, *dstBuffer; GLint prevY = -1; @@ -138,42 +148,43 @@ blit_nearest(struct gl_context *ctx, case GL_COLOR_BUFFER_BIT: readRb = ctx->ReadBuffer->_ColorReadBuffer; drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0]; - comps = 4; + + if (readRb->Format == drawRb->Format) { + mode = DIRECT; + pixelSize = _mesa_get_format_bytes(readRb->Format); + } else { + mode = UNPACK_RGBA_FLOAT; + pixelSize = 16; + } + break; case GL_DEPTH_BUFFER_BIT: - readRb = ctx->ReadBuffer->_DepthBuffer; - drawRb = ctx->DrawBuffer->_DepthBuffer; - comps = 1; + readRb = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; + drawRb = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; + + /* 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 + * masking for things like DEPTH copies of Z24S8. + */ + if (readRb->Format == MESA_FORMAT_Z32_FLOAT || + readRb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) { + mode = UNPACK_Z_FLOAT; + } else { + mode = UNPACK_Z_INT; + } + pixelSize = 4; break; case GL_STENCIL_BUFFER_BIT: - readRb = ctx->ReadBuffer->_StencilBuffer; - drawRb = ctx->DrawBuffer->_StencilBuffer; - comps = 1; + readRb = ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer; + drawRb = ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer; + mode = UNPACK_S; + pixelSize = 1; break; default: _mesa_problem(ctx, "unexpected buffer in blit_nearest()"); return; } - switch (readRb->DataType) { - case GL_UNSIGNED_BYTE: - pixelSize = comps * sizeof(GLubyte); - break; - case GL_UNSIGNED_SHORT: - pixelSize = comps * sizeof(GLushort); - break; - case GL_UNSIGNED_INT: - pixelSize = comps * sizeof(GLuint); - break; - case GL_FLOAT: - pixelSize = comps * sizeof(GLfloat); - break; - default: - _mesa_problem(ctx, "unexpected buffer type (0x%x) in blit_nearest", - readRb->DataType); - return; - } - /* choose row resampler */ switch (pixelSize) { case 1: @@ -197,6 +208,62 @@ 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; + } + + 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; + } + else { + /* copy in normal (bottom->up) order */ + srcRowStride = rowStride; + dstRowStride = rowStride; + } + } + 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"); + 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; + } + } + /* allocate the src/dst row buffers */ srcBuffer = malloc(pixelSize * srcWidth); if (!srcBuffer) { @@ -211,9 +278,8 @@ blit_nearest(struct gl_context *ctx, } for (dstRow = 0; dstRow < dstHeight; dstRow++) { - const GLint dstY = dstYpos + dstRow; GLint srcRow = (dstRow * srcHeight) / dstHeight; - GLint srcY; + GLubyte *dstRowStart = dstMap + dstRowStride * dstRow; ASSERT(srcRow >= 0); ASSERT(srcRow < srcHeight); @@ -222,21 +288,67 @@ blit_nearest(struct gl_context *ctx, srcRow = srcHeight - 1 - srcRow; } - srcY = srcYpos + srcRow; - /* get pixel row from source and resample to match dest width */ - if (prevY != srcY) { - readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY, srcBuffer); + 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 = srcY; + prevY = srcRow; } /* store pixel row in destination */ - drawRb->PutRow(ctx, drawRb, dstWidth, dstXpos, dstY, dstBuffer, NULL); + 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); + + ctx->Driver.UnmapRenderbuffer(ctx, readRb); + if (drawRb != readRb) { + ctx->Driver.UnmapRenderbuffer(ctx, drawRb); + } } @@ -449,117 +561,6 @@ blit_linear(struct gl_context *ctx, free(dstBuffer); } - -/** - * Simple case: Blit color, depth or stencil with no scaling or flipping. - * XXX we could easily support vertical flipping here. - */ -static void -simple_blit(struct gl_context *ctx, - GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, - GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, - GLbitfield buffer) -{ - struct gl_renderbuffer *readRb, *drawRb; - const GLint width = srcX1 - srcX0; - const GLint height = srcY1 - srcY0; - GLint row, srcY, dstY, yStep; - GLint comps, bytesPerRow; - void *rowBuffer; - - /* only one buffer */ - ASSERT(_mesa_bitcount(buffer) == 1); - /* no flipping checks */ - ASSERT(srcX0 < srcX1); - ASSERT(srcY0 < srcY1); - ASSERT(dstX0 < dstX1); - ASSERT(dstY0 < dstY1); - /* size checks */ - ASSERT(srcX1 - srcX0 == dstX1 - dstX0); - ASSERT(srcY1 - srcY0 == dstY1 - dstY0); - - /* From the GL_ARB_framebuffer_object spec: - * - * "If the source and destination buffers are identical, and the source - * and destination rectangles overlap, the result of the blit operation - * is undefined." - * - * However, we provide the expected result anyway by flipping the order of - * the memcpy of rows. - */ - if (srcY0 > dstY0) { - /* src above dst: copy bottom-to-top */ - yStep = 1; - srcY = srcY0; - dstY = dstY0; - } - else { - /* src below dst: copy top-to-bottom */ - yStep = -1; - srcY = srcY1 - 1; - dstY = dstY1 - 1; - } - - switch (buffer) { - case GL_COLOR_BUFFER_BIT: - readRb = ctx->ReadBuffer->_ColorReadBuffer; - drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0]; - comps = 4; - break; - case GL_DEPTH_BUFFER_BIT: - readRb = ctx->ReadBuffer->_DepthBuffer; - drawRb = ctx->DrawBuffer->_DepthBuffer; - comps = 1; - break; - case GL_STENCIL_BUFFER_BIT: - readRb = ctx->ReadBuffer->_StencilBuffer; - drawRb = ctx->DrawBuffer->_StencilBuffer; - comps = 1; - break; - default: - _mesa_problem(ctx, "unexpected buffer in simple_blit()"); - return; - } - - ASSERT(readRb->DataType == drawRb->DataType); - - /* compute bytes per row */ - switch (readRb->DataType) { - case GL_UNSIGNED_BYTE: - bytesPerRow = comps * width * sizeof(GLubyte); - break; - case GL_UNSIGNED_SHORT: - bytesPerRow = comps * width * sizeof(GLushort); - break; - case GL_UNSIGNED_INT: - bytesPerRow = comps * width * sizeof(GLuint); - break; - case GL_FLOAT: - bytesPerRow = comps * width * sizeof(GLfloat); - break; - default: - _mesa_problem(ctx, "unexpected buffer type in simple_blit"); - return; - } - - /* allocate the row buffer */ - rowBuffer = malloc(bytesPerRow); - if (!rowBuffer) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT"); - return; - } - - for (row = 0; row < height; row++) { - readRb->GetRow(ctx, readRb, width, srcX0, srcY, rowBuffer); - drawRb->PutRow(ctx, drawRb, width, dstX0, dstY, rowBuffer, NULL); - srcY += yStep; - dstY += yStep; - } - - free(rowBuffer); -} - - /** * Software fallback for glBlitFramebufferEXT(). */ @@ -574,6 +575,11 @@ _swrast_BlitFramebuffer(struct gl_context *ctx, GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT }; + static const GLenum buffer_enums[3] = { + GL_COLOR, + GL_DEPTH, + GL_STENCIL, + }; GLint i; if (!_mesa_clip_blit(ctx, &srcX0, &srcY0, &srcX1, &srcY1, @@ -584,41 +590,47 @@ _swrast_BlitFramebuffer(struct gl_context *ctx, if (SWRAST_CONTEXT(ctx)->NewState) _swrast_validate_derived(ctx); - swrast_render_start(ctx); - + /* First, try covering whatever buffers possible using the fast 1:1 copy + * path. + */ if (srcX1 - srcX0 == dstX1 - dstX0 && srcY1 - srcY0 == dstY1 - dstY0 && srcX0 < srcX1 && srcY0 < srcY1 && dstX0 < dstX1 && dstY0 < dstY1) { - /* no stretching or flipping. - * filter doesn't matter. - */ for (i = 0; i < 3; i++) { if (mask & buffers[i]) { - simple_blit(ctx, srcX0, srcY0, srcX1, srcY1, - dstX0, dstY0, dstX1, dstY1, buffers[i]); - } + if (swrast_fast_copy_pixels(ctx, + srcX0, srcY0, + srcX1 - srcX0, srcY1 - srcY0, + dstX0, dstY0, + buffer_enums[i])) { + mask &= ~buffers[i]; + } + } + } + + if (!mask) + return; + } + + if (filter == GL_NEAREST) { + for (i = 0; i < 3; i++) { + if (mask & buffers[i]) { + blit_nearest(ctx, srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, buffers[i]); + } } } else { - if (filter == GL_NEAREST) { - for (i = 0; i < 3; i++) { - if (mask & buffers[i]) { - blit_nearest(ctx, srcX0, srcY0, srcX1, srcY1, - dstX0, dstY0, dstX1, dstY1, buffers[i]); - } - } - } - else { - ASSERT(filter == GL_LINEAR); - if (mask & GL_COLOR_BUFFER_BIT) { /* depth/stencil not allowed */ - blit_linear(ctx, srcX0, srcY0, srcX1, srcY1, - dstX0, dstY0, dstX1, dstY1); - } + 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); } } - swrast_render_finish(ctx); } diff --git a/mesalib/src/mesa/swrast/s_copypix.c b/mesalib/src/mesa/swrast/s_copypix.c index 1dc4286a3..1e0f9fe7d 100644 --- a/mesalib/src/mesa/swrast/s_copypix.c +++ b/mesalib/src/mesa/swrast/s_copypix.c @@ -422,13 +422,13 @@ copy_stencil_pixels( struct gl_context *ctx, GLint srcx, GLint srcy, /** - * Try to do a fast copy pixels with memcpy. + * Try to do a fast 1:1 blit with memcpy. * \return GL_TRUE if successful, GL_FALSE otherwise. */ -static GLboolean -fast_copy_pixels(struct gl_context *ctx, - GLint srcX, GLint srcY, GLsizei width, GLsizei height, - GLint dstX, GLint dstY, GLenum type) +GLboolean +swrast_fast_copy_pixels(struct gl_context *ctx, + GLint srcX, GLint srcY, GLsizei width, GLsizei height, + GLint dstX, GLint dstY, GLenum type) { struct gl_framebuffer *srcFb = ctx->ReadBuffer; struct gl_framebuffer *dstFb = ctx->DrawBuffer; @@ -438,14 +438,6 @@ fast_copy_pixels(struct gl_context *ctx, GLubyte *srcMap, *dstMap; GLint srcRowStride, dstRowStride; - if (SWRAST_CONTEXT(ctx)->_RasterMask != 0x0 || - ctx->Pixel.ZoomX != 1.0F || - ctx->Pixel.ZoomY != 1.0F || - ctx->_ImageTransferState) { - /* can't handle these */ - return GL_FALSE; - } - if (type == GL_COLOR) { if (dstFb->_NumColorDrawBuffers != 1) return GL_FALSE; @@ -508,7 +500,7 @@ fast_copy_pixels(struct gl_context *ctx, srcRb->Width, srcRb->Height, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, &map, &rowStride); - if (!srcMap) { + if (!map) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels"); return GL_TRUE; /* don't retry with slow path */ } @@ -582,7 +574,12 @@ _swrast_CopyPixels( struct gl_context *ctx, if (swrast->NewState) _swrast_validate_derived( ctx ); - if (fast_copy_pixels(ctx, srcx, srcy, width, height, destx, desty, type)) { + if (!(SWRAST_CONTEXT(ctx)->_RasterMask != 0x0 || + ctx->Pixel.ZoomX != 1.0F || + ctx->Pixel.ZoomY != 1.0F || + ctx->_ImageTransferState) && + swrast_fast_copy_pixels(ctx, srcx, srcy, width, height, destx, desty, + type)) { /* all done */ return; } diff --git a/mesalib/src/mesa/swrast/s_depth.c b/mesalib/src/mesa/swrast/s_depth.c index f87adaa84..53f21cb69 100644 --- a/mesalib/src/mesa/swrast/s_depth.c +++ b/mesalib/src/mesa/swrast/s_depth.c @@ -489,7 +489,6 @@ _swrast_clear_depth_buffer(struct gl_context *ctx) { struct gl_renderbuffer *rb = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; - GLuint clearValue; GLint x, y, width, height; GLubyte *map; GLint rowStride, i, j; @@ -500,14 +499,6 @@ _swrast_clear_depth_buffer(struct gl_context *ctx) return; } - /* compute integer clearing value */ - if (ctx->Depth.Clear == 1.0) { - clearValue = ctx->DrawBuffer->_DepthMax; - } - else { - clearValue = (GLuint) (ctx->Depth.Clear * ctx->DrawBuffer->_DepthMaxF); - } - /* compute region to clear */ x = ctx->DrawBuffer->_Xmin; y = ctx->DrawBuffer->_Ymin; diff --git a/mesalib/src/mesa/swrast/s_span.c b/mesalib/src/mesa/swrast/s_span.c index 4124e444e..8f02eeae7 100644 --- a/mesalib/src/mesa/swrast/s_span.c +++ b/mesalib/src/mesa/swrast/s_span.c @@ -776,7 +776,7 @@ clip_span( struct gl_context *ctx, SWspan *span ) span->intTex[1] += leftClip * span->intTexStep[1]; #define SHIFT_ARRAY(ARRAY, SHIFT, LEN) \ - memcpy(ARRAY, ARRAY + (SHIFT), (LEN) * sizeof(ARRAY[0])) + memmove(ARRAY, ARRAY + (SHIFT), (LEN) * sizeof(ARRAY[0])) for (i = 0; i < FRAG_ATTRIB_MAX; i++) { if (span->arrayAttribs & (1 << i)) { diff --git a/mesalib/src/mesa/swrast/swrast.h b/mesalib/src/mesa/swrast/swrast.h index dd4055159..468d22f0b 100644 --- a/mesalib/src/mesa/swrast/swrast.h +++ b/mesalib/src/mesa/swrast/swrast.h @@ -110,6 +110,11 @@ _swrast_CopyPixels( struct gl_context *ctx, GLsizei width, GLsizei height, GLenum type ); +extern GLboolean +swrast_fast_copy_pixels(struct gl_context *ctx, + GLint srcX, GLint srcY, GLsizei width, GLsizei height, + GLint dstX, GLint dstY, GLenum type); + extern void _swrast_DrawPixels( struct gl_context *ctx, GLint x, GLint y, |