s/GLchan/GLubyte/
[mesa.git] / src / mesa / main / texstate.c
index d96b73a2f5b81e6a7fc73125532ef4db918dc0de..0687e5760c9b96303f22cf726c6da41880e95a7b 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * Mesa 3-D graphics library
- * Version:  5.1
+ * Version:  6.5.1
  *
- * Copyright (C) 1999-2003  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2006  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"),
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
+/** 
+ * \file texstate.c
+ *
+ * Texture state handling.
+ */
 
 #include "glheader.h"
 #include "colormac.h"
+#include "colortab.h"
 #include "context.h"
 #include "enums.h"
-#include "extensions.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 "math/m_matrix.h"
+#include "shaderobjects.h"
 
 
 
-#ifdef SPECIALCAST
-/* Needed for an Amiga compiler */
 #define ENUM_TO_FLOAT(X) ((GLfloat)(GLint)(X))
 #define ENUM_TO_DOUBLE(X) ((GLdouble)(GLint)(X))
-#else
-/* all other compilers */
-#define ENUM_TO_FLOAT(X) ((GLfloat)(X))
-#define ENUM_TO_DOUBLE(X) ((GLdouble)(X))
-#endif
 
 
+/**
+ * Default texture combine environment state.  This is used to initialize
+ * a context's texture units and as the basis for converting "classic"
+ * texture environmnets to ARB_texture_env_combine style values.
+ */
+static const struct gl_tex_env_combine_state default_combine_state = {
+   GL_MODULATE, GL_MODULATE,
+   { GL_TEXTURE, GL_PREVIOUS, GL_CONSTANT },
+   { GL_TEXTURE, GL_PREVIOUS, GL_CONSTANT },
+   { GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_ALPHA },
+   { GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA },
+   0, 0,
+   2, 2
+};
+
+
+/**
+ * Copy a texture binding.  Helper used by _mesa_copy_texture_state().
+ */
+static void
+copy_texture_binding(const GLcontext *ctx,
+                     struct gl_texture_object **dst,
+                     struct gl_texture_object *src)
+{
+   /* only copy if names differ (per OpenGL SI) */
+   if ((*dst)->Name != src->Name) {
+      /* unbind/delete dest binding which we're changing */
+      (*dst)->RefCount--;
+      if ((*dst)->RefCount == 0) {
+         /* time to delete this texture object */
+         ASSERT((*dst)->Name != 0);
+         ASSERT(ctx->Driver.DeleteTexture);
+         /* XXX cast-away const, unfortunately */
+         (*ctx->Driver.DeleteTexture)((GLcontext *) ctx, *dst);
+      }
+      /* make new binding, incrementing ref count */
+      *dst = src;
+      src->RefCount++;
+   }
+}
+
 
+/**
+ * Used by glXCopyContext to copy texture state from one context to another.
+ */
 void
 _mesa_copy_texture_state( const GLcontext *src, GLcontext *dst )
 {
@@ -90,26 +134,26 @@ _mesa_copy_texture_state( const GLcontext *src, GLcontext *dst )
       dst->Texture.Unit[i].LodBias = src->Texture.Unit[i].LodBias;
 
       /* GL_EXT_texture_env_combine */
-      dst->Texture.Unit[i].CombineModeRGB = src->Texture.Unit[i].CombineModeRGB;
-      dst->Texture.Unit[i].CombineModeA = src->Texture.Unit[i].CombineModeA;
-      COPY_3V(dst->Texture.Unit[i].CombineSourceRGB, src->Texture.Unit[i].CombineSourceRGB);
-      COPY_3V(dst->Texture.Unit[i].CombineSourceA, src->Texture.Unit[i].CombineSourceA);
-      COPY_3V(dst->Texture.Unit[i].CombineOperandRGB, src->Texture.Unit[i].CombineOperandRGB);
-      COPY_3V(dst->Texture.Unit[i].CombineOperandA, src->Texture.Unit[i].CombineOperandA);
-      dst->Texture.Unit[i].CombineScaleShiftRGB = src->Texture.Unit[i].CombineScaleShiftRGB;
-      dst->Texture.Unit[i].CombineScaleShiftA = src->Texture.Unit[i].CombineScaleShiftA;
-
-      /* texture object state */
-      _mesa_copy_texture_object(dst->Texture.Unit[i].Current1D,
-                                src->Texture.Unit[i].Current1D);
-      _mesa_copy_texture_object(dst->Texture.Unit[i].Current2D,
-                                src->Texture.Unit[i].Current2D);
-      _mesa_copy_texture_object(dst->Texture.Unit[i].Current3D,
-                                src->Texture.Unit[i].Current3D);
-      _mesa_copy_texture_object(dst->Texture.Unit[i].CurrentCubeMap,
-                                src->Texture.Unit[i].CurrentCubeMap);
-      _mesa_copy_texture_object(dst->Texture.Unit[i].CurrentRect,
-                                src->Texture.Unit[i].CurrentRect);
+      dst->Texture.Unit[i].Combine.ModeRGB = src->Texture.Unit[i].Combine.ModeRGB;
+      dst->Texture.Unit[i].Combine.ModeA = src->Texture.Unit[i].Combine.ModeA;
+      COPY_3V(dst->Texture.Unit[i].Combine.SourceRGB, src->Texture.Unit[i].Combine.SourceRGB);
+      COPY_3V(dst->Texture.Unit[i].Combine.SourceA, src->Texture.Unit[i].Combine.SourceA);
+      COPY_3V(dst->Texture.Unit[i].Combine.OperandRGB, src->Texture.Unit[i].Combine.OperandRGB);
+      COPY_3V(dst->Texture.Unit[i].Combine.OperandA, src->Texture.Unit[i].Combine.OperandA);
+      dst->Texture.Unit[i].Combine.ScaleShiftRGB = src->Texture.Unit[i].Combine.ScaleShiftRGB;
+      dst->Texture.Unit[i].Combine.ScaleShiftA = src->Texture.Unit[i].Combine.ScaleShiftA;
+
+      /* copy texture object bindings, not contents of texture objects */
+      copy_texture_binding(src, &dst->Texture.Unit[i].Current1D,
+                           src->Texture.Unit[i].Current1D);
+      copy_texture_binding(src, &dst->Texture.Unit[i].Current2D,
+                           src->Texture.Unit[i].Current2D);
+      copy_texture_binding(src, &dst->Texture.Unit[i].Current3D,
+                           src->Texture.Unit[i].Current3D);
+      copy_texture_binding(src, &dst->Texture.Unit[i].CurrentCubeMap,
+                           src->Texture.Unit[i].CurrentCubeMap);
+      copy_texture_binding(src, &dst->Texture.Unit[i].CurrentRect,
+                           src->Texture.Unit[i].CurrentRect);
    }
 }
 
@@ -123,22 +167,22 @@ _mesa_print_texunit_state( GLcontext *ctx, GLuint unit )
    const struct gl_texture_unit *texUnit = ctx->Texture.Unit + unit;
    _mesa_printf("Texture Unit %d\n", unit);
    _mesa_printf("  GL_TEXTURE_ENV_MODE = %s\n", _mesa_lookup_enum_by_nr(texUnit->EnvMode));
-   _mesa_printf("  GL_COMBINE_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->CombineModeRGB));
-   _mesa_printf("  GL_COMBINE_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->CombineModeA));
-   _mesa_printf("  GL_SOURCE0_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->CombineSourceRGB[0]));
-   _mesa_printf("  GL_SOURCE1_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->CombineSourceRGB[1]));
-   _mesa_printf("  GL_SOURCE2_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->CombineSourceRGB[2]));
-   _mesa_printf("  GL_SOURCE0_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->CombineSourceA[0]));
-   _mesa_printf("  GL_SOURCE1_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->CombineSourceA[1]));
-   _mesa_printf("  GL_SOURCE2_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->CombineSourceA[2]));
-   _mesa_printf("  GL_OPERAND0_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->CombineOperandRGB[0]));
-   _mesa_printf("  GL_OPERAND1_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->CombineOperandRGB[1]));
-   _mesa_printf("  GL_OPERAND2_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->CombineOperandRGB[2]));
-   _mesa_printf("  GL_OPERAND0_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->CombineOperandA[0]));
-   _mesa_printf("  GL_OPERAND1_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->CombineOperandA[1]));
-   _mesa_printf("  GL_OPERAND2_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->CombineOperandA[2]));
-   _mesa_printf("  GL_RGB_SCALE = %d\n", 1 << texUnit->CombineScaleShiftRGB);
-   _mesa_printf("  GL_ALPHA_SCALE = %d\n", 1 << texUnit->CombineScaleShiftA);
+   _mesa_printf("  GL_COMBINE_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.ModeRGB));
+   _mesa_printf("  GL_COMBINE_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.ModeA));
+   _mesa_printf("  GL_SOURCE0_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[0]));
+   _mesa_printf("  GL_SOURCE1_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[1]));
+   _mesa_printf("  GL_SOURCE2_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[2]));
+   _mesa_printf("  GL_SOURCE0_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[0]));
+   _mesa_printf("  GL_SOURCE1_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[1]));
+   _mesa_printf("  GL_SOURCE2_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[2]));
+   _mesa_printf("  GL_OPERAND0_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[0]));
+   _mesa_printf("  GL_OPERAND1_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[1]));
+   _mesa_printf("  GL_OPERAND2_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[2]));
+   _mesa_printf("  GL_OPERAND0_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[0]));
+   _mesa_printf("  GL_OPERAND1_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[1]));
+   _mesa_printf("  GL_OPERAND2_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[2]));
+   _mesa_printf("  GL_RGB_SCALE = %d\n", 1 << texUnit->Combine.ScaleShiftRGB);
+   _mesa_printf("  GL_ALPHA_SCALE = %d\n", 1 << texUnit->Combine.ScaleShiftA);
    _mesa_printf("  GL_TEXTURE_ENV_COLOR = (%f, %f, %f, %f)\n", texUnit->EnvColor[0], texUnit->EnvColor[1], texUnit->EnvColor[2], texUnit->EnvColor[3]);
 }
 
@@ -148,14 +192,141 @@ _mesa_print_texunit_state( GLcontext *ctx, GLuint unit )
 /*                       Texture Environment                          */
 /**********************************************************************/
 
+/**
+ * Convert "classic" texture environment to ARB_texture_env_combine style
+ * environments.
+ * 
+ * \param state  texture_env_combine state vector to be filled-in.
+ * \param mode   Classic texture environment mode (i.e., \c GL_REPLACE,
+ *               \c GL_BLEND, \c GL_DECAL, etc.).
+ * \param texBaseFormat  Base format of the texture associated with the
+ *               texture unit.
+ */
+static void
+calculate_derived_texenv( struct gl_tex_env_combine_state *state,
+                         GLenum mode, GLenum texBaseFormat )
+{
+   GLenum mode_rgb;
+   GLenum mode_a;
 
-void
+   *state = default_combine_state;
+
+   switch (texBaseFormat) {
+   case GL_ALPHA:
+      state->SourceRGB[0] = GL_PREVIOUS;
+      break;
+
+   case GL_LUMINANCE_ALPHA:
+   case GL_INTENSITY:
+   case GL_RGBA:
+      break;
+
+   case GL_LUMINANCE:
+   case GL_RGB:
+   case GL_YCBCR_MESA:
+      state->SourceA[0] = GL_PREVIOUS;
+      break;
+      
+   default:
+      _mesa_problem(NULL, "Invalid texBaseFormat in calculate_derived_texenv");
+      return;
+   }
+
+   switch (mode) {
+   case GL_REPLACE:
+   case GL_MODULATE:
+      mode_rgb = (texBaseFormat == GL_ALPHA) ? GL_REPLACE : mode;
+      mode_a   = mode;
+      break;
+   
+   case GL_DECAL:
+      mode_rgb = GL_INTERPOLATE;
+      mode_a   = GL_REPLACE;
+
+      state->SourceA[0] = GL_PREVIOUS;
+
+      /* Having alpha / luminance / intensity textures replace using the
+       * incoming fragment color matches the definition in NV_texture_shader.
+       * The 1.5 spec simply marks these as "undefined".
+       */
+      switch (texBaseFormat) {
+      case GL_ALPHA:
+      case GL_LUMINANCE:
+      case GL_LUMINANCE_ALPHA:
+      case GL_INTENSITY:
+        state->SourceRGB[0] = GL_PREVIOUS;
+        break;
+      case GL_RGB:
+      case GL_YCBCR_MESA:
+        mode_rgb = GL_REPLACE;
+        break;
+      case GL_RGBA:
+        state->SourceRGB[2] = GL_TEXTURE;
+        break;
+      }
+      break;
+
+   case GL_BLEND:
+      mode_rgb = GL_INTERPOLATE;
+      mode_a   = GL_MODULATE;
+
+      switch (texBaseFormat) {
+      case GL_ALPHA:
+        mode_rgb = GL_REPLACE;
+        break;
+      case GL_INTENSITY:
+        mode_a = GL_INTERPOLATE;
+        state->SourceA[0] = GL_CONSTANT;
+        state->OperandA[2] = GL_SRC_ALPHA;
+        /* FALLTHROUGH */
+      case GL_LUMINANCE:
+      case GL_RGB:
+      case GL_LUMINANCE_ALPHA:
+      case GL_RGBA:
+      case GL_YCBCR_MESA:
+        state->SourceRGB[2] = GL_TEXTURE;
+        state->SourceA[2]   = GL_TEXTURE;
+        state->SourceRGB[0] = GL_CONSTANT;
+        state->OperandRGB[2] = GL_SRC_COLOR;
+        break;
+      }
+      break;
+
+   case GL_ADD:
+      mode_rgb = (texBaseFormat == GL_ALPHA) ? GL_REPLACE : GL_ADD;
+      mode_a   = (texBaseFormat == GL_INTENSITY) ? GL_ADD : GL_MODULATE;
+      break;
+
+   default:
+      _mesa_problem(NULL,
+                    "Invalid texture env mode in calculate_derived_texenv");
+      return;
+   }
+   
+   state->ModeRGB = (state->SourceRGB[0] != GL_PREVIOUS)
+       ? mode_rgb : GL_REPLACE;
+   state->ModeA   = (state->SourceA[0]   != GL_PREVIOUS)
+       ? mode_a   : GL_REPLACE;
+}
+
+
+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));
 
@@ -164,6 +335,8 @@ _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param )
       case GL_TEXTURE_ENV_MODE:
          {
             const GLenum mode = (GLenum) (GLint) *param;
+           if (texUnit->EnvMode == mode)
+              return;
             if (mode == GL_MODULATE ||
                 mode == GL_BLEND ||
                 mode == GL_DECAL ||
@@ -173,8 +346,6 @@ _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param )
                  (ctx->Extensions.EXT_texture_env_combine ||
                   ctx->Extensions.ARB_texture_env_combine))) {
                /* legal */
-               if (texUnit->EnvMode == mode)
-                  return;
                FLUSH_VERTICES(ctx, _NEW_TEXTURE);
                texUnit->EnvMode = mode;
             }
@@ -201,6 +372,8 @@ _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param )
         if (ctx->Extensions.EXT_texture_env_combine ||
              ctx->Extensions.ARB_texture_env_combine) {
            const GLenum mode = (GLenum) (GLint) *param;
+           if (texUnit->Combine.ModeRGB == mode)
+              return;
            switch (mode) {
            case GL_REPLACE:
            case GL_MODULATE:
@@ -241,10 +414,8 @@ _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param )
                TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
               return;
            }
-           if (texUnit->CombineModeRGB == mode)
-              return;
            FLUSH_VERTICES(ctx, _NEW_TEXTURE);
-           texUnit->CombineModeRGB = mode;
+           texUnit->Combine.ModeRGB = mode;
         }
         else {
             TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
@@ -255,6 +426,8 @@ _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param )
         if (ctx->Extensions.EXT_texture_env_combine ||
              ctx->Extensions.ARB_texture_env_combine) {
            const GLenum mode = (GLenum) (GLint) *param;
+           if (texUnit->Combine.ModeA == mode)
+              return;
             switch (mode) {
            case GL_REPLACE:
            case GL_MODULATE:
@@ -281,11 +454,8 @@ _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param )
               TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
               return;
            }
-
-           if (texUnit->CombineModeA == mode)
-               return;
            FLUSH_VERTICES(ctx, _NEW_TEXTURE);
-           texUnit->CombineModeA = mode;
+           texUnit->Combine.ModeA = mode;
         }
         else {
             TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
@@ -299,6 +469,8 @@ _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param )
             ctx->Extensions.ARB_texture_env_combine) {
            const GLenum source = (GLenum) (GLint) *param;
            const GLuint s = pname - GL_SOURCE0_RGB;
+           if (texUnit->Combine.SourceRGB[s] == source)
+              return;
             if (source == GL_TEXTURE ||
                 source == GL_CONSTANT ||
                 source == GL_PRIMARY_COLOR ||
@@ -309,10 +481,8 @@ _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param )
                 (ctx->Extensions.ATI_texture_env_combine3 &&
                  (source == GL_ZERO || source == GL_ONE))) {
                /* legal */
-               if (texUnit->CombineSourceRGB[s] == source)
-                  return;
               FLUSH_VERTICES(ctx, _NEW_TEXTURE);
-              texUnit->CombineSourceRGB[s] = source;
+              texUnit->Combine.SourceRGB[s] = source;
             }
             else {
                TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", source);
@@ -331,6 +501,8 @@ _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param )
              ctx->Extensions.ARB_texture_env_combine) {
            const GLenum source = (GLenum) (GLint) *param;
            const GLuint s = pname - GL_SOURCE0_ALPHA;
+           if (texUnit->Combine.SourceA[s] == source)
+              return;
             if (source == GL_TEXTURE ||
                 source == GL_CONSTANT ||
                 source == GL_PRIMARY_COLOR ||
@@ -341,10 +513,8 @@ _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param )
                (ctx->Extensions.ATI_texture_env_combine3 &&
                  (source == GL_ZERO || source == GL_ONE))) {
                /* legal */
-              if (texUnit->CombineSourceA[s] == source)
-                  return;
               FLUSH_VERTICES(ctx, _NEW_TEXTURE);
-              texUnit->CombineSourceA[s] = source;
+              texUnit->Combine.SourceA[s] = source;
             }
             else {
                TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", source);
@@ -362,15 +532,15 @@ _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param )
             ctx->Extensions.ARB_texture_env_combine) {
            const GLenum operand = (GLenum) (GLint) *param;
            const GLuint s = pname - GL_OPERAND0_RGB;
+           if (texUnit->Combine.OperandRGB[s] == operand)
+              return;
            switch (operand) {
            case GL_SRC_COLOR:
            case GL_ONE_MINUS_SRC_COLOR:
            case GL_SRC_ALPHA:
            case GL_ONE_MINUS_SRC_ALPHA:
-              if (texUnit->CombineOperandRGB[s] == operand)
-                 return;
               FLUSH_VERTICES(ctx, _NEW_TEXTURE);
-              texUnit->CombineOperandRGB[s] = operand;
+              texUnit->Combine.OperandRGB[s] = operand;
               break;
            default:
                TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", operand);
@@ -387,14 +557,13 @@ _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param )
         if (ctx->Extensions.EXT_texture_env_combine ||
              ctx->Extensions.ARB_texture_env_combine) {
            const GLenum operand = (GLenum) (GLint) *param;
+           if (texUnit->Combine.OperandA[pname-GL_OPERAND0_ALPHA] == operand)
+              return;
            switch (operand) {
            case GL_SRC_ALPHA:
            case GL_ONE_MINUS_SRC_ALPHA:
-              if (texUnit->CombineOperandA[pname-GL_OPERAND0_ALPHA] ==
-                  operand)
-                 return;
               FLUSH_VERTICES(ctx, _NEW_TEXTURE);
-              texUnit->CombineOperandA[pname-GL_OPERAND0_ALPHA] = operand;
+              texUnit->Combine.OperandA[pname-GL_OPERAND0_ALPHA] = operand;
               break;
            default:
                TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", operand);
@@ -407,46 +576,66 @@ _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param )
         }
         break;
       case GL_OPERAND2_RGB:
-        if (ctx->Extensions.EXT_texture_env_combine ||
-             ctx->Extensions.ARB_texture_env_combine) {
+        if (ctx->Extensions.ARB_texture_env_combine) {
            const GLenum operand = (GLenum) (GLint) *param;
+           if (texUnit->Combine.OperandRGB[2] == operand)
+              return;
            switch (operand) {
            case GL_SRC_COLOR:           /* ARB combine only */
            case GL_ONE_MINUS_SRC_COLOR: /* ARB combine only */
            case GL_SRC_ALPHA:
            case GL_ONE_MINUS_SRC_ALPHA: /* ARB combine only */
-              if (texUnit->CombineOperandRGB[2] == operand)
-                 return;
               FLUSH_VERTICES(ctx, _NEW_TEXTURE);
-              texUnit->CombineOperandRGB[2] = operand;
+              texUnit->Combine.OperandRGB[2] = operand;
                break;
            default:
                TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", operand);
               return;
            }
         }
+        else if (ctx->Extensions.EXT_texture_env_combine) {
+           const GLenum operand = (GLenum) (GLint) *param;
+           if (texUnit->Combine.OperandRGB[2] == operand)
+              return;
+           /* operand must be GL_SRC_ALPHA which is the initial value - thus
+              don't need to actually compare the operand to the possible value */
+           else {
+               TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", operand);
+              return;
+           }
+        }
         else {
             TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
            return;
         }
         break;
       case GL_OPERAND2_ALPHA:
-        if (ctx->Extensions.EXT_texture_env_combine ||
-             ctx->Extensions.ARB_texture_env_combine) {
+        if (ctx->Extensions.ARB_texture_env_combine) {
            const GLenum operand = (GLenum) (GLint) *param;
+           if (texUnit->Combine.OperandA[2] == operand)
+              return;
            switch (operand) {
            case GL_SRC_ALPHA:
            case GL_ONE_MINUS_SRC_ALPHA: /* ARB combine only */
-              if (texUnit->CombineOperandA[2] == operand)
-                 return;
               FLUSH_VERTICES(ctx, _NEW_TEXTURE);
-              texUnit->CombineOperandA[2] = operand;
+              texUnit->Combine.OperandA[2] = operand;
               break;
            default:
                TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", operand);
               return;
            }
         }
+        else if (ctx->Extensions.EXT_texture_env_combine) {
+           const GLenum operand = (GLenum) (GLint) *param;
+           if (texUnit->Combine.OperandA[2] == operand)
+              return;
+           /* operand must be GL_SRC_ALPHA which is the initial value - thus
+              don't need to actually compare the operand to the possible value */
+           else {
+               TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", operand);
+              return;
+           }
+        }
         else {
             TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
            return;
@@ -470,10 +659,10 @@ _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param )
                             "glTexEnv(GL_RGB_SCALE not 1, 2 or 4)" );
               return;
            }
-           if (texUnit->CombineScaleShiftRGB == newshift)
+           if (texUnit->Combine.ScaleShiftRGB == newshift)
               return;
            FLUSH_VERTICES(ctx, _NEW_TEXTURE);
-           texUnit->CombineScaleShiftRGB = newshift;
+           texUnit->Combine.ScaleShiftRGB = newshift;
         }
         else {
             TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
@@ -498,10 +687,10 @@ _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param )
                             "glTexEnv(GL_ALPHA_SCALE not 1, 2 or 4)" );
               return;
            }
-           if (texUnit->CombineScaleShiftA == newshift)
+           if (texUnit->Combine.ScaleShiftA == newshift)
               return;
            FLUSH_VERTICES(ctx, _NEW_TEXTURE);
-           texUnit->CombineScaleShiftA = newshift;
+           texUnit->Combine.ScaleShiftA = newshift;
         }
         else {
             TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
@@ -523,8 +712,7 @@ _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param )
         if (texUnit->LodBias == param[0])
            return;
         FLUSH_VERTICES(ctx, _NEW_TEXTURE);
-         texUnit->LodBias = CLAMP(param[0], -ctx->Const.MaxTextureLodBias,
-                                  ctx->Const.MaxTextureLodBias);
+         texUnit->LodBias = param[0];
       }
       else {
          TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
@@ -532,8 +720,9 @@ _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param )
       }
    }
    else if (target == GL_POINT_SPRITE_NV) {
-      /* GL_NV_point_sprite */
-      if (!ctx->Extensions.NV_point_sprite) {
+      /* GL_ARB_point_sprite / GL_NV_point_sprite */
+      if (!ctx->Extensions.NV_point_sprite
+         && !ctx->Extensions.ARB_point_sprite) {
         _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(target=0x%x)", target );
         return;
       }
@@ -578,7 +767,7 @@ _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param )
 }
 
 
-void
+void GLAPIENTRY
 _mesa_TexEnvf( GLenum target, GLenum pname, GLfloat param )
 {
    _mesa_TexEnvfv( target, pname, &param );
@@ -586,7 +775,7 @@ _mesa_TexEnvf( GLenum target, GLenum pname, GLfloat param )
 
 
 
-void
+void GLAPIENTRY
 _mesa_TexEnvi( GLenum target, GLenum pname, GLint param )
 {
    GLfloat p[4];
@@ -596,7 +785,7 @@ _mesa_TexEnvi( GLenum target, GLenum pname, GLint param )
 }
 
 
-void
+void GLAPIENTRY
 _mesa_TexEnviv( GLenum target, GLenum pname, const GLint *param )
 {
    GLfloat p[4];
@@ -614,13 +803,23 @@ _mesa_TexEnviv( GLenum target, GLenum pname, const GLint *param )
 }
 
 
-void
+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:
@@ -632,7 +831,7 @@ _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
          case GL_COMBINE_RGB:
             if (ctx->Extensions.EXT_texture_env_combine ||
                 ctx->Extensions.ARB_texture_env_combine) {
-               *params = (GLfloat) texUnit->CombineModeRGB;
+               *params = (GLfloat) texUnit->Combine.ModeRGB;
             }
             else {
                _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
@@ -641,7 +840,7 @@ _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
          case GL_COMBINE_ALPHA:
             if (ctx->Extensions.EXT_texture_env_combine ||
                 ctx->Extensions.ARB_texture_env_combine) {
-               *params = (GLfloat) texUnit->CombineModeA;
+               *params = (GLfloat) texUnit->Combine.ModeA;
             }
             else {
                _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
@@ -650,7 +849,7 @@ _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
          case GL_SOURCE0_RGB:
             if (ctx->Extensions.EXT_texture_env_combine ||
                 ctx->Extensions.ARB_texture_env_combine) {
-               *params = (GLfloat) texUnit->CombineSourceRGB[0];
+               *params = (GLfloat) texUnit->Combine.SourceRGB[0];
             }
             else {
                _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
@@ -659,7 +858,7 @@ _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
          case GL_SOURCE1_RGB:
             if (ctx->Extensions.EXT_texture_env_combine ||
                 ctx->Extensions.ARB_texture_env_combine) {
-               *params = (GLfloat) texUnit->CombineSourceRGB[1];
+               *params = (GLfloat) texUnit->Combine.SourceRGB[1];
             }
             else {
                _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
@@ -668,7 +867,7 @@ _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
          case GL_SOURCE2_RGB:
             if (ctx->Extensions.EXT_texture_env_combine ||
                 ctx->Extensions.ARB_texture_env_combine) {
-               *params = (GLfloat) texUnit->CombineSourceRGB[2];
+               *params = (GLfloat) texUnit->Combine.SourceRGB[2];
             }
             else {
                _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
@@ -677,7 +876,7 @@ _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
          case GL_SOURCE0_ALPHA:
             if (ctx->Extensions.EXT_texture_env_combine ||
                 ctx->Extensions.ARB_texture_env_combine) {
-               *params = (GLfloat) texUnit->CombineSourceA[0];
+               *params = (GLfloat) texUnit->Combine.SourceA[0];
             }
             else {
                _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
@@ -686,7 +885,7 @@ _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
          case GL_SOURCE1_ALPHA:
             if (ctx->Extensions.EXT_texture_env_combine ||
                 ctx->Extensions.ARB_texture_env_combine) {
-               *params = (GLfloat) texUnit->CombineSourceA[1];
+               *params = (GLfloat) texUnit->Combine.SourceA[1];
             }
             else {
                _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
@@ -695,7 +894,7 @@ _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
          case GL_SOURCE2_ALPHA:
             if (ctx->Extensions.EXT_texture_env_combine ||
                 ctx->Extensions.ARB_texture_env_combine) {
-               *params = (GLfloat) texUnit->CombineSourceA[2];
+               *params = (GLfloat) texUnit->Combine.SourceA[2];
             }
             else {
                _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
@@ -704,7 +903,7 @@ _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
          case GL_OPERAND0_RGB:
             if (ctx->Extensions.EXT_texture_env_combine ||
                 ctx->Extensions.ARB_texture_env_combine) {
-               *params = (GLfloat) texUnit->CombineOperandRGB[0];
+               *params = (GLfloat) texUnit->Combine.OperandRGB[0];
             }
             else {
                _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
@@ -713,7 +912,7 @@ _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
          case GL_OPERAND1_RGB:
             if (ctx->Extensions.EXT_texture_env_combine ||
                 ctx->Extensions.ARB_texture_env_combine) {
-               *params = (GLfloat) texUnit->CombineOperandRGB[1];
+               *params = (GLfloat) texUnit->Combine.OperandRGB[1];
             }
             else {
                _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
@@ -722,7 +921,7 @@ _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
          case GL_OPERAND2_RGB:
             if (ctx->Extensions.EXT_texture_env_combine ||
                 ctx->Extensions.ARB_texture_env_combine) {
-               *params = (GLfloat) texUnit->CombineOperandRGB[2];
+               *params = (GLfloat) texUnit->Combine.OperandRGB[2];
             }
             else {
                _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
@@ -731,7 +930,7 @@ _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
          case GL_OPERAND0_ALPHA:
             if (ctx->Extensions.EXT_texture_env_combine ||
                 ctx->Extensions.ARB_texture_env_combine) {
-               *params = (GLfloat) texUnit->CombineOperandA[0];
+               *params = (GLfloat) texUnit->Combine.OperandA[0];
             }
             else {
                _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
@@ -740,7 +939,7 @@ _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
          case GL_OPERAND1_ALPHA:
             if (ctx->Extensions.EXT_texture_env_combine ||
                 ctx->Extensions.ARB_texture_env_combine) {
-               *params = (GLfloat) texUnit->CombineOperandA[1];
+               *params = (GLfloat) texUnit->Combine.OperandA[1];
             }
             else {
                _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
@@ -749,7 +948,7 @@ _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
          case GL_OPERAND2_ALPHA:
             if (ctx->Extensions.EXT_texture_env_combine ||
                 ctx->Extensions.ARB_texture_env_combine) {
-               *params = (GLfloat) texUnit->CombineOperandA[2];
+               *params = (GLfloat) texUnit->Combine.OperandA[2];
             }
             else {
                _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
@@ -758,9 +957,9 @@ _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
          case GL_RGB_SCALE:
             if (ctx->Extensions.EXT_texture_env_combine ||
                 ctx->Extensions.ARB_texture_env_combine) {
-               if (texUnit->CombineScaleShiftRGB == 0)
+               if (texUnit->Combine.ScaleShiftRGB == 0)
                   *params = 1.0;
-               else if (texUnit->CombineScaleShiftRGB == 1)
+               else if (texUnit->Combine.ScaleShiftRGB == 1)
                   *params = 2.0;
                else
                   *params = 4.0;
@@ -773,9 +972,9 @@ _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
          case GL_ALPHA_SCALE:
             if (ctx->Extensions.EXT_texture_env_combine ||
                 ctx->Extensions.ARB_texture_env_combine) {
-               if (texUnit->CombineScaleShiftA == 0)
+               if (texUnit->Combine.ScaleShiftA == 0)
                   *params = 1.0;
-               else if (texUnit->CombineScaleShiftA == 1)
+               else if (texUnit->Combine.ScaleShiftA == 1)
                   *params = 2.0;
                else
                   *params = 4.0;
@@ -804,8 +1003,9 @@ _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
       }
    }
    else if (target == GL_POINT_SPRITE_NV) {
-      /* GL_NV_point_sprite */
-      if (!ctx->Extensions.NV_point_sprite) {
+      /* GL_ARB_point_sprite / GL_NV_point_sprite */
+      if (!ctx->Extensions.NV_point_sprite
+         && !ctx->Extensions.ARB_point_sprite) {
          _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" );
          return;
       }
@@ -824,13 +1024,23 @@ _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
 }
 
 
-void
+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:
@@ -845,7 +1055,7 @@ _mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params )
          case GL_COMBINE_RGB:
             if (ctx->Extensions.EXT_texture_env_combine ||
                 ctx->Extensions.ARB_texture_env_combine) {
-               *params = (GLint) texUnit->CombineModeRGB;
+               *params = (GLint) texUnit->Combine.ModeRGB;
             }
             else {
                _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
@@ -854,7 +1064,7 @@ _mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params )
          case GL_COMBINE_ALPHA:
             if (ctx->Extensions.EXT_texture_env_combine ||
                 ctx->Extensions.ARB_texture_env_combine) {
-               *params = (GLint) texUnit->CombineModeA;
+               *params = (GLint) texUnit->Combine.ModeA;
             }
             else {
                _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
@@ -863,7 +1073,7 @@ _mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params )
          case GL_SOURCE0_RGB:
             if (ctx->Extensions.EXT_texture_env_combine ||
                 ctx->Extensions.ARB_texture_env_combine) {
-               *params = (GLint) texUnit->CombineSourceRGB[0];
+               *params = (GLint) texUnit->Combine.SourceRGB[0];
             }
             else {
                _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
@@ -872,7 +1082,7 @@ _mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params )
          case GL_SOURCE1_RGB:
             if (ctx->Extensions.EXT_texture_env_combine ||
                 ctx->Extensions.ARB_texture_env_combine) {
-               *params = (GLint) texUnit->CombineSourceRGB[1];
+               *params = (GLint) texUnit->Combine.SourceRGB[1];
             }
             else {
                _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
@@ -881,7 +1091,7 @@ _mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params )
          case GL_SOURCE2_RGB:
             if (ctx->Extensions.EXT_texture_env_combine ||
                 ctx->Extensions.ARB_texture_env_combine) {
-               *params = (GLint) texUnit->CombineSourceRGB[2];
+               *params = (GLint) texUnit->Combine.SourceRGB[2];
             }
             else {
                _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
@@ -890,7 +1100,7 @@ _mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params )
          case GL_SOURCE0_ALPHA:
             if (ctx->Extensions.EXT_texture_env_combine ||
                 ctx->Extensions.ARB_texture_env_combine) {
-               *params = (GLint) texUnit->CombineSourceA[0];
+               *params = (GLint) texUnit->Combine.SourceA[0];
             }
             else {
                _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
@@ -899,7 +1109,7 @@ _mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params )
          case GL_SOURCE1_ALPHA:
             if (ctx->Extensions.EXT_texture_env_combine ||
                 ctx->Extensions.ARB_texture_env_combine) {
-               *params = (GLint) texUnit->CombineSourceA[1];
+               *params = (GLint) texUnit->Combine.SourceA[1];
             }
             else {
                _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
@@ -908,7 +1118,7 @@ _mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params )
          case GL_SOURCE2_ALPHA:
             if (ctx->Extensions.EXT_texture_env_combine ||
                 ctx->Extensions.ARB_texture_env_combine) {
-               *params = (GLint) texUnit->CombineSourceA[2];
+               *params = (GLint) texUnit->Combine.SourceA[2];
             }
             else {
                _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
@@ -917,7 +1127,7 @@ _mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params )
          case GL_OPERAND0_RGB:
             if (ctx->Extensions.EXT_texture_env_combine ||
                 ctx->Extensions.ARB_texture_env_combine) {
-               *params = (GLint) texUnit->CombineOperandRGB[0];
+               *params = (GLint) texUnit->Combine.OperandRGB[0];
             }
             else {
                _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
@@ -926,7 +1136,7 @@ _mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params )
          case GL_OPERAND1_RGB:
             if (ctx->Extensions.EXT_texture_env_combine ||
                 ctx->Extensions.ARB_texture_env_combine) {
-               *params = (GLint) texUnit->CombineOperandRGB[1];
+               *params = (GLint) texUnit->Combine.OperandRGB[1];
             }
             else {
                _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
@@ -935,7 +1145,7 @@ _mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params )
          case GL_OPERAND2_RGB:
             if (ctx->Extensions.EXT_texture_env_combine ||
                 ctx->Extensions.ARB_texture_env_combine) {
-               *params = (GLint) texUnit->CombineOperandRGB[2];
+               *params = (GLint) texUnit->Combine.OperandRGB[2];
             }
             else {
                _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
@@ -944,7 +1154,7 @@ _mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params )
          case GL_OPERAND0_ALPHA:
             if (ctx->Extensions.EXT_texture_env_combine ||
                 ctx->Extensions.ARB_texture_env_combine) {
-               *params = (GLint) texUnit->CombineOperandA[0];
+               *params = (GLint) texUnit->Combine.OperandA[0];
             }
             else {
                _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
@@ -953,7 +1163,7 @@ _mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params )
          case GL_OPERAND1_ALPHA:
             if (ctx->Extensions.EXT_texture_env_combine ||
                 ctx->Extensions.ARB_texture_env_combine) {
-               *params = (GLint) texUnit->CombineOperandA[1];
+               *params = (GLint) texUnit->Combine.OperandA[1];
             }
             else {
                _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
@@ -962,7 +1172,7 @@ _mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params )
          case GL_OPERAND2_ALPHA:
             if (ctx->Extensions.EXT_texture_env_combine ||
                 ctx->Extensions.ARB_texture_env_combine) {
-               *params = (GLint) texUnit->CombineOperandA[2];
+               *params = (GLint) texUnit->Combine.OperandA[2];
             }
             else {
                _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
@@ -971,9 +1181,9 @@ _mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params )
          case GL_RGB_SCALE:
             if (ctx->Extensions.EXT_texture_env_combine ||
                 ctx->Extensions.ARB_texture_env_combine) {
-               if (texUnit->CombineScaleShiftRGB == 0)
+               if (texUnit->Combine.ScaleShiftRGB == 0)
                   *params = 1;
-               else if (texUnit->CombineScaleShiftRGB == 1)
+               else if (texUnit->Combine.ScaleShiftRGB == 1)
                   *params = 2;
                else
                   *params = 4;
@@ -986,9 +1196,9 @@ _mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params )
          case GL_ALPHA_SCALE:
             if (ctx->Extensions.EXT_texture_env_combine ||
                 ctx->Extensions.ARB_texture_env_combine) {
-               if (texUnit->CombineScaleShiftA == 0)
+               if (texUnit->Combine.ScaleShiftA == 0)
                   *params = 1;
-               else if (texUnit->CombineScaleShiftA == 1)
+               else if (texUnit->Combine.ScaleShiftA == 1)
                   *params = 2;
                else
                   *params = 4;
@@ -1018,8 +1228,9 @@ _mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params )
       }
    }
    else if (target == GL_POINT_SPRITE_NV) {
-      /* GL_NV_point_sprite */
-      if (!ctx->Extensions.NV_point_sprite) {
+      /* GL_ARB_point_sprite / GL_NV_point_sprite */
+      if (!ctx->Extensions.NV_point_sprite
+         && !ctx->Extensions.ARB_point_sprite) {
          _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(target)" );
          return;
       }
@@ -1044,21 +1255,50 @@ _mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params )
 /*                       Texture Parameters                           */
 /**********************************************************************/
 
+static GLboolean 
+_mesa_validate_texture_wrap_mode(GLcontext * ctx,
+                                GLenum target, GLenum eparam)
+{
+   const struct gl_extensions * const e = & ctx->Extensions;
 
-void
+   if (eparam == GL_CLAMP || eparam == GL_CLAMP_TO_EDGE ||
+       (eparam == GL_CLAMP_TO_BORDER && e->ARB_texture_border_clamp)) {
+      /* any texture target */
+      return GL_TRUE;
+   }
+   else if (target != GL_TEXTURE_RECTANGLE_NV &&
+           (eparam == GL_REPEAT ||
+            (eparam == GL_MIRRORED_REPEAT &&
+             e->ARB_texture_mirrored_repeat) ||
+            (eparam == GL_MIRROR_CLAMP_EXT &&
+             (e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp)) ||
+            (eparam == GL_MIRROR_CLAMP_TO_EDGE_EXT &&
+             (e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp)) ||
+            (eparam == GL_MIRROR_CLAMP_TO_BORDER_EXT &&
+             (e->EXT_texture_mirror_clamp)))) {
+      /* non-rectangle texture */
+      return GL_TRUE;
+   }
+
+   _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
+   return GL_FALSE;
+}
+
+
+void GLAPIENTRY
 _mesa_TexParameterf( GLenum target, GLenum pname, GLfloat param )
 {
    _mesa_TexParameterfv(target, pname, &param);
 }
 
 
-void
+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))
@@ -1068,6 +1308,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:
@@ -1137,81 +1383,34 @@ _mesa_TexParameterfv( GLenum target, GLenum pname, const GLfloat *params )
       case GL_TEXTURE_WRAP_S:
          if (texObj->WrapS == eparam)
             return;
-         if (eparam == GL_CLAMP || eparam == GL_CLAMP_TO_EDGE ||
-             (eparam == GL_CLAMP_TO_BORDER &&
-              ctx->Extensions.ARB_texture_border_clamp)) {
-            /* any texture target */
-            FLUSH_VERTICES(ctx, _NEW_TEXTURE);
-            texObj->WrapS = eparam;
-         }
-         else if (texObj->Target != GL_TEXTURE_RECTANGLE_NV &&
-                  (eparam == GL_REPEAT ||
-                   (eparam == GL_MIRRORED_REPEAT &&
-                    ctx->Extensions.ARB_texture_mirrored_repeat) ||
-                   (eparam == GL_MIRROR_CLAMP_ATI &&
-                    ctx->Extensions.ATI_texture_mirror_once) ||
-                   (eparam == GL_MIRROR_CLAMP_TO_EDGE_ATI &&
-                    ctx->Extensions.ATI_texture_mirror_once))) {
-            /* non-rectangle texture */
+         if (_mesa_validate_texture_wrap_mode(ctx, texObj->Target, eparam)) {
             FLUSH_VERTICES(ctx, _NEW_TEXTURE);
             texObj->WrapS = eparam;
          }
          else {
-            _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
             return;
          }
          break;
       case GL_TEXTURE_WRAP_T:
          if (texObj->WrapT == eparam)
             return;
-         if (eparam == GL_CLAMP || eparam == GL_CLAMP_TO_EDGE ||
-             (eparam == GL_CLAMP_TO_BORDER &&
-              ctx->Extensions.ARB_texture_border_clamp)) {
-            /* any texture target */
-            FLUSH_VERTICES(ctx, _NEW_TEXTURE);
-            texObj->WrapT = eparam;
-         }
-         else if (texObj->Target != GL_TEXTURE_RECTANGLE_NV &&
-                  (eparam == GL_REPEAT ||
-                   (eparam == GL_MIRRORED_REPEAT &&
-                    ctx->Extensions.ARB_texture_mirrored_repeat) ||
-                   (eparam == GL_MIRROR_CLAMP_ATI &&
-                    ctx->Extensions.ATI_texture_mirror_once) ||
-                   (eparam == GL_MIRROR_CLAMP_TO_EDGE_ATI &&
-                    ctx->Extensions.ATI_texture_mirror_once))) {
-            /* non-rectangle texture */
+         if (_mesa_validate_texture_wrap_mode(ctx, texObj->Target, eparam)) {
             FLUSH_VERTICES(ctx, _NEW_TEXTURE);
             texObj->WrapT = eparam;
          }
          else {
-            _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
             return;
          }
          break;
       case GL_TEXTURE_WRAP_R:
          if (texObj->WrapR == eparam)
             return;
-         if (eparam == GL_CLAMP || eparam == GL_CLAMP_TO_EDGE ||
-             (eparam == GL_CLAMP_TO_BORDER &&
-              ctx->Extensions.ARB_texture_border_clamp)) {
-            /* any texture target */
-            FLUSH_VERTICES(ctx, _NEW_TEXTURE);
-            texObj->WrapR = eparam;
-         }
-         else if (texObj->Target != GL_TEXTURE_RECTANGLE_NV &&
-                  (eparam == GL_REPEAT ||
-                   (eparam == GL_MIRRORED_REPEAT &&
-                    ctx->Extensions.ARB_texture_mirrored_repeat) ||
-                   (eparam == GL_MIRROR_CLAMP_ATI &&
-                    ctx->Extensions.ATI_texture_mirror_once) ||
-                   (eparam == GL_MIRROR_CLAMP_TO_EDGE_ATI &&
-                    ctx->Extensions.ATI_texture_mirror_once))) {
-            /* non-rectangle texture */
+         if (_mesa_validate_texture_wrap_mode(ctx, texObj->Target, eparam)) {
             FLUSH_VERTICES(ctx, _NEW_TEXTURE);
             texObj->WrapR = eparam;
          }
          else {
-            _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
+           return;
          }
          break;
       case GL_TEXTURE_BORDER_COLOR:
@@ -1268,7 +1467,9 @@ _mesa_TexParameterfv( GLenum target, GLenum pname, const GLfloat *params )
               return;
            }
             FLUSH_VERTICES(ctx, _NEW_TEXTURE);
-            texObj->MaxAnisotropy = params[0];
+            /* clamp to max, that's what NVIDIA does */
+            texObj->MaxAnisotropy = MIN2(params[0],
+                                         ctx->Const.MaxTextureMaxAnisotropy);
          }
          else {
             _mesa_error(ctx, GL_INVALID_ENUM,
@@ -1394,6 +1595,15 @@ _mesa_TexParameterfv( GLenum target, GLenum pname, const GLfloat *params )
             return;
          }
          break;
+      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);
+               texObj->LodBias = params[0];
+            }
+         }
+         break;
 
       default:
          _mesa_error(ctx, GL_INVALID_ENUM,
@@ -1409,17 +1619,20 @@ _mesa_TexParameterfv( GLenum target, GLenum pname, const GLfloat *params )
 }
 
 
-void
+void GLAPIENTRY
 _mesa_TexParameteri( GLenum target, GLenum pname, GLint param )
 {
    GLfloat fparam[4];
-   fparam[0] = (GLfloat) param;
+   if (pname == GL_TEXTURE_PRIORITY)
+      fparam[0] = INT_TO_FLOAT(param);
+   else
+      fparam[0] = (GLfloat) param;
    fparam[1] = fparam[2] = fparam[3] = 0.0;
    _mesa_TexParameterfv(target, pname, fparam);
 }
 
 
-void
+void GLAPIENTRY
 _mesa_TexParameteriv( GLenum target, GLenum pname, const GLint *params )
 {
    GLfloat fparam[4];
@@ -1430,14 +1643,17 @@ _mesa_TexParameteriv( GLenum target, GLenum pname, const GLint *params )
       fparam[3] = INT_TO_FLOAT(params[3]);
    }
    else {
-      fparam[0] = (GLfloat) params[0];
+      if (pname == GL_TEXTURE_PRIORITY)
+         fparam[0] = INT_TO_FLOAT(params[0]);
+      else
+         fparam[0] = (GLfloat) params[0];
       fparam[1] = fparam[2] = fparam[3] = 0.0F;
    }
    _mesa_TexParameterfv(target, pname, fparam);
 }
 
 
-void
+void GLAPIENTRY
 _mesa_GetTexLevelParameterfv( GLenum target, GLint level,
                               GLenum pname, GLfloat *params )
 {
@@ -1479,18 +1695,26 @@ tex_image_dimensions(GLcontext *ctx, GLenum target)
 }
 
 
-void
+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;
    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) {
@@ -1498,32 +1722,10 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
       return;
    }
 
-   switch (target) {
-   case GL_TEXTURE_1D:
-   case GL_PROXY_TEXTURE_1D:
-   case GL_TEXTURE_2D:
-   case GL_PROXY_TEXTURE_2D:
-      maxLevels = ctx->Const.MaxTextureLevels;
-      break;
-   case GL_TEXTURE_3D:
-   case GL_PROXY_TEXTURE_3D:
-      maxLevels = ctx->Const.Max3DTextureLevels;
-      break;
-   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:
-   case GL_PROXY_TEXTURE_CUBE_MAP:
-      maxLevels = ctx->Const.MaxCubeTextureLevels;
-      break;
-   case GL_TEXTURE_RECTANGLE_NV:
-   case GL_PROXY_TEXTURE_RECTANGLE_NV:
-      maxLevels = 1;
-      break;
-   default:
-      _mesa_problem(ctx, "switch in _mesa_GetTexLevelParameter");
+   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");
       return;
    }
 
@@ -1542,11 +1744,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
       return;
    }
 
-   isProxy = (target == GL_PROXY_TEXTURE_1D) ||
-             (target == GL_PROXY_TEXTURE_2D) ||
-             (target == GL_PROXY_TEXTURE_3D) ||
-             (target == GL_PROXY_TEXTURE_CUBE_MAP) ||
-             (target == GL_PROXY_TEXTURE_RECTANGLE_NV);
+   isProxy = _mesa_is_proxy_texture(target);
 
    switch (pname) {
       case GL_TEXTURE_WIDTH:
@@ -1559,38 +1757,39 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
          *params = img->Depth;
          return;
       case GL_TEXTURE_INTERNAL_FORMAT:
-         *params = img->IntFormat;
+         *params = img->InternalFormat;
          return;
       case GL_TEXTURE_BORDER:
          *params = img->Border;
          return;
       case GL_TEXTURE_RED_SIZE:
-         if (img->Format == GL_RGB || img->Format == GL_RGBA)
+         if (img->_BaseFormat == GL_RGB || img->_BaseFormat == GL_RGBA)
             *params = img->TexFormat->RedBits;
          else
             *params = 0;
          return;
       case GL_TEXTURE_GREEN_SIZE:
-         if (img->Format == GL_RGB || img->Format == GL_RGBA)
+         if (img->_BaseFormat == GL_RGB || img->_BaseFormat == GL_RGBA)
             *params = img->TexFormat->GreenBits;
          else
             *params = 0;
          return;
       case GL_TEXTURE_BLUE_SIZE:
-         if (img->Format == GL_RGB || img->Format == GL_RGBA)
+         if (img->_BaseFormat == GL_RGB || img->_BaseFormat == GL_RGBA)
             *params = img->TexFormat->BlueBits;
          else
             *params = 0;
          return;
       case GL_TEXTURE_ALPHA_SIZE:
-         if (img->Format == GL_ALPHA || img->Format == GL_LUMINANCE_ALPHA ||
-             img->Format == GL_RGBA)
+         if (img->_BaseFormat == GL_ALPHA ||
+             img->_BaseFormat == GL_LUMINANCE_ALPHA ||
+             img->_BaseFormat == GL_RGBA)
             *params = img->TexFormat->AlphaBits;
          else
             *params = 0;
          return;
       case GL_TEXTURE_INTENSITY_SIZE:
-         if (img->Format != GL_INTENSITY)
+         if (img->_BaseFormat != GL_INTENSITY)
             *params = 0;
          else if (img->TexFormat->IntensityBits > 0)
             *params = img->TexFormat->IntensityBits;
@@ -1598,8 +1797,8 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
             *params = MIN2(img->TexFormat->RedBits, img->TexFormat->GreenBits);
          return;
       case GL_TEXTURE_LUMINANCE_SIZE:
-         if (img->Format != GL_LUMINANCE &&
-             img->Format != GL_LUMINANCE_ALPHA)
+         if (img->_BaseFormat != GL_LUMINANCE &&
+             img->_BaseFormat != GL_LUMINANCE_ALPHA)
             *params = 0;
          else if (img->TexFormat->LuminanceBits > 0)
             *params = img->TexFormat->LuminanceBits;
@@ -1607,30 +1806,44 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
             *params = MIN2(img->TexFormat->RedBits, img->TexFormat->GreenBits);
          return;
       case GL_TEXTURE_INDEX_SIZE_EXT:
-         if (img->Format == GL_COLOR_INDEX)
+         if (img->_BaseFormat == GL_COLOR_INDEX)
             *params = img->TexFormat->IndexBits;
          else
             *params = 0;
          return;
-      case GL_DEPTH_BITS:
-         /* XXX this isn't in the GL_SGIX_depth_texture spec
-          * but seems appropriate.
-          */
-         if (ctx->Extensions.SGIX_depth_texture)
+      case GL_TEXTURE_DEPTH_SIZE_ARB:
+         if (ctx->Extensions.SGIX_depth_texture ||
+             ctx->Extensions.ARB_depth_texture)
             *params = img->TexFormat->DepthBits;
          else
             _mesa_error(ctx, GL_INVALID_ENUM,
                         "glGetTexLevelParameter[if]v(pname)");
          return;
+      case GL_TEXTURE_STENCIL_SIZE_EXT:
+         if (ctx->Extensions.EXT_packed_depth_stencil) {
+            *params = img->TexFormat->StencilBits;
+         }
+         else {
+            _mesa_error(ctx, GL_INVALID_ENUM,
+                        "glGetTexLevelParameter[if]v(pname)");
+         }
+         return;
 
       /* 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,
@@ -1647,6 +1860,71 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
          }
          return;
 
+      /* GL_ARB_texture_float */
+      case GL_TEXTURE_RED_TYPE_ARB:
+         if (ctx->Extensions.ARB_texture_float) {
+            *params = img->TexFormat->RedBits ? img->TexFormat->DataType : GL_NONE;
+         }
+         else {
+            _mesa_error(ctx, GL_INVALID_ENUM,
+                        "glGetTexLevelParameter[if]v(pname)");
+         }
+         return;
+      case GL_TEXTURE_GREEN_TYPE_ARB:
+         if (ctx->Extensions.ARB_texture_float) {
+            *params = img->TexFormat->GreenBits ? img->TexFormat->DataType : GL_NONE;
+         }
+         else {
+            _mesa_error(ctx, GL_INVALID_ENUM,
+                        "glGetTexLevelParameter[if]v(pname)");
+         }
+         return;
+      case GL_TEXTURE_BLUE_TYPE_ARB:
+         if (ctx->Extensions.ARB_texture_float) {
+            *params = img->TexFormat->BlueBits ? img->TexFormat->DataType : GL_NONE;
+         }
+         else {
+            _mesa_error(ctx, GL_INVALID_ENUM,
+                        "glGetTexLevelParameter[if]v(pname)");
+         }
+         return;
+      case GL_TEXTURE_ALPHA_TYPE_ARB:
+         if (ctx->Extensions.ARB_texture_float) {
+            *params = img->TexFormat->AlphaBits ? img->TexFormat->DataType : GL_NONE;
+         }
+         else {
+            _mesa_error(ctx, GL_INVALID_ENUM,
+                        "glGetTexLevelParameter[if]v(pname)");
+         }
+         return;
+      case GL_TEXTURE_LUMINANCE_TYPE_ARB:
+         if (ctx->Extensions.ARB_texture_float) {
+            *params = img->TexFormat->LuminanceBits ? img->TexFormat->DataType : GL_NONE;
+         }
+         else {
+            _mesa_error(ctx, GL_INVALID_ENUM,
+                        "glGetTexLevelParameter[if]v(pname)");
+         }
+         return;
+      case GL_TEXTURE_INTENSITY_TYPE_ARB:
+         if (ctx->Extensions.ARB_texture_float) {
+            *params = img->TexFormat->IntensityBits ? img->TexFormat->DataType : GL_NONE;
+         }
+         else {
+            _mesa_error(ctx, GL_INVALID_ENUM,
+                        "glGetTexLevelParameter[if]v(pname)");
+         }
+         return;
+      case GL_TEXTURE_DEPTH_TYPE_ARB:
+         if (ctx->Extensions.ARB_texture_float) {
+            *params = img->TexFormat->DepthBits ? img->TexFormat->DataType : GL_NONE;
+         }
+         else {
+            _mesa_error(ctx, GL_INVALID_ENUM,
+                        "glGetTexLevelParameter[if]v(pname)");
+         }
+         return;
+
       default:
          _mesa_error(ctx, GL_INVALID_ENUM,
                      "glGetTexLevelParameter[if]v(pname)");
@@ -1655,14 +1933,22 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
 
 
 
-void
+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;
+   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)");
@@ -1764,6 +2050,12 @@ _mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params )
             return;
          }
          break;
+      case GL_TEXTURE_LOD_BIAS:
+         if (ctx->Extensions.EXT_texture_lod_bias) {
+            *params = obj->LodBias;
+            return;
+         }
+         break;
       default:
          ; /* silence warnings */
    }
@@ -1773,14 +2065,22 @@ _mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params )
 }
 
 
-void
+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)");
@@ -1827,7 +2127,7 @@ _mesa_GetTexParameteriv( GLenum target, GLenum pname, GLint *params )
          }
          return;
       case GL_TEXTURE_PRIORITY:
-         *params = (GLint) obj->Priority;
+         *params = FLOAT_TO_INT(obj->Priority);
          return;
       case GL_TEXTURE_MIN_LOD:
          *params = (GLint) obj->MinLod;
@@ -1889,6 +2189,12 @@ _mesa_GetTexParameteriv( GLenum target, GLenum pname, GLint *params )
             return;
          }
          break;
+      case GL_TEXTURE_LOD_BIAS:
+         if (ctx->Extensions.EXT_texture_lod_bias) {
+            *params = (GLint) obj->LodBias;
+            return;
+         }
+         break;
       default:
          ; /* silence warnings */
    }
@@ -1903,13 +2209,12 @@ _mesa_GetTexParameteriv( GLenum target, GLenum pname, GLint *params )
 /*                    Texture Coord Generation                        */
 /**********************************************************************/
 
-
-void
+#if FEATURE_texgen
+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))
@@ -1919,11 +2224,18 @@ _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) {
            GLenum mode = (GLenum) (GLint) *params;
-           GLuint bits;
+           GLbitfield bits;
            switch (mode) {
            case GL_OBJECT_LINEAR:
               bits = TEXGEN_OBJ_LINEAR;
@@ -1954,16 +2266,12 @@ _mesa_TexGenfv( GLenum coord, GLenum pname, const GLfloat *params )
            if (TEST_EQ_4V(texUnit->ObjectPlaneS, params))
                return;
            FLUSH_VERTICES(ctx, _NEW_TEXTURE);
-           texUnit->ObjectPlaneS[0] = params[0];
-           texUnit->ObjectPlaneS[1] = params[1];
-           texUnit->ObjectPlaneS[2] = params[2];
-           texUnit->ObjectPlaneS[3] = params[3];
+            COPY_4FV(texUnit->ObjectPlaneS, params);
         }
         else if (pname==GL_EYE_PLANE) {
            GLfloat tmp[4];
-
             /* Transform plane equation by the inverse modelview matrix */
-            if (ctx->ModelviewMatrixStack.Top->flags & MAT_DIRTY_INVERSE) {
+            if (_math_matrix_is_dirty(ctx->ModelviewMatrixStack.Top)) {
                _math_matrix_analyse( ctx->ModelviewMatrixStack.Top );
             }
             _mesa_transform_vector( tmp, params, ctx->ModelviewMatrixStack.Top->inv );
@@ -1980,7 +2288,7 @@ _mesa_TexGenfv( GLenum coord, GLenum pname, const GLfloat *params )
       case GL_T:
          if (pname==GL_TEXTURE_GEN_MODE) {
            GLenum mode = (GLenum) (GLint) *params;
-           GLuint bitt;
+           GLbitfield bitt;
            switch (mode) {
                case GL_OBJECT_LINEAR:
                   bitt = TEXGEN_OBJ_LINEAR;
@@ -2011,15 +2319,12 @@ _mesa_TexGenfv( GLenum coord, GLenum pname, const GLfloat *params )
            if (TEST_EQ_4V(texUnit->ObjectPlaneT, params))
                return;
            FLUSH_VERTICES(ctx, _NEW_TEXTURE);
-           texUnit->ObjectPlaneT[0] = params[0];
-           texUnit->ObjectPlaneT[1] = params[1];
-           texUnit->ObjectPlaneT[2] = params[2];
-           texUnit->ObjectPlaneT[3] = params[3];
+            COPY_4FV(texUnit->ObjectPlaneT, params);
         }
         else if (pname==GL_EYE_PLANE) {
            GLfloat tmp[4];
             /* Transform plane equation by the inverse modelview matrix */
-           if (ctx->ModelviewMatrixStack.Top->flags & MAT_DIRTY_INVERSE) {
+           if (_math_matrix_is_dirty(ctx->ModelviewMatrixStack.Top)) {
                _math_matrix_analyse( ctx->ModelviewMatrixStack.Top );
             }
             _mesa_transform_vector( tmp, params, ctx->ModelviewMatrixStack.Top->inv );
@@ -2036,7 +2341,7 @@ _mesa_TexGenfv( GLenum coord, GLenum pname, const GLfloat *params )
       case GL_R:
          if (pname==GL_TEXTURE_GEN_MODE) {
            GLenum mode = (GLenum) (GLint) *params;
-           GLuint bitr;
+           GLbitfield bitr;
            switch (mode) {
            case GL_OBJECT_LINEAR:
               bitr = TEXGEN_OBJ_LINEAR;
@@ -2064,15 +2369,12 @@ _mesa_TexGenfv( GLenum coord, GLenum pname, const GLfloat *params )
            if (TEST_EQ_4V(texUnit->ObjectPlaneR, params))
                return;
            FLUSH_VERTICES(ctx, _NEW_TEXTURE);
-           texUnit->ObjectPlaneR[0] = params[0];
-           texUnit->ObjectPlaneR[1] = params[1];
-           texUnit->ObjectPlaneR[2] = params[2];
-           texUnit->ObjectPlaneR[3] = params[3];
+           COPY_4FV(texUnit->ObjectPlaneR, params);
         }
         else if (pname==GL_EYE_PLANE) {
            GLfloat tmp[4];
             /* Transform plane equation by the inverse modelview matrix */
-            if (ctx->ModelviewMatrixStack.Top->flags & MAT_DIRTY_INVERSE) {
+            if (_math_matrix_is_dirty(ctx->ModelviewMatrixStack.Top)) {
                _math_matrix_analyse( ctx->ModelviewMatrixStack.Top );
             }
             _mesa_transform_vector( tmp, params, ctx->ModelviewMatrixStack.Top->inv );
@@ -2089,7 +2391,7 @@ _mesa_TexGenfv( GLenum coord, GLenum pname, const GLfloat *params )
       case GL_Q:
          if (pname==GL_TEXTURE_GEN_MODE) {
            GLenum mode = (GLenum) (GLint) *params;
-           GLuint bitq;
+           GLbitfield bitq;
            switch (mode) {
            case GL_OBJECT_LINEAR:
               bitq = TEXGEN_OBJ_LINEAR;
@@ -2111,15 +2413,12 @@ _mesa_TexGenfv( GLenum coord, GLenum pname, const GLfloat *params )
            if (TEST_EQ_4V(texUnit->ObjectPlaneQ, params))
                return;
            FLUSH_VERTICES(ctx, _NEW_TEXTURE);
-           texUnit->ObjectPlaneQ[0] = params[0];
-           texUnit->ObjectPlaneQ[1] = params[1];
-           texUnit->ObjectPlaneQ[2] = params[2];
-           texUnit->ObjectPlaneQ[3] = params[3];
+            COPY_4FV(texUnit->ObjectPlaneQ, params);
         }
         else if (pname==GL_EYE_PLANE) {
            GLfloat tmp[4];
             /* Transform plane equation by the inverse modelview matrix */
-            if (ctx->ModelviewMatrixStack.Top->flags & MAT_DIRTY_INVERSE) {
+            if (_math_matrix_is_dirty(ctx->ModelviewMatrixStack.Top)) {
                _math_matrix_analyse( ctx->ModelviewMatrixStack.Top );
             }
             _mesa_transform_vector( tmp, params, ctx->ModelviewMatrixStack.Top->inv );
@@ -2143,19 +2442,24 @@ _mesa_TexGenfv( GLenum coord, GLenum pname, const GLfloat *params )
 }
 
 
-void
+void GLAPIENTRY
 _mesa_TexGeniv(GLenum coord, GLenum pname, const GLint *params )
 {
    GLfloat p[4];
    p[0] = (GLfloat) params[0];
-   p[1] = (GLfloat) params[1];
-   p[2] = (GLfloat) params[2];
-   p[3] = (GLfloat) params[3];
+   if (pname == GL_TEXTURE_GEN_MODE) {
+      p[1] = p[2] = p[3] = 0.0F;
+   }
+   else {
+      p[1] = (GLfloat) params[1];
+      p[2] = (GLfloat) params[2];
+      p[3] = (GLfloat) params[3];
+   }
    _mesa_TexGenfv(coord, pname, p);
 }
 
 
-void
+void GLAPIENTRY
 _mesa_TexGend(GLenum coord, GLenum pname, GLdouble param )
 {
    GLfloat p = (GLfloat) param;
@@ -2163,26 +2467,31 @@ _mesa_TexGend(GLenum coord, GLenum pname, GLdouble param )
 }
 
 
-void
+void GLAPIENTRY
 _mesa_TexGendv(GLenum coord, GLenum pname, const GLdouble *params )
 {
    GLfloat p[4];
    p[0] = (GLfloat) params[0];
-   p[1] = (GLfloat) params[1];
-   p[2] = (GLfloat) params[2];
-   p[3] = (GLfloat) params[3];
+   if (pname == GL_TEXTURE_GEN_MODE) {
+      p[1] = p[2] = p[3] = 0.0F;
+   }
+   else {
+      p[1] = (GLfloat) params[1];
+      p[2] = (GLfloat) params[2];
+      p[3] = (GLfloat) params[3];
+   }
    _mesa_TexGenfv( coord, pname, p );
 }
 
 
-void
+void GLAPIENTRY
 _mesa_TexGenf( GLenum coord, GLenum pname, GLfloat param )
 {
    _mesa_TexGenfv(coord, pname, &param);
 }
 
 
-void
+void GLAPIENTRY
 _mesa_TexGeni( GLenum coord, GLenum pname, GLint param )
 {
    _mesa_TexGeniv( coord, pname, &param );
@@ -2190,14 +2499,20 @@ _mesa_TexGeni( GLenum coord, GLenum pname, GLint param )
 
 
 
-void
+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) {
@@ -2267,14 +2582,20 @@ _mesa_GetTexGendv( GLenum coord, GLenum pname, GLdouble *params )
 
 
 
-void
+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) {
@@ -2344,14 +2665,20 @@ _mesa_GetTexGenfv( GLenum coord, GLenum pname, GLfloat *params )
 
 
 
-void
+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) {
@@ -2442,23 +2769,24 @@ _mesa_GetTexGeniv( GLenum coord, GLenum pname, GLint *params )
         return;
    }
 }
+#endif
 
 
 /* GL_ARB_multitexture */
-void
-_mesa_ActiveTextureARB( GLenum target )
+void GLAPIENTRY
+_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;
    }
 
@@ -2480,15 +2808,15 @@ _mesa_ActiveTextureARB( GLenum target )
 
 
 /* GL_ARB_multitexture */
-void
-_mesa_ClientActiveTextureARB( GLenum target )
+void GLAPIENTRY
+_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;
    }
 
@@ -2499,131 +2827,412 @@ _mesa_ClientActiveTextureARB( GLenum target )
 
 
 /**********************************************************************/
-/*                     Pixel Texgen Extensions                        */
+/*****                    State management                        *****/
 /**********************************************************************/
 
-void
-_mesa_PixelTexGenSGIX(GLenum mode)
+
+/**
+ * \note This routine refers to derived texture attribute values to
+ * compute the ENABLE_TEXMAT flags, but is only called on
+ * _NEW_TEXTURE_MATRIX.  On changes to _NEW_TEXTURE, the ENABLE_TEXMAT
+ * flags are updated by _mesa_update_textures(), below.
+ *
+ * \param ctx GL context.
+ */
+static void
+update_texture_matrices( GLcontext *ctx )
 {
-   GLenum newRgbSource, newAlphaSource;
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
+   GLuint i;
 
-   switch (mode) {
-      case GL_NONE:
-         newRgbSource = GL_PIXEL_GROUP_COLOR_SGIS;
-         newAlphaSource = GL_PIXEL_GROUP_COLOR_SGIS;
-         break;
-      case GL_ALPHA:
-         newRgbSource = GL_PIXEL_GROUP_COLOR_SGIS;
-         newAlphaSource = GL_CURRENT_RASTER_COLOR;
-         break;
-      case GL_RGB:
-         newRgbSource = GL_CURRENT_RASTER_COLOR;
-         newAlphaSource = GL_PIXEL_GROUP_COLOR_SGIS;
-         break;
-      case GL_RGBA:
-         newRgbSource = GL_CURRENT_RASTER_COLOR;
-         newAlphaSource = GL_CURRENT_RASTER_COLOR;
-         break;
-      default:
-         _mesa_error(ctx, GL_INVALID_ENUM, "glPixelTexGenSGIX(mode)");
-         return;
-   }
+   ctx->Texture._TexMatEnabled = 0;
 
-   if (newRgbSource == ctx->Pixel.FragmentRgbSource &&
-       newAlphaSource == ctx->Pixel.FragmentAlphaSource)
-      return;
+   for (i=0; i < ctx->Const.MaxTextureUnits; i++) {
+      if (_math_matrix_is_dirty(ctx->TextureMatrixStack[i].Top)) {
+        _math_matrix_analyse( ctx->TextureMatrixStack[i].Top );
+
+        if (ctx->Texture.Unit[i]._ReallyEnabled &&
+            ctx->TextureMatrixStack[i].Top->type != MATRIX_IDENTITY)
+           ctx->Texture._TexMatEnabled |= ENABLE_TEXMAT(i);
 
-   FLUSH_VERTICES(ctx, _NEW_PIXEL);
-   ctx->Pixel.FragmentRgbSource = newRgbSource;
-   ctx->Pixel.FragmentAlphaSource = newAlphaSource;
+        if (ctx->Driver.TextureMatrix)
+           ctx->Driver.TextureMatrix( ctx, i, ctx->TextureMatrixStack[i].Top);
+      }
+   }
 }
 
 
-void
-_mesa_PixelTexGenParameterfSGIS(GLenum target, GLfloat value)
+/**
+ * Helper function for determining which texture object (1D, 2D, cube, etc)
+ * should actually be used.
+ */
+static void
+texture_override(GLcontext *ctx,
+                 struct gl_texture_unit *texUnit, GLbitfield enableBits,
+                 struct gl_texture_object *texObj, GLuint textureBit)
 {
-   _mesa_PixelTexGenParameteriSGIS(target, (GLint) value);
+   if (!texUnit->_ReallyEnabled && (enableBits & textureBit)) {
+      if (!texObj->Complete) {
+         _mesa_test_texobj_completeness(ctx, texObj);
+      }
+      if (texObj->Complete) {
+         texUnit->_ReallyEnabled = textureBit;
+         texUnit->_Current = texObj;
+      }
+   }
 }
 
 
-void
-_mesa_PixelTexGenParameterfvSGIS(GLenum target, const GLfloat *value)
+/**
+ * \note This routine refers to derived texture matrix values to
+ * compute the ENABLE_TEXMAT flags, but is only called on
+ * _NEW_TEXTURE.  On changes to _NEW_TEXTURE_MATRIX, the ENABLE_TEXMAT
+ * flags are updated by _mesa_update_texture_matrices, above.
+ *
+ * \param ctx GL context.
+ */
+static void
+update_texture_state( GLcontext *ctx )
 {
-   _mesa_PixelTexGenParameteriSGIS(target, (GLint) *value);
-}
+   GLuint unit;
 
+#if FEATURE_ARB_fragment_shader
+   struct gl2_program_intf **prog = ctx->ShaderObjects.CurrentProgram;
+   GLbitfield progteximageusage[MAX_TEXTURE_IMAGE_UNITS];
+#endif
 
-void
-_mesa_PixelTexGenParameteriSGIS(GLenum target, GLint value)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
+   ctx->NewState |= _NEW_TEXTURE; /* TODO: only set this if there are 
+                                  * actual changes. 
+                                  */
+
+   ctx->Texture._EnabledUnits = 0;
+   ctx->Texture._GenFlags = 0;
+   ctx->Texture._TexMatEnabled = 0;
+   ctx->Texture._TexGenEnabled = 0;
+
+#if FEATURE_ARB_fragment_shader
+   /*
+    * 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);
+   }
+#endif /* FEATURE_ARB_fragment_shader */
+
+   /*
+    * Update texture unit state.
+    */
+   for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
+      struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+      GLbitfield enableBits;
+
+      texUnit->_Current = NULL;
+      texUnit->_ReallyEnabled = 0;
+      texUnit->_GenFlags = 0;
+
+      /* Get the bitmask of texture enables */
+#if FEATURE_ARB_fragment_shader
+      if (ctx->ShaderObjects._FragmentShaderPresent) {
+         enableBits = progteximageusage[unit];
+      }
+      else
+#endif
+      if (ctx->FragmentProgram._Enabled) {
+         enableBits = ctx->FragmentProgram.Current->TexturesUsed[unit];
+      }
+      else {
+         if (!texUnit->Enabled)
+            continue;
+         enableBits = texUnit->Enabled;
+      }
 
-   if (value != GL_CURRENT_RASTER_COLOR && value != GL_PIXEL_GROUP_COLOR_SGIS) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glPixelTexGenParameterSGIS(value)");
-      return;
+      /* Look for the highest-priority texture target that's enabled and
+       * complete.  That's the one we'll use for texturing.  If we're using
+       * a fragment program we're guaranteed that bitcount(enabledBits) <= 1.
+       */
+      texture_override(ctx, texUnit, enableBits,
+                       texUnit->CurrentCubeMap, TEXTURE_CUBE_BIT);
+      texture_override(ctx, texUnit, enableBits,
+                       texUnit->Current3D, TEXTURE_3D_BIT);
+      texture_override(ctx, texUnit, enableBits,
+                       texUnit->CurrentRect, TEXTURE_RECT_BIT);
+      texture_override(ctx, texUnit, enableBits,
+                       texUnit->Current2D, TEXTURE_2D_BIT);
+      texture_override(ctx, texUnit, enableBits,
+                       texUnit->Current1D, TEXTURE_1D_BIT);
+
+      if (!texUnit->_ReallyEnabled) {
+         continue;
+      }
+
+      if (texUnit->_ReallyEnabled)
+         ctx->Texture._EnabledUnits |= (1 << unit);
+
+      if (texUnit->EnvMode == GL_COMBINE) {
+        texUnit->_CurrentCombine = & texUnit->Combine;
+      }
+      else {
+         const struct gl_texture_object *texObj = texUnit->_Current;
+         GLenum format = texObj->Image[0][texObj->BaseLevel]->_BaseFormat;
+         if (format == GL_COLOR_INDEX) {
+            format = GL_RGBA;  /* a bit of a hack */
+         }
+         else if (format == GL_DEPTH_COMPONENT
+                  || format == GL_DEPTH_STENCIL_EXT) {
+            format = texObj->DepthMode;
+         }
+        calculate_derived_texenv(&texUnit->_EnvMode, texUnit->EnvMode, format);
+        texUnit->_CurrentCombine = & texUnit->_EnvMode;
+      }
+
+      switch (texUnit->_CurrentCombine->ModeRGB) {
+      case GL_REPLACE:
+        texUnit->_CurrentCombine->_NumArgsRGB = 1;
+        break;
+      case GL_MODULATE:
+      case GL_ADD:
+      case GL_ADD_SIGNED:
+      case GL_SUBTRACT:
+      case GL_DOT3_RGB:
+      case GL_DOT3_RGBA:
+      case GL_DOT3_RGB_EXT:
+      case GL_DOT3_RGBA_EXT:
+        texUnit->_CurrentCombine->_NumArgsRGB = 2;
+        break;
+      case GL_INTERPOLATE:
+      case GL_MODULATE_ADD_ATI:
+      case GL_MODULATE_SIGNED_ADD_ATI:
+      case GL_MODULATE_SUBTRACT_ATI:
+        texUnit->_CurrentCombine->_NumArgsRGB = 3;
+        break;
+      default:
+        texUnit->_CurrentCombine->_NumArgsRGB = 0;
+         _mesa_problem(ctx, "invalid RGB combine mode in update_texture_state");
+         return;
+      }
+
+      switch (texUnit->_CurrentCombine->ModeA) {
+      case GL_REPLACE:
+        texUnit->_CurrentCombine->_NumArgsA = 1;
+        break;
+      case GL_MODULATE:
+      case GL_ADD:
+      case GL_ADD_SIGNED:
+      case GL_SUBTRACT:
+        texUnit->_CurrentCombine->_NumArgsA = 2;
+        break;
+      case GL_INTERPOLATE:
+      case GL_MODULATE_ADD_ATI:
+      case GL_MODULATE_SIGNED_ADD_ATI:
+      case GL_MODULATE_SUBTRACT_ATI:
+        texUnit->_CurrentCombine->_NumArgsA = 3;
+        break;
+      default:
+        texUnit->_CurrentCombine->_NumArgsA = 0;
+         _mesa_problem(ctx, "invalid Alpha combine mode in update_texture_state");
+        break;
+      }
+
+      if (texUnit->TexGenEnabled) {
+        if (texUnit->TexGenEnabled & S_BIT) {
+           texUnit->_GenFlags |= texUnit->_GenBitS;
+        }
+        if (texUnit->TexGenEnabled & T_BIT) {
+           texUnit->_GenFlags |= texUnit->_GenBitT;
+        }
+        if (texUnit->TexGenEnabled & Q_BIT) {
+           texUnit->_GenFlags |= texUnit->_GenBitQ;
+        }
+        if (texUnit->TexGenEnabled & R_BIT) {
+           texUnit->_GenFlags |= texUnit->_GenBitR;
+        }
+
+        ctx->Texture._TexGenEnabled |= ENABLE_TEXGEN(unit);
+        ctx->Texture._GenFlags |= texUnit->_GenFlags;
+      }
+
+      if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY)
+        ctx->Texture._TexMatEnabled |= ENABLE_TEXMAT(unit);
    }
 
-   switch (target) {
-   case GL_PIXEL_FRAGMENT_RGB_SOURCE_SGIS:
-      if (ctx->Pixel.FragmentRgbSource == (GLenum) value)
-        return;
-      FLUSH_VERTICES(ctx, _NEW_PIXEL);
-      ctx->Pixel.FragmentRgbSource = (GLenum) value;
-      break;
-   case GL_PIXEL_FRAGMENT_ALPHA_SOURCE_SGIS:
-      if (ctx->Pixel.FragmentAlphaSource == (GLenum) value)
-        return;
-      FLUSH_VERTICES(ctx, _NEW_PIXEL);
-      ctx->Pixel.FragmentAlphaSource = (GLenum) value;
-      break;
-   default:
-      _mesa_error(ctx, GL_INVALID_ENUM, "glPixelTexGenParameterSGIS(target)");
-      return;
+   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;
+   }
+   else if (ctx->FragmentProgram._Enabled) {
+      ctx->Texture._EnabledCoordUnits |=
+         (ctx->FragmentProgram.Current->Base.InputsRead >> FRAG_ATTRIB_TEX0);
    }
 }
 
 
-void
-_mesa_PixelTexGenParameterivSGIS(GLenum target, const GLint *value)
+void _mesa_update_texture( GLcontext *ctx, GLuint new_state )
 {
-  _mesa_PixelTexGenParameteriSGIS(target, *value);
+   if (new_state & _NEW_TEXTURE_MATRIX)
+      update_texture_matrices( ctx );
+
+   if (new_state & (_NEW_TEXTURE | _NEW_PROGRAM))
+      update_texture_state( ctx );
 }
 
 
-void
-_mesa_GetPixelTexGenParameterfvSGIS(GLenum target, GLfloat *value)
+/**********************************************************************/
+/*****                      Initialization                        *****/
+/**********************************************************************/
+
+/**
+ * Allocate the proxy textures for the given context.
+ * 
+ * \param ctx the context to allocate proxies for.
+ * 
+ * \return GL_TRUE on success, or GL_FALSE on failure
+ * 
+ * If run out of memory part way through the allocations, clean up and return
+ * GL_FALSE.
+ */
+static GLboolean
+alloc_proxy_textures( GLcontext *ctx )
 {
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
+   ctx->Texture.Proxy1D = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_1D);
+   if (!ctx->Texture.Proxy1D)
+      goto cleanup;
+
+   ctx->Texture.Proxy2D = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_2D);
+   if (!ctx->Texture.Proxy2D)
+      goto cleanup;
+
+   ctx->Texture.Proxy3D = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_3D);
+   if (!ctx->Texture.Proxy3D)
+      goto cleanup;
+
+   ctx->Texture.ProxyCubeMap = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_CUBE_MAP_ARB);
+   if (!ctx->Texture.ProxyCubeMap)
+      goto cleanup;
+
+   ctx->Texture.ProxyRect = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_RECTANGLE_NV);
+   if (!ctx->Texture.ProxyRect)
+      goto cleanup;
+
+   return GL_TRUE;
+
+ cleanup:
+   if (ctx->Texture.Proxy1D)
+      (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy1D);
+   if (ctx->Texture.Proxy2D)
+      (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy2D);
+   if (ctx->Texture.Proxy3D)
+      (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy3D);
+   if (ctx->Texture.ProxyCubeMap)
+      (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.ProxyCubeMap);
+   if (ctx->Texture.ProxyRect)
+      (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.ProxyRect);
+   return GL_FALSE;
+}
 
-   if (target == GL_PIXEL_FRAGMENT_RGB_SOURCE_SGIS) {
-      *value = (GLfloat) ctx->Pixel.FragmentRgbSource;
-   }
-   else if (target == GL_PIXEL_FRAGMENT_ALPHA_SOURCE_SGIS) {
-      *value = (GLfloat) ctx->Pixel.FragmentAlphaSource;
-   }
-   else {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelTexGenParameterfvSGIS(target)");
-   }
+
+/**
+ * Initialize a texture unit.
+ *
+ * \param ctx GL context.
+ * \param unit texture unit number to be initialized.
+ */
+static void
+init_texture_unit( GLcontext *ctx, GLuint unit )
+{
+   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+
+   texUnit->EnvMode = GL_MODULATE;
+   ASSIGN_4V( texUnit->EnvColor, 0.0, 0.0, 0.0, 0.0 );
+
+   texUnit->Combine = default_combine_state;
+   texUnit->_EnvMode = default_combine_state;
+   texUnit->_CurrentCombine = & texUnit->_EnvMode;
+
+   texUnit->TexGenEnabled = 0;
+   texUnit->GenModeS = GL_EYE_LINEAR;
+   texUnit->GenModeT = GL_EYE_LINEAR;
+   texUnit->GenModeR = GL_EYE_LINEAR;
+   texUnit->GenModeQ = GL_EYE_LINEAR;
+   texUnit->_GenBitS = TEXGEN_EYE_LINEAR;
+   texUnit->_GenBitT = TEXGEN_EYE_LINEAR;
+   texUnit->_GenBitR = TEXGEN_EYE_LINEAR;
+   texUnit->_GenBitQ = TEXGEN_EYE_LINEAR;
+
+   /* Yes, these plane coefficients are correct! */
+   ASSIGN_4V( texUnit->ObjectPlaneS, 1.0, 0.0, 0.0, 0.0 );
+   ASSIGN_4V( texUnit->ObjectPlaneT, 0.0, 1.0, 0.0, 0.0 );
+   ASSIGN_4V( texUnit->ObjectPlaneR, 0.0, 0.0, 0.0, 0.0 );
+   ASSIGN_4V( texUnit->ObjectPlaneQ, 0.0, 0.0, 0.0, 0.0 );
+   ASSIGN_4V( texUnit->EyePlaneS, 1.0, 0.0, 0.0, 0.0 );
+   ASSIGN_4V( texUnit->EyePlaneT, 0.0, 1.0, 0.0, 0.0 );
+   ASSIGN_4V( texUnit->EyePlaneR, 0.0, 0.0, 0.0, 0.0 );
+   ASSIGN_4V( texUnit->EyePlaneQ, 0.0, 0.0, 0.0, 0.0 );
+
+   texUnit->Current1D = ctx->Shared->Default1D;
+   texUnit->Current2D = ctx->Shared->Default2D;
+   texUnit->Current3D = ctx->Shared->Default3D;
+   texUnit->CurrentCubeMap = ctx->Shared->DefaultCubeMap;
+   texUnit->CurrentRect = ctx->Shared->DefaultRect;
+}
+
+
+/**
+ * Initialize texture state for the given context.
+ */
+GLboolean
+_mesa_init_texture(GLcontext *ctx)
+{
+   GLuint i;
+
+   assert(MAX_TEXTURE_LEVELS >= MAX_3D_TEXTURE_LEVELS);
+   assert(MAX_TEXTURE_LEVELS >= MAX_CUBE_TEXTURE_LEVELS);
+
+   /* Effectively bind the default textures to all texture units */
+   ctx->Shared->Default1D->RefCount += MAX_TEXTURE_UNITS;
+   ctx->Shared->Default2D->RefCount += MAX_TEXTURE_UNITS;
+   ctx->Shared->Default3D->RefCount += MAX_TEXTURE_UNITS;
+   ctx->Shared->DefaultCubeMap->RefCount += MAX_TEXTURE_UNITS;
+   ctx->Shared->DefaultRect->RefCount += MAX_TEXTURE_UNITS;
+
+   /* Texture group */
+   ctx->Texture.CurrentUnit = 0;      /* multitexture */
+   ctx->Texture._EnabledUnits = 0;
+   for (i=0; i<MAX_TEXTURE_UNITS; i++)
+      init_texture_unit( ctx, i );
+   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;
+
+   return GL_TRUE;
 }
 
 
+/**
+ * Free dynamically-allocted texture data attached to the given context.
+ */
 void
-_mesa_GetPixelTexGenParameterivSGIS(GLenum target, GLint *value)
+_mesa_free_texture_data(GLcontext *ctx)
 {
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
+   GLuint i;
 
-   if (target == GL_PIXEL_FRAGMENT_RGB_SOURCE_SGIS) {
-      *value = (GLint) ctx->Pixel.FragmentRgbSource;
-   }
-   else if (target == GL_PIXEL_FRAGMENT_ALPHA_SOURCE_SGIS) {
-      *value = (GLint) ctx->Pixel.FragmentAlphaSource;
-   }
-   else {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelTexGenParameterivSGIS(target)");
-   }
+   /* Free proxy texture objects */
+   (ctx->Driver.DeleteTexture)(ctx,  ctx->Texture.Proxy1D );
+   (ctx->Driver.DeleteTexture)(ctx,  ctx->Texture.Proxy2D );
+   (ctx->Driver.DeleteTexture)(ctx,  ctx->Texture.Proxy3D );
+   (ctx->Driver.DeleteTexture)(ctx,  ctx->Texture.ProxyCubeMap );
+   (ctx->Driver.DeleteTexture)(ctx,  ctx->Texture.ProxyRect );
+
+   for (i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++)
+      _mesa_free_colortable_data( &ctx->Texture.Unit[i].ColorTable );
+
+   _mesa_TexEnvProgramCacheDestroy( ctx );
 }