diff options
-rw-r--r-- | src/mesa/main/copyimage.c | 151 |
1 files changed, 130 insertions, 21 deletions
diff --git a/src/mesa/main/copyimage.c b/src/mesa/main/copyimage.c index 455929dc2ff..fd22f28892c 100644 --- a/src/mesa/main/copyimage.c +++ b/src/mesa/main/copyimage.c @@ -33,6 +33,12 @@ #include "texobj.h" #include "fbobject.h" #include "textureview.h" +#include "glformats.h" + +enum mesa_block_class { + BLOCK_CLASS_128_BITS, + BLOCK_CLASS_64_BITS +}; static bool prepare_target(struct gl_context *ctx, GLuint name, GLenum *target, int level, @@ -253,6 +259,124 @@ check_region_bounds(struct gl_context *ctx, struct gl_texture_image *tex_image, return true; } +static bool +compressed_format_compatible(struct gl_context *ctx, + GLenum compressedFormat, GLenum otherFormat) +{ + enum mesa_block_class compressedClass, otherClass; + + /* Two view-incompatible compressed formats are never compatible. */ + if (_mesa_is_compressed_format(ctx, otherFormat)) { + return false; + } + + /* + * From ARB_copy_image spec: + * Table 4.X.1 (Compatible internal formats for copying between + * compressed and uncompressed internal formats) + * --------------------------------------------------------------------- + * | Texel / | Uncompressed | | + * | Block | internal format | Compressed internal format | + * | size | | | + * --------------------------------------------------------------------- + * | 128-bit | RGBA32UI, | COMPRESSED_RGBA_S3TC_DXT3_EXT, | + * | | RGBA32I, | COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT,| + * | | RGBA32F | COMPRESSED_RGBA_S3TC_DXT5_EXT, | + * | | | COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT,| + * | | | COMPRESSED_RG_RGTC2, | + * | | | COMPRESSED_SIGNED_RG_RGTC2, | + * | | | COMPRESSED_RGBA_BPTC_UNORM, | + * | | | COMPRESSED_SRGB_ALPHA_BPTC_UNORM, | + * | | | COMPRESSED_RGB_BPTC_SIGNED_FLOAT, | + * | | | COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT | + * --------------------------------------------------------------------- + * | 64-bit | RGBA16F, RG32F, | COMPRESSED_RGB_S3TC_DXT1_EXT, | + * | | RGBA16UI, RG32UI, | COMPRESSED_SRGB_S3TC_DXT1_EXT, | + * | | RGBA16I, RG32I, | COMPRESSED_RGBA_S3TC_DXT1_EXT, | + * | | RGBA16, | COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT,| + * | | RGBA16_SNORM | COMPRESSED_RED_RGTC1, | + * | | | COMPRESSED_SIGNED_RED_RGTC1 | + * --------------------------------------------------------------------- + */ + + switch (compressedFormat) { + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: + case GL_COMPRESSED_RG_RGTC2: + case GL_COMPRESSED_SIGNED_RG_RGTC2: + case GL_COMPRESSED_RGBA_BPTC_UNORM: + case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM: + case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT: + case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT: + compressedClass = BLOCK_CLASS_128_BITS; + break; + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: + case GL_COMPRESSED_RED_RGTC1: + case GL_COMPRESSED_SIGNED_RED_RGTC1: + compressedClass = BLOCK_CLASS_64_BITS; + break; + default: + return false; + } + + switch (otherFormat) { + case GL_RGBA32UI: + case GL_RGBA32I: + case GL_RGBA32F: + otherClass = BLOCK_CLASS_128_BITS; + break; + case GL_RGBA16F: + case GL_RG32F: + case GL_RGBA16UI: + case GL_RG32UI: + case GL_RGBA16I: + case GL_RG32I: + case GL_RGBA16: + case GL_RGBA16_SNORM: + otherClass = BLOCK_CLASS_64_BITS; + break; + default: + return false; + } + + return compressedClass == otherClass; +} + +static bool +copy_format_compatible(struct gl_context *ctx, + GLenum srcFormat, GLenum dstFormat) +{ + /* + * From ARB_copy_image spec: + * For the purposes of CopyImageSubData, two internal formats + * are considered compatible if any of the following conditions are + * met: + * * the formats are the same, + * * the formats are considered compatible according to the + * compatibility rules used for texture views as defined in + * section 3.9.X. In particular, if both internal formats are listed + * in the same entry of Table 3.X.2, they are considered compatible, or + * * one format is compressed and the other is uncompressed and + * Table 4.X.1 lists the two formats in the same row. + */ + + if (_mesa_texture_view_compatible_format(ctx, srcFormat, dstFormat)) { + /* Also checks if formats are equal. */ + return true; + } else if (_mesa_is_compressed_format(ctx, srcFormat)) { + return compressed_format_compatible(ctx, srcFormat, dstFormat); + } else if (_mesa_is_compressed_format(ctx, dstFormat)) { + return compressed_format_compatible(ctx, dstFormat, srcFormat); + } + + return false; +} + void GLAPIENTRY _mesa_CopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, @@ -265,7 +389,7 @@ _mesa_CopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel, struct gl_texture_object *srcTexObj, *dstTexObj; struct gl_texture_image *srcTexImage, *dstTexImage; GLuint src_bw, src_bh, dst_bw, dst_bh; - int i, srcNewZ, dstNewZ, Bpt; + int i, srcNewZ, dstNewZ; if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glCopyImageSubData(%u, %s, %d, %d, %d, %d, " @@ -306,15 +430,6 @@ _mesa_CopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel, goto cleanup; } - /* Very simple sanity check. This is sufficient if one of the textures - * is compressed. */ - Bpt = _mesa_get_format_bytes(srcTexImage->TexFormat); - if (_mesa_get_format_bytes(dstTexImage->TexFormat) != Bpt) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glCopyImageSubData(internalFormat mismatch)"); - goto cleanup; - } - if (!check_region_bounds(ctx, srcTexImage, srcX, srcY, srcZ, srcWidth, srcHeight, srcDepth, "src")) goto cleanup; @@ -324,17 +439,11 @@ _mesa_CopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel, (srcHeight / src_bh) * dst_bh, srcDepth, "dst")) goto cleanup; - if (_mesa_is_format_compressed(srcTexImage->TexFormat)) { - /* XXX: Technically, we should probaby do some more specific checking - * here. However, this should be sufficient for all compressed - * formats that mesa supports since it is a direct memory copy. - */ - } else if (_mesa_is_format_compressed(dstTexImage->TexFormat)) { - } else if (_mesa_texture_view_compatible_format(ctx, - srcTexImage->InternalFormat, - dstTexImage->InternalFormat)) { - } else { - return; /* Error logged by _mesa_texture_view_compatible_format */ + if (!copy_format_compatible(ctx, srcTexImage->InternalFormat, + dstTexImage->InternalFormat)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCopyImageSubData(internalFormat mismatch)"); + goto cleanup; } for (i = 0; i < srcDepth; ++i) { |