|
|
@@ -208,6 +208,11 @@ read_stencil_pixels( struct gl_context *ctx, |
|
|
|
ctx->Driver.UnmapRenderbuffer(ctx, rb); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Try to do glReadPixels of RGBA data using a simple memcpy or swizzle. |
|
|
|
* \return GL_TRUE if successful, GL_FALSE otherwise (use the slow path) |
|
|
|
*/ |
|
|
|
static GLboolean |
|
|
|
fast_read_rgba_pixels_memcpy( struct gl_context *ctx, |
|
|
|
GLint x, GLint y, |
|
|
@@ -220,9 +225,23 @@ fast_read_rgba_pixels_memcpy( struct gl_context *ctx, |
|
|
|
struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer; |
|
|
|
GLubyte *dst, *map; |
|
|
|
int dstStride, stride, j, texelBytes; |
|
|
|
|
|
|
|
if (!_mesa_format_matches_format_and_type(rb->Format, format, type, |
|
|
|
ctx->Pack.SwapBytes)) |
|
|
|
GLboolean swizzle_rb = GL_FALSE, copy_xrgb = GL_FALSE; |
|
|
|
|
|
|
|
/* XXX we could check for other swizzle/special cases here as needed */ |
|
|
|
if (rb->Format == MESA_FORMAT_RGBA8888_REV && |
|
|
|
format == GL_BGRA && |
|
|
|
type == GL_UNSIGNED_INT_8_8_8_8_REV && |
|
|
|
!ctx->Pack.SwapBytes) { |
|
|
|
swizzle_rb = GL_TRUE; |
|
|
|
} |
|
|
|
else if (rb->Format == MESA_FORMAT_XRGB8888 && |
|
|
|
format == GL_BGRA && |
|
|
|
type == GL_UNSIGNED_INT_8_8_8_8_REV && |
|
|
|
!ctx->Pack.SwapBytes) { |
|
|
|
copy_xrgb = GL_TRUE; |
|
|
|
} |
|
|
|
else if (!_mesa_format_matches_format_and_type(rb->Format, format, type, |
|
|
|
ctx->Pack.SwapBytes)) |
|
|
|
return GL_FALSE; |
|
|
|
|
|
|
|
/* If the format is unsigned normalized then we can ignore clamping |
|
|
@@ -247,10 +266,39 @@ fast_read_rgba_pixels_memcpy( struct gl_context *ctx, |
|
|
|
} |
|
|
|
|
|
|
|
texelBytes = _mesa_get_format_bytes(rb->Format); |
|
|
|
for (j = 0; j < height; j++) { |
|
|
|
memcpy(dst, map, width * texelBytes); |
|
|
|
dst += dstStride; |
|
|
|
map += stride; |
|
|
|
|
|
|
|
if (swizzle_rb) { |
|
|
|
/* swap R/B */ |
|
|
|
for (j = 0; j < height; j++) { |
|
|
|
int i; |
|
|
|
for (i = 0; i < width; i++) { |
|
|
|
GLuint *dst4 = (GLuint *) dst, *map4 = (GLuint *) map; |
|
|
|
GLuint pixel = map4[i]; |
|
|
|
dst4[i] = (pixel & 0xff00ff00) |
|
|
|
| ((pixel & 0x00ff0000) >> 16) |
|
|
|
| ((pixel & 0x000000ff) << 16); |
|
|
|
} |
|
|
|
dst += dstStride; |
|
|
|
map += stride; |
|
|
|
} |
|
|
|
} else if (copy_xrgb) { |
|
|
|
/* convert xrgb -> argb */ |
|
|
|
for (j = 0; j < height; j++) { |
|
|
|
GLuint *dst4 = (GLuint *) dst, *map4 = (GLuint *) map; |
|
|
|
int i; |
|
|
|
for (i = 0; i < width; i++) { |
|
|
|
dst4[i] = map4[i] | 0xff000000; /* set A=0xff */ |
|
|
|
} |
|
|
|
dst += dstStride; |
|
|
|
map += stride; |
|
|
|
} |
|
|
|
} else { |
|
|
|
/* just memcpy */ |
|
|
|
for (j = 0; j < height; j++) { |
|
|
|
memcpy(dst, map, width * texelBytes); |
|
|
|
dst += dstStride; |
|
|
|
map += stride; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
ctx->Driver.UnmapRenderbuffer(ctx, rb); |