mesa: more comments, clean-ups
[mesa.git] / src / mesa / main / texparam.c
index 8df22fe9e2e0a5321549435c82b88602bfd1f9d8..05d144270ecdcd4219cf154874676b7d2d685c02 100644 (file)
@@ -3,7 +3,7 @@
  * Version:  7.5
  *
  * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
- * Copyright (C) 1999-2009  VMware, Inc.  All Rights Reserved.
+ * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -38,6 +38,7 @@
 #include "main/texcompress.h"
 #include "main/texparam.h"
 #include "main/teximage.h"
+#include "main/texstate.h"
 #include "shader/prog_instruction.h"
 
 
@@ -69,7 +70,7 @@ validate_texture_wrap_mode(GLcontext * ctx, GLenum target, GLenum wrap)
       return GL_TRUE;
    }
 
-   _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
+   _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param=0x%x)", wrap );
    return GL_FALSE;
 }
 
@@ -88,33 +89,33 @@ get_texobj(GLcontext *ctx, GLenum target)
       return NULL;
    }
 
-   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+   texUnit = _mesa_get_current_tex_unit(ctx);
 
    switch (target) {
    case GL_TEXTURE_1D:
-      return texUnit->Current1D;
+      return texUnit->CurrentTex[TEXTURE_1D_INDEX];
    case GL_TEXTURE_2D:
-      return texUnit->Current2D;
+      return texUnit->CurrentTex[TEXTURE_2D_INDEX];
    case GL_TEXTURE_3D:
-      return texUnit->Current3D;
+      return texUnit->CurrentTex[TEXTURE_3D_INDEX];
    case GL_TEXTURE_CUBE_MAP:
       if (ctx->Extensions.ARB_texture_cube_map) {
-         return texUnit->CurrentCubeMap;
+         return texUnit->CurrentTex[TEXTURE_CUBE_INDEX];
       }
       break;
    case GL_TEXTURE_RECTANGLE_NV:
       if (ctx->Extensions.NV_texture_rectangle) {
-         return texUnit->CurrentRect;
+         return texUnit->CurrentTex[TEXTURE_RECT_INDEX];
       }
       break;
    case GL_TEXTURE_1D_ARRAY_EXT:
       if (ctx->Extensions.MESA_texture_array) {
-         return texUnit->Current1DArray;
+         return texUnit->CurrentTex[TEXTURE_1D_ARRAY_INDEX];
       }
       break;
    case GL_TEXTURE_2D_ARRAY_EXT:
       if (ctx->Extensions.MESA_texture_array) {
-         return texUnit->Current2DArray;
+         return texUnit->CurrentTex[TEXTURE_2D_ARRAY_INDEX];
       }
       break;
    default:
@@ -165,8 +166,25 @@ set_swizzle_component(GLuint *swizzle, GLuint comp, GLuint swz)
 }
 
 
-/** Set an integer-valued texture parameter */
-static void
+/**
+ * This is called just prior to changing any texture object state.
+ * Any pending rendering will be flushed out, we'll set the _NEW_TEXTURE
+ * state flag and then mark the texture object as 'incomplete' so that any
+ * per-texture derived state gets recomputed.
+ */
+static INLINE void
+flush(GLcontext *ctx, struct gl_texture_object *texObj)
+{
+   FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+   texObj->_Complete = GL_FALSE;
+}
+
+
+/**
+ * Set an integer-valued texture parameter
+ * \return GL_TRUE if legal AND the value changed, GL_FALSE otherwise
+ */
+static GLboolean
 set_tex_parameteri(GLcontext *ctx,
                    struct gl_texture_object *texObj,
                    GLenum pname, const GLint *params)
@@ -174,124 +192,141 @@ set_tex_parameteri(GLcontext *ctx,
    switch (pname) {
    case GL_TEXTURE_MIN_FILTER:
       if (texObj->MinFilter == params[0])
-         return;
+         return GL_FALSE;
       switch (params[0]) {
       case GL_NEAREST:
       case GL_LINEAR:
-         FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+         flush(ctx, texObj);
          texObj->MinFilter = params[0];
-         return;
+         return GL_TRUE;
       case GL_NEAREST_MIPMAP_NEAREST:
       case GL_LINEAR_MIPMAP_NEAREST:
       case GL_NEAREST_MIPMAP_LINEAR:
       case GL_LINEAR_MIPMAP_LINEAR:
          if (texObj->Target != GL_TEXTURE_RECTANGLE_NV) {
-            FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+            flush(ctx, texObj);
             texObj->MinFilter = params[0];
-            return;
+            return GL_TRUE;
          }
          /* fall-through */
       default:
-         _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
+         _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param=0x%x)",
+                      params[0] );
       }
-      return;
+      return GL_FALSE;
 
    case GL_TEXTURE_MAG_FILTER:
       if (texObj->MagFilter == params[0])
-         return;
+         return GL_FALSE;
       switch (params[0]) {
       case GL_NEAREST:
       case GL_LINEAR:
-         FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+         flush(ctx, texObj);
          texObj->MagFilter = params[0];
-         return;
+         return GL_TRUE;
       default:
-         _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
+         _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param=0x%x)",
+                      params[0]);
       }
-      return;
+      return GL_FALSE;
 
    case GL_TEXTURE_WRAP_S:
       if (texObj->WrapS == params[0])
-         return;
+         return GL_FALSE;
       if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) {
-         FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+         flush(ctx, texObj);
          texObj->WrapS = params[0];
+         return GL_TRUE;
       }
-      return;
+      return GL_FALSE;
 
    case GL_TEXTURE_WRAP_T:
       if (texObj->WrapT == params[0])
-         return;
+         return GL_FALSE;
       if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) {
-         FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+         flush(ctx, texObj);
          texObj->WrapT = params[0];
+         return GL_TRUE;
       }
-      return;
+      return GL_FALSE;
 
    case GL_TEXTURE_WRAP_R:
       if (texObj->WrapR == params[0])
-         return;
+         return GL_FALSE;
       if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) {
-         FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+         flush(ctx, texObj);
          texObj->WrapR = params[0];
+         return GL_TRUE;
       }
-      return;
+      return GL_FALSE;
 
    case GL_TEXTURE_BASE_LEVEL:
       if (texObj->BaseLevel == params[0])
-         return;
+         return GL_FALSE;
       if (params[0] < 0 ||
           (texObj->Target == GL_TEXTURE_RECTANGLE_ARB && params[0] != 0)) {
-         _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)");
-         return;
+         _mesa_error(ctx, GL_INVALID_VALUE,
+                     "glTexParameter(param=%d)", params[0]);
+         return GL_FALSE;
       }
-      FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+      flush(ctx, texObj);
       texObj->BaseLevel = params[0];
-      return;
+      return GL_TRUE;
 
    case GL_TEXTURE_MAX_LEVEL:
       if (texObj->MaxLevel == params[0])
-         return;
+         return GL_FALSE;
       if (params[0] < 0 || texObj->Target == GL_TEXTURE_RECTANGLE_ARB) {
-         _mesa_error(ctx, GL_INVALID_OPERATION, "glTexParameter(param)");
-         return;
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glTexParameter(param=%d)", params[0]);
+         return GL_FALSE;
       }
-      FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+      flush(ctx, texObj);
       texObj->MaxLevel = params[0];
-      return;
+      return GL_TRUE;
 
    case GL_GENERATE_MIPMAP_SGIS:
       if (ctx->Extensions.SGIS_generate_mipmap) {
-         FLUSH_VERTICES(ctx, _NEW_TEXTURE);
-         texObj->GenerateMipmap = params[0] ? GL_TRUE : GL_FALSE;
+         if (texObj->GenerateMipmap != params[0]) {
+            flush(ctx, texObj);
+            texObj->GenerateMipmap = params[0] ? GL_TRUE : GL_FALSE;
+            return GL_TRUE;
+         }
+         return GL_FALSE;
       }
       else {
          _mesa_error(ctx, GL_INVALID_ENUM,
                      "glTexParameter(pname=GL_GENERATE_MIPMAP_SGIS)");
       }
-      return;
+      return GL_FALSE;
 
    case GL_TEXTURE_COMPARE_MODE_ARB:
       if (ctx->Extensions.ARB_shadow &&
           (params[0] == GL_NONE ||
            params[0] == GL_COMPARE_R_TO_TEXTURE_ARB)) {
-         FLUSH_VERTICES(ctx, _NEW_TEXTURE);
-         texObj->CompareMode = params[0];
+         if (texObj->CompareMode != params[0]) {
+            flush(ctx, texObj);
+            texObj->CompareMode = params[0];
+            return GL_TRUE;
+         }
+         return GL_FALSE;
       }
       else {
          _mesa_error(ctx, GL_INVALID_ENUM,
                      "glTexParameter(GL_TEXTURE_COMPARE_MODE_ARB)");
       }
-      return;
+      return GL_FALSE;
 
    case GL_TEXTURE_COMPARE_FUNC_ARB:
       if (ctx->Extensions.ARB_shadow) {
+         if (texObj->CompareFunc == params[0])
+            return GL_FALSE;
          switch (params[0]) {
          case GL_LEQUAL:
          case GL_GEQUAL:
-            FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+            flush(ctx, texObj);
             texObj->CompareFunc = params[0];
-            return;
+            return GL_TRUE;
          case GL_EQUAL:
          case GL_NOTEQUAL:
          case GL_LESS:
@@ -299,9 +334,9 @@ set_tex_parameteri(GLcontext *ctx,
          case GL_ALWAYS:
          case GL_NEVER:
             if (ctx->Extensions.EXT_shadow_funcs) {
-               FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+               flush(ctx, texObj);
                texObj->CompareFunc = params[0];
-               return;
+               return GL_TRUE;
             }
             /* fall-through */
          default:
@@ -310,23 +345,26 @@ set_tex_parameteri(GLcontext *ctx,
          }
       }
       else {
-         _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(param)");
+         _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=0x%x)", pname);
       }
-      return;
+      return GL_FALSE;
 
    case GL_DEPTH_TEXTURE_MODE_ARB:
       if (ctx->Extensions.ARB_depth_texture &&
           (params[0] == GL_LUMINANCE ||
            params[0] == GL_INTENSITY ||
            params[0] == GL_ALPHA)) {
-         FLUSH_VERTICES(ctx, _NEW_TEXTURE);
-         texObj->DepthMode = params[0];
+         if (texObj->DepthMode != params[0]) {
+            flush(ctx, texObj);
+            texObj->DepthMode = params[0];
+            return GL_TRUE;
+         }
       }
       else {
          _mesa_error(ctx, GL_INVALID_ENUM,
                      "glTexParameter(GL_DEPTH_TEXTURE_MODE_ARB)");
       }
-      return;
+      return GL_FALSE;
 
 #ifdef FEATURE_OES_draw_texture
    case GL_TEXTURE_CROP_RECT_OES:
@@ -334,7 +372,7 @@ set_tex_parameteri(GLcontext *ctx,
       texObj->CropRect[1] = params[1];
       texObj->CropRect[2] = params[2];
       texObj->CropRect[3] = params[3];
-      return;
+      return GL_TRUE;
 #endif
 
    case GL_TEXTURE_SWIZZLE_R_EXT:
@@ -347,23 +385,23 @@ set_tex_parameteri(GLcontext *ctx,
          if (swz < 0) {
             _mesa_error(ctx, GL_INVALID_OPERATION,
                         "glTexParameter(swizzle 0x%x)", params[0]);
-            return;
+            return GL_FALSE;
          }
          ASSERT(comp < 4);
          if (swz >= 0) {
-            FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+            flush(ctx, texObj);
             texObj->Swizzle[comp] = params[0];
             set_swizzle_component(&texObj->_Swizzle, comp, swz);
-            return;
+            return GL_TRUE;
          }
       }
       _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=0x%x)", pname);
-      return;
+      return GL_FALSE;
 
    case GL_TEXTURE_SWIZZLE_RGBA_EXT:
       if (ctx->Extensions.EXT_texture_swizzle) {
          GLuint comp;
-         FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+         flush(ctx, texObj);
          for (comp = 0; comp < 4; comp++) {
             const GLint swz = comp_to_swizzle(params[comp]);
             if (swz >= 0) {
@@ -373,22 +411,26 @@ set_tex_parameteri(GLcontext *ctx,
             else {
                _mesa_error(ctx, GL_INVALID_OPERATION,
                            "glTexParameter(swizzle 0x%x)", params[comp]);
-               return;
+               return GL_FALSE;
             }
          }
-         return;
+         return GL_TRUE;
       }
       _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=0x%x)", pname);
-      return;
+      return GL_FALSE;
 
    default:
       _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=0x%x)", pname);
    }
+   return GL_FALSE;
 }
 
 
-/** Set a float-valued texture parameter */
-static void
+/**
+ * Set a float-valued texture parameter
+ * \return GL_TRUE if legal AND the value changed, GL_FALSE otherwise
+ */
+static GLboolean
 set_tex_parameterf(GLcontext *ctx,
                    struct gl_texture_object *texObj,
                    GLenum pname, const GLfloat *params)
@@ -396,82 +438,90 @@ set_tex_parameterf(GLcontext *ctx,
    switch (pname) {
    case GL_TEXTURE_MIN_LOD:
       if (texObj->MinLod == params[0])
-         return;
-      FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+         return GL_FALSE;
+      flush(ctx, texObj);
       texObj->MinLod = params[0];
-      return;
+      return GL_TRUE;
 
    case GL_TEXTURE_MAX_LOD:
       if (texObj->MaxLod == params[0])
-         return;
-      FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+         return GL_FALSE;
+      flush(ctx, texObj);
       texObj->MaxLod = params[0];
-      return;
+      return GL_TRUE;
 
    case GL_TEXTURE_PRIORITY:
-      FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+      flush(ctx, texObj);
       texObj->Priority = CLAMP(params[0], 0.0F, 1.0F);
-      return;
+      return GL_TRUE;
 
    case GL_TEXTURE_MAX_ANISOTROPY_EXT:
       if (ctx->Extensions.EXT_texture_filter_anisotropic) {
+         if (texObj->MaxAnisotropy == params[0])
+            return GL_FALSE;
          if (params[0] < 1.0) {
             _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
-            return;
+            return GL_FALSE;
          }
-         FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+         flush(ctx, texObj);
          /* clamp to max, that's what NVIDIA does */
          texObj->MaxAnisotropy = MIN2(params[0],
                                       ctx->Const.MaxTextureMaxAnisotropy);
+         return GL_TRUE;
       }
       else {
-         _mesa_error(ctx, GL_INVALID_ENUM,
-                     "glTexParameter(pname=GL_TEXTURE_MAX_ANISOTROPY_EXT)");
+         static GLuint count = 0;
+         if (count++ < 10)
+            _mesa_error(ctx, GL_INVALID_ENUM,
+                        "glTexParameter(pname=GL_TEXTURE_MAX_ANISOTROPY_EXT)");
       }
-      return;
+      return GL_FALSE;
 
    case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB:
       if (ctx->Extensions.ARB_shadow_ambient) {
-         FLUSH_VERTICES(ctx, _NEW_TEXTURE);
-         texObj->CompareFailValue = CLAMP(params[0], 0.0F, 1.0F);
+         if (texObj->CompareFailValue != params[0]) {
+            flush(ctx, texObj);
+            texObj->CompareFailValue = CLAMP(params[0], 0.0F, 1.0F);
+            return GL_TRUE;
+         }
       }
       else {
          _mesa_error(ctx, GL_INVALID_ENUM,
                     "glTexParameter(pname=GL_TEXTURE_COMPARE_FAIL_VALUE_ARB)");
       }
-      return;
+      return GL_FALSE;
 
    case GL_TEXTURE_LOD_BIAS:
       /* NOTE: this is really part of OpenGL 1.4, not EXT_texture_lod_bias */
       if (ctx->Extensions.EXT_texture_lod_bias) {
          if (texObj->LodBias != params[0]) {
-            FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+            flush(ctx, texObj);
             texObj->LodBias = params[0];
+            return GL_TRUE;
          }
+         return GL_FALSE;
       }
       break;
 
    case GL_TEXTURE_BORDER_COLOR:
-      FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+      flush(ctx, texObj);
       texObj->BorderColor[RCOMP] = params[0];
       texObj->BorderColor[GCOMP] = params[1];
       texObj->BorderColor[BCOMP] = params[2];
       texObj->BorderColor[ACOMP] = params[3];
-      UNCLAMPED_FLOAT_TO_CHAN(texObj->_BorderChan[RCOMP], params[0]);
-      UNCLAMPED_FLOAT_TO_CHAN(texObj->_BorderChan[GCOMP], params[1]);
-      UNCLAMPED_FLOAT_TO_CHAN(texObj->_BorderChan[BCOMP], params[2]);
-      UNCLAMPED_FLOAT_TO_CHAN(texObj->_BorderChan[ACOMP], params[3]);
-      return;
+      return GL_TRUE;
 
    default:
       _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=0x%x)", pname);
    }
+   return GL_FALSE;
 }
 
 
 void GLAPIENTRY
 _mesa_TexParameterf(GLenum target, GLenum pname, GLfloat param)
 {
+   GLboolean need_update;
    struct gl_texture_object *texObj;
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
@@ -495,17 +545,15 @@ _mesa_TexParameterf(GLenum target, GLenum pname, GLfloat param)
       {
          /* convert float param to int */
          GLint p = (GLint) param;
-         set_tex_parameteri(ctx, texObj, pname, &p);
+         need_update = set_tex_parameteri(ctx, texObj, pname, &p);
       }
-      return;
+      break;
    default:
       /* this will generate an error if pname is illegal */
-      set_tex_parameterf(ctx, texObj, pname, &param);
+      need_update = set_tex_parameterf(ctx, texObj, pname, &param);
    }
 
-   texObj->_Complete = GL_FALSE;
-
-   if (ctx->Driver.TexParameter && ctx->ErrorValue == GL_NO_ERROR) {
+   if (ctx->Driver.TexParameter && need_update) {
       ctx->Driver.TexParameter(ctx, target, texObj, pname, &param);
    }
 }
@@ -514,6 +562,7 @@ _mesa_TexParameterf(GLenum target, GLenum pname, GLfloat param)
 void GLAPIENTRY
 _mesa_TexParameterfv(GLenum target, GLenum pname, const GLfloat *params)
 {
+   GLboolean need_update;
    struct gl_texture_object *texObj;
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
@@ -537,7 +586,7 @@ _mesa_TexParameterfv(GLenum target, GLenum pname, const GLfloat *params)
       {
          /* convert float param to int */
          GLint p = (GLint) params[0];
-         set_tex_parameteri(ctx, texObj, pname, &p);
+         need_update = set_tex_parameteri(ctx, texObj, pname, &p);
       }
       break;
 
@@ -550,19 +599,17 @@ _mesa_TexParameterfv(GLenum target, GLenum pname, const GLfloat *params)
          iparams[1] = (GLint) params[1];
          iparams[2] = (GLint) params[2];
          iparams[3] = (GLint) params[3];
-         set_tex_parameteri(ctx, target, iparams);
+         need_update = set_tex_parameteri(ctx, target, iparams);
       }
       break;
 #endif
 
    default:
       /* this will generate an error if pname is illegal */
-      set_tex_parameterf(ctx, texObj, pname, params);
+      need_update = set_tex_parameterf(ctx, texObj, pname, params);
    }
 
-   texObj->_Complete = GL_FALSE;
-
-   if (ctx->Driver.TexParameter && ctx->ErrorValue == GL_NO_ERROR) {
+   if (ctx->Driver.TexParameter && need_update) {
       ctx->Driver.TexParameter(ctx, target, texObj, pname, params);
    }
 }
@@ -571,6 +618,7 @@ _mesa_TexParameterfv(GLenum target, GLenum pname, const GLfloat *params)
 void GLAPIENTRY
 _mesa_TexParameteri(GLenum target, GLenum pname, GLint param)
 {
+   GLboolean need_update;
    struct gl_texture_object *texObj;
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
@@ -589,17 +637,15 @@ _mesa_TexParameteri(GLenum target, GLenum pname, GLint param)
       {
          GLfloat fparam = (GLfloat) param;
          /* convert int param to float */
-         set_tex_parameterf(ctx, texObj, pname, &fparam);
+         need_update = set_tex_parameterf(ctx, texObj, pname, &fparam);
       }
       break;
    default:
       /* this will generate an error if pname is illegal */
-      set_tex_parameteri(ctx, texObj, pname, &param);
+      need_update = set_tex_parameteri(ctx, texObj, pname, &param);
    }
 
-   texObj->_Complete = GL_FALSE;
-
-   if (ctx->Driver.TexParameter && ctx->ErrorValue == GL_NO_ERROR) {
+   if (ctx->Driver.TexParameter && need_update) {
       GLfloat fparam = (GLfloat) param;
       ctx->Driver.TexParameter(ctx, target, texObj, pname, &fparam);
    }
@@ -609,6 +655,7 @@ _mesa_TexParameteri(GLenum target, GLenum pname, GLint param)
 void GLAPIENTRY
 _mesa_TexParameteriv(GLenum target, GLenum pname, const GLint *params)
 {
+   GLboolean need_update;
    struct gl_texture_object *texObj;
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
@@ -626,7 +673,7 @@ _mesa_TexParameteriv(GLenum target, GLenum pname, const GLint *params)
          fparams[1] = INT_TO_FLOAT(params[1]);
          fparams[2] = INT_TO_FLOAT(params[2]);
          fparams[3] = INT_TO_FLOAT(params[3]);
-         set_tex_parameterf(ctx, texObj, pname, fparams);
+         need_update = set_tex_parameterf(ctx, texObj, pname, fparams);
       }
       break;
    case GL_TEXTURE_MIN_LOD:
@@ -638,17 +685,15 @@ _mesa_TexParameteriv(GLenum target, GLenum pname, const GLint *params)
       {
          /* convert int param to float */
          GLfloat fparam = (GLfloat) params[0];
-         set_tex_parameterf(ctx, texObj, pname, &fparam);
+         need_update = set_tex_parameterf(ctx, texObj, pname, &fparam);
       }
       break;
    default:
       /* this will generate an error if pname is illegal */
-      set_tex_parameteri(ctx, texObj, pname, params);
+      need_update = set_tex_parameteri(ctx, texObj, pname, params);
    }
 
-   texObj->_Complete = GL_FALSE;
-
-   if (ctx->Driver.TexParameter && ctx->ErrorValue == GL_NO_ERROR) {
+   if (ctx->Driver.TexParameter && need_update) {
       GLfloat fparams[4];
       fparams[0] = INT_TO_FLOAT(params[0]);
       if (pname == GL_TEXTURE_BORDER_COLOR ||
@@ -672,44 +717,6 @@ _mesa_GetTexLevelParameterfv( GLenum target, GLint level,
 }
 
 
-static GLuint
-tex_image_dimensions(GLcontext *ctx, GLenum target)
-{
-   switch (target) {
-      case GL_TEXTURE_1D:
-      case GL_PROXY_TEXTURE_1D:
-         return 1;
-      case GL_TEXTURE_2D:
-      case GL_PROXY_TEXTURE_2D:
-         return 2;
-      case GL_TEXTURE_3D:
-      case GL_PROXY_TEXTURE_3D:
-         return 3;
-      case GL_TEXTURE_CUBE_MAP:
-      case GL_PROXY_TEXTURE_CUBE_MAP:
-      case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
-      case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
-      case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
-      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
-      case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
-      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
-         return ctx->Extensions.ARB_texture_cube_map ? 2 : 0;
-      case GL_TEXTURE_RECTANGLE_NV:
-      case GL_PROXY_TEXTURE_RECTANGLE_NV:
-         return ctx->Extensions.NV_texture_rectangle ? 2 : 0;
-      case GL_TEXTURE_1D_ARRAY_EXT:
-      case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
-         return ctx->Extensions.MESA_texture_array ? 2 : 0;
-      case GL_TEXTURE_2D_ARRAY_EXT:
-      case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
-         return ctx->Extensions.MESA_texture_array ? 3 : 0;
-      default:
-         _mesa_problem(ctx, "bad target in _mesa_tex_target_dimensions()");
-         return 0;
-   }
-}
-
-
 void GLAPIENTRY
 _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
                               GLenum pname, GLint *params )
@@ -717,7 +724,6 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
    const struct gl_texture_unit *texUnit;
    struct gl_texture_object *texObj;
    const struct gl_texture_image *img = NULL;
-   GLuint dimensions;
    GLboolean isProxy;
    GLint maxLevels;
    GET_CURRENT_CONTEXT(ctx);
@@ -729,19 +735,13 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
       return;
    }
 
-   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+   texUnit = _mesa_get_current_tex_unit(ctx);
 
    /* this will catch bad target values */
-   dimensions = tex_image_dimensions(ctx, target);  /* 1, 2 or 3 */
-   if (dimensions == 0) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexLevelParameter[if]v(target)");
-      return;
-   }
-
    maxLevels = _mesa_max_texture_levels(ctx, target);
    if (maxLevels == 0) {
-      /* should not happen since <target> was just checked above */
-      _mesa_problem(ctx, "maxLevels=0 in _mesa_GetTexLevelParameter");
+      _mesa_error(ctx, GL_INVALID_ENUM,
+                  "glGetTexLevelParameter[if]v(target=0x%x)", target);
       return;
    }
 
@@ -838,7 +838,8 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
                         "glGetTexLevelParameter[if]v(pname)");
          break;
       case GL_TEXTURE_STENCIL_SIZE_EXT:
-         if (ctx->Extensions.EXT_packed_depth_stencil) {
+         if (ctx->Extensions.EXT_packed_depth_stencil ||
+             ctx->Extensions.ARB_framebuffer_object) {
             *params = img->TexFormat->StencilBits;
          }
          else {
@@ -957,7 +958,7 @@ _mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params )
       return;
    }
 
-   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+   texUnit = _mesa_get_current_tex_unit(ctx);
 
    obj = _mesa_select_tex_object(ctx, texUnit, target);
    if (!obj) {
@@ -1124,7 +1125,7 @@ _mesa_GetTexParameteriv( GLenum target, GLenum pname, GLint *params )
       return;
    }
 
-   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+   texUnit = _mesa_get_current_tex_unit(ctx);
 
    obj = _mesa_select_tex_object(ctx, texUnit, target);
    if (!obj) {