aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/mesa/swrast
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/mesa/swrast')
-rw-r--r--mesalib/src/mesa/swrast/s_blit.c352
-rw-r--r--mesalib/src/mesa/swrast/s_copypix.c27
-rw-r--r--mesalib/src/mesa/swrast/s_depth.c9
-rw-r--r--mesalib/src/mesa/swrast/s_span.c2
-rw-r--r--mesalib/src/mesa/swrast/swrast.h5
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,