diff options
-rw-r--r-- | src/mesa/main/teximage.c | 157 |
1 files changed, 84 insertions, 73 deletions
diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c index d9df7866394..83e79a5a31c 100644 --- a/src/mesa/main/teximage.c +++ b/src/mesa/main/teximage.c @@ -1343,60 +1343,6 @@ _mesa_legal_texture_dimensions(struct gl_context *ctx, GLenum target, /** - * Do error checking of xoffset, yoffset, width, height for glTexSubImage, - * glCopyTexSubImage and glCompressedTexSubImage. - * Basically, check that the subregion is aligned to the compressed format's - * block size. See comments in function for more info. - * \return GL_TRUE if error found, GL_FALSE otherwise. - */ -static GLboolean -error_check_subtexture_dimensions(struct gl_context *ctx, - const char *function, - GLuint dims, - gl_format texFormat, - GLint xoffset, GLint yoffset, - GLsizei subWidth, GLsizei subHeight, - GLsizei texWidth, GLsizei texHeight) -{ - GLuint bw, bh; - - /* - * The OpenGL spec (and GL_ARB_texture_compression) says only whole - * compressed texture images can be updated. But, that restriction may be - * relaxed for particular compressed formats. At this time, all the - * compressed formats supported by Mesa allow sub-textures to be updated - * along compressed block boundaries. - */ - _mesa_get_format_block_size(texFormat, &bw, &bh); - - /* offset must be multiple of block size */ - if ((xoffset % bw != 0) || (yoffset % bh != 0)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "%s%dD(xoffset = %d, yoffset = %d)", - function, dims, xoffset, yoffset); - return GL_TRUE; - } - - /* size must be multiple of bw by bh or equal to whole texture size */ - if ((subWidth % bw != 0) && subWidth != texWidth) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "%s%dD(width = %d)", function, dims, subWidth); - return GL_TRUE; - } - - if ((subHeight % bh != 0) && subHeight != texHeight) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "%s%dD(height = %d)", function, dims, subHeight); - return GL_TRUE; - } - - return GL_FALSE; -} - - - - -/** * This is the fallback for Driver.TestProxyTexImage() for doing device- * specific texture image size checks. * @@ -1703,6 +1649,17 @@ compressed_tex_size(GLsizei width, GLsizei height, GLsizei depth, } +/* + * Return compressed texture block size, in pixels. + */ +static void +get_compressed_block_size(GLenum glformat, GLuint *bw, GLuint *bh) +{ + gl_format mesaFormat = _mesa_glenum_to_compressed_format(glformat); + _mesa_get_format_block_size(mesaFormat, bw, bh); +} + + /** * Test the glTexImage[123]D() parameters for errors. * @@ -2238,19 +2195,35 @@ subtexture_error_check2( struct gl_context *ctx, GLuint dimensions, } if (_mesa_is_format_compressed(destTex->TexFormat)) { + GLuint bw, bh; + if (compressedteximage_only_format(ctx, destTex->InternalFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexSubImage%dD(no compression for format)", dimensions); return GL_TRUE; } - if (error_check_subtexture_dimensions(ctx, "glTexSubImage", dimensions, - destTex->TexFormat, - xoffset, yoffset, - width, height, - destTex->Width, destTex->Height)) { + /* do tests which depend on compression block size */ + _mesa_get_format_block_size(destTex->TexFormat, &bw, &bh); + + /* offset must be multiple of block size */ + if ((xoffset % bw != 0) || (yoffset % bh != 0)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTexSubImage%dD(xoffset = %d, yoffset = %d)", + dimensions, xoffset, yoffset); return GL_TRUE; } + /* size must be multiple of bw by bh or equal to whole texture size */ + if ((width % bw != 0) && (GLuint) width != destTex->Width) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTexSubImage%dD(width = %d)", dimensions, width); + return GL_TRUE; + } + if ((height % bh != 0) && (GLuint) height != destTex->Height) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTexSubImage%dD(height = %d)", dimensions, height); + return GL_TRUE; + } } if (ctx->Version >= 30 || ctx->Extensions.EXT_texture_integer) { @@ -2556,14 +2529,23 @@ copytexsubimage_error_check2( struct gl_context *ctx, GLuint dimensions, "glCopyTexSubImage%dD(no compression for format)", dimensions); return GL_TRUE; } - - if (error_check_subtexture_dimensions(ctx, "glCopyTexSubImage", - dimensions, teximage->TexFormat, - xoffset, yoffset, width, height, - teximage->Width, - teximage->Height)) { + /* offset must be multiple of 4 */ + if ((xoffset & 3) || (yoffset & 3)) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCopyTexSubImage%dD(xoffset or yoffset)", dimensions); return GL_TRUE; } + /* size must be multiple of 4 */ + if ((width & 3) != 0 && (GLuint) width != teximage->Width) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCopyTexSubImage%dD(width)", dimensions); + return GL_TRUE; + } + if ((height & 3) != 0 && (GLuint) height != teximage->Height) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCopyTexSubImage%dD(height)", dimensions); + return GL_TRUE; + } } if (teximage->InternalFormat == GL_YCBCR_MESA) { @@ -3537,7 +3519,7 @@ compressed_subtexture_error_check(struct gl_context *ctx, GLint dimensions, GLenum format, GLsizei imageSize) { GLint expectedSize, maxLevels = 0, maxTextureSize; - + GLuint bw, bh; (void) zoffset; if (dimensions == 1) { @@ -3589,6 +3571,16 @@ compressed_subtexture_error_check(struct gl_context *ctx, GLint dimensions, /* * do checks which depend on compression block size */ + get_compressed_block_size(format, &bw, &bh); + + if ((xoffset % bw != 0) || (yoffset % bh != 0)) + return GL_INVALID_VALUE; + + if ((width % bw != 0) && width != 2 && width != 1) + return GL_INVALID_VALUE; + + if ((height % bh != 0) && height != 2 && height != 1) + return GL_INVALID_VALUE; expectedSize = compressed_tex_size(width, height, depth, format); if (expectedSize != imageSize) @@ -3604,7 +3596,6 @@ compressed_subtexture_error_check(struct gl_context *ctx, GLint dimensions, */ static GLboolean compressed_subtexture_error_check2(struct gl_context *ctx, GLuint dims, - GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, struct gl_texture_image *texImage) @@ -3623,13 +3614,34 @@ compressed_subtexture_error_check2(struct gl_context *ctx, GLuint dims, return GL_TRUE; } - if (error_check_subtexture_dimensions(ctx, "glCompressedTexSubImage", dims, - texImage->TexFormat, - xoffset, yoffset, width, height, - texImage->Width, texImage->Height)) { + if (((width == 1 || width == 2) && + width != (GLsizei) texImage->Width) || + (width > (GLsizei) texImage->Width)) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCompressedTexSubImage%uD(width=%d)", dims, width); return GL_TRUE; } + if (dims >= 2) { + if (((height == 1 || height == 2) && + height != (GLsizei) texImage->Height) || + (height > (GLsizei) texImage->Height)) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCompressedTexSubImage%uD(height=%d)", dims, height); + return GL_TRUE; + } + } + + if (dims >= 3) { + if (((depth == 1 || depth == 2) && + depth != (GLsizei) texImage->Depth) || + (depth > (GLsizei) texImage->Depth)) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCompressedTexSubImage%uD(depth=%d)", dims, depth); + return GL_TRUE; + } + } + return GL_FALSE; } @@ -3701,8 +3713,7 @@ compressed_tex_sub_image(GLuint dims, GLenum target, GLint level, texImage = _mesa_select_tex_image(ctx, texObj, target, level); assert(texImage); - if (compressed_subtexture_error_check2(ctx, dims, xoffset, yoffset, - width, height, depth, + if (compressed_subtexture_error_check2(ctx, dims, width, height, depth, format, texImage)) { /* error was recorded */ } |