diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mesa/drivers/dri/intel/intel_tex_image.c | 105 |
1 files changed, 102 insertions, 3 deletions
diff --git a/src/mesa/drivers/dri/intel/intel_tex_image.c b/src/mesa/drivers/dri/intel/intel_tex_image.c index 7e57e99be63..0199837cbe4 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_image.c +++ b/src/mesa/drivers/dri/intel/intel_tex_image.c @@ -6,6 +6,7 @@ #include "main/bufferobj.h" #include "main/convolve.h" #include "main/context.h" +#include "main/image.h" #include "main/texcompress.h" #include "main/texstore.h" #include "main/texgetimage.h" @@ -619,6 +620,100 @@ intelCompressedTexImage2D( GLcontext *ctx, GLenum target, GLint level, /** + * Try to use memcpy() to do a glGetTexImage(). + * \return GL_TRUE if done, GL_FALSE otherwise + */ +static GLboolean +memcpy_get_tex_image(GLcontext *ctx, GLenum target, GLint level, + GLenum format, GLenum type, GLvoid * pixels, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + GLboolean memCopy = GL_FALSE; + + /* Texture image should have been mapped already */ + assert(texImage->Data); + + /* + * Check if the src/dst formats are compatible. + * Also note that GL's pixel transfer ops don't apply to glGetTexImage() + * so we don't have to worry about those. + */ + if ((texObj->Target == GL_TEXTURE_1D || + texObj->Target == GL_TEXTURE_2D || + texObj->Target == GL_TEXTURE_RECTANGLE || + (texObj->Target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && + texObj->Target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))) { + if (texImage->TexFormat == MESA_FORMAT_ARGB8888 && + format == GL_BGRA && + type == GL_UNSIGNED_BYTE && + _mesa_little_endian()) { + memCopy = GL_TRUE; + } + else if (texImage->TexFormat == MESA_FORMAT_AL88 && + format == GL_LUMINANCE_ALPHA && + type == GL_UNSIGNED_BYTE && + _mesa_little_endian()) { + memCopy = GL_TRUE; + } + else if (texImage->TexFormat == MESA_FORMAT_L8 && + format == GL_LUMINANCE && + type == GL_UNSIGNED_BYTE) { + memCopy = GL_TRUE; + } + else if (texImage->TexFormat == MESA_FORMAT_A8 && + format == GL_ALPHA && + type == GL_UNSIGNED_BYTE) { + memCopy = GL_TRUE; + } + } + + if (memCopy) { + struct gl_pixelstore_attrib *pack = &ctx->Pack; + + if (_mesa_is_bufferobj(pack->BufferObj)) { + /* Packing texture image into a PBO */ + GLubyte *buf = (GLubyte *) + ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, + GL_WRITE_ONLY_ARB, pack->BufferObj); + if (!buf) { + /* out of memory or other unexpected error */ + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage(map PBO failed)"); + return GL_TRUE; /* failed, but done */ + } + pixels = ADD_POINTERS(buf, pixels); + } + + { + const GLuint bpp = _mesa_get_format_bytes(texImage->TexFormat); + const GLuint bytesPerRow = texImage->Width * bpp; + GLubyte *dst = + _mesa_image_address2d(&ctx->Pack, pixels, texImage->Width, + texImage->Height, format, type, 0, 0); + const GLint dstRowStride = + _mesa_image_row_stride(&ctx->Pack, texImage->Width, format, type); + const GLubyte *src = texImage->Data; + const GLint srcRowStride = texImage->RowStride * bpp; + GLuint row; + + printf("Fast getteximage!\n"); + for (row = 0; row < texImage->Height; row++) { + memcpy(dst, src, bytesPerRow); + dst += dstRowStride; + src += srcRowStride; + } + } + + if (_mesa_is_bufferobj(pack->BufferObj)) { + ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, pack->BufferObj); + } + } + + return memCopy; +} + + +/** * Need to map texture image into memory before copying image data, * then unmap it. */ @@ -667,9 +762,13 @@ intel_get_tex_image(GLcontext * ctx, GLenum target, GLint level, if (compressed) { _mesa_get_compressed_teximage(ctx, target, level, pixels, texObj, texImage); - } else { - _mesa_get_teximage(ctx, target, level, format, type, pixels, - texObj, texImage); + } + else { + if (!memcpy_get_tex_image(ctx, target, level, format, type, pixels, + texObj, texImage)) { + _mesa_get_teximage(ctx, target, level, format, type, pixels, + texObj, texImage); + } } |