X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fmesa%2Fmain%2Ftexgetimage.c;h=69067df9f5dde6b0422395cd772eb07a76fe15b5;hb=c73245882c7ff1277b190b97f093f7b423a22f10;hp=8bbea831c31b09c0746f2a88ba780d4f88766012;hpb=1a4f398a63f6b7b9258a0a63ba22fb0e95937c54;p=mesa.git diff --git a/src/mesa/main/texgetimage.c b/src/mesa/main/texgetimage.c index 8bbea831c31..69067df9f5d 100644 --- a/src/mesa/main/texgetimage.c +++ b/src/mesa/main/texgetimage.c @@ -35,6 +35,7 @@ #include "context.h" #include "formats.h" #include "format_unpack.h" +#include "glformats.h" #include "image.h" #include "mfeatures.h" #include "mtypes.h" @@ -79,7 +80,7 @@ get_tex_depth(struct gl_context *ctx, GLuint dimensions, const GLint height = texImage->Height; const GLint depth = texImage->Depth; GLint img, row; - GLfloat *depthRow = (GLfloat *) malloc(width * sizeof(GLfloat)); + GLfloat *depthRow = malloc(width * sizeof(GLfloat)); if (!depthRow) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); @@ -228,6 +229,8 @@ get_tex_rgba_compressed(struct gl_context *ctx, GLuint dimensions, const gl_format texFormat = _mesa_get_srgb_format_linear(texImage->TexFormat); const GLenum baseFormat = _mesa_get_format_base_format(texFormat); + const GLenum destBaseFormat = _mesa_base_tex_format(ctx, format); + GLenum rebaseFormat = GL_NONE; const GLuint width = texImage->Width; const GLuint height = texImage->Height; const GLuint depth = texImage->Depth; @@ -235,7 +238,7 @@ get_tex_rgba_compressed(struct gl_context *ctx, GLuint dimensions, GLuint row; /* Decompress into temp float buffer, then pack into user buffer */ - tempImage = (GLfloat *) malloc(width * height * depth + tempImage = malloc(width * height * depth * 4 * sizeof(GLfloat)); if (!tempImage) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()"); @@ -259,18 +262,37 @@ get_tex_rgba_compressed(struct gl_context *ctx, GLuint dimensions, } else { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); + free(tempImage); + return; } } if (baseFormat == GL_LUMINANCE || + baseFormat == GL_INTENSITY || baseFormat == GL_LUMINANCE_ALPHA) { - /* Set green and blue to zero since the pack function here will - * compute L=R+G+B. + /* If a luminance (or intensity) texture is read back as RGB(A), the + * returned value should be (L,0,0,1), not (L,L,L,1). Set rebaseFormat + * here to get G=B=0. */ - GLuint i; - for (i = 0; i < width * height; i++) { - tempImage[i * 4 + GCOMP] = tempImage[i * 4 + BCOMP] = 0.0f; - } + rebaseFormat = texImage->_BaseFormat; + } + else if ((baseFormat == GL_RGBA || + baseFormat == GL_RGB || + baseFormat == GL_RG) && + (destBaseFormat == GL_LUMINANCE || + destBaseFormat == GL_LUMINANCE_ALPHA || + destBaseFormat == GL_LUMINANCE_INTEGER_EXT || + destBaseFormat == GL_LUMINANCE_ALPHA_INTEGER_EXT)) { + /* If we're reading back an RGB(A) texture as luminance then we need + * to return L=tex(R). Note, that's different from glReadPixels which + * returns L=R+G+B. + */ + rebaseFormat = GL_LUMINANCE_ALPHA; /* this covers GL_LUMINANCE too */ + } + + if (rebaseFormat) { + _mesa_rebase_rgba_float(width * height, (GLfloat (*)[4]) tempImage, + rebaseFormat); } srcRow = tempImage; @@ -301,15 +323,18 @@ get_tex_rgba_uncompressed(struct gl_context *ctx, GLuint dimensions, const gl_format texFormat = _mesa_get_srgb_format_linear(texImage->TexFormat); const GLuint width = texImage->Width; + const GLenum destBaseFormat = _mesa_base_tex_format(ctx, format); + GLenum rebaseFormat = GL_NONE; GLuint height = texImage->Height; GLuint depth = texImage->Depth; GLuint img, row; GLfloat (*rgba)[4]; GLuint (*rgba_uint)[4]; - GLboolean is_integer = _mesa_is_format_integer_color(texImage->TexFormat); + GLboolean tex_is_integer = _mesa_is_format_integer_color(texImage->TexFormat); + GLboolean tex_is_uint = _mesa_is_format_unsigned(texImage->TexFormat); /* Allocate buffer for one row of texels */ - rgba = (GLfloat (*)[4]) malloc(4 * width * sizeof(GLfloat)); + rgba = malloc(4 * width * sizeof(GLfloat)); rgba_uint = (GLuint (*)[4]) rgba; if (!rgba) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()"); @@ -321,6 +346,29 @@ get_tex_rgba_uncompressed(struct gl_context *ctx, GLuint dimensions, height = 1; } + if (texImage->_BaseFormat == GL_LUMINANCE || + texImage->_BaseFormat == GL_INTENSITY || + texImage->_BaseFormat == GL_LUMINANCE_ALPHA) { + /* If a luminance (or intensity) texture is read back as RGB(A), the + * returned value should be (L,0,0,1), not (L,L,L,1). Set rebaseFormat + * here to get G=B=0. + */ + rebaseFormat = texImage->_BaseFormat; + } + else if ((texImage->_BaseFormat == GL_RGBA || + texImage->_BaseFormat == GL_RGB || + texImage->_BaseFormat == GL_RG) && + (destBaseFormat == GL_LUMINANCE || + destBaseFormat == GL_LUMINANCE_ALPHA || + destBaseFormat == GL_LUMINANCE_INTEGER_EXT || + destBaseFormat == GL_LUMINANCE_ALPHA_INTEGER_EXT)) { + /* If we're reading back an RGB(A) texture as luminance then we need + * to return L=tex(R). Note, that's different from glReadPixels which + * returns L=R+G+B. + */ + rebaseFormat = GL_LUMINANCE_ALPHA; /* this covers GL_LUMINANCE too */ + } + for (img = 0; img < depth; img++) { GLubyte *srcMap; GLint rowstride; @@ -336,78 +384,23 @@ get_tex_rgba_uncompressed(struct gl_context *ctx, GLuint dimensions, width, height, format, type, img, row, 0); - if (is_integer) { + if (tex_is_integer) { _mesa_unpack_uint_rgba_row(texFormat, width, src, rgba_uint); - - if (texImage->_BaseFormat == GL_ALPHA) { - GLuint col; - for (col = 0; col < width; col++) { - rgba_uint[col][RCOMP] = 0; - rgba_uint[col][GCOMP] = 0; - rgba_uint[col][BCOMP] = 0; - } - } - else if (texImage->_BaseFormat == GL_LUMINANCE) { - GLuint col; - for (col = 0; col < width; col++) { - rgba_uint[col][GCOMP] = 0; - rgba_uint[col][BCOMP] = 0; - rgba_uint[col][ACOMP] = 1; - } - } - else if (texImage->_BaseFormat == GL_LUMINANCE_ALPHA) { - GLuint col; - for (col = 0; col < width; col++) { - rgba_uint[col][GCOMP] = 0; - rgba_uint[col][BCOMP] = 0; - } - } - else if (texImage->_BaseFormat == GL_INTENSITY) { - GLuint col; - for (col = 0; col < width; col++) { - rgba_uint[col][GCOMP] = 0; - rgba_uint[col][BCOMP] = 0; - rgba_uint[col][ACOMP] = 1; - } - } - - _mesa_pack_rgba_span_int(ctx, width, rgba_uint, - format, type, dest); + if (rebaseFormat) + _mesa_rebase_rgba_uint(width, rgba_uint, rebaseFormat); + if (tex_is_uint) { + _mesa_pack_rgba_span_from_uints(ctx, width, + (GLuint (*)[4]) rgba_uint, + format, type, dest); + } else { + _mesa_pack_rgba_span_from_ints(ctx, width, + (GLint (*)[4]) rgba_uint, + format, type, dest); + } } else { _mesa_unpack_rgba_row(texFormat, width, src, rgba); - - if (texImage->_BaseFormat == GL_ALPHA) { - GLuint col; - for (col = 0; col < width; col++) { - rgba[col][RCOMP] = 0.0F; - rgba[col][GCOMP] = 0.0F; - rgba[col][BCOMP] = 0.0F; - } - } - else if (texImage->_BaseFormat == GL_LUMINANCE) { - GLuint col; - for (col = 0; col < width; col++) { - rgba[col][GCOMP] = 0.0F; - rgba[col][BCOMP] = 0.0F; - rgba[col][ACOMP] = 1.0F; - } - } - else if (texImage->_BaseFormat == GL_LUMINANCE_ALPHA) { - GLuint col; - for (col = 0; col < width; col++) { - rgba[col][GCOMP] = 0.0F; - rgba[col][BCOMP] = 0.0F; - } - } - else if (texImage->_BaseFormat == GL_INTENSITY) { - GLuint col; - for (col = 0; col < width; col++) { - rgba[col][GCOMP] = 0.0F; - rgba[col][BCOMP] = 0.0F; - rgba[col][ACOMP] = 1.0F; - } - } - + if (rebaseFormat) + _mesa_rebase_rgba_float(width, rgba, rebaseFormat); _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, format, type, dest, &ctx->Pack, transferOps); @@ -451,15 +444,6 @@ get_tex_rgba(struct gl_context *ctx, GLuint dimensions, transferOps |= IMAGE_CLAMP_BIT; } } - /* This applies to RGB, RGBA textures. if the format is either LUMINANCE - * or LUMINANCE ALPHA, luminance (L) is computed as L=R+G+B .we need to - * clamp the sum to [0,1]. - */ - else if ((format == GL_LUMINANCE || - format == GL_LUMINANCE_ALPHA) && - dataType == GL_UNSIGNED_NORMALIZED) { - transferOps |= IMAGE_CLAMP_BIT; - } if (_mesa_is_format_compressed(texImage->TexFormat)) { get_tex_rgba_compressed(ctx, dimensions, format, type, @@ -674,6 +658,36 @@ _mesa_get_compressed_teximage(struct gl_context *ctx, } +/** + * Validate the texture target enum supplied to glTexImage or + * glCompressedTexImage. + */ +static GLboolean +legal_getteximage_target(struct gl_context *ctx, GLenum target) +{ + switch (target) { + case GL_TEXTURE_1D: + case GL_TEXTURE_2D: + case GL_TEXTURE_3D: + return GL_TRUE; + case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: + return ctx->Extensions.ARB_texture_cube_map; + case GL_TEXTURE_RECTANGLE_NV: + return ctx->Extensions.NV_texture_rectangle; + case GL_TEXTURE_1D_ARRAY_EXT: + case GL_TEXTURE_2D_ARRAY_EXT: + return (ctx->Extensions.MESA_texture_array || + ctx->Extensions.EXT_texture_array); + default: + return GL_FALSE; + } +} + /** * Do error checking for a glGetTexImage() call. @@ -690,11 +704,12 @@ getteximage_error_check(struct gl_context *ctx, GLenum target, GLint level, const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2; GLenum baseFormat, err; - if (maxLevels == 0) { + if (!legal_getteximage_target(ctx, target)) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target=0x%x)", target); return GL_TRUE; } + assert(maxLevels != 0); if (level < 0 || level >= maxLevels) { _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" ); return GL_TRUE; @@ -708,7 +723,7 @@ getteximage_error_check(struct gl_context *ctx, GLenum target, GLint level, texObj = _mesa_get_current_tex_object(ctx, target); - if (!texObj || _mesa_is_proxy_texture(target)) { + if (!texObj) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)"); return GL_TRUE; } @@ -852,25 +867,19 @@ getcompressedteximage_error_check(struct gl_context *ctx, GLenum target, const GLint maxLevels = _mesa_max_texture_levels(ctx, target); GLuint compressedSize; - if (maxLevels == 0) { + if (!legal_getteximage_target(ctx, target)) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImage(target=0x%x)", target); return GL_TRUE; } + assert(maxLevels != 0); if (level < 0 || level >= maxLevels) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(bad level = %d)", level); return GL_TRUE; } - if (_mesa_is_proxy_texture(target)) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetCompressedTexImageARB(bad target = %s)", - _mesa_lookup_enum_by_nr(target)); - return GL_TRUE; - } - texObj = _mesa_get_current_tex_object(ctx, target); if (!texObj) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)"); @@ -899,7 +908,7 @@ getcompressedteximage_error_check(struct gl_context *ctx, GLenum target, if (!_mesa_is_bufferobj(ctx->Pack.BufferObj)) { /* do bounds checking on writing to client memory */ - if (clientMemSize < compressedSize) { + if (clientMemSize < (GLsizei) compressedSize) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetnCompressedTexImageARB(out of bounds access:" " bufSize (%d) is too small)", clientMemSize); @@ -966,7 +975,7 @@ _mesa_GetnCompressedTexImageARB(GLenum target, GLint level, GLsizei bufSize, } void GLAPIENTRY -_mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img) +_mesa_GetCompressedTexImage(GLenum target, GLint level, GLvoid *img) { _mesa_GetnCompressedTexImageARB(target, level, INT_MAX, img); }