illegal to set GL_TEXTURE_MAX_LEVEL w/ GL_TEXTURE_RECTANGLE_ARB
[mesa.git] / src / mesa / main / texstate.c
index daf579a7bfc8101b1878d3e1df25a32250038b18..51e19b7f4e7a589dea938c4dad9f2d1f98a12548 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.5
+ * Version:  6.5.3
  *
- * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2007  Brian Paul   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"),
 #include "context.h"
 #include "enums.h"
 #include "macros.h"
+#include "texcompress.h"
 #include "texobj.h"
 #include "teximage.h"
 #include "texstate.h"
 #include "texenvprogram.h"
 #include "mtypes.h"
 #include "math/m_xform.h"
-#include "shaderobjects.h"
-
 
 
 #define ENUM_TO_FLOAT(X) ((GLfloat)(GLint)(X))
@@ -143,6 +142,8 @@ _mesa_copy_texture_state( const GLcontext *src, GLcontext *dst )
       dst->Texture.Unit[i].Combine.ScaleShiftA = src->Texture.Unit[i].Combine.ScaleShiftA;
 
       /* copy texture object bindings, not contents of texture objects */
+      _mesa_lock_context_textures(dst);
+
       copy_texture_binding(src, &dst->Texture.Unit[i].Current1D,
                            src->Texture.Unit[i].Current1D);
       copy_texture_binding(src, &dst->Texture.Unit[i].Current2D,
@@ -153,6 +154,8 @@ _mesa_copy_texture_state( const GLcontext *src, GLcontext *dst )
                            src->Texture.Unit[i].CurrentCubeMap);
       copy_texture_binding(src, &dst->Texture.Unit[i].CurrentRect,
                            src->Texture.Unit[i].CurrentRect);
+
+      _mesa_unlock_context_textures(dst);
    }
 }
 
@@ -312,10 +315,20 @@ calculate_derived_texenv( struct gl_tex_env_combine_state *state,
 void GLAPIENTRY
 _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param )
 {
+   GLuint maxUnit;
    GET_CURRENT_CONTEXT(ctx);
-   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+   struct gl_texture_unit *texUnit;
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
+   maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV)
+      ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxTextureImageUnits;
+   if (ctx->Texture.CurrentUnit >= maxUnit) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "glTexEnvfv(current unit)");
+      return;
+   }
+
+   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+
 #define TE_ERROR(errCode, msg, value)                          \
    _mesa_error(ctx, errCode, msg, _mesa_lookup_enum_by_nr(value));
 
@@ -795,10 +808,20 @@ _mesa_TexEnviv( GLenum target, GLenum pname, const GLint *param )
 void GLAPIENTRY
 _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
 {
+   GLuint maxUnit;
+   const struct gl_texture_unit *texUnit;
    GET_CURRENT_CONTEXT(ctx);
-   const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
+   maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV)
+      ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxTextureImageUnits;
+   if (ctx->Texture.CurrentUnit >= maxUnit) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexEnvfv(current unit)");
+      return;
+   }
+
+   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+
    if (target == GL_TEXTURE_ENV) {
       switch (pname) {
          case GL_TEXTURE_ENV_MODE:
@@ -1006,10 +1029,20 @@ _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
 void GLAPIENTRY
 _mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params )
 {
+   GLuint maxUnit;
+   const struct gl_texture_unit *texUnit;
    GET_CURRENT_CONTEXT(ctx);
-   const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
+   maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV)
+      ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxTextureImageUnits;
+   if (ctx->Texture.CurrentUnit >= maxUnit) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexEnviv(current unit)");
+      return;
+   }
+
+   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+
    if (target == GL_TEXTURE_ENV) {
       switch (pname) {
          case GL_TEXTURE_ENV_MODE:
@@ -1264,10 +1297,10 @@ _mesa_TexParameterf( GLenum target, GLenum pname, GLfloat param )
 void GLAPIENTRY
 _mesa_TexParameterfv( GLenum target, GLenum pname, const GLfloat *params )
 {
-   GET_CURRENT_CONTEXT(ctx);
-   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
-   GLenum eparam = (GLenum) (GLint) params[0];
+   const GLenum eparam = (GLenum) (GLint) params[0];
+   struct gl_texture_unit *texUnit;
    struct gl_texture_object *texObj;
+   GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE))
@@ -1277,6 +1310,12 @@ _mesa_TexParameterfv( GLenum target, GLenum pname, const GLfloat *params )
                   *params,
                  _mesa_lookup_enum_by_nr(eparam));
 
+   if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureImageUnits) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "glTexParameterfv(current unit)");
+      return;
+   }
+
+   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
 
    switch (target) {
       case GL_TEXTURE_1D:
@@ -1401,11 +1440,11 @@ _mesa_TexParameterfv( GLenum target, GLenum pname, const GLfloat *params )
          break;
       case GL_TEXTURE_BASE_LEVEL:
          if (params[0] < 0.0) {
-            _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
+            _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)");
             return;
          }
-         if (target == GL_TEXTURE_RECTANGLE_NV && params[0] != 0.0) {
-            _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
+         if (target == GL_TEXTURE_RECTANGLE_ARB && params[0] != 0.0) {
+            _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)");
             return;
          }
          FLUSH_VERTICES(ctx, _NEW_TEXTURE);
@@ -1413,7 +1452,11 @@ _mesa_TexParameterfv( GLenum target, GLenum pname, const GLfloat *params )
          break;
       case GL_TEXTURE_MAX_LEVEL:
          if (params[0] < 0.0) {
-            _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
+            _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)");
+            return;
+         }
+         if (target == GL_TEXTURE_RECTANGLE_ARB) {
+            _mesa_error(ctx, GL_INVALID_OPERATION, "glTexParameter(param)");
             return;
          }
          FLUSH_VERTICES(ctx, _NEW_TEXTURE);
@@ -1662,14 +1705,23 @@ void GLAPIENTRY
 _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
                               GLenum pname, GLint *params )
 {
-   GET_CURRENT_CONTEXT(ctx);
-   const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+   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);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
+   if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureImageUnits) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glGetTexLevelParameteriv(current unit)");
+      return;
+   }
+
+   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+
    /* this will catch bad target values */
    dimensions = tex_image_dimensions(ctx, target);  /* 1, 2 or 3 */
    if (dimensions == 0) {
@@ -1689,14 +1741,17 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
       return;
    }
 
-   img = _mesa_select_tex_image(ctx, texUnit, target, level);
+   texObj = _mesa_select_tex_object(ctx, texUnit, target);
+   _mesa_lock_texture(ctx, texObj);
+
+   img = _mesa_select_tex_image(ctx, texObj, target, level);
    if (!img || !img->TexFormat) {
       /* undefined texture image */
       if (pname == GL_TEXTURE_COMPONENTS)
          *params = 1;
       else
          *params = 0;
-      return;
+      goto out;
    }
 
    isProxy = _mesa_is_proxy_texture(target);
@@ -1704,37 +1759,37 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
    switch (pname) {
       case GL_TEXTURE_WIDTH:
          *params = img->Width;
-         return;
+         break;
       case GL_TEXTURE_HEIGHT:
          *params = img->Height;
-         return;
+         break;
       case GL_TEXTURE_DEPTH:
          *params = img->Depth;
-         return;
+         break;
       case GL_TEXTURE_INTERNAL_FORMAT:
          *params = img->InternalFormat;
-         return;
+         break;
       case GL_TEXTURE_BORDER:
          *params = img->Border;
-         return;
+         break;
       case GL_TEXTURE_RED_SIZE:
          if (img->_BaseFormat == GL_RGB || img->_BaseFormat == GL_RGBA)
             *params = img->TexFormat->RedBits;
          else
             *params = 0;
-         return;
+         break;
       case GL_TEXTURE_GREEN_SIZE:
          if (img->_BaseFormat == GL_RGB || img->_BaseFormat == GL_RGBA)
             *params = img->TexFormat->GreenBits;
          else
             *params = 0;
-         return;
+         break;
       case GL_TEXTURE_BLUE_SIZE:
          if (img->_BaseFormat == GL_RGB || img->_BaseFormat == GL_RGBA)
             *params = img->TexFormat->BlueBits;
          else
             *params = 0;
-         return;
+         break;
       case GL_TEXTURE_ALPHA_SIZE:
          if (img->_BaseFormat == GL_ALPHA ||
              img->_BaseFormat == GL_LUMINANCE_ALPHA ||
@@ -1742,7 +1797,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
             *params = img->TexFormat->AlphaBits;
          else
             *params = 0;
-         return;
+         break;
       case GL_TEXTURE_INTENSITY_SIZE:
          if (img->_BaseFormat != GL_INTENSITY)
             *params = 0;
@@ -1750,7 +1805,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
             *params = img->TexFormat->IntensityBits;
          else /* intensity probably stored as rgb texture */
             *params = MIN2(img->TexFormat->RedBits, img->TexFormat->GreenBits);
-         return;
+         break;
       case GL_TEXTURE_LUMINANCE_SIZE:
          if (img->_BaseFormat != GL_LUMINANCE &&
              img->_BaseFormat != GL_LUMINANCE_ALPHA)
@@ -1759,13 +1814,13 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
             *params = img->TexFormat->LuminanceBits;
          else /* luminance probably stored as rgb texture */
             *params = MIN2(img->TexFormat->RedBits, img->TexFormat->GreenBits);
-         return;
+         break;
       case GL_TEXTURE_INDEX_SIZE_EXT:
          if (img->_BaseFormat == GL_COLOR_INDEX)
             *params = img->TexFormat->IndexBits;
          else
             *params = 0;
-         return;
+         break;
       case GL_TEXTURE_DEPTH_SIZE_ARB:
          if (ctx->Extensions.SGIX_depth_texture ||
              ctx->Extensions.ARB_depth_texture)
@@ -1773,7 +1828,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
          else
             _mesa_error(ctx, GL_INVALID_ENUM,
                         "glGetTexLevelParameter[if]v(pname)");
-         return;
+         break;
       case GL_TEXTURE_STENCIL_SIZE_EXT:
          if (ctx->Extensions.EXT_packed_depth_stencil) {
             *params = img->TexFormat->StencilBits;
@@ -1782,22 +1837,29 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
             _mesa_error(ctx, GL_INVALID_ENUM,
                         "glGetTexLevelParameter[if]v(pname)");
          }
-         return;
+         break;
 
       /* GL_ARB_texture_compression */
       case GL_TEXTURE_COMPRESSED_IMAGE_SIZE:
          if (ctx->Extensions.ARB_texture_compression) {
-            if (img->IsCompressed && !isProxy)
-               *params = img->CompressedSize;
-            else
+            if (img->IsCompressed && !isProxy) {
+               /* Don't use ctx->Driver.CompressedTextureSize() since that
+                * may returned a padded hardware size.
+                */
+               *params = _mesa_compressed_texture_size(ctx, img->Width,
+                                                   img->Height, img->Depth,
+                                                   img->TexFormat->MesaFormat);
+            }
+            else {
                _mesa_error(ctx, GL_INVALID_OPERATION,
                            "glGetTexLevelParameter[if]v(pname)");
+            }
          }
          else {
             _mesa_error(ctx, GL_INVALID_ENUM,
                         "glGetTexLevelParameter[if]v(pname)");
          }
-         return;
+         break;
       case GL_TEXTURE_COMPRESSED:
          if (ctx->Extensions.ARB_texture_compression) {
             *params = (GLint) img->IsCompressed;
@@ -1806,7 +1868,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
             _mesa_error(ctx, GL_INVALID_ENUM,
                         "glGetTexLevelParameter[if]v(pname)");
          }
-         return;
+         break;
 
       /* GL_ARB_texture_float */
       case GL_TEXTURE_RED_TYPE_ARB:
@@ -1817,7 +1879,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
             _mesa_error(ctx, GL_INVALID_ENUM,
                         "glGetTexLevelParameter[if]v(pname)");
          }
-         return;
+         break;
       case GL_TEXTURE_GREEN_TYPE_ARB:
          if (ctx->Extensions.ARB_texture_float) {
             *params = img->TexFormat->GreenBits ? img->TexFormat->DataType : GL_NONE;
@@ -1826,7 +1888,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
             _mesa_error(ctx, GL_INVALID_ENUM,
                         "glGetTexLevelParameter[if]v(pname)");
          }
-         return;
+         break;
       case GL_TEXTURE_BLUE_TYPE_ARB:
          if (ctx->Extensions.ARB_texture_float) {
             *params = img->TexFormat->BlueBits ? img->TexFormat->DataType : GL_NONE;
@@ -1835,7 +1897,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
             _mesa_error(ctx, GL_INVALID_ENUM,
                         "glGetTexLevelParameter[if]v(pname)");
          }
-         return;
+         break;
       case GL_TEXTURE_ALPHA_TYPE_ARB:
          if (ctx->Extensions.ARB_texture_float) {
             *params = img->TexFormat->AlphaBits ? img->TexFormat->DataType : GL_NONE;
@@ -1844,7 +1906,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
             _mesa_error(ctx, GL_INVALID_ENUM,
                         "glGetTexLevelParameter[if]v(pname)");
          }
-         return;
+         break;
       case GL_TEXTURE_LUMINANCE_TYPE_ARB:
          if (ctx->Extensions.ARB_texture_float) {
             *params = img->TexFormat->LuminanceBits ? img->TexFormat->DataType : GL_NONE;
@@ -1853,7 +1915,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
             _mesa_error(ctx, GL_INVALID_ENUM,
                         "glGetTexLevelParameter[if]v(pname)");
          }
-         return;
+         break;
       case GL_TEXTURE_INTENSITY_TYPE_ARB:
          if (ctx->Extensions.ARB_texture_float) {
             *params = img->TexFormat->IntensityBits ? img->TexFormat->DataType : GL_NONE;
@@ -1862,7 +1924,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
             _mesa_error(ctx, GL_INVALID_ENUM,
                         "glGetTexLevelParameter[if]v(pname)");
          }
-         return;
+         break;
       case GL_TEXTURE_DEPTH_TYPE_ARB:
          if (ctx->Extensions.ARB_texture_float) {
             *params = img->TexFormat->DepthBits ? img->TexFormat->DataType : GL_NONE;
@@ -1871,12 +1933,15 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
             _mesa_error(ctx, GL_INVALID_ENUM,
                         "glGetTexLevelParameter[if]v(pname)");
          }
-         return;
+         break;
 
       default:
          _mesa_error(ctx, GL_INVALID_ENUM,
                      "glGetTexLevelParameter[if]v(pname)");
    }
+
+ out:
+   _mesa_unlock_texture(ctx, texObj);
 }
 
 
@@ -1884,39 +1949,49 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
 void GLAPIENTRY
 _mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params )
 {
-   GET_CURRENT_CONTEXT(ctx);
-   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+   struct gl_texture_unit *texUnit;
    struct gl_texture_object *obj;
+   GLboolean error = GL_FALSE;
+   GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
+   if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureImageUnits) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glGetTexParameterfv(current unit)");
+      return;
+   }
+
+   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+
    obj = _mesa_select_tex_object(ctx, texUnit, target);
    if (!obj) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameterfv(target)");
       return;
    }
 
+   _mesa_lock_texture(ctx, obj);
    switch (pname) {
       case GL_TEXTURE_MAG_FILTER:
         *params = ENUM_TO_FLOAT(obj->MagFilter);
-        return;
+        break;
       case GL_TEXTURE_MIN_FILTER:
          *params = ENUM_TO_FLOAT(obj->MinFilter);
-         return;
+         break;
       case GL_TEXTURE_WRAP_S:
          *params = ENUM_TO_FLOAT(obj->WrapS);
-         return;
+         break;
       case GL_TEXTURE_WRAP_T:
          *params = ENUM_TO_FLOAT(obj->WrapT);
-         return;
+         break;
       case GL_TEXTURE_WRAP_R:
          *params = ENUM_TO_FLOAT(obj->WrapR);
-         return;
+         break;
       case GL_TEXTURE_BORDER_COLOR:
          params[0] = CLAMP(obj->BorderColor[0], 0.0F, 1.0F);
          params[1] = CLAMP(obj->BorderColor[1], 0.0F, 1.0F);
          params[2] = CLAMP(obj->BorderColor[2], 0.0F, 1.0F);
          params[3] = CLAMP(obj->BorderColor[3], 0.0F, 1.0F);
-         return;
+         break;
       case GL_TEXTURE_RESIDENT:
          {
             GLboolean resident;
@@ -1926,93 +2001,113 @@ _mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params )
                resident = GL_TRUE;
             *params = ENUM_TO_FLOAT(resident);
          }
-         return;
+         break;
       case GL_TEXTURE_PRIORITY:
          *params = obj->Priority;
-         return;
+         break;
       case GL_TEXTURE_MIN_LOD:
          *params = obj->MinLod;
-         return;
+         break;
       case GL_TEXTURE_MAX_LOD:
          *params = obj->MaxLod;
-         return;
+         break;
       case GL_TEXTURE_BASE_LEVEL:
          *params = (GLfloat) obj->BaseLevel;
-         return;
+         break;
       case GL_TEXTURE_MAX_LEVEL:
          *params = (GLfloat) obj->MaxLevel;
-         return;
+         break;
       case GL_TEXTURE_MAX_ANISOTROPY_EXT:
          if (ctx->Extensions.EXT_texture_filter_anisotropic) {
             *params = obj->MaxAnisotropy;
-            return;
          }
+        else
+           error = 1;
          break;
       case GL_TEXTURE_COMPARE_SGIX:
          if (ctx->Extensions.SGIX_shadow) {
             *params = (GLfloat) obj->CompareFlag;
-            return;
          }
+        else 
+           error = 1;
          break;
       case GL_TEXTURE_COMPARE_OPERATOR_SGIX:
          if (ctx->Extensions.SGIX_shadow) {
             *params = (GLfloat) obj->CompareOperator;
-            return;
          }
+        else 
+           error = 1;
          break;
       case GL_SHADOW_AMBIENT_SGIX: /* aka GL_TEXTURE_COMPARE_FAIL_VALUE_ARB */
          if (ctx->Extensions.SGIX_shadow_ambient) {
             *params = obj->ShadowAmbient;
-            return;
          }
+        else 
+           error = 1;
          break;
       case GL_GENERATE_MIPMAP_SGIS:
          if (ctx->Extensions.SGIS_generate_mipmap) {
             *params = (GLfloat) obj->GenerateMipmap;
-            return;
          }
+        else 
+           error = 1;
          break;
       case GL_TEXTURE_COMPARE_MODE_ARB:
          if (ctx->Extensions.ARB_shadow) {
             *params = (GLfloat) obj->CompareMode;
-            return;
          }
+        else 
+           error = 1;
          break;
       case GL_TEXTURE_COMPARE_FUNC_ARB:
          if (ctx->Extensions.ARB_shadow) {
             *params = (GLfloat) obj->CompareFunc;
-            return;
          }
+        else 
+           error = 1;
          break;
       case GL_DEPTH_TEXTURE_MODE_ARB:
          if (ctx->Extensions.ARB_depth_texture) {
             *params = (GLfloat) obj->DepthMode;
-            return;
          }
+        else 
+           error = 1;
          break;
       case GL_TEXTURE_LOD_BIAS:
          if (ctx->Extensions.EXT_texture_lod_bias) {
             *params = obj->LodBias;
-            return;
          }
+        else 
+           error = 1;
          break;
       default:
-         ; /* silence warnings */
+        error = 1;
+        break;
    }
-   /* If we get here, pname was an unrecognized enum */
-   _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameterfv(pname=0x%x)",
-               pname);
+   if (error)
+      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameterfv(pname=0x%x)",
+                 pname);
+
+   _mesa_unlock_texture(ctx, obj);
 }
 
 
 void GLAPIENTRY
 _mesa_GetTexParameteriv( GLenum target, GLenum pname, GLint *params )
 {
-   GET_CURRENT_CONTEXT(ctx);
-   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+   struct gl_texture_unit *texUnit;
    struct gl_texture_object *obj;
+   GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
+   if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureImageUnits) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glGetTexParameteriv(current unit)");
+      return;
+   }
+
+   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+
    obj = _mesa_select_tex_object(ctx, texUnit, target);
    if (!obj) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameteriv(target)");
@@ -2146,8 +2241,7 @@ void GLAPIENTRY
 _mesa_TexGenfv( GLenum coord, GLenum pname, const GLfloat *params )
 {
    GET_CURRENT_CONTEXT(ctx);
-   GLuint tUnit = ctx->Texture.CurrentUnit;
-   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[tUnit];
+   struct gl_texture_unit *texUnit;
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE))
@@ -2157,6 +2251,13 @@ _mesa_TexGenfv( GLenum coord, GLenum pname, const GLfloat *params )
                   *params,
                  _mesa_lookup_enum_by_nr((GLenum) (GLint) *params));
 
+   if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "glTexGen(current unit)");
+      return;
+   }
+
+   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+
    switch (coord) {
       case GL_S:
          if (pname==GL_TEXTURE_GEN_MODE) {
@@ -2428,11 +2529,17 @@ _mesa_TexGeni( GLenum coord, GLenum pname, GLint param )
 void GLAPIENTRY
 _mesa_GetTexGendv( GLenum coord, GLenum pname, GLdouble *params )
 {
+   const struct gl_texture_unit *texUnit;
    GET_CURRENT_CONTEXT(ctx);
-   GLuint tUnit = ctx->Texture.CurrentUnit;
-   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[tUnit];
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
+   if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexGendv(current unit)");
+      return;
+   }
+
+   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+
    switch (coord) {
       case GL_S:
          if (pname==GL_TEXTURE_GEN_MODE) {
@@ -2505,11 +2612,17 @@ _mesa_GetTexGendv( GLenum coord, GLenum pname, GLdouble *params )
 void GLAPIENTRY
 _mesa_GetTexGenfv( GLenum coord, GLenum pname, GLfloat *params )
 {
+   const struct gl_texture_unit *texUnit;
    GET_CURRENT_CONTEXT(ctx);
-   GLuint tUnit = ctx->Texture.CurrentUnit;
-   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[tUnit];
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
+   if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexGenfv(current unit)");
+      return;
+   }
+
+   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+
    switch (coord) {
       case GL_S:
          if (pname==GL_TEXTURE_GEN_MODE) {
@@ -2582,11 +2695,17 @@ _mesa_GetTexGenfv( GLenum coord, GLenum pname, GLfloat *params )
 void GLAPIENTRY
 _mesa_GetTexGeniv( GLenum coord, GLenum pname, GLint *params )
 {
+   const struct gl_texture_unit *texUnit;
    GET_CURRENT_CONTEXT(ctx);
-   GLuint tUnit = ctx->Texture.CurrentUnit;
-   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[tUnit];
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
+   if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexGeniv(current unit)");
+      return;
+   }
+
+   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+
    switch (coord) {
       case GL_S:
          if (pname==GL_TEXTURE_GEN_MODE) {
@@ -2679,21 +2798,22 @@ _mesa_GetTexGeniv( GLenum coord, GLenum pname, GLint *params )
 }
 #endif
 
+
 /* GL_ARB_multitexture */
 void GLAPIENTRY
-_mesa_ActiveTextureARB( GLenum target )
+_mesa_ActiveTextureARB(GLenum texture)
 {
    GET_CURRENT_CONTEXT(ctx);
-   const GLuint texUnit = target - GL_TEXTURE0;
+   const GLuint texUnit = texture - GL_TEXTURE0;
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
       _mesa_debug(ctx, "glActiveTexture %s\n",
-                  _mesa_lookup_enum_by_nr(target));
+                  _mesa_lookup_enum_by_nr(texture));
 
-   /* Cater for texture unit 0 is first, therefore use >= */
+   /* XXX error-check against max(coordunits, imageunits) */
    if (texUnit >= ctx->Const.MaxTextureUnits) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glActiveTexture(target)");
+      _mesa_error(ctx, GL_INVALID_ENUM, "glActiveTexture(texture)");
       return;
    }
 
@@ -2716,14 +2836,14 @@ _mesa_ActiveTextureARB( GLenum target )
 
 /* GL_ARB_multitexture */
 void GLAPIENTRY
-_mesa_ClientActiveTextureARB( GLenum target )
+_mesa_ClientActiveTextureARB(GLenum texture)
 {
    GET_CURRENT_CONTEXT(ctx);
-   GLuint texUnit = target - GL_TEXTURE0;
+   GLuint texUnit = texture - GL_TEXTURE0;
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
-   if (texUnit >= ctx->Const.MaxTextureUnits) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glClientActiveTexture(target)");
+   if (texUnit >= ctx->Const.MaxTextureCoordUnits) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glClientActiveTexture(texture)");
       return;
    }
 
@@ -2801,8 +2921,18 @@ static void
 update_texture_state( GLcontext *ctx )
 {
    GLuint unit;
-   struct gl2_program_intf **prog = ctx->ShaderObjects.CurrentProgram;
-   GLbitfield progteximageusage[MAX_TEXTURE_IMAGE_UNITS];
+   struct gl_fragment_program *fprog;
+
+   if (ctx->Shader.CurrentProgram &&
+       ctx->Shader.CurrentProgram->LinkStatus) {
+      fprog = ctx->Shader.CurrentProgram->FragmentProgram;
+   }
+   else if (ctx->FragmentProgram._Enabled) {
+      fprog = ctx->FragmentProgram.Current;
+   }
+   else {
+      fprog = NULL;
+   }
 
    ctx->NewState |= _NEW_TEXTURE; /* TODO: only set this if there are 
                                   * actual changes. 
@@ -2813,15 +2943,6 @@ update_texture_state( GLcontext *ctx )
    ctx->Texture._TexMatEnabled = 0;
    ctx->Texture._TexGenEnabled = 0;
 
-   /*
-    * Grab texture image usage state from shader program. It must be
-    * grabbed every time uniform sampler changes, so maybe there is a
-    * better place to perform these rather expensive computations.
-    */
-   if (ctx->ShaderObjects._FragmentShaderPresent) {
-      (**prog).GetTextureImageUsage (prog, progteximageusage);
-   }
-
    /*
     * Update texture unit state.
     */
@@ -2833,12 +2954,14 @@ update_texture_state( GLcontext *ctx )
       texUnit->_ReallyEnabled = 0;
       texUnit->_GenFlags = 0;
 
-      /* Get the bitmask of texture enables */
-      if (ctx->ShaderObjects._FragmentShaderPresent) {
-         enableBits = progteximageusage[unit];
-      }
-      else if (ctx->FragmentProgram._Enabled) {
-         enableBits = ctx->FragmentProgram.Current->TexturesUsed[unit];
+      /* Get the bitmask of texture enables.
+       * enableBits will be a mask of the TEXTURE_*_BIT flags indicating
+       * which texture targets are enabled (fixed function) or referenced
+       * by a fragment shader/program.  When multiple flags are set, we'll
+       * settle on the one with highest priority (see texture_override below).
+       */
+      if (fprog) {
+         enableBits = fprog->Base.TexturesUsed[unit];
       }
       else {
          if (!texUnit->Enabled)
@@ -2955,21 +3078,23 @@ update_texture_state( GLcontext *ctx )
         ctx->Texture._TexMatEnabled |= ENABLE_TEXMAT(unit);
    }
 
-   ctx->Texture._EnabledCoordUnits = ctx->Texture._EnabledUnits;
-   /* Fragment programs may need texture coordinates but not the
-    * corresponding texture images.
-    */
-   if (ctx->ShaderObjects.CurrentProgram != NULL) {
-      ctx->Texture._EnabledCoordUnits |= (1 << ctx->Const.MaxTextureCoordUnits) - 1;
+   /* Determine which texture coordinate sets are actually needed */
+   if (fprog) {
+      const GLuint coordMask = (1 << MAX_TEXTURE_COORD_UNITS) - 1;
+      ctx->Texture._EnabledCoordUnits
+         = (fprog->Base.InputsRead >> FRAG_ATTRIB_TEX0) & coordMask;
    }
-   else if (ctx->FragmentProgram._Enabled) {
-      ctx->Texture._EnabledCoordUnits |=
-         (ctx->FragmentProgram.Current->Base.InputsRead >> FRAG_ATTRIB_TEX0);
+   else {
+      ctx->Texture._EnabledCoordUnits = ctx->Texture._EnabledUnits;
    }
 }
 
 
-void _mesa_update_texture( GLcontext *ctx, GLuint new_state )
+/**
+ * Update texture-related derived state.
+ */
+void
+_mesa_update_texture( GLcontext *ctx, GLuint new_state )
 {
    if (new_state & _NEW_TEXTURE_MATRIX)
       update_texture_matrices( ctx );
@@ -3105,6 +3230,8 @@ _mesa_init_texture(GLcontext *ctx)
    ctx->Texture.SharedPalette = GL_FALSE;
    _mesa_init_colortable(&ctx->Texture.Palette);
 
+   _mesa_TexEnvProgramCacheInit( ctx );
+
    /* Allocate proxy textures */
    if (!alloc_proxy_textures( ctx ))
       return GL_FALSE;