mesa: Refactor compressed texture error checks to work with paletted textures
authorIan Romanick <ian.d.romanick@intel.com>
Mon, 12 Sep 2011 16:46:09 +0000 (11:46 -0500)
committerIan Romanick <ian.d.romanick@intel.com>
Mon, 19 Sep 2011 17:04:47 +0000 (10:04 -0700)
This code was really broken before.  A lot of the error checks were
done much later (too late), and some of the error checks would fail.
The underlying problem is that Mesa doesn't ever keep compressed paletted
textures in their original format.  The textures are immediately
converted to some RGB or RGBA format.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=39991
Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Brian Paul <brianp@vmware.com>
Tested-by: Jin Yang <jin.a.yang@intel.com>
src/mesa/main/teximage.c

index 76dcd9c514d800e8577e6cfba23b9e0d75201cee..fa00183ac65f38963dc87c5128f548d548b08d74 100644 (file)
@@ -3031,15 +3031,12 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions,
    const GLenum proxyTarget = get_proxy_target(target);
    const GLint maxLevels = _mesa_max_texture_levels(ctx, target);
    GLint expectedSize;
+   GLenum choose_format;
+   GLenum choose_type;
+   GLenum proxy_format;
 
    *reason = ""; /* no error */
 
-   /* check level */
-   if (level < 0 || level >= maxLevels) {
-      *reason = "level";
-      return GL_INVALID_VALUE;
-   }
-
    if (!target_can_be_compressed(ctx, target, internalFormat)) {
       *reason = "target";
       return GL_INVALID_ENUM;
@@ -3051,6 +3048,68 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions,
       return GL_INVALID_ENUM;
    }
 
+   switch (internalFormat) {
+#if FEATURE_ES
+   case GL_PALETTE4_RGB8_OES:
+   case GL_PALETTE4_RGBA8_OES:
+   case GL_PALETTE4_R5_G6_B5_OES:
+   case GL_PALETTE4_RGBA4_OES:
+   case GL_PALETTE4_RGB5_A1_OES:
+   case GL_PALETTE8_RGB8_OES:
+   case GL_PALETTE8_RGBA8_OES:
+   case GL_PALETTE8_R5_G6_B5_OES:
+   case GL_PALETTE8_RGBA4_OES:
+   case GL_PALETTE8_RGB5_A1_OES:
+      _mesa_cpal_compressed_format_type(internalFormat, &choose_format,
+                                       &choose_type);
+      proxy_format = choose_format;
+
+      /* check level */
+      if (level > 0 || level < -maxLevels) {
+        *reason = "level";
+        return GL_INVALID_VALUE;
+      }
+
+      if (dimensions != 2) {
+        *reason = "compressed paletted textures must be 2D";
+        return GL_INVALID_OPERATION;
+      }
+
+      /* Figure out the expected texture size (in bytes).  This will be
+       * checked against the actual size later.
+       */
+      expectedSize = _mesa_cpal_compressed_size(level, internalFormat,
+                                               width, height);
+
+      /* This is for the benefit of the TestProxyTexImage below.  It expects
+       * level to be non-negative.  OES_compressed_paletted_texture uses a
+       * weird mechanism where the level specified to glCompressedTexImage2D
+       * is -(n-1) number of levels in the texture, and the data specifies the
+       * complete mipmap stack.  This is done to ensure the palette is the
+       * same for all levels.
+       */
+      level = -level;
+      break;
+#endif
+
+   default:
+      choose_format = GL_NONE;
+      choose_type = GL_NONE;
+      proxy_format = internalFormat;
+
+      /* check level */
+      if (level < 0 || level >= maxLevels) {
+        *reason = "level";
+        return GL_INVALID_VALUE;
+      }
+
+      /* Figure out the expected texture size (in bytes).  This will be
+       * checked against the actual size later.
+       */
+      expectedSize = compressed_tex_size(width, height, depth, internalFormat);
+      break;
+   }
+
    /* This should really never fail */
    if (_mesa_base_tex_format(ctx, internalFormat) < 0) {
       *reason = "internalFormat";
@@ -3073,8 +3132,8 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions,
    /* check image size against compression block size */
    {
       gl_format texFormat =
-         ctx->Driver.ChooseTextureFormat(ctx, internalFormat,
-                                         GL_NONE, GL_NONE);
+         ctx->Driver.ChooseTextureFormat(ctx, proxy_format,
+                                        choose_format, choose_type);
       GLuint bw, bh;
 
       _mesa_get_format_block_size(texFormat, &bw, &bh);
@@ -3092,15 +3151,15 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions,
 
    /* check image sizes */
    if (!ctx->Driver.TestProxyTexImage(ctx, proxyTarget, level,
-                                      internalFormat, GL_NONE, GL_NONE,
-                                      width, height, depth, border)) {
+                                     proxy_format, choose_format,
+                                     choose_type,
+                                     width, height, depth, border)) {
       /* See error comment above */
       *reason = "invalid width, height or format";
       return GL_INVALID_OPERATION;
    }
 
    /* check image size in bytes */
-   expectedSize = compressed_tex_size(width, height, depth, internalFormat);
    if (expectedSize != imageSize) {
       /* Per GL_ARB_texture_compression:  GL_INVALID_VALUE is generated [...]
        * if <imageSize> is not consistent with the format, dimensions, and