Merge branch 'asm-shader-rework-2'
[mesa.git] / src / mesa / main / texstate.c
index 7cddec0bcec719c49dd5dc497ea3197611bb80d8..b9311d0ffc94a5879648399aedf4a55a46999331 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Mesa 3-D graphics library
- * Version:  7.1
+ * Version:  7.5
  *
  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
  *
  */
 
 #include "glheader.h"
+#include "mfeatures.h"
 #include "colormac.h"
-#if FEATURE_colortable
 #include "colortab.h"
-#endif
 #include "context.h"
 #include "enums.h"
 #include "macros.h"
@@ -42,7 +41,6 @@
 #include "texstate.h"
 #include "texenvprogram.h"
 #include "mtypes.h"
-#include "math/m_xform.h"
 
 
 
@@ -69,7 +67,7 @@ static const struct gl_tex_env_combine_state default_combine_state = {
 void
 _mesa_copy_texture_state( const GLcontext *src, GLcontext *dst )
 {
-   GLuint i;
+   GLuint u, tex;
 
    ASSERT(src);
    ASSERT(dst);
@@ -81,57 +79,32 @@ _mesa_copy_texture_state( const GLcontext *src, GLcontext *dst )
    dst->Texture.SharedPalette = src->Texture.SharedPalette;
 
    /* per-unit state */
-   for (i = 0; i < src->Const.MaxTextureImageUnits; i++) {
-      dst->Texture.Unit[i].Enabled = src->Texture.Unit[i].Enabled;
-      dst->Texture.Unit[i].EnvMode = src->Texture.Unit[i].EnvMode;
-      COPY_4V(dst->Texture.Unit[i].EnvColor, src->Texture.Unit[i].EnvColor);
-      dst->Texture.Unit[i].TexGenEnabled = src->Texture.Unit[i].TexGenEnabled;
-      dst->Texture.Unit[i].GenModeS = src->Texture.Unit[i].GenModeS;
-      dst->Texture.Unit[i].GenModeT = src->Texture.Unit[i].GenModeT;
-      dst->Texture.Unit[i].GenModeR = src->Texture.Unit[i].GenModeR;
-      dst->Texture.Unit[i].GenModeQ = src->Texture.Unit[i].GenModeQ;
-      dst->Texture.Unit[i]._GenBitS = src->Texture.Unit[i]._GenBitS;
-      dst->Texture.Unit[i]._GenBitT = src->Texture.Unit[i]._GenBitT;
-      dst->Texture.Unit[i]._GenBitR = src->Texture.Unit[i]._GenBitR;
-      dst->Texture.Unit[i]._GenBitQ = src->Texture.Unit[i]._GenBitQ;
-      dst->Texture.Unit[i]._GenFlags = src->Texture.Unit[i]._GenFlags;
-      COPY_4V(dst->Texture.Unit[i].ObjectPlaneS, src->Texture.Unit[i].ObjectPlaneS);
-      COPY_4V(dst->Texture.Unit[i].ObjectPlaneT, src->Texture.Unit[i].ObjectPlaneT);
-      COPY_4V(dst->Texture.Unit[i].ObjectPlaneR, src->Texture.Unit[i].ObjectPlaneR);
-      COPY_4V(dst->Texture.Unit[i].ObjectPlaneQ, src->Texture.Unit[i].ObjectPlaneQ);
-      COPY_4V(dst->Texture.Unit[i].EyePlaneS, src->Texture.Unit[i].EyePlaneS);
-      COPY_4V(dst->Texture.Unit[i].EyePlaneT, src->Texture.Unit[i].EyePlaneT);
-      COPY_4V(dst->Texture.Unit[i].EyePlaneR, src->Texture.Unit[i].EyePlaneR);
-      COPY_4V(dst->Texture.Unit[i].EyePlaneQ, src->Texture.Unit[i].EyePlaneQ);
-      dst->Texture.Unit[i].LodBias = src->Texture.Unit[i].LodBias;
+   for (u = 0; u < src->Const.MaxTextureImageUnits; u++) {
+      dst->Texture.Unit[u].Enabled = src->Texture.Unit[u].Enabled;
+      dst->Texture.Unit[u].EnvMode = src->Texture.Unit[u].EnvMode;
+      COPY_4V(dst->Texture.Unit[u].EnvColor, src->Texture.Unit[u].EnvColor);
+      dst->Texture.Unit[u].TexGenEnabled = src->Texture.Unit[u].TexGenEnabled;
+      dst->Texture.Unit[u].GenS = src->Texture.Unit[u].GenS;
+      dst->Texture.Unit[u].GenT = src->Texture.Unit[u].GenT;
+      dst->Texture.Unit[u].GenR = src->Texture.Unit[u].GenR;
+      dst->Texture.Unit[u].GenQ = src->Texture.Unit[u].GenQ;
+      dst->Texture.Unit[u].LodBias = src->Texture.Unit[u].LodBias;
 
       /* GL_EXT_texture_env_combine */
-      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;
+      dst->Texture.Unit[u].Combine = src->Texture.Unit[u].Combine;
+
+      /* GL_ATI_envmap_bumpmap - need this? */
+      dst->Texture.Unit[u].BumpTarget = src->Texture.Unit[u].BumpTarget;
+      COPY_4V(dst->Texture.Unit[u].RotMatrix, src->Texture.Unit[u].RotMatrix);
+
 
       /* copy texture object bindings, not contents of texture objects */
       _mesa_lock_context_textures(dst);
 
-      _mesa_reference_texobj(&dst->Texture.Unit[i].Current1D,
-                             src->Texture.Unit[i].Current1D);
-      _mesa_reference_texobj(&dst->Texture.Unit[i].Current2D,
-                             src->Texture.Unit[i].Current2D);
-      _mesa_reference_texobj(&dst->Texture.Unit[i].Current3D,
-                             src->Texture.Unit[i].Current3D);
-      _mesa_reference_texobj(&dst->Texture.Unit[i].CurrentCubeMap,
-                             src->Texture.Unit[i].CurrentCubeMap);
-      _mesa_reference_texobj(&dst->Texture.Unit[i].CurrentRect,
-                             src->Texture.Unit[i].CurrentRect);
-      _mesa_reference_texobj(&dst->Texture.Unit[i].Current1DArray,
-                             src->Texture.Unit[i].Current1DArray);
-      _mesa_reference_texobj(&dst->Texture.Unit[i].Current2DArray,
-                             src->Texture.Unit[i].Current2DArray);
+      for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
+         _mesa_reference_texobj(&dst->Texture.Unit[u].CurrentTex[tex],
+                                src->Texture.Unit[u].CurrentTex[tex]);
+      }
 
       _mesa_unlock_context_textures(dst);
    }
@@ -204,11 +177,14 @@ calculate_derived_texenv( struct gl_tex_env_combine_state *state,
    case GL_LUMINANCE:
    case GL_RGB:
    case GL_YCBCR_MESA:
+   case GL_DUDV_ATI:
       state->SourceA[0] = GL_PREVIOUS;
       break;
       
    default:
-      _mesa_problem(NULL, "Invalid texBaseFormat in calculate_derived_texenv");
+      _mesa_problem(NULL,
+                    "Invalid texBaseFormat 0x%x in calculate_derived_texenv",
+                    texBaseFormat);
       return;
    }
 
@@ -241,6 +217,7 @@ calculate_derived_texenv( struct gl_tex_env_combine_state *state,
         break;
       case GL_RGB:
       case GL_YCBCR_MESA:
+      case GL_DUDV_ATI:
         mode_rgb = GL_REPLACE;
         break;
       case GL_RGBA:
@@ -267,6 +244,7 @@ calculate_derived_texenv( struct gl_tex_env_combine_state *state,
       case GL_LUMINANCE_ALPHA:
       case GL_RGBA:
       case GL_YCBCR_MESA:
+      case GL_DUDV_ATI:
         state->SourceRGB[2] = GL_TEXTURE;
         state->SourceA[2]   = GL_TEXTURE;
         state->SourceRGB[0] = GL_CONSTANT;
@@ -282,7 +260,8 @@ calculate_derived_texenv( struct gl_tex_env_combine_state *state,
 
    default:
       _mesa_problem(NULL,
-                    "Invalid texture env mode in calculate_derived_texenv");
+                    "Invalid texture env mode 0x%x in calculate_derived_texenv",
+                    mode);
       return;
    }
    
@@ -364,84 +343,119 @@ _mesa_ClientActiveTextureARB(GLenum texture)
 static void
 update_texture_matrices( GLcontext *ctx )
 {
-   GLuint i;
+   GLuint u;
 
-   ctx->Texture._TexMatEnabled = 0;
+   ctx->Texture._TexMatEnabled = 0x0;
 
-   for (i=0; i < ctx->Const.MaxTextureCoordUnits; i++) {
-      if (_math_matrix_is_dirty(ctx->TextureMatrixStack[i].Top)) {
-        _math_matrix_analyse( ctx->TextureMatrixStack[i].Top );
+   for (u = 0; u < ctx->Const.MaxTextureCoordUnits; u++) {
+      if (_math_matrix_is_dirty(ctx->TextureMatrixStack[u].Top)) {
+        _math_matrix_analyse( ctx->TextureMatrixStack[u].Top );
 
-        if (ctx->Texture.Unit[i]._ReallyEnabled &&
-            ctx->TextureMatrixStack[i].Top->type != MATRIX_IDENTITY)
-           ctx->Texture._TexMatEnabled |= ENABLE_TEXMAT(i);
+        if (ctx->Texture.Unit[u]._ReallyEnabled &&
+            ctx->TextureMatrixStack[u].Top->type != MATRIX_IDENTITY)
+           ctx->Texture._TexMatEnabled |= ENABLE_TEXMAT(u);
 
         if (ctx->Driver.TextureMatrix)
-           ctx->Driver.TextureMatrix( ctx, i, ctx->TextureMatrixStack[i].Top);
+           ctx->Driver.TextureMatrix( ctx, u, ctx->TextureMatrixStack[u].Top);
       }
    }
 }
 
 
 /**
- * Update texture object's _Function field.  We need to do this
- * whenever any of the texture object's shadow-related fields change
- * or when we start/stop using a fragment program.
- *
- * This function could be expanded someday to update additional per-object
- * fields that depend on assorted state changes.
+ * Examine texture unit's combine/env state to update derived state.
  */
 static void
-update_texture_compare_function(GLcontext *ctx,
-                                struct gl_texture_object *tObj)
+update_tex_combine(GLcontext *ctx, struct gl_texture_unit *texUnit)
 {
-   /* XXX temporarily disable this test since it breaks the GLSL
-    * shadow2D(), etc. functions.
+   struct gl_tex_env_combine_state *combine;
+
+   /* Set the texUnit->_CurrentCombine field to point to the user's combiner
+    * state, or the combiner state which is derived from traditional texenv
+    * mode.
     */
-   if (0 /*ctx->FragmentProgram._Current*/) {
-      /* Texel/coordinate comparison is ignored for programs.
-       * See GL_ARB_fragment_program/shader spec for details.
-       */
-      tObj->_Function = GL_NONE;
+   if (texUnit->EnvMode == GL_COMBINE ||
+       texUnit->EnvMode == GL_COMBINE4_NV) {
+      texUnit->_CurrentCombine = & texUnit->Combine;
    }
-   else if (tObj->CompareFlag) {
-      /* GL_SGIX_shadow */
-      if (tObj->CompareOperator == GL_TEXTURE_LEQUAL_R_SGIX) {
-         tObj->_Function = GL_LEQUAL;
+   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 {
-         ASSERT(tObj->CompareOperator == GL_TEXTURE_GEQUAL_R_SGIX);
-         tObj->_Function = GL_GEQUAL;
+      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;
    }
-   else if (tObj->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB) {
-      /* GL_ARB_shadow */
-      tObj->_Function = tObj->CompareFunc;
-   }
-   else {
-      tObj->_Function = GL_NONE;  /* pass depth through as grayscale */
-   }
-}
 
+   combine = texUnit->_CurrentCombine;
 
-/**
- * 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)
-{
-   if (!texUnit->_ReallyEnabled && (enableBits & textureBit)) {
-      if (!texObj->_Complete) {
-         _mesa_test_texobj_completeness(ctx, texObj);
-      }
-      if (texObj->_Complete) {
-         texUnit->_ReallyEnabled = textureBit;
-         texUnit->_Current = texObj;
-         update_texture_compare_function(ctx, texObj);
-      }
+   /* Determine number of source RGB terms in the combiner function */
+   switch (combine->ModeRGB) {
+   case GL_REPLACE:
+      combine->_NumArgsRGB = 1;
+      break;
+   case GL_ADD:
+   case GL_ADD_SIGNED:
+      if (texUnit->EnvMode == GL_COMBINE4_NV)
+         combine->_NumArgsRGB = 4;
+      else
+         combine->_NumArgsRGB = 2;
+      break;
+   case GL_MODULATE:
+   case GL_SUBTRACT:
+   case GL_DOT3_RGB:
+   case GL_DOT3_RGBA:
+   case GL_DOT3_RGB_EXT:
+   case GL_DOT3_RGBA_EXT:
+      combine->_NumArgsRGB = 2;
+      break;
+   case GL_INTERPOLATE:
+   case GL_MODULATE_ADD_ATI:
+   case GL_MODULATE_SIGNED_ADD_ATI:
+   case GL_MODULATE_SUBTRACT_ATI:
+      combine->_NumArgsRGB = 3;
+      break;
+   case GL_BUMP_ENVMAP_ATI:
+      /* no real arguments for this case */
+      combine->_NumArgsRGB = 0;
+      break;
+   default:
+      combine->_NumArgsRGB = 0;
+      _mesa_problem(ctx, "invalid RGB combine mode in update_texture_state");
+      return;
+   }
+
+   /* Determine number of source Alpha terms in the combiner function */
+   switch (combine->ModeA) {
+   case GL_REPLACE:
+      combine->_NumArgsA = 1;
+      break;
+   case GL_ADD:
+   case GL_ADD_SIGNED:
+      if (texUnit->EnvMode == GL_COMBINE4_NV)
+         combine->_NumArgsA = 4;
+      else
+         combine->_NumArgsA = 2;
+      break;
+   case GL_MODULATE:
+   case GL_SUBTRACT:
+      combine->_NumArgsA = 2;
+      break;
+   case GL_INTERPOLATE:
+   case GL_MODULATE_ADD_ATI:
+   case GL_MODULATE_SIGNED_ADD_ATI:
+   case GL_MODULATE_SUBTRACT_ATI:
+      combine->_NumArgsA = 3;
+      break;
+   default:
+      combine->_NumArgsA = 0;
+      _mesa_problem(ctx, "invalid Alpha combine mode in update_texture_state");
+      break;
    }
 }
 
@@ -460,6 +474,7 @@ update_texture_state( GLcontext *ctx )
    GLuint unit;
    struct gl_fragment_program *fprog = NULL;
    struct gl_vertex_program *vprog = NULL;
+   GLbitfield enabledFragUnits = 0x0;
 
    if (ctx->Shader.CurrentProgram &&
        ctx->Shader.CurrentProgram->LinkStatus) {
@@ -478,156 +493,98 @@ update_texture_state( GLcontext *ctx )
       }
    }
 
-   ctx->NewState |= _NEW_TEXTURE; /* TODO: only set this if there are 
-                                  * actual changes. 
-                                  */
+   /* TODO: only set this if there are actual changes */
+   ctx->NewState |= _NEW_TEXTURE;
 
-   ctx->Texture._EnabledUnits = 0;
-   ctx->Texture._GenFlags = 0;
-   ctx->Texture._TexMatEnabled = 0;
-   ctx->Texture._TexGenEnabled = 0;
+   ctx->Texture._EnabledUnits = 0x0;
+   ctx->Texture._GenFlags = 0x0;
+   ctx->Texture._TexMatEnabled = 0x0;
+   ctx->Texture._TexGenEnabled = 0x0;
 
    /*
     * Update texture unit state.
     */
    for (unit = 0; unit < ctx->Const.MaxTextureImageUnits; unit++) {
       struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
-      GLbitfield enableBits;
+      GLbitfield enabledVertTargets = 0x0;
+      GLbitfield enabledFragTargets = 0x0;
+      GLbitfield enabledTargets = 0x0;
+      GLuint texIndex;
 
-      texUnit->_Current = NULL;
-      texUnit->_ReallyEnabled = 0;
-      texUnit->_GenFlags = 0;
-
-      /* Get the bitmask of texture enables.
+      /* Get the bitmask of texture target enables.
        * enableBits will be a mask of the TEXTURE_*_BIT flags indicating
        * which texture targets are enabled (fixed function) or referenced
        * by a fragment shader/program.  When multiple flags are set, we'll
-       * settle on the one with highest priority (see texture_override below).
+       * settle on the one with highest priority (see below).
        */
-      if (fprog || vprog) {
-         enableBits = 0x0;
-         if (fprog)
-            enableBits |= fprog->Base.TexturesUsed[unit];
-         if (vprog)
-            enableBits |= vprog->Base.TexturesUsed[unit];
+      if (vprog) {
+         enabledVertTargets |= vprog->Base.TexturesUsed[unit];
+      }
+
+      if (fprog) {
+         enabledFragTargets |= fprog->Base.TexturesUsed[unit];
       }
       else {
-         if (!texUnit->Enabled)
-            continue;
-         enableBits = texUnit->Enabled;
+         /* fixed-function fragment program */
+         enabledFragTargets |= texUnit->Enabled;
       }
 
-      ASSERT(texUnit->Current1D);
-      ASSERT(texUnit->Current2D);
-      ASSERT(texUnit->Current3D);
-      ASSERT(texUnit->CurrentCubeMap);
-      ASSERT(texUnit->CurrentRect);
-      ASSERT(texUnit->Current1DArray);
-      ASSERT(texUnit->Current2DArray);
-
-      /* 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->Current2DArray, TEXTURE_2D_ARRAY_BIT);
-      texture_override(ctx, texUnit, enableBits,
-                       texUnit->Current1DArray, TEXTURE_1D_ARRAY_BIT);
-      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);
+      enabledTargets = enabledVertTargets | enabledFragTargets;
 
-      if (!texUnit->_ReallyEnabled) {
+      texUnit->_ReallyEnabled = 0x0;
+
+      if (enabledTargets == 0x0) {
+         /* neither vertex nor fragment processing uses this unit */
          continue;
       }
 
-      if (texUnit->_ReallyEnabled)
-         ctx->Texture._EnabledUnits |= (1 << unit);
-
-      if (texUnit->EnvMode == GL_COMBINE ||
-          texUnit->EnvMode == GL_COMBINE4_NV) {
-        texUnit->_CurrentCombine = & texUnit->Combine;
+      /* Look for the highest priority texture target that's enabled (or used
+       * by the vert/frag shaders) and "complete".  That's the one we'll use
+       * for texturing.  If we're using vert/frag program we're guaranteed
+       * that bitcount(enabledBits) <= 1.
+       * Note that the TEXTURE_x_INDEX values are in high to low priority.
+       */
+      for (texIndex = 0; texIndex < NUM_TEXTURE_TARGETS; texIndex++) {
+         if (enabledTargets & (1 << texIndex)) {
+            struct gl_texture_object *texObj = texUnit->CurrentTex[texIndex];
+            if (!texObj->_Complete) {
+               _mesa_test_texobj_completeness(ctx, texObj);
+            }
+            if (texObj->_Complete) {
+               texUnit->_ReallyEnabled = 1 << texIndex;
+               _mesa_reference_texobj(&texUnit->_Current, texObj);
+               break;
+            }
+         }
       }
-      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 */
+
+      if (!texUnit->_ReallyEnabled) {
+         if (fprog) {
+            /* If we get here it means the shader is expecting a texture
+             * object, but there isn't one (or it's incomplete).  Use the
+             * fallback texture.
+             */
+            struct gl_texture_object *texObj = _mesa_get_fallback_texture(ctx);
+            texUnit->_ReallyEnabled = 1 << TEXTURE_2D_INDEX;
+            _mesa_reference_texobj(&texUnit->_Current, texObj);
          }
-         else if (format == GL_DEPTH_COMPONENT
-                  || format == GL_DEPTH_STENCIL_EXT) {
-            format = texObj->DepthMode;
+         else {
+            /* fixed-function: texture unit is really disabled */
+            continue;
          }
-        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_ADD:
-      case GL_ADD_SIGNED:
-         if (texUnit->EnvMode == GL_COMBINE4_NV)
-            texUnit->_CurrentCombine->_NumArgsRGB = 4;
-         else
-            texUnit->_CurrentCombine->_NumArgsRGB = 2;
-         break;
-      case GL_MODULATE:
-      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;
-      }
+      /* if we get here, we know this texture unit is enabled */
 
-      switch (texUnit->_CurrentCombine->ModeA) {
-      case GL_REPLACE:
-        texUnit->_CurrentCombine->_NumArgsA = 1;
-        break;
-      case GL_ADD:
-      case GL_ADD_SIGNED:
-         if (texUnit->EnvMode == GL_COMBINE4_NV)
-            texUnit->_CurrentCombine->_NumArgsA = 4;
-         else
-            texUnit->_CurrentCombine->_NumArgsA = 2;
-         break;
-      case GL_MODULATE:
-      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;
-      }
+      ctx->Texture._EnabledUnits |= (1 << unit);
+
+      if (enabledFragTargets)
+         enabledFragUnits |= (1 << unit);
+
+      update_tex_combine(ctx, texUnit);
    }
 
+
    /* Determine which texture coordinate sets are actually needed */
    if (fprog) {
       const GLuint coordMask = (1 << MAX_TEXTURE_COORD_UNITS) - 1;
@@ -635,28 +592,30 @@ update_texture_state( GLcontext *ctx )
          = (fprog->Base.InputsRead >> FRAG_ATTRIB_TEX0) & coordMask;
    }
    else {
-      ctx->Texture._EnabledCoordUnits = ctx->Texture._EnabledUnits;
+      ctx->Texture._EnabledCoordUnits = enabledFragUnits;
    }
 
    /* Setup texgen for those texture coordinate sets that are in use */
    for (unit = 0; unit < ctx->Const.MaxTextureCoordUnits; unit++) {
       struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
 
+      texUnit->_GenFlags = 0x0;
+
       if (!(ctx->Texture._EnabledCoordUnits & (1 << unit)))
         continue;
 
       if (texUnit->TexGenEnabled) {
         if (texUnit->TexGenEnabled & S_BIT) {
-           texUnit->_GenFlags |= texUnit->_GenBitS;
+           texUnit->_GenFlags |= texUnit->GenS._ModeBit;
         }
         if (texUnit->TexGenEnabled & T_BIT) {
-           texUnit->_GenFlags |= texUnit->_GenBitT;
-        }
-        if (texUnit->TexGenEnabled & Q_BIT) {
-           texUnit->_GenFlags |= texUnit->_GenBitQ;
+           texUnit->_GenFlags |= texUnit->GenT._ModeBit;
         }
         if (texUnit->TexGenEnabled & R_BIT) {
-           texUnit->_GenFlags |= texUnit->_GenBitR;
+           texUnit->_GenFlags |= texUnit->GenR._ModeBit;
+        }
+        if (texUnit->TexGenEnabled & Q_BIT) {
+           texUnit->_GenFlags |= texUnit->GenQ._ModeBit;
         }
 
         ctx->Texture._TexGenEnabled |= ENABLE_TEXGEN(unit);
@@ -739,6 +698,7 @@ static void
 init_texture_unit( GLcontext *ctx, GLuint unit )
 {
    struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+   GLuint tex;
 
    texUnit->EnvMode = GL_MODULATE;
    ASSIGN_4V( texUnit->EnvColor, 0.0, 0.0, 0.0, 0.0 );
@@ -746,35 +706,36 @@ init_texture_unit( GLcontext *ctx, GLuint unit )
    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;
+   texUnit->BumpTarget = GL_TEXTURE0;
+
+   texUnit->TexGenEnabled = 0x0;
+   texUnit->GenS.Mode = GL_EYE_LINEAR;
+   texUnit->GenT.Mode = GL_EYE_LINEAR;
+   texUnit->GenR.Mode = GL_EYE_LINEAR;
+   texUnit->GenQ.Mode = GL_EYE_LINEAR;
+   texUnit->GenS._ModeBit = TEXGEN_EYE_LINEAR;
+   texUnit->GenT._ModeBit = TEXGEN_EYE_LINEAR;
+   texUnit->GenR._ModeBit = TEXGEN_EYE_LINEAR;
+   texUnit->GenQ._ModeBit = 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 );
+   ASSIGN_4V( texUnit->GenS.ObjectPlane, 1.0, 0.0, 0.0, 0.0 );
+   ASSIGN_4V( texUnit->GenT.ObjectPlane, 0.0, 1.0, 0.0, 0.0 );
+   ASSIGN_4V( texUnit->GenR.ObjectPlane, 0.0, 0.0, 0.0, 0.0 );
+   ASSIGN_4V( texUnit->GenQ.ObjectPlane, 0.0, 0.0, 0.0, 0.0 );
+   ASSIGN_4V( texUnit->GenS.EyePlane, 1.0, 0.0, 0.0, 0.0 );
+   ASSIGN_4V( texUnit->GenT.EyePlane, 0.0, 1.0, 0.0, 0.0 );
+   ASSIGN_4V( texUnit->GenR.EyePlane, 0.0, 0.0, 0.0, 0.0 );
+   ASSIGN_4V( texUnit->GenQ.EyePlane, 0.0, 0.0, 0.0, 0.0 );
+
+   /* no mention of this in spec, but maybe id matrix expected? */
+   ASSIGN_4V( texUnit->RotMatrix, 1.0, 0.0, 0.0, 1.0 );
 
    /* initialize current texture object ptrs to the shared default objects */
-   _mesa_reference_texobj(&texUnit->Current1D, ctx->Shared->Default1D);
-   _mesa_reference_texobj(&texUnit->Current2D, ctx->Shared->Default2D);
-   _mesa_reference_texobj(&texUnit->Current3D, ctx->Shared->Default3D);
-   _mesa_reference_texobj(&texUnit->CurrentCubeMap, ctx->Shared->DefaultCubeMap);
-   _mesa_reference_texobj(&texUnit->CurrentRect, ctx->Shared->DefaultRect);
-   _mesa_reference_texobj(&texUnit->Current1DArray, ctx->Shared->Default1DArray);
-   _mesa_reference_texobj(&texUnit->Current2DArray, ctx->Shared->Default2DArray);
+   for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
+      _mesa_reference_texobj(&texUnit->CurrentTex[tex],
+                             ctx->Shared->DefaultTex[tex]);
+   }
 }
 
 
@@ -784,26 +745,22 @@ init_texture_unit( GLcontext *ctx, GLuint unit )
 GLboolean
 _mesa_init_texture(GLcontext *ctx)
 {
-   GLuint i;
-
-   assert(MAX_TEXTURE_LEVELS >= MAX_3D_TEXTURE_LEVELS);
-   assert(MAX_TEXTURE_LEVELS >= MAX_CUBE_TEXTURE_LEVELS);
+   GLuint u;
 
    /* Texture group */
    ctx->Texture.CurrentUnit = 0;      /* multitexture */
-   ctx->Texture._EnabledUnits = 0;
+   ctx->Texture._EnabledUnits = 0x0;
    ctx->Texture.SharedPalette = GL_FALSE;
-#if FEATURE_colortable
    _mesa_init_colortable(&ctx->Texture.Palette);
-#endif
 
-   for (i = 0; i < MAX_TEXTURE_UNITS; i++)
-      init_texture_unit( ctx, i );
+   for (u = 0; u < MAX_TEXTURE_UNITS; u++)
+      init_texture_unit(ctx, u);
 
    /* After we're done initializing the context's texture state the default
     * texture objects' refcounts should be at least MAX_TEXTURE_UNITS + 1.
     */
-   assert(ctx->Shared->Default1D->RefCount >= MAX_TEXTURE_UNITS + 1);
+   assert(ctx->Shared->DefaultTex[TEXTURE_1D_INDEX]->RefCount
+          >= MAX_TEXTURE_UNITS + 1);
 
    /* Allocate proxy textures */
    if (!alloc_proxy_textures( ctx ))
@@ -823,27 +780,20 @@ _mesa_free_texture_data(GLcontext *ctx)
 
    /* unreference current textures */
    for (u = 0; u < MAX_TEXTURE_IMAGE_UNITS; u++) {
-      struct gl_texture_unit *unit = ctx->Texture.Unit + u;
-      _mesa_reference_texobj(&unit->Current1D, NULL);
-      _mesa_reference_texobj(&unit->Current2D, NULL);
-      _mesa_reference_texobj(&unit->Current3D, NULL);
-      _mesa_reference_texobj(&unit->CurrentCubeMap, NULL);
-      _mesa_reference_texobj(&unit->CurrentRect, NULL);
-      _mesa_reference_texobj(&unit->Current1DArray, NULL);
-      _mesa_reference_texobj(&unit->Current2DArray, NULL);
+      /* The _Current texture could account for another reference */
+      _mesa_reference_texobj(&ctx->Texture.Unit[u]._Current, NULL);
+
+      for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
+         _mesa_reference_texobj(&ctx->Texture.Unit[u].CurrentTex[tgt], NULL);
+      }
    }
 
    /* Free proxy texture objects */
    for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++)
       ctx->Driver.DeleteTexture(ctx, ctx->Texture.ProxyTex[tgt]);
 
-#if FEATURE_colortable
-   {
-      GLuint i;
-      for (i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++)
-         _mesa_free_colortable_data( &ctx->Texture.Unit[i].ColorTable );
-   }
-#endif
+   for (u = 0; u < MAX_TEXTURE_IMAGE_UNITS; u++)
+      _mesa_free_colortable_data(&ctx->Texture.Unit[u].ColorTable);
 }
 
 
@@ -855,17 +805,13 @@ _mesa_free_texture_data(GLcontext *ctx)
 void
 _mesa_update_default_objects_texture(GLcontext *ctx)
 {
-   GLuint i;
-
-   for (i = 0; i < MAX_TEXTURE_UNITS; i++) {
-      struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
-
-      _mesa_reference_texobj(&texUnit->Current1D, ctx->Shared->Default1D);
-      _mesa_reference_texobj(&texUnit->Current2D, ctx->Shared->Default2D);
-      _mesa_reference_texobj(&texUnit->Current3D, ctx->Shared->Default3D);
-      _mesa_reference_texobj(&texUnit->CurrentCubeMap, ctx->Shared->DefaultCubeMap);
-      _mesa_reference_texobj(&texUnit->CurrentRect, ctx->Shared->DefaultRect);
-      _mesa_reference_texobj(&texUnit->Current1DArray, ctx->Shared->Default1DArray);
-      _mesa_reference_texobj(&texUnit->Current2DArray, ctx->Shared->Default2DArray);
+   GLuint u, tex;
+
+   for (u = 0; u < MAX_TEXTURE_UNITS; u++) {
+      struct gl_texture_unit *texUnit = &ctx->Texture.Unit[u];
+      for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
+         _mesa_reference_texobj(&texUnit->CurrentTex[tex],
+                                ctx->Shared->DefaultTex[tex]);
+      }
    }
 }