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 <kenneth@whitecape.org> Reviewed-by: Brian Paul <brianp@vmware.com>
This commit is contained in:
+34
-133
@@ -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;
|
||||
}
|
||||
|
||||
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 {
|
||||
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 */
|
||||
blit_linear(ctx, srcX0, srcY0, srcX1, srcY1,
|
||||
dstX0, dstY0, dstX1, dstY1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user