fixed pointer arithmetic error in glCopyPixels
[mesa.git] / src / mesa / main / teximage.c
index 349e857743e51899f4b9214b3ec532fafbbd63dc..89cf12c8d0815cba1dfe447aabf649ecab6fdcb8 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: teximage.c,v 1.92 2001/04/19 22:39:50 brianp Exp $ */
+/* $Id: teximage.c,v 1.106 2001/11/18 22:48:13 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -39,6 +39,7 @@
 #include "texformat.h"
 #include "teximage.h"
 #include "texstate.h"
+#include "texstore.h"
 #include "mtypes.h"
 #include "swrast/s_span.h" /* XXX SWRAST hack */
 #endif
@@ -57,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;
 
@@ -100,6 +104,7 @@ static void PrintTexture(const struct gl_texture_image *img)
       }
       printf("\n");
    }
+#endif
 }
 #endif
 
@@ -306,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;
 }
 
 
@@ -319,15 +328,17 @@ is_compressed_format(GLcontext *ctx, GLenum internalFormat)
  * according to the target and level parameters.
  * This was basically prompted by the introduction of cube maps.
  */
-static void
-set_tex_image(struct gl_texture_object *tObj,
-              GLenum target, GLint level,
-              struct gl_texture_image *texImage)
+void
+_mesa_set_tex_image(struct gl_texture_object *tObj,
+                    GLenum target, GLint level,
+                    struct gl_texture_image *texImage)
 {
    ASSERT(tObj);
    ASSERT(texImage);
    switch (target) {
+      case GL_TEXTURE_1D:
       case GL_TEXTURE_2D:
+      case GL_TEXTURE_3D:
          tObj->Image[level] = texImage;
          return;
       case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
@@ -349,7 +360,7 @@ set_tex_image(struct gl_texture_object *tObj,
          tObj->NegZ[level] = texImage;
          return;
       default:
-         _mesa_problem(NULL, "bad target in set_tex_image()");
+         _mesa_problem(NULL, "bad target in _mesa_set_tex_image()");
          return;
    }
 }
@@ -440,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];
@@ -496,6 +508,7 @@ _mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_unit *texUnit,
 
 
 
+#if 000 /* not used anymore */
 /*
  * glTexImage[123]D can accept a NULL image pointer.  In this case we
  * create a texture image with unspecified image contents per the OpenGL
@@ -508,6 +521,7 @@ make_null_texture(GLint width, GLint height, GLint depth, GLenum format)
    const GLint numPixels = width * height * depth;
    GLubyte *data = (GLubyte *) MALLOC(numPixels * components * sizeof(GLubyte));
 
+#ifdef DEBUG
    /*
     * Let's see if anyone finds this.  If glTexImage2D() is called with
     * a NULL image pointer then load the texture image with something
@@ -540,9 +554,11 @@ make_null_texture(GLint width, GLint height, GLint depth, GLenum format)
          }
       }
    }
+#endif
 
    return data;
 }
+#endif
 
 
 
@@ -581,14 +597,15 @@ clear_teximage_fields(struct gl_texture_image *img)
 /*
  * Initialize basic fields of the gl_texture_image struct.
  */
-static void
-init_teximage_fields(GLcontext *ctx,
-                     struct gl_texture_image *img,
-                     GLsizei width, GLsizei height, GLsizei depth,
-                     GLint border, GLenum internalFormat)
+void
+_mesa_init_teximage_fields(GLcontext *ctx,
+                           struct gl_texture_image *img,
+                           GLsizei width, GLsizei height, GLsizei depth,
+                           GLint border, GLenum internalFormat)
 {
    ASSERT(img);
    img->Format = _mesa_base_tex_format( ctx, internalFormat );
+   ASSERT(img->Format > 0);
    img->IntFormat = internalFormat;
    img->Border = border;
    img->Width = width;
@@ -628,6 +645,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);
@@ -635,6 +653,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 ||
@@ -646,6 +665,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);
@@ -653,12 +676,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) {
@@ -670,7 +697,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];
@@ -682,7 +709,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];
@@ -706,7 +733,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];
@@ -718,7 +745,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);
@@ -747,6 +774,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
@@ -781,12 +810,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) {
@@ -801,19 +833,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);
@@ -875,14 +914,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 != -((GLint)destTex->Border)) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glTexSubImage1/2/3D(xoffset != -border");
+         return GL_TRUE;
+      }
+      if (dimensions > 1 && yoffset != -((GLint)destTex->Border)) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glTexSubImage2/3D(yoffset != -border");
+         return GL_TRUE;
+      }
+      if (dimensions > 2 && zoffset != -((GLint)destTex->Border)) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glTexSubImage3D(zoffset != -border");
+         return GL_TRUE;
+      }
+   }
+
    return GL_FALSE;
 }
 
@@ -898,12 +956,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) {
@@ -918,8 +978,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];
@@ -929,7 +996,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);
@@ -939,7 +1006,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);
@@ -958,14 +1025,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);
@@ -986,12 +1053,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) {
@@ -1006,15 +1076,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);
@@ -1085,6 +1162,25 @@ copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions,
       }
    }
 
+   compressed = is_compressed_format(ctx, teximage->IntFormat);
+   if (compressed) {
+      if (xoffset != -((GLint)teximage->Border)) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glCopyTexSubImage1/2/3D(xoffset != -border");
+         return GL_TRUE;
+      }
+      if (dimensions > 1 && yoffset != -((GLint)teximage->Border)) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glCopyTexSubImage2/3D(yoffset != -border");
+         return GL_TRUE;
+      }
+      if (dimensions > 2 && zoffset != -((GLint)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;
 }
@@ -1098,10 +1194,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;
    }
@@ -1130,13 +1246,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 */
@@ -1148,89 +1257,10 @@ _mesa_GetTexImage( GLenum target, GLint level, GLenum format,
       return;
    }
 
-   if (ctx->NewState & _NEW_PIXEL)
-      _mesa_update_state(ctx);
-
-   if (is_color_format(format) &&
-       ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
-      /* convert texture image to GL_RGBA, GL_FLOAT */
-      GLint width = texImage->Width;
-      GLint height = texImage->Height;
-      GLint depth = texImage->Depth;
-      GLint img, row;
-      GLfloat *tmpImage, *convImage;
-      tmpImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
-      if (!tmpImage) {
-         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
-         return;
-      }
-      convImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
-      if (!convImage) {
-         FREE(tmpImage);
-         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
-         return;
-      }
-
-      for (img = 0; img < depth; img++) {
-         GLint convWidth, convHeight;
-
-         /* convert texture data to GLfloat/GL_RGBA */
-         for (row = 0; row < height; row++) {
-            GLchan texels[1 << MAX_TEXTURE_LEVELS][4];
-            GLint col;
-            GLfloat *dst = tmpImage + row * width * 4;
-            for (col = 0; col < width; col++) {
-               (*texImage->FetchTexel)(texImage, col, row, img,
-                                       texels[col]);
-            }
-            _mesa_unpack_float_color_span(ctx, width, GL_RGBA, dst,
-                         GL_RGBA, CHAN_TYPE, texels,
-                         &_mesa_native_packing,
-                         ctx->_ImageTransferState & IMAGE_PRE_CONVOLUTION_BITS,
-                         GL_FALSE);
-         }
-
-         convWidth = width;
-         convHeight = height;
-
-         /* convolve */
-         if (target == GL_TEXTURE_1D) {
-            if (ctx->Pixel.Convolution1DEnabled) {
-               _mesa_convolve_1d_image(ctx, &convWidth, tmpImage, convImage);
-            }
-         }
-         else {
-            if (ctx->Pixel.Convolution2DEnabled) {
-               _mesa_convolve_2d_image(ctx, &convWidth, &convHeight,
-                                       tmpImage, convImage);
-            }
-            else if (ctx->Pixel.Separable2DEnabled) {
-               _mesa_convolve_sep_image(ctx, &convWidth, &convHeight,
-                                        tmpImage, convImage);
-            }
-         }
-
-         /* pack convolved image */
-         for (row = 0; row < convHeight; row++) {
-            const GLfloat *src = convImage + row * convWidth * 4;
-            GLvoid *dest = _mesa_image_address(&ctx->Pack, pixels,
-                                               convWidth, convHeight,
-                                               format, type, img, row, 0);
-            _mesa_pack_float_rgba_span(ctx, convWidth,
-                       (const GLfloat(*)[4]) src,
-                       format, type, dest, &ctx->Pack,
-                       ctx->_ImageTransferState & IMAGE_POST_CONVOLUTION_BITS);
-         }
-      }
-
-      FREE(tmpImage);
-      FREE(convImage);
-   }
-   else {
-      /* no convolution, or non-rgba image */
-      GLint width = texImage->Width;
-      GLint height = texImage->Height;
-      GLint depth = texImage->Depth;
+   {
+      const GLint width = texImage->Width;
+      const GLint height = texImage->Height;
+      const GLint depth = texImage->Depth;
       GLint img, row;
       for (img = 0; img < depth; img++) {
          for (row = 0; row < height; row++) {
@@ -1249,7 +1279,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];
@@ -1271,11 +1301,11 @@ _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 */
-   } /* convolution */
+   }
 }
 
 
@@ -1324,13 +1354,15 @@ _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
          texImage->Data = NULL;
       }
       clear_teximage_fields(texImage); /* not really needed, but helpful */
-      init_teximage_fields(ctx, texImage, postConvWidth, 1, 1,
-                           border, 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);
+
+#if 0 /* don't make default teximage anymore */
       if (pixels) {
          (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat,
                                    width, border, format, type, pixels,
@@ -1346,11 +1378,24 @@ _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
             FREE(dummy);
          }
       }
+#else
+      /* <pixels> may be null! */
+      (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat,
+                                width, border, format, type, pixels,
+                                &ctx->Unpack, texObj, texImage);
+#endif
 
       ASSERT(texImage->TexFormat);
-      texImage->FetchTexel = texImage->TexFormat->FetchTexel1D;
+      if (!texImage->FetchTexel) {
+         /* If driver didn't explicitly set this, use the default */
+         texImage->FetchTexel = texImage->TexFormat->FetchTexel1D;
+      }
       ASSERT(texImage->FetchTexel);
 
+      if (texImage->IsCompressed) {
+         ASSERT(texImage->CompressedSize > 0);
+      }
+
       /* state update */
       texObj->Complete = GL_FALSE;
       ctx->NewState |= _NEW_TEXTURE;
@@ -1365,8 +1410,8 @@ _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
          struct gl_texture_image *texImage;
          texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
          texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
-         init_teximage_fields(ctx, texImage, postConvWidth, 1, 1,
-                              border, internalFormat);
+         _mesa_init_teximage_fields(ctx, texImage, postConvWidth, 1, 1,
+                                    border, internalFormat);
          ASSERT(ctx->Driver.TestProxyTexImage);
          error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
                                                   internalFormat, format, type,
@@ -1422,7 +1467,7 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
 
       if (!texImage) {
          texImage = _mesa_alloc_texture_image();
-         set_tex_image(texObj, target, level, texImage);
+         _mesa_set_tex_image(texObj, target, level, texImage);
          if (!texImage) {
             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
             return;
@@ -1434,13 +1479,15 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
          texImage->Data = NULL;
       }
       clear_teximage_fields(texImage); /* not really needed, but helpful */
-      init_teximage_fields(ctx, texImage, postConvWidth, postConvHeight, 1,
-                           border, 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);
+
+#if 0 /* don't make default teximage anymore */
       if (pixels) {
          (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat,
                                    width, height, border, format, type, pixels,
@@ -1456,16 +1503,31 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
             FREE(dummy);
          }
       }
+#else
+      /* <pixels> may be null! */
+      (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat,
+                                width, height, border, format, type, pixels,
+                                &ctx->Unpack, texObj, texImage);
+#endif
 
       ASSERT(texImage->TexFormat);
-      texImage->FetchTexel = texImage->TexFormat->FetchTexel2D;
+      if (!texImage->FetchTexel) {
+         /* If driver didn't explicitly set this, use the default */
+         texImage->FetchTexel = texImage->TexFormat->FetchTexel2D;
+      }
       ASSERT(texImage->FetchTexel);
 
+      if (texImage->IsCompressed) {
+         ASSERT(texImage->CompressedSize > 0);
+      }
+
       /* state update */
       texObj->Complete = GL_FALSE;
       ctx->NewState |= _NEW_TEXTURE;
    }
-   else if (target == GL_PROXY_TEXTURE_2D) {
+   else if (target == GL_PROXY_TEXTURE_2D ||
+            (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB &&
+             ctx->Extensions.ARB_texture_cube_map)) {
       /* Proxy texture: check for errors and update proxy state */
       GLenum error = texture_error_check(ctx, target, level, internalFormat,
                                format, type, 2,
@@ -1475,8 +1537,8 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
          struct gl_texture_image *texImage;
          texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
          texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
-         init_teximage_fields(ctx, texImage, postConvWidth, postConvHeight, 1,
-                              border, internalFormat);
+         _mesa_init_teximage_fields(ctx, texImage, postConvWidth,
+                                    postConvHeight, 1, border, internalFormat);
          ASSERT(ctx->Driver.TestProxyTexImage);
          error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
                                     internalFormat, format, type,
@@ -1484,7 +1546,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]);
          }
       }
@@ -1501,7 +1565,7 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
  * Note that width and height include the border.
  */
 void
-_mesa_TexImage3D( GLenum target, GLint level, GLenum internalFormat,
+_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
                   GLsizei width, GLsizei height, GLsizei depth,
                   GLint border, GLenum format, GLenum type,
                   const GLvoid *pixels )
@@ -1536,13 +1600,15 @@ _mesa_TexImage3D( GLenum target, GLint level, GLenum internalFormat,
          texImage->Data = NULL;
       }
       clear_teximage_fields(texImage); /* not really needed, but helpful */
-      init_teximage_fields(ctx, texImage, width, height, depth, border,
-                           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);
+
+#if 0 /* don't make default teximage anymore */
       if (pixels) {
          (*ctx->Driver.TexImage3D)(ctx, target, level, (GLint) internalFormat,
                                    width, height, depth, border,
@@ -1560,11 +1626,24 @@ _mesa_TexImage3D( GLenum target, GLint level, GLenum internalFormat,
             FREE(dummy);
          }
       }
+#else
+      /* <pixels> may be null! */
+      (*ctx->Driver.TexImage3D)(ctx, target, level, internalFormat,
+                                width, height, depth, border, format, type,
+                                pixels, &ctx->Unpack, texObj, texImage);
+#endif
 
       ASSERT(texImage->TexFormat);
-      texImage->FetchTexel = texImage->TexFormat->FetchTexel3D;
+      if (!texImage->FetchTexel) {
+         /* If driver didn't explicitly set this, use the default */
+         texImage->FetchTexel = texImage->TexFormat->FetchTexel3D;
+      }
       ASSERT(texImage->FetchTexel);
 
+      if (texImage->IsCompressed) {
+         ASSERT(texImage->CompressedSize > 0);
+      }
+
       /* state update */
       texObj->Complete = GL_FALSE;
       ctx->NewState |= _NEW_TEXTURE;
@@ -1578,8 +1657,8 @@ _mesa_TexImage3D( GLenum target, GLint level, GLenum internalFormat,
          struct gl_texture_image *texImage;
          texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
          texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
-         init_teximage_fields(ctx, texImage, width, height, 1,
-                              border, internalFormat);
+         _mesa_init_teximage_fields(ctx, texImage, width, height, 1,
+                                    border, internalFormat);
          ASSERT(ctx->Driver.TestProxyTexImage);
          error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
                                                  internalFormat, format, type,
@@ -1587,7 +1666,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]);
          }
       }
@@ -1624,7 +1703,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 */
@@ -1670,7 +1749,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 */
@@ -1718,7 +1797,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,
@@ -1763,7 +1842,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)) {
@@ -1779,7 +1858,7 @@ _mesa_CopyTexImage1D( GLenum target, GLint level,
    texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
    if (!texImage) {
       texImage = _mesa_alloc_texture_image();
-      set_tex_image(texObj, target, level, texImage);
+      _mesa_set_tex_image(texObj, target, level, texImage);
       if (!texImage) {
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
          return;
@@ -1792,8 +1871,8 @@ _mesa_CopyTexImage1D( GLenum target, GLint level,
    }
 
    clear_teximage_fields(texImage); /* not really needed, but helpful */
-   init_teximage_fields(ctx, texImage, postConvWidth, 1, 1,
-                        border, internalFormat);
+   _mesa_init_teximage_fields(ctx, texImage, postConvWidth, 1, 1,
+                              border, internalFormat);
 
 
    ASSERT(ctx->Driver.CopyTexImage1D);
@@ -1801,7 +1880,10 @@ _mesa_CopyTexImage1D( GLenum target, GLint level,
                                  x, y, width, border);
 
    ASSERT(texImage->TexFormat);
-   texImage->FetchTexel = texImage->TexFormat->FetchTexel1D;
+   if (!texImage->FetchTexel) {
+      /* If driver didn't explicitly set this, use the default */
+      texImage->FetchTexel = texImage->TexFormat->FetchTexel1D;
+   }
    ASSERT(texImage->FetchTexel);
 
    /* state update */
@@ -1823,7 +1905,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)) {
@@ -1840,7 +1922,7 @@ _mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
    texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
    if (!texImage) {
       texImage = _mesa_alloc_texture_image();
-      set_tex_image(texObj, target, level, texImage);
+      _mesa_set_tex_image(texObj, target, level, texImage);
       if (!texImage) {
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
          return;
@@ -1853,15 +1935,18 @@ _mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
    }
 
    clear_teximage_fields(texImage); /* not really needed, but helpful */
-   init_teximage_fields(ctx, texImage, postConvWidth, postConvHeight, 1,
-                        border, internalFormat);
+   _mesa_init_teximage_fields(ctx, texImage, postConvWidth, postConvHeight, 1,
+                              border, internalFormat);
 
    ASSERT(ctx->Driver.CopyTexImage2D);
    (*ctx->Driver.CopyTexImage2D)(ctx, target, level, internalFormat,
                                  x, y, width, height, border);
 
    ASSERT(texImage->TexFormat);
-   texImage->FetchTexel = texImage->TexFormat->FetchTexel2D;
+   if (!texImage->FetchTexel) {
+      /* If driver didn't explicitly set this, use the default */
+      texImage->FetchTexel = texImage->TexFormat->FetchTexel2D;
+   }
    ASSERT(texImage->FetchTexel);
 
    /* state update */
@@ -1882,7 +1967,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 */
@@ -1918,7 +2003,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 */
@@ -1956,7 +2041,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 */
@@ -2034,7 +2119,8 @@ _mesa_CompressedTexImage1DARB(GLenum target, GLint level,
          texImage->Data = NULL;
       }
 
-      init_teximage_fields(ctx, texImage, width, 1, 1, border, internalFormat);
+      _mesa_init_teximage_fields(ctx, texImage, width, 1, 1,
+                                 border, internalFormat);
 
       if (ctx->Extensions.ARB_texture_compression) {
          ASSERT(ctx->Driver.CompressedTexImage1D);
@@ -2058,8 +2144,8 @@ _mesa_CompressedTexImage1DARB(GLenum target, GLint level,
          struct gl_texture_image *texImage;
          texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
          texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
-         init_teximage_fields(ctx, texImage, width, 1, 1,
-                              border, internalFormat);
+         _mesa_init_teximage_fields(ctx, texImage, width, 1, 1,
+                                    border, internalFormat);
          ASSERT(ctx->Driver.TestProxyTexImage);
          error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
                                              internalFormat, GL_NONE, GL_NONE,
@@ -2073,7 +2159,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;
    }
 }
@@ -2132,8 +2218,8 @@ _mesa_CompressedTexImage2DARB(GLenum target, GLint level,
          texImage->Data = NULL;
       }
 
-      init_teximage_fields(ctx, texImage, width, height, 1, border,
-                           internalFormat);
+      _mesa_init_teximage_fields(ctx, texImage, width, height, 1, border,
+                                 internalFormat);
 
       if (ctx->Extensions.ARB_texture_compression) {
          ASSERT(ctx->Driver.CompressedTexImage2D);
@@ -2157,8 +2243,8 @@ _mesa_CompressedTexImage2DARB(GLenum target, GLint level,
          struct gl_texture_image *texImage;
          texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
          texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
-         init_teximage_fields(ctx, texImage, width, height, 1,
-                              border, internalFormat);
+         _mesa_init_teximage_fields(ctx, texImage, width, height, 1,
+                                    border, internalFormat);
          ASSERT(ctx->Driver.TestProxyTexImage);
          error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
                                               internalFormat, GL_NONE, GL_NONE,
@@ -2166,13 +2252,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;
    }
 }
@@ -2228,8 +2316,8 @@ _mesa_CompressedTexImage3DARB(GLenum target, GLint level,
          texImage->Data = NULL;
       }
 
-      init_teximage_fields(ctx, texImage, width, height, depth, border,
-                           internalFormat);
+      _mesa_init_teximage_fields(ctx, texImage, width, height, depth, border,
+                                 internalFormat);
 
       if (ctx->Extensions.ARB_texture_compression) {
          ASSERT(ctx->Driver.CompressedTexImage3D);
@@ -2254,8 +2342,8 @@ _mesa_CompressedTexImage3DARB(GLenum target, GLint level,
          struct gl_texture_image *texImage;
          texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
          texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
-         init_teximage_fields(ctx, texImage, width, height, depth,
-                              border, internalFormat);
+         _mesa_init_teximage_fields(ctx, texImage, width, height, depth,
+                                    border, internalFormat);
          ASSERT(ctx->Driver.TestProxyTexImage);
          error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
                                              internalFormat, GL_NONE, GL_NONE,
@@ -2263,13 +2351,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;
    }
 }
@@ -2386,11 +2474,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;
    }
 
@@ -2399,12 +2507,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;
    }