Przeglądaj źródła

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>
tags/mesa-8.0-rc1
Eric Anholt 13 lat temu
rodzic
commit
fb5252a351
3 zmienionych plików z 46 dodań i 139 usunięć
  1. 34
    133
      src/mesa/swrast/s_blit.c
  2. 7
    6
      src/mesa/swrast/s_copypix.c
  3. 5
    0
      src/mesa/swrast/swrast.h

+ 34
- 133
src/mesa/swrast/s_blit.c Wyświetl plik

@@ -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);
}
}


+ 7
- 6
src/mesa/swrast/s_copypix.c Wyświetl plik

@@ -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;
}

+ 5
- 0
src/mesa/swrast/swrast.h Wyświetl plik

@@ -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,

Ładowanie…
Anuluj
Zapisz