From fb5252a3518dadd51e88e87382e6510998e9e2f4 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 4 Jan 2012 16:10:14 -0800 Subject: [PATCH] swrast: Use the fast copypixels code to implement fast glBlitFramebuffer(). They were meaning to do the same thing of memcpying rows, so just write the code once. Reviewed-by: Kenneth Graunke Reviewed-by: Brian Paul --- src/mesa/swrast/s_blit.c | 167 ++++++++---------------------------- src/mesa/swrast/s_copypix.c | 13 +-- src/mesa/swrast/swrast.h | 5 ++ 3 files changed, 46 insertions(+), 139 deletions(-) diff --git a/src/mesa/swrast/s_blit.c b/src/mesa/swrast/s_blit.c index 803ad2e899d..6ad4f3fbc92 100644 --- a/src/mesa/swrast/s_blit.c +++ b/src/mesa/swrast/s_blit.c @@ -449,117 +449,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 +463,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,39 +478,46 @@ _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; } - 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]); - } - } + + swrast_render_start(ctx); + + 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); - } + } + 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); } } diff --git a/src/mesa/swrast/s_copypix.c b/src/mesa/swrast/s_copypix.c index 8fae01f079d..a14b44b9d24 100644 --- a/src/mesa/swrast/s_copypix.c +++ b/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; @@ -578,7 +578,8 @@ _swrast_CopyPixels( struct gl_context *ctx, ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F || ctx->_ImageTransferState) && - fast_copy_pixels(ctx, srcx, srcy, width, height, destx, desty, type)) { + swrast_fast_copy_pixels(ctx, srcx, srcy, width, height, destx, desty, + type)) { /* all done */ return; } diff --git a/src/mesa/swrast/swrast.h b/src/mesa/swrast/swrast.h index dd40551592f..468d22f0b88 100644 --- a/src/mesa/swrast/swrast.h +++ b/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, -- 2.30.2