mesa: consolidate subtexture xoffset/yoffset/width/height error checking code
authorBrian Paul <brianp@vmware.com>
Sat, 22 Sep 2012 15:30:23 +0000 (09:30 -0600)
committerBrian Paul <brianp@vmware.com>
Wed, 26 Sep 2012 13:43:49 +0000 (07:43 -0600)
This is the code that checks if a subtexture region is aligned to the
compressed format's block size.

src/mesa/main/teximage.c

index 51763084be804167822666ffb18106ac59a1f65f..dd158e29dc9a5f3e1b5cd3816d2a46f134f456ff 100644 (file)
@@ -1342,6 +1342,60 @@ _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.
@@ -1649,17 +1703,6 @@ 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.
  * 
@@ -2195,35 +2238,19 @@ 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;
       }
 
-      /* 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);
+      if (error_check_subtexture_dimensions(ctx, "glTexSubImage", dimensions,
+                                            destTex->TexFormat,
+                                            xoffset, yoffset,
+                                            width, height,
+                                            destTex->Width, destTex->Height)) {
          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) {
@@ -2514,23 +2541,14 @@ copytexsubimage_error_check(struct gl_context *ctx, GLuint dimensions,
                "glCopyTexSubImage%dD(no compression for format)", dimensions);
          return GL_TRUE;
       }
-      /* offset must be multiple of 4 */
-      if ((xoffset & 3) || (yoffset & 3)) {
-         _mesa_error(ctx, GL_INVALID_VALUE,
-                     "glCopyTexSubImage%dD(xoffset or yoffset)", dimensions);
+
+      if (error_check_subtexture_dimensions(ctx, "glCopyTexSubImage",
+                                            dimensions, texImage->TexFormat,
+                                            xoffset, yoffset, width, height,
+                                            texImage->Width,
+                                            texImage->Height)) {
          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) {
@@ -3500,7 +3518,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) {
@@ -3549,20 +3567,6 @@ compressed_subtexture_error_check(struct gl_context *ctx, GLint dimensions,
    if (level < 0 || level >= maxLevels)
       return GL_INVALID_VALUE;
 
-   /*
-    * 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_OPERATION;
-
-   if ((width % bw != 0) && width != 2 && width != 1)
-      return GL_INVALID_OPERATION;
-
-   if ((height % bh != 0) && height != 2 && height != 1)
-      return GL_INVALID_OPERATION;
-
    expectedSize = compressed_tex_size(width, height, depth, format);
    if (expectedSize != imageSize)
       return GL_INVALID_VALUE;
@@ -3577,6 +3581,7 @@ 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)
@@ -3595,34 +3600,13 @@ compressed_subtexture_error_check2(struct gl_context *ctx, GLuint dims,
       return GL_TRUE;
    }
 
-   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);
+   if (error_check_subtexture_dimensions(ctx, "glCompressedTexSubImage", dims,
+                                         texImage->TexFormat,
+                                         xoffset, yoffset, width, height,
+                                         texImage->Width, texImage->Height)) {
       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;
 }
 
@@ -3694,7 +3678,8 @@ 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, width, height, depth,
+      if (compressed_subtexture_error_check2(ctx, dims, xoffset, yoffset,
+                                             width, height, depth,
                                              format, texImage)) {
          /* error was recorded */
       }