assorted changes for supporting GLfloat color channels (not done)
[mesa.git] / src / mesa / main / teximage.c
index 0dbbb187c67f20aaeec1867c5a608dfa431510ed..ffddeffbabc79da27eb186557ab4a49772b6a0f2 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: teximage.c,v 1.96 2001/06/12 22:05:34 brianp Exp $ */
+/* $Id: teximage.c,v 1.100 2001/07/13 20:07:37 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -58,6 +58,9 @@
 #ifdef DEBUG
 static void PrintTexture(const struct gl_texture_image *img)
 {
+#if CHAN_TYPE == GL_FLOAT
+   _mesa_problem(NULL, "PrintTexture doesn't support float channels");
+#else
    GLuint i, j, c;
    const GLchan *data = (const GLchan *) img->Data;
 
@@ -101,6 +104,7 @@ static void PrintTexture(const struct gl_texture_image *img)
       }
       printf("\n");
    }
+#endif
 }
 #endif
 
@@ -307,10 +311,14 @@ is_index_format(GLenum format)
 static GLboolean
 is_compressed_format(GLcontext *ctx, GLenum internalFormat)
 {
-    if (ctx->Driver.IsCompressedFormat) {
-        return (*ctx->Driver.IsCompressedFormat)(ctx, internalFormat);
-    }
-    return GL_FALSE;
+   if (ctx->Driver.BaseCompressedTexFormat) {
+      GLint b = (*ctx->Driver.BaseCompressedTexFormat)(ctx, internalFormat);
+      if (b > 0)
+         return GL_TRUE;
+      else
+         return GL_FALSE;
+   }
+   return GL_FALSE;
 }
 
 
@@ -443,6 +451,7 @@ _mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_unit *texUnit,
                        GLenum target, GLint level)
 {
    ASSERT(texUnit);
+   ASSERT(level < MAX_TEXTURE_LEVELS);
    switch (target) {
       case GL_TEXTURE_1D:
          return texUnit->Current1D->Image[level];
@@ -592,6 +601,7 @@ _mesa_init_teximage_fields(GLcontext *ctx,
 {
    ASSERT(img);
    img->Format = _mesa_base_tex_format( ctx, internalFormat );
+   ASSERT(img->Format > 0);
    img->IntFormat = internalFormat;
    img->Border = border;
    img->Width = width;
@@ -631,6 +641,7 @@ texture_error_check( GLcontext *ctx, GLenum target,
 {
    GLboolean isProxy;
    GLint iformat;
+   GLint maxLevels = 0, maxTextureSize;
 
    if (dimensions == 1) {
       isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_1D);
@@ -638,6 +649,7 @@ texture_error_check( GLcontext *ctx, GLenum target,
          _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
          return GL_TRUE;
       }
+      maxLevels = ctx->Const.MaxTextureLevels;
    }
    else if (dimensions == 2) {
       isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_2D ||
@@ -649,6 +661,10 @@ texture_error_check( GLcontext *ctx, GLenum target,
           _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
           return GL_TRUE;
       }
+      if (target == GL_PROXY_TEXTURE_2D && target == GL_TEXTURE_2D)
+         maxLevels = ctx->Const.MaxTextureLevels;
+      else
+         maxLevels = ctx->Const.MaxCubeTextureLevels;
    }
    else if (dimensions == 3) {
       isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_3D);
@@ -656,12 +672,16 @@ texture_error_check( GLcontext *ctx, GLenum target,
          _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
          return GL_TRUE;
       }
+      maxLevels = ctx->Const.Max3DTextureLevels;
    }
    else {
       _mesa_problem( ctx, "bad dims in texture_error_check" );
       return GL_TRUE;
    }
 
+   ASSERT(maxLevels > 0);
+   maxTextureSize = 1 << (maxLevels - 1);
+
    /* Border */
    if (border != 0 && border != 1) {
       if (!isProxy) {
@@ -673,7 +693,7 @@ texture_error_check( GLcontext *ctx, GLenum target,
    }
 
    /* Width */
-   if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
+   if (width < 2 * border || width > 2 + maxTextureSize
        || logbase2( width - 2 * border ) < 0) {
       if (!isProxy) {
          char message[100];
@@ -685,7 +705,7 @@ texture_error_check( GLcontext *ctx, GLenum target,
 
    /* Height */
    if (dimensions >= 2) {
-      if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
+      if (height < 2 * border || height > 2 + maxTextureSize
           || logbase2( height - 2 * border ) < 0) {
          if (!isProxy) {
             char message[100];
@@ -709,7 +729,7 @@ texture_error_check( GLcontext *ctx, GLenum target,
 
    /* Depth */
    if (dimensions >= 3) {
-      if (depth < 2 * border || depth > 2 + ctx->Const.MaxTextureSize
+      if (depth < 2 * border || depth > 2 + maxTextureSize
           || logbase2( depth - 2 * border ) < 0) {
          if (!isProxy) {
             char message[100];
@@ -721,7 +741,7 @@ texture_error_check( GLcontext *ctx, GLenum target,
    }
 
    /* Level */
-   if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
+   if (level < 0 || level >= maxLevels) {
       if (!isProxy) {
          char message[100];
          sprintf(message, "glTexImage%dD(level=%d)", dimensions, level);
@@ -750,6 +770,8 @@ texture_error_check( GLcontext *ctx, GLenum target,
       return GL_TRUE;
    }
 
+   ASSERT(iformat > 0);
+
    if (!is_compressed_format( ctx, internalFormat ) &&
        !_mesa_is_legal_format_and_type( format, type )) {
       /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
@@ -784,12 +806,15 @@ subtexture_error_check( GLcontext *ctx, GLuint dimensions,
 {
    struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
    struct gl_texture_image *destTex;
+   GLint maxLevels = 0;
+   GLboolean compressed;
 
    if (dimensions == 1) {
       if (target != GL_TEXTURE_1D) {
          _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" );
          return GL_TRUE;
       }
+      maxLevels = ctx->Const.MaxTextureLevels;
    }
    else if (dimensions == 2) {
       if (ctx->Extensions.ARB_texture_cube_map) {
@@ -804,19 +829,26 @@ subtexture_error_check( GLcontext *ctx, GLuint dimensions,
          _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
          return GL_TRUE;
       }
+      if (target == GL_PROXY_TEXTURE_2D && target == GL_TEXTURE_2D)
+         maxLevels = ctx->Const.MaxTextureLevels;
+      else
+         maxLevels = ctx->Const.MaxCubeTextureLevels;
    }
    else if (dimensions == 3) {
       if (target != GL_TEXTURE_3D) {
          _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
          return GL_TRUE;
       }
+      maxLevels = ctx->Const.Max3DTextureLevels;
    }
    else {
       _mesa_problem( ctx, "bad dims in texture_error_check" );
       return GL_TRUE;
    }
 
-   if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
+   ASSERT(maxLevels > 0);
+
+   if (level < 0 || level >= maxLevels) {
       char message[100];
       sprintf(message, "glTexSubImage2D(level=%d)", level);
       _mesa_error(ctx, GL_INVALID_ENUM, message);
@@ -878,14 +910,33 @@ subtexture_error_check( GLcontext *ctx, GLuint dimensions,
       }
    }
 
-   if (!is_compressed_format(ctx, destTex->IntFormat) &&
-       !_mesa_is_legal_format_and_type(format, type)) {
+   compressed = is_compressed_format(ctx, destTex->IntFormat);
+
+   if (!compressed && !_mesa_is_legal_format_and_type(format, type)) {
       char message[100];
       sprintf(message, "glTexSubImage%dD(format or type)", dimensions);
       _mesa_error(ctx, GL_INVALID_ENUM, message);
       return GL_TRUE;
    }
 
+   if (compressed) {
+      if (xoffset != -destTex->Border) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glTexSubImage1/2/3D(xoffset != -border");
+         return GL_TRUE;
+      }
+      if (dimensions > 1 && yoffset != -destTex->Border) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glTexSubImage2/3D(yoffset != -border");
+         return GL_TRUE;
+      }
+      if (dimensions > 2 && zoffset != -destTex->Border) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glTexSubImage3D(zoffset != -border");
+         return GL_TRUE;
+      }
+   }
+
    return GL_FALSE;
 }
 
@@ -901,12 +952,14 @@ copytexture_error_check( GLcontext *ctx, GLuint dimensions,
                          GLint width, GLint height, GLint border )
 {
    GLint iformat;
+   GLint maxLevels = 0, maxTextureSize;
 
    if (dimensions == 1) {
       if (target != GL_TEXTURE_1D) {
          _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" );
          return GL_TRUE;
       }
+      maxLevels = ctx->Const.MaxTextureLevels;
    }
    else if (dimensions == 2) {
       if (ctx->Extensions.ARB_texture_cube_map) {
@@ -921,8 +974,15 @@ copytexture_error_check( GLcontext *ctx, GLuint dimensions,
          _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
          return GL_TRUE;
       }
+      if (target == GL_PROXY_TEXTURE_2D && target == GL_TEXTURE_2D)
+         maxLevels = ctx->Const.MaxTextureLevels;
+      else
+         maxLevels = ctx->Const.MaxCubeTextureLevels;
    }
 
+   ASSERT(maxLevels > 0);
+   maxTextureSize = 1 << (maxLevels - 1);
+
    /* Border */
    if (border != 0 && border != 1) {
       char message[100];
@@ -932,7 +992,7 @@ copytexture_error_check( GLcontext *ctx, GLuint dimensions,
    }
 
    /* Width */
-   if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
+   if (width < 2 * border || width > 2 + maxTextureSize
        || logbase2( width - 2 * border ) < 0) {
       char message[100];
       sprintf(message, "glCopyTexImage%dD(width=%d)", dimensions, width);
@@ -942,7 +1002,7 @@ copytexture_error_check( GLcontext *ctx, GLuint dimensions,
 
    /* Height */
    if (dimensions >= 2) {
-      if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
+      if (height < 2 * border || height > 2 + maxTextureSize
           || logbase2( height - 2 * border ) < 0) {
          char message[100];
          sprintf(message, "glCopyTexImage%dD(height=%d)", dimensions, height);
@@ -961,14 +1021,14 @@ copytexture_error_check( GLcontext *ctx, GLuint dimensions,
    }
 
    /* Level */
-   if (level < 0 || level>=ctx->Const.MaxTextureLevels) {
+   if (level < 0 || level >= maxLevels) {
       char message[100];
       sprintf(message, "glCopyTexImage%dD(level=%d)", dimensions, level);
       _mesa_error(ctx, GL_INVALID_VALUE, message);
       return GL_TRUE;
    }
 
-   iformat = _mesa_base_tex_format( ctx, internalFormat );
+   iformat = _mesa_base_tex_format(ctx, internalFormat);
    if (iformat < 0) {
       char message[100];
       sprintf(message, "glCopyTexImage%dD(internalFormat)", dimensions);
@@ -989,12 +1049,15 @@ copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions,
 {
    struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
    struct gl_texture_image *teximage;
+   GLint maxLevels = 0;
+   GLboolean compressed;
 
    if (dimensions == 1) {
       if (target != GL_TEXTURE_1D) {
          _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
          return GL_TRUE;
       }
+      maxLevels = ctx->Const.MaxTextureLevels;
    }
    else if (dimensions == 2) {
       if (ctx->Extensions.ARB_texture_cube_map) {
@@ -1009,15 +1072,22 @@ copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions,
          _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
          return GL_TRUE;
       }
+      if (target == GL_PROXY_TEXTURE_2D && target == GL_TEXTURE_2D)
+         maxLevels = ctx->Const.MaxTextureLevels;
+      else
+         maxLevels = ctx->Const.MaxCubeTextureLevels;
    }
    else if (dimensions == 3) {
       if (target != GL_TEXTURE_3D) {
          _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" );
          return GL_TRUE;
       }
+      maxLevels = ctx->Const.Max3DTextureLevels;
    }
 
-   if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
+   ASSERT(maxLevels > 0);
+
+   if (level < 0 || level >= maxLevels) {
       char message[100];
       sprintf(message, "glCopyTexSubImage%dD(level=%d)", dimensions, level);
       _mesa_error(ctx, GL_INVALID_VALUE, message);
@@ -1088,6 +1158,25 @@ copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions,
       }
    }
 
+   compressed = is_compressed_format(ctx, teximage->IntFormat);
+   if (compressed) {
+      if (xoffset != -teximage->Border) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glCopyTexSubImage1/2/3D(xoffset != -border");
+         return GL_TRUE;
+      }
+      if (dimensions > 1 && yoffset != -teximage->Border) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glCopyTexSubImage2/3D(yoffset != -border");
+         return GL_TRUE;
+      }
+      if (dimensions > 2 && zoffset != -teximage->Border) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glCopyTexSubImage3D(zoffset != -border");
+         return GL_TRUE;
+      }
+   }
+
    /* if we get here, the parameters are OK */
    return GL_FALSE;
 }
@@ -1101,10 +1190,30 @@ _mesa_GetTexImage( GLenum target, GLint level, GLenum format,
    const struct gl_texture_unit *texUnit;
    const struct gl_texture_object *texObj;
    struct gl_texture_image *texImage;
+   GLint maxLevels = 0;
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
 
-   if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
+   texUnit = &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]);
+   texObj = _mesa_select_tex_object(ctx, texUnit, target);
+   if (!texObj || is_proxy_target(target)) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)");
+      return;
+   }
+
+   if (target == GL_TEXTURE_1D || target == GL_TEXTURE_2D) {
+      maxLevels = ctx->Const.MaxTextureLevels;
+   }
+   else if (target == GL_TEXTURE_3D) {
+      maxLevels = ctx->Const.Max3DTextureLevels;
+   }
+   else {
+      maxLevels = ctx->Const.MaxCubeTextureLevels;
+   }
+
+   ASSERT(maxLevels > 0);
+
+   if (level < 0 || level >= maxLevels) {
       _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
       return;
    }
@@ -1133,13 +1242,6 @@ _mesa_GetTexImage( GLenum target, GLint level, GLenum format,
    if (!pixels)
       return;
 
-   texUnit = &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]);
-   texObj = _mesa_select_tex_object(ctx, texUnit, target);
-   if (!texObj || is_proxy_target(target)) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)");
-      return;
-   }
-
    texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
    if (!texImage) {
       /* invalid mipmap level, not an error */
@@ -1173,7 +1275,7 @@ _mesa_GetTexImage( GLenum target, GLint level, GLenum format,
                }
                _mesa_pack_index_span(ctx, width, type, dest,
                                      indexRow, &ctx->Pack,
-                                     ctx->_ImageTransferState);
+                                     0 /* no image transfer */);
             }
             else if (format == GL_DEPTH_COMPONENT) {
                GLfloat depthRow[MAX_WIDTH];
@@ -1195,7 +1297,7 @@ _mesa_GetTexImage( GLenum target, GLint level, GLenum format,
                }
                _mesa_pack_rgba_span(ctx, width, (const GLchan (*)[4])rgba,
                                     format, type, dest, &ctx->Pack,
-                                    ctx->_ImageTransferState);
+                                    0 /* no image transfer */);
             } /* format */
          } /* row */
       } /* img */
@@ -1251,7 +1353,7 @@ _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
       _mesa_init_teximage_fields(ctx, texImage, postConvWidth, 1, 1,
                                  border, internalFormat);
 
-      if (ctx->NewState & _NEW_PIXEL)
+      if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
          _mesa_update_state(ctx);
 
       ASSERT(ctx->Driver.TexImage1D);
@@ -1278,6 +1380,10 @@ _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
       }
       ASSERT(texImage->FetchTexel);
 
+      if (texImage->IsCompressed) {
+         ASSERT(texImage->CompressedSize > 0);
+      }
+
       /* state update */
       texObj->Complete = GL_FALSE;
       ctx->NewState |= _NEW_TEXTURE;
@@ -1364,7 +1470,7 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
       _mesa_init_teximage_fields(ctx, texImage, postConvWidth, postConvHeight,
                                  1, border, internalFormat);
 
-      if (ctx->NewState & _NEW_PIXEL)
+      if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
          _mesa_update_state(ctx);
 
       ASSERT(ctx->Driver.TexImage2D);
@@ -1391,6 +1497,10 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
       }
       ASSERT(texImage->FetchTexel);
 
+      if (texImage->IsCompressed) {
+         ASSERT(texImage->CompressedSize > 0);
+      }
+
       /* state update */
       texObj->Complete = GL_FALSE;
       ctx->NewState |= _NEW_TEXTURE;
@@ -1414,7 +1524,9 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
       }
       if (error) {
          /* if error, clear all proxy texture image parameters */
-         if (level >= 0 && level < ctx->Const.MaxTextureLevels) {
+         const GLint maxLevels = (target == GL_PROXY_TEXTURE_2D) ?
+            ctx->Const.MaxTextureLevels : ctx->Const.MaxCubeTextureLevels;
+         if (level >= 0 && level < maxLevels) {
             clear_teximage_fields(ctx->Texture.Proxy2D->Image[level]);
          }
       }
@@ -1469,7 +1581,7 @@ _mesa_TexImage3D( GLenum target, GLint level, GLenum internalFormat,
       _mesa_init_teximage_fields(ctx, texImage, width, height, depth, border,
                                  internalFormat);
 
-      if (ctx->NewState & _NEW_PIXEL)
+      if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
          _mesa_update_state(ctx);
 
       ASSERT(ctx->Driver.TexImage3D);
@@ -1498,6 +1610,10 @@ _mesa_TexImage3D( GLenum target, GLint level, GLenum internalFormat,
       }
       ASSERT(texImage->FetchTexel);
 
+      if (texImage->IsCompressed) {
+         ASSERT(texImage->CompressedSize > 0);
+      }
+
       /* state update */
       texObj->Complete = GL_FALSE;
       ctx->NewState |= _NEW_TEXTURE;
@@ -1520,7 +1636,7 @@ _mesa_TexImage3D( GLenum target, GLint level, GLenum internalFormat,
       }
       if (error) {
          /* if error, clear all proxy texture image parameters */
-         if (level >= 0 && level < ctx->Const.MaxTextureLevels) {
+         if (level >= 0 && level < ctx->Const.Max3DTextureLevels) {
             clear_teximage_fields(ctx->Texture.Proxy3D->Image[level]);
          }
       }
@@ -1557,7 +1673,7 @@ _mesa_TexSubImage1D( GLenum target, GLint level,
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
 
-   if (ctx->NewState & _NEW_PIXEL)
+   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
       _mesa_update_state(ctx);
 
    /* XXX should test internal format */
@@ -1603,7 +1719,7 @@ _mesa_TexSubImage2D( GLenum target, GLint level,
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
 
-   if (ctx->NewState & _NEW_PIXEL)
+   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
       _mesa_update_state(ctx);
 
    /* XXX should test internal format */
@@ -1651,7 +1767,7 @@ _mesa_TexSubImage3D( GLenum target, GLint level,
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
 
-   if (ctx->NewState & _NEW_PIXEL)
+   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
       _mesa_update_state(ctx);
 
    if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
@@ -1696,7 +1812,7 @@ _mesa_CopyTexImage1D( GLenum target, GLint level,
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
 
-   if (ctx->NewState & _NEW_PIXEL)
+   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
       _mesa_update_state(ctx);
 
    if (is_color_format(internalFormat)) {
@@ -1759,7 +1875,7 @@ _mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
 
-   if (ctx->NewState & _NEW_PIXEL)
+   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
       _mesa_update_state(ctx);
 
    if (is_color_format(internalFormat)) {
@@ -1821,7 +1937,7 @@ _mesa_CopyTexSubImage1D( GLenum target, GLint level,
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
 
-   if (ctx->NewState & _NEW_PIXEL)
+   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
       _mesa_update_state(ctx);
 
    /* XXX should test internal format */
@@ -1857,7 +1973,7 @@ _mesa_CopyTexSubImage2D( GLenum target, GLint level,
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
 
-   if (ctx->NewState & _NEW_PIXEL)
+   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
       _mesa_update_state(ctx);
 
    /* XXX should test internal format */
@@ -1895,7 +2011,7 @@ _mesa_CopyTexSubImage3D( GLenum target, GLint level,
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
 
-   if (ctx->NewState & _NEW_PIXEL)
+   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
       _mesa_update_state(ctx);
 
    /* XXX should test internal format */
@@ -2013,7 +2129,7 @@ _mesa_CompressedTexImage1DARB(GLenum target, GLint level,
       }
    }
    else {
-      _mesa_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB(target)" );
+      _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB(target)");
       return;
    }
 }
@@ -2106,13 +2222,15 @@ _mesa_CompressedTexImage2DARB(GLenum target, GLint level,
       }
       if (error) {
          /* if error, clear all proxy texture image parameters */
-         if (level >= 0 && level < ctx->Const.MaxTextureLevels) {
+         const GLint maxLevels = (target == GL_PROXY_TEXTURE_2D) ?
+            ctx->Const.MaxTextureLevels : ctx->Const.MaxCubeTextureLevels;
+         if (level >= 0 && level < maxLevels) {
             clear_teximage_fields(ctx->Texture.Proxy2D->Image[level]);
          }
       }
    }
    else {
-      _mesa_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB(target)" );
+      _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB(target)");
       return;
    }
 }
@@ -2203,13 +2321,13 @@ _mesa_CompressedTexImage3DARB(GLenum target, GLint level,
       }
       if (error) {
          /* if error, clear all proxy texture image parameters */
-         if (level >= 0 && level < ctx->Const.MaxTextureLevels) {
+         if (level >= 0 && level < ctx->Const.Max3DTextureLevels) {
             clear_teximage_fields(ctx->Texture.Proxy3D->Image[level]);
          }
       }
    }
    else {
-      _mesa_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB(target)" );
+      _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB(target)");
       return;
    }
 }
@@ -2326,11 +2444,31 @@ _mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img)
    const struct gl_texture_unit *texUnit;
    const struct gl_texture_object *texObj;
    struct gl_texture_image *texImage;
+   GLint maxLevels;
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
 
-   if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
-      _mesa_error( ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)" );
+   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+   texObj = _mesa_select_tex_object(ctx, texUnit, target);
+   if (!texObj) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB");
+      return;
+   }
+
+   if (target == GL_TEXTURE_1D || target == GL_TEXTURE_2D) {
+      maxLevels = ctx->Const.MaxTextureLevels;
+   }
+   else if (target == GL_TEXTURE_3D) {
+      maxLevels = ctx->Const.Max3DTextureLevels;
+   }
+   else {
+      maxLevels = ctx->Const.MaxCubeTextureLevels;
+   }
+
+   ASSERT(maxLevels > 0);
+
+   if (level < 0 || level >= maxLevels) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
       return;
    }
 
@@ -2339,12 +2477,9 @@ _mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img)
       return;
    }
 
-   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
-   texObj = _mesa_select_tex_object(ctx, texUnit, target);
    texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
-
    if (!texImage) {
-      /* invalid mipmap level */
+      /* probably invalid mipmap level */
       _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
       return;
    }