[03/13] mesa: separate legacy stuff from gl_texture_unit into gl_fixedfunc_texture_unit

Submitted by Marek Olšák on Feb. 9, 2018, 1:18 a.m.

Details

Message ID 1518139128-20324-3-git-send-email-maraeo@gmail.com
State New
Headers show
Series "Series without cover letter" ( rev: 1 ) in Mesa

Not browsing as part of any series.

Commit Message

Marek Olšák Feb. 9, 2018, 1:18 a.m.
From: Marek Olšák <marek.olsak@amd.com>

---
 src/mesa/drivers/common/meta.c                  | 18 +++---
 src/mesa/drivers/dri/i915/i830_texblend.c       |  3 +-
 src/mesa/drivers/dri/nouveau/nouveau_util.h     |  2 +-
 src/mesa/drivers/dri/nouveau/nv04_context.c     | 14 +++--
 src/mesa/drivers/dri/nouveau/nv04_state_frag.c  |  6 +-
 src/mesa/drivers/dri/nouveau/nv10_state_frag.c  |  4 +-
 src/mesa/drivers/dri/nouveau/nv10_state_tex.c   |  5 +-
 src/mesa/drivers/dri/nouveau/nv20_state_tex.c   |  3 +-
 src/mesa/drivers/dri/r200/r200_tex.c            |  3 +-
 src/mesa/drivers/dri/r200/r200_texstate.c       | 31 +++++----
 src/mesa/drivers/dri/radeon/radeon_maos_verts.c |  2 +-
 src/mesa/drivers/dri/radeon/radeon_state.c      |  2 +-
 src/mesa/drivers/dri/radeon/radeon_tex.c        |  3 +-
 src/mesa/drivers/dri/radeon/radeon_texstate.c   | 13 ++--
 src/mesa/main/attrib.c                          | 17 ++---
 src/mesa/main/context.c                         |  6 +-
 src/mesa/main/enable.c                          | 23 ++++---
 src/mesa/main/ff_fragment_shader.cpp            |  3 +-
 src/mesa/main/ffvertex_prog.c                   |  3 +-
 src/mesa/main/get.c                             |  7 ++-
 src/mesa/main/get_hash_params.py                | 10 +--
 src/mesa/main/mtypes.h                          | 40 +++++++-----
 src/mesa/main/rastpos.c                         |  5 +-
 src/mesa/main/texenv.c                          | 40 +++++++-----
 src/mesa/main/texgen.c                          | 18 +++---
 src/mesa/main/texstate.c                        | 83 ++++++++++++++-----------
 src/mesa/main/texstate.h                        | 15 +++++
 src/mesa/program/prog_statevars.c               | 20 +++---
 src/mesa/swrast/s_context.c                     |  2 +-
 src/mesa/swrast/s_texcombine.c                  |  3 +-
 src/mesa/swrast/s_triangle.c                    | 10 +--
 src/mesa/tnl/t_vb_texgen.c                      | 10 +--
 32 files changed, 250 insertions(+), 174 deletions(-)

Patch hide | download patch | download mbox

diff --git a/src/mesa/drivers/common/meta.c b/src/mesa/drivers/common/meta.c
index a7dd139..cd898e2 100644
--- a/src/mesa/drivers/common/meta.c
+++ b/src/mesa/drivers/common/meta.c
@@ -624,28 +624,28 @@  _mesa_meta_begin(struct gl_context *ctx, GLbitfield state)
       save->Stencil = ctx->Stencil; /* struct copy */
       if (ctx->Stencil.Enabled)
          _mesa_set_enable(ctx, GL_STENCIL_TEST, GL_FALSE);
       /* NOTE: other stencil state not reset */
    }
 
    if (state & MESA_META_TEXTURE) {
       GLuint u, tgt;
 
       save->ActiveUnit = ctx->Texture.CurrentUnit;
-      save->EnvMode = ctx->Texture.Unit[0].EnvMode;
+      save->EnvMode = ctx->Texture.FixedFuncUnit[0].EnvMode;
 
       /* Disable all texture units */
       for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
-         save->TexEnabled[u] = ctx->Texture.Unit[u].Enabled;
-         save->TexGenEnabled[u] = ctx->Texture.Unit[u].TexGenEnabled;
-         if (ctx->Texture.Unit[u].Enabled ||
-             ctx->Texture.Unit[u].TexGenEnabled) {
+         save->TexEnabled[u] = ctx->Texture.FixedFuncUnit[u].Enabled;
+         save->TexGenEnabled[u] = ctx->Texture.FixedFuncUnit[u].TexGenEnabled;
+         if (ctx->Texture.FixedFuncUnit[u].Enabled ||
+             ctx->Texture.FixedFuncUnit[u].TexGenEnabled) {
             _mesa_ActiveTexture(GL_TEXTURE0 + u);
             _mesa_set_enable(ctx, GL_TEXTURE_2D, GL_FALSE);
             if (ctx->Extensions.ARB_texture_cube_map)
                _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE);
 
             _mesa_set_enable(ctx, GL_TEXTURE_1D, GL_FALSE);
             _mesa_set_enable(ctx, GL_TEXTURE_3D, GL_FALSE);
             if (ctx->Extensions.NV_texture_rectangle)
                _mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE, GL_FALSE);
             _mesa_set_enable(ctx, GL_TEXTURE_GEN_S, GL_FALSE);
@@ -1058,28 +1058,28 @@  _mesa_meta_end(struct gl_context *ctx)
          if (ctx->Texture.Unit[0].CurrentTex[tgt] != save->CurrentTexture[tgt]) {
             FLUSH_VERTICES(ctx, _NEW_TEXTURE);
             _mesa_reference_texobj(&ctx->Texture.Unit[0].CurrentTex[tgt],
                                    save->CurrentTexture[tgt]);
          }
          _mesa_reference_texobj(&save->CurrentTexture[tgt], NULL);
       }
 
       /* Restore fixed function texture enables, texgen */
       for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
-         if (ctx->Texture.Unit[u].Enabled != save->TexEnabled[u]) {
+         if (ctx->Texture.FixedFuncUnit[u].Enabled != save->TexEnabled[u]) {
             FLUSH_VERTICES(ctx, _NEW_TEXTURE);
-            ctx->Texture.Unit[u].Enabled = save->TexEnabled[u];
+            ctx->Texture.FixedFuncUnit[u].Enabled = save->TexEnabled[u];
          }
 
-         if (ctx->Texture.Unit[u].TexGenEnabled != save->TexGenEnabled[u]) {
+         if (ctx->Texture.FixedFuncUnit[u].TexGenEnabled != save->TexGenEnabled[u]) {
             FLUSH_VERTICES(ctx, _NEW_TEXTURE);
-            ctx->Texture.Unit[u].TexGenEnabled = save->TexGenEnabled[u];
+            ctx->Texture.FixedFuncUnit[u].TexGenEnabled = save->TexGenEnabled[u];
          }
       }
 
       /* restore current unit state */
       _mesa_ActiveTexture(GL_TEXTURE0 + save->ActiveUnit);
    }
 
    if (state & MESA_META_TRANSFORM) {
       GLuint activeTexture = ctx->Texture.CurrentUnit;
       _mesa_ActiveTexture(GL_TEXTURE0);
diff --git a/src/mesa/drivers/dri/i915/i830_texblend.c b/src/mesa/drivers/dri/i915/i830_texblend.c
index 15d6d54..390a54f 100644
--- a/src/mesa/drivers/dri/i915/i830_texblend.c
+++ b/src/mesa/drivers/dri/i915/i830_texblend.c
@@ -381,21 +381,22 @@  i830SetTexEnvCombine(struct i830_context * i830,
       return emit_factor(blendUnit, state, used, factor);
    else
       return used;
 }
 
 
 static void
 emit_texblend(struct i830_context *i830, GLuint unit, GLuint blendUnit,
               bool last_stage)
 {
-   struct gl_texture_unit *texUnit = &i830->intel.ctx.Texture.Unit[unit];
+   struct gl_fixedfunc_texture_unit *texUnit =
+      &i830->intel.ctx.Texture.FixedFuncUnit[unit];
    GLuint tmp[I830_TEXBLEND_SIZE], tmp_sz;
 
 
    if (0)
       fprintf(stderr, "%s unit %d\n", __func__, unit);
 
    /* Update i830->state.TexBlend
     */
    tmp_sz = i830SetTexEnvCombine(i830, texUnit->_CurrentCombine, blendUnit,
                                  GetTexelOp(unit), tmp, texUnit->EnvColor);
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_util.h b/src/mesa/drivers/dri/nouveau/nouveau_util.h
index 8087445..088a256 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_util.h
+++ b/src/mesa/drivers/dri/nouveau/nouveau_util.h
@@ -186,21 +186,21 @@  is_negative_operand(int op)
 	return op == GL_ONE_MINUS_SRC_COLOR || op == GL_ONE_MINUS_SRC_ALPHA;
 }
 
 static inline GLboolean
 is_texture_source(int s)
 {
 	return s == GL_TEXTURE || (s >= GL_TEXTURE0 && s <= GL_TEXTURE31);
 }
 
 static inline struct gl_texgen *
-get_texgen_coord(struct gl_texture_unit *u, int i)
+get_texgen_coord(struct gl_fixedfunc_texture_unit *u, int i)
 {
 	return ((struct gl_texgen *[])
 		{ &u->GenS, &u->GenT, &u->GenR, &u->GenQ }) [i];
 }
 
 static inline float *
 get_texgen_coeff(struct gl_texgen *c)
 {
 	if (c->Mode == GL_OBJECT_LINEAR)
 		return c->ObjectPlane;
diff --git a/src/mesa/drivers/dri/nouveau/nv04_context.c b/src/mesa/drivers/dri/nouveau/nv04_context.c
index 4dbb950..324595e 100644
--- a/src/mesa/drivers/dri/nouveau/nv04_context.c
+++ b/src/mesa/drivers/dri/nouveau/nv04_context.c
@@ -25,43 +25,45 @@ 
  */
 
 #include "nouveau_driver.h"
 #include "nouveau_context.h"
 #include "nouveau_fbo.h"
 #include "nouveau_util.h"
 #include "nv04_3d.xml.h"
 #include "nv04_driver.h"
 
 static GLboolean
-texunit_needs_combiners(struct gl_texture_unit *u)
+texunit_needs_combiners(struct gl_texture_unit *u,
+                        struct gl_fixedfunc_texture_unit *f)
 {
 	struct gl_texture_object *t = u->_Current;
 	struct gl_texture_image *ti = t->Image[0][t->BaseLevel];
 
 	return ti->TexFormat == MESA_FORMAT_A_UNORM8 ||
 		ti->TexFormat == MESA_FORMAT_L_UNORM8 ||
-		u->EnvMode == GL_COMBINE ||
-		u->EnvMode == GL_COMBINE4_NV ||
-		u->EnvMode == GL_BLEND ||
-		u->EnvMode == GL_ADD;
+		f->EnvMode == GL_COMBINE ||
+		f->EnvMode == GL_COMBINE4_NV ||
+		f->EnvMode == GL_BLEND ||
+		f->EnvMode == GL_ADD;
 }
 
 struct nouveau_object *
 nv04_context_engine(struct gl_context *ctx)
 {
 	struct nv04_context *nctx = to_nv04_context(ctx);
 	struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw;
 	struct nouveau_pushbuf *push = context_push(ctx);
 	struct nouveau_object *fahrenheit;
 
 	if ((ctx->Texture.Unit[0]._Current &&
-	     texunit_needs_combiners(&ctx->Texture.Unit[0])) ||
+	     texunit_needs_combiners(&ctx->Texture.Unit[0],
+                                     &ctx->Texture.FixedFuncUnit[0])) ||
 	    ctx->Texture.Unit[1]._Current ||
 	    ctx->Stencil.Enabled ||
 	    GET_COLORMASK(ctx->Color.ColorMask, 0) != 0xf)
 		fahrenheit = hw->eng3dm;
 	else
 		fahrenheit = hw->eng3d;
 
 	if (fahrenheit != nctx->eng3d) {
 		BEGIN_NV04(push, NV01_SUBC(3D, OBJECT), 1);
 		PUSH_DATA (push, fahrenheit->handle);
diff --git a/src/mesa/drivers/dri/nouveau/nv04_state_frag.c b/src/mesa/drivers/dri/nouveau/nv04_state_frag.c
index bfe8eae..26e2e91 100644
--- a/src/mesa/drivers/dri/nouveau/nv04_state_frag.c
+++ b/src/mesa/drivers/dri/nouveau/nv04_state_frag.c
@@ -57,21 +57,21 @@  struct combiner_state {
 	uint32_t hw;
 };
 
 #define __INIT_COMBINER_ALPHA_A GL_TRUE
 #define __INIT_COMBINER_ALPHA_RGB GL_FALSE
 
 /* Initialize a combiner_state struct from the texture unit
  * context. */
 #define INIT_COMBINER(chan, ctx, rc, i) do {			\
 		struct gl_tex_env_combine_state *c =		\
-			ctx->Texture.Unit[i]._CurrentCombine;	\
+			ctx->Texture.FixedFuncUnit[i]._CurrentCombine;	\
 		(rc)->ctx = ctx;				\
 		(rc)->unit = i;					\
 		(rc)->alpha = __INIT_COMBINER_ALPHA_##chan;	\
 		(rc)->premodulate = c->_NumArgs##chan == 4;	\
 		(rc)->mode = c->Mode##chan;			\
 		(rc)->source = c->Source##chan;			\
 		(rc)->operand = c->Operand##chan;		\
 		(rc)->logscale = c->ScaleShift##chan;		\
 		(rc)->hw = 0;					\
 	} while (0)
@@ -280,20 +280,20 @@  nv04_emit_tex_env(struct gl_context *ctx, int emit)
 		INPUT_SRC(&rc_a, 3, ZERO, 0);
 		INPUT_SRC(&rc_c, 3, ZERO, 0);
 
 		UNSIGNED_OP(&rc_a);
 		UNSIGNED_OP(&rc_c);
 	}
 
 	/* calculate non-multitex state */
 	nv04->blend &= ~NV04_TEXTURED_TRIANGLE_BLEND_TEXTURE_MAP__MASK;
 	if (ctx->Texture._MaxEnabledTexImageUnit != -1)
-		nv04->blend |= get_texenv_mode(ctx->Texture.Unit[0].EnvMode);
+		nv04->blend |= get_texenv_mode(ctx->Texture.FixedFuncUnit[0].EnvMode);
 	else
 		nv04->blend |= get_texenv_mode(GL_MODULATE);
 
 	/* update calculated multitex state */
 	nv04->alpha[i] = rc_a.hw;
 	nv04->color[i] = rc_c.hw;
 	nv04->factor   = pack_rgba_f(MESA_FORMAT_B8G8R8A8_UNORM,
-				     ctx->Texture.Unit[0].EnvColor);
+				     ctx->Texture.FixedFuncUnit[0].EnvColor);
 }
diff --git a/src/mesa/drivers/dri/nouveau/nv10_state_frag.c b/src/mesa/drivers/dri/nouveau/nv10_state_frag.c
index 42dff08..27400d3 100644
--- a/src/mesa/drivers/dri/nouveau/nv10_state_frag.c
+++ b/src/mesa/drivers/dri/nouveau/nv10_state_frag.c
@@ -73,21 +73,21 @@  struct combiner_state {
 
 	/* Derived HW state */
 	uint64_t in;
 	uint32_t out;
 };
 
 /* Initialize a combiner_state struct from the texture unit
  * context. */
 #define INIT_COMBINER(chan, ctx, rc, i) do {			\
 		struct gl_tex_env_combine_state *c =		\
-			ctx->Texture.Unit[i]._CurrentCombine;	\
+			ctx->Texture.FixedFuncUnit[i]._CurrentCombine;	\
 		(rc)->ctx = ctx;				\
 		(rc)->unit = i;					\
 		(rc)->premodulate = c->_NumArgs##chan == 4;	\
 		(rc)->mode = c->Mode##chan;			\
 		(rc)->source = c->Source##chan;			\
 		(rc)->operand = c->Operand##chan;		\
 		(rc)->logscale = c->ScaleShift##chan;		\
 		(rc)->in = (rc)->out = 0;			\
 	} while (0)
 
@@ -325,21 +325,21 @@  nv10_get_general_combiner(struct gl_context *ctx, int i,
 			INIT_COMBINER(A, ctx, &rc_a, i);
 
 		setup_combiner(&rc_c);
 		setup_combiner(&rc_a);
 
 	} else {
 		rc_a.in = rc_a.out = rc_c.in = rc_c.out = 0;
 	}
 
 	*k = pack_rgba_f(MESA_FORMAT_B8G8R8A8_UNORM,
-			 ctx->Texture.Unit[i].EnvColor);
+			 ctx->Texture.FixedFuncUnit[i].EnvColor);
 	*a_in = rc_a.in;
 	*a_out = rc_a.out;
 	*c_in = rc_c.in;
 	*c_out = rc_c.out;
 }
 
 void
 nv10_get_final_combiner(struct gl_context *ctx, uint64_t *in, int *n)
 {
 	struct combiner_state rc = {};
diff --git a/src/mesa/drivers/dri/nouveau/nv10_state_tex.c b/src/mesa/drivers/dri/nouveau/nv10_state_tex.c
index d85adfa..d741d41 100644
--- a/src/mesa/drivers/dri/nouveau/nv10_state_tex.c
+++ b/src/mesa/drivers/dri/nouveau/nv10_state_tex.c
@@ -32,21 +32,22 @@ 
 #include "nouveau_util.h"
 #include "nv10_driver.h"
 #include "main/samplerobj.h"
 
 void
 nv10_emit_tex_gen(struct gl_context *ctx, int emit)
 {
 	const int i = emit - NOUVEAU_STATE_TEX_GEN0;
 	struct nouveau_context *nctx = to_nouveau_context(ctx);
 	struct nouveau_pushbuf *push = context_push(ctx);
-	struct gl_texture_unit *unit = &ctx->Texture.Unit[i];
+	struct gl_fixedfunc_texture_unit *unit =
+           &ctx->Texture.FixedFuncUnit[i];
 	int j;
 
 	for (j = 0; j < 4; j++) {
 		if (nctx->fallback == HWTNL && (unit->TexGenEnabled & 1 << j)) {
 			struct gl_texgen *coord = get_texgen_coord(unit, j);
 			float *k = get_texgen_coeff(coord);
 
 			if (k) {
 				BEGIN_NV04(push, NV10_3D(TEX_GEN_COEFF(i, j)), 4);
 				PUSH_DATAp(push, k, 4);
@@ -66,21 +67,21 @@  nv10_emit_tex_gen(struct gl_context *ctx, int emit)
 
 void
 nv10_emit_tex_mat(struct gl_context *ctx, int emit)
 {
 	const int i = emit - NOUVEAU_STATE_TEX_MAT0;
 	struct nouveau_context *nctx = to_nouveau_context(ctx);
 	struct nouveau_pushbuf *push = context_push(ctx);
 
 	if (nctx->fallback == HWTNL &&
 	    ((ctx->Texture._TexMatEnabled & 1 << i) ||
-	     ctx->Texture.Unit[i]._GenFlags)) {
+	     ctx->Texture.FixedFuncUnit[i]._GenFlags)) {
 		BEGIN_NV04(push, NV10_3D(TEX_MATRIX_ENABLE(i)), 1);
 		PUSH_DATA (push, 1);
 
 		BEGIN_NV04(push, NV10_3D(TEX_MATRIX(i, 0)), 16);
 		PUSH_DATAm(push, ctx->TextureMatrixStack[i].Top->m);
 
 	} else {
 		BEGIN_NV04(push, NV10_3D(TEX_MATRIX_ENABLE(i)), 1);
 		PUSH_DATA (push, 0);
 	}
diff --git a/src/mesa/drivers/dri/nouveau/nv20_state_tex.c b/src/mesa/drivers/dri/nouveau/nv20_state_tex.c
index 72df814..9960ae0 100644
--- a/src/mesa/drivers/dri/nouveau/nv20_state_tex.c
+++ b/src/mesa/drivers/dri/nouveau/nv20_state_tex.c
@@ -32,21 +32,22 @@ 
 #include "nouveau_util.h"
 #include "nv20_driver.h"
 #include "main/samplerobj.h"
 
 void
 nv20_emit_tex_gen(struct gl_context *ctx, int emit)
 {
 	const int i = emit - NOUVEAU_STATE_TEX_GEN0;
 	struct nouveau_context *nctx = to_nouveau_context(ctx);
 	struct nouveau_pushbuf *push = context_push(ctx);
-	struct gl_texture_unit *unit = &ctx->Texture.Unit[i];
+	struct gl_fixedfunc_texture_unit *unit =
+           &ctx->Texture.FixedFuncUnit[i];
 	int j;
 
 	for (j = 0; j < 4; j++) {
 		if (nctx->fallback == HWTNL && (unit->TexGenEnabled & 1 << j)) {
 			struct gl_texgen *coord = get_texgen_coord(unit, j);
 			float *k = get_texgen_coeff(coord);
 
 			if (k) {
 				BEGIN_NV04(push, NV20_3D(TEX_GEN_COEFF(i, j)), 4);
 				PUSH_DATAp(push, k, 4);
diff --git a/src/mesa/drivers/dri/r200/r200_tex.c b/src/mesa/drivers/dri/r200/r200_tex.c
index 0696c0d..1b217b9 100644
--- a/src/mesa/drivers/dri/r200/r200_tex.c
+++ b/src/mesa/drivers/dri/r200/r200_tex.c
@@ -290,21 +290,22 @@  static void r200SetTexBorderColor( radeonTexObjPtr t, const GLfloat color[4] )
    CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]);
    CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]);
    t->pp_border_color = radeonPackColor( 4, c[0], c[1], c[2], c[3] );
 }
 
 static void r200TexEnv( struct gl_context *ctx, GLenum target,
 			  GLenum pname, const GLfloat *param )
 {
    r200ContextPtr rmesa = R200_CONTEXT(ctx);
    GLuint unit = ctx->Texture.CurrentUnit;
-   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+   struct gl_fixedfunc_texture_unit *texUnit =
+      &ctx->Texture.FixedFuncUnit[unit];
 
    radeon_print(RADEON_TEXTURE | RADEON_STATE, RADEON_VERBOSE, "%s( %s )\n",
 	       __func__, _mesa_enum_to_string( pname ) );
 
    /* This is incorrect: Need to maintain this data for each of
     * GL_TEXTURE_{123}D, GL_TEXTURE_RECTANGLE_NV, etc, and switch
     * between them according to _Current->Target.
     */
    switch ( pname ) {
    case GL_TEXTURE_ENV_COLOR: {
diff --git a/src/mesa/drivers/dri/r200/r200_texstate.c b/src/mesa/drivers/dri/r200/r200_texstate.c
index dcf211f..60a2007 100644
--- a/src/mesa/drivers/dri/r200/r200_texstate.c
+++ b/src/mesa/drivers/dri/r200/r200_texstate.c
@@ -210,21 +210,23 @@  do {							\
 } while (0)
 
 
 /* ================================================================
  * Texture unit state management
  */
 
 static GLboolean r200UpdateTextureEnv( struct gl_context *ctx, int unit, int slot, GLuint replaceargs )
 {
    r200ContextPtr rmesa = R200_CONTEXT(ctx);
-   const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+   const struct gl_texture_unit *rtexUnit = &ctx->Texture.Unit[unit];
+   const struct gl_fixedfunc_texture_unit *texUnit =
+      &ctx->Texture.FixedFuncUnit[unit];
    GLuint color_combine, alpha_combine;
    GLuint color_scale = rmesa->hw.pix[slot].cmd[PIX_PP_TXCBLEND2] &
       ~(R200_TXC_SCALE_MASK | R200_TXC_OUTPUT_REG_MASK | R200_TXC_TFACTOR_SEL_MASK |
 	R200_TXC_TFACTOR1_SEL_MASK);
    GLuint alpha_scale = rmesa->hw.pix[slot].cmd[PIX_PP_TXABLEND2] &
       ~(R200_TXA_DOT_ALPHA | R200_TXA_SCALE_MASK | R200_TXA_OUTPUT_REG_MASK |
 	R200_TXA_TFACTOR_SEL_MASK | R200_TXA_TFACTOR1_SEL_MASK);
 
    if ( R200_DEBUG & RADEON_TEXTURE ) {
       fprintf( stderr, "%s( %p, %d )\n", __func__, (void *)ctx, unit );
@@ -237,40 +239,40 @@  static GLboolean r200UpdateTextureEnv( struct gl_context *ctx, int unit, int slo
     * textures being a notable exception.
     */
 
    color_scale |= ((rmesa->state.texture.unit[unit].outputreg + 1) << R200_TXC_OUTPUT_REG_SHIFT) |
 			(unit << R200_TXC_TFACTOR_SEL_SHIFT) |
 			(replaceargs << R200_TXC_TFACTOR1_SEL_SHIFT);
    alpha_scale |= ((rmesa->state.texture.unit[unit].outputreg + 1) << R200_TXA_OUTPUT_REG_SHIFT) |
 			(unit << R200_TXA_TFACTOR_SEL_SHIFT) |
 			(replaceargs << R200_TXA_TFACTOR1_SEL_SHIFT);
 
-   if ( !texUnit->_Current ) {
+   if ( !rtexUnit->_Current ) {
       assert( unit == 0);
       color_combine = R200_TXC_ARG_A_ZERO | R200_TXC_ARG_B_ZERO
 	  | R200_TXC_ARG_C_DIFFUSE_COLOR | R200_TXC_OP_MADD;
       alpha_combine = R200_TXA_ARG_A_ZERO | R200_TXA_ARG_B_ZERO
 	  | R200_TXA_ARG_C_DIFFUSE_ALPHA | R200_TXA_OP_MADD;
    }
    else {
       GLuint color_arg[3], alpha_arg[3];
       GLuint i;
       const GLuint numColorArgs = texUnit->_CurrentCombine->_NumArgsRGB;
       const GLuint numAlphaArgs = texUnit->_CurrentCombine->_NumArgsA;
       GLuint RGBshift = texUnit->_CurrentCombine->ScaleShiftRGB;
       GLuint Ashift = texUnit->_CurrentCombine->ScaleShiftA;
 
 
       const GLint replaceoprgb =
-	 ctx->Texture.Unit[replaceargs]._CurrentCombine->OperandRGB[0] - GL_SRC_COLOR;
+	 ctx->Texture.FixedFuncUnit[replaceargs]._CurrentCombine->OperandRGB[0] - GL_SRC_COLOR;
       const GLint replaceopa =
-	 ctx->Texture.Unit[replaceargs]._CurrentCombine->OperandA[0] - GL_SRC_ALPHA;
+	 ctx->Texture.FixedFuncUnit[replaceargs]._CurrentCombine->OperandA[0] - GL_SRC_ALPHA;
 
       /* Step 1:
        * Extract the color and alpha combine function arguments.
        */
       for ( i = 0 ; i < numColorArgs ; i++ ) {
 	 GLint op = texUnit->_CurrentCombine->OperandRGB[i] - GL_SRC_COLOR;
 	 const GLint srcRGBi = texUnit->_CurrentCombine->SourceRGB[i];
 	 assert(op >= 0);
 	 assert(op <= 3);
 	 switch ( srcRGBi ) {
@@ -279,21 +281,21 @@  static GLboolean r200UpdateTextureEnv( struct gl_context *ctx, int unit, int slo
 	    break;
 	 case GL_CONSTANT:
 	    color_arg[i] = r200_tfactor_color[op];
 	    break;
 	 case GL_PRIMARY_COLOR:
 	    color_arg[i] = r200_primary_color[op];
 	    break;
 	 case GL_PREVIOUS:
 	    if (replaceargs != unit) {
 	       const GLint srcRGBreplace =
-		  ctx->Texture.Unit[replaceargs]._CurrentCombine->SourceRGB[0];
+		  ctx->Texture.FixedFuncUnit[replaceargs]._CurrentCombine->SourceRGB[0];
 	       if (op >= 2) {
 		  op = op ^ replaceopa;
 	       }
 	       else {
 		  op = op ^ replaceoprgb;
 	       }
 	       switch (srcRGBreplace) {
 	       case GL_TEXTURE:
 		  color_arg[i] = r200_register_color[op][replaceargs];
 		  break;
@@ -366,21 +368,21 @@  static GLboolean r200UpdateTextureEnv( struct gl_context *ctx, int unit, int slo
 	    break;
 	 case GL_CONSTANT:
 	    alpha_arg[i] = r200_tfactor_alpha[op];
 	    break;
 	 case GL_PRIMARY_COLOR:
 	    alpha_arg[i] = r200_primary_alpha[op];
 	    break;
 	 case GL_PREVIOUS:
 	    if (replaceargs != unit) {
 	       const GLint srcAreplace =
-		  ctx->Texture.Unit[replaceargs]._CurrentCombine->SourceA[0];
+		  ctx->Texture.FixedFuncUnit[replaceargs]._CurrentCombine->SourceA[0];
 	       op = op ^ replaceopa;
 	       switch (srcAreplace) {
 	       case GL_TEXTURE:
 		  alpha_arg[i] = r200_register_alpha[op][replaceargs];
 		  break;
 	       case GL_CONSTANT:
 		  alpha_arg[i] = r200_tfactor1_alpha[op];
 		  break;
 	       case GL_PRIMARY_COLOR:
 		  alpha_arg[i] = r200_primary_alpha[op];
@@ -764,21 +766,23 @@  static GLboolean r200UpdateAllTexEnv( struct gl_context *ctx )
 
    /* find highest used unit */
    for ( j = 0; j < R200_MAX_TEXTURE_UNITS; j++) {
       if (ctx->Texture.Unit[j]._Current) {
 	 maxunitused = j;
       }
    }
    stageref[maxunitused + 1] = REF_COLOR | REF_ALPHA;
 
    for ( j = maxunitused; j >= 0; j-- ) {
-      const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[j];
+      const struct gl_texture_unit *rtexUnit = &ctx->Texture.Unit[j];
+      const struct gl_fixedfunc_texture_unit *texUnit =
+         &ctx->Texture.FixedFuncUnit[j];
 
       rmesa->state.texture.unit[j].outputreg = -1;
 
       if (stageref[j + 1]) {
 
 	 /* use the lowest available reg. That gets us automatically reg0 for the last stage.
 	    need this even for disabled units, as it may get referenced due to the replace
 	    optimization */
 	 for ( i = 0 ; i < R200_MAX_TEXTURE_UNITS; i++ ) {
 	    if (texregfree[i]) {
@@ -786,21 +790,21 @@  static GLboolean r200UpdateAllTexEnv( struct gl_context *ctx )
 	       break;
 	    }
 	 }
 	 if (rmesa->state.texture.unit[j].outputreg == -1) {
 	    /* no more free regs we can use. Need a fallback :-( */
 	    return GL_FALSE;
          }
 
          nextunit[j] = currentnext;
 
-         if (!texUnit->_Current) {
+         if (!rtexUnit->_Current) {
 	 /* the not enabled stages are referenced "indirectly",
             must not cut off the lower stages */
 	    stageref[j] = REF_COLOR | REF_ALPHA;
 	    continue;
          }
 	 currentnext = j;
  
 	 const GLuint numColorArgs = texUnit->_CurrentCombine->_NumArgsRGB;
 	 const GLuint numAlphaArgs = texUnit->_CurrentCombine->_NumArgsA;
 	 const GLboolean isdot3rgba = (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA) ||
@@ -873,24 +877,24 @@  static GLboolean r200UpdateAllTexEnv( struct gl_context *ctx )
    ok = GL_TRUE;
    currslot = 0;
    rmesa->state.envneeded = 1;
 
    i = 0;
    while ((i <= maxunitused) && (i >= 0)) {
       /* only output instruction if the results are referenced */
       if (ctx->Texture.Unit[i]._Current && stageref[i+1]) {
          GLuint replaceunit = i;
 	 /* try to optimize GL_REPLACE away (only one level deep though) */
-	 if (	(ctx->Texture.Unit[i]._CurrentCombine->ModeRGB == GL_REPLACE) &&
-		(ctx->Texture.Unit[i]._CurrentCombine->ModeA == GL_REPLACE) &&
-		(ctx->Texture.Unit[i]._CurrentCombine->ScaleShiftRGB == 0) &&
-		(ctx->Texture.Unit[i]._CurrentCombine->ScaleShiftA == 0) &&
+	 if (	(ctx->Texture.FixedFuncUnit[i]._CurrentCombine->ModeRGB == GL_REPLACE) &&
+		(ctx->Texture.FixedFuncUnit[i]._CurrentCombine->ModeA == GL_REPLACE) &&
+		(ctx->Texture.FixedFuncUnit[i]._CurrentCombine->ScaleShiftRGB == 0) &&
+		(ctx->Texture.FixedFuncUnit[i]._CurrentCombine->ScaleShiftA == 0) &&
 		(nextunit[i] > 0) ) {
 	    /* yippie! can optimize it away! */
 	    replaceunit = i;
 	    i = nextunit[i];
 	 }
 
 	 /* need env instruction slot */
 	 rmesa->state.envneeded |= 1 << currslot;
 	 ok = r200UpdateTextureEnv( ctx, i, currslot, replaceunit );
 	 if (!ok) return GL_FALSE;
@@ -1079,21 +1083,22 @@  static GLuint r200_need_dis_texgen(const GLbitfield texGenEnabled,
    return needtgenable;
 }
 
 
 /*
  * Returns GL_FALSE if fallback required.  
  */
 static GLboolean r200_validate_texgen( struct gl_context *ctx, GLuint unit )
 {  
    r200ContextPtr rmesa = R200_CONTEXT(ctx);
-   const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+   const struct gl_fixedfunc_texture_unit *texUnit =
+      &ctx->Texture.FixedFuncUnit[unit];
    GLuint inputshift = R200_TEXGEN_0_INPUT_SHIFT + unit*4;
    GLuint tgi, tgcm;
    GLuint mode = 0;
    GLboolean mixed_fallback = GL_FALSE;
    static const GLfloat I[16] = {
       1,  0,  0,  0,
       0,  1,  0,  0,
       0,  0,  1,  0,
       0,  0,  0,  1 };
    static const GLfloat reflect[16] = {
diff --git a/src/mesa/drivers/dri/radeon/radeon_maos_verts.c b/src/mesa/drivers/dri/radeon/radeon_maos_verts.c
index 9a77850..c9c91f8 100644
--- a/src/mesa/drivers/dri/radeon/radeon_maos_verts.c
+++ b/src/mesa/drivers/dri/radeon/radeon_maos_verts.c
@@ -345,21 +345,21 @@  void radeonEmitArrays( struct gl_context *ctx, GLuint inputs )
 
    for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
       if (inputs & VERT_BIT_TEX(unit)) {
 	 req |= RADEON_ST_BIT(unit);
 	 /* assume we need the 3rd coord if texgen is active for r/q OR at least
 	    3 coords are submitted. This may not be 100% correct */
 	 if (VB->AttribPtr[_TNL_ATTRIB_TEX0 + unit]->size >= 3) {
 	    req |= RADEON_Q_BIT(unit);
 	    vtx |= RADEON_Q_BIT(unit);
 	 }
-	 if ( (ctx->Texture.Unit[unit].TexGenEnabled & (R_BIT | Q_BIT)) )
+	 if ( (ctx->Texture.FixedFuncUnit[unit].TexGenEnabled & (R_BIT | Q_BIT)) )
 	    vtx |= RADEON_Q_BIT(unit);
 	 else if ((VB->AttribPtr[_TNL_ATTRIB_TEX0 + unit]->size >= 3) &&
 	          (!ctx->Texture.Unit[unit]._Current ||
                    ctx->Texture.Unit[unit]._Current->Target != GL_TEXTURE_CUBE_MAP)) {
 	    GLuint swaptexmatcol = (VB->AttribPtr[_TNL_ATTRIB_TEX0 + unit]->size - 3);
 	    if (((rmesa->NeedTexMatrix >> unit) & 1) &&
 		 (swaptexmatcol != ((rmesa->TexMatColSwap >> unit) & 1)))
 	       radeonUploadTexMatrix( rmesa, unit, swaptexmatcol ) ;
 	 }
       }
diff --git a/src/mesa/drivers/dri/radeon/radeon_state.c b/src/mesa/drivers/dri/radeon/radeon_state.c
index e413df3..58d8fc5 100644
--- a/src/mesa/drivers/dri/radeon/radeon_state.c
+++ b/src/mesa/drivers/dri/radeon/radeon_state.c
@@ -1883,21 +1883,21 @@  static void update_texturematrix( struct gl_context *ctx )
 		  ctx->TextureMatrixStack[unit].Top );
 	    }
 	 }
 	 else if (rmesa->TexGenEnabled & (RADEON_TEXMAT_0_ENABLE << unit)) {
 	    _math_matrix_copy( &rmesa->tmpmat[unit], &rmesa->TexGenMatrix[unit] );
 	    needMatrix = GL_TRUE;
 	 }
 	 if (needMatrix) {
 	    rmesa->NeedTexMatrix |= 1 << unit;
 	    radeonUploadTexMatrix( rmesa, unit,
-			!ctx->Texture.Unit[unit].TexGenEnabled );
+			!ctx->Texture.FixedFuncUnit[unit].TexGenEnabled );
 	 }
       }
    }
 
    tpc = (texMatEnabled | rmesa->TexGenEnabled);
 
    /* TCL_TEX_COMPUTED_x is TCL_TEX_INPUT_x | 0x8 */
    vs &= ~((RADEON_TCL_TEX_COMPUTED_TEX_0 << RADEON_TCL_TEX_0_OUTPUT_SHIFT) |
 	   (RADEON_TCL_TEX_COMPUTED_TEX_0 << RADEON_TCL_TEX_1_OUTPUT_SHIFT) |
 	   (RADEON_TCL_TEX_COMPUTED_TEX_0 << RADEON_TCL_TEX_2_OUTPUT_SHIFT));
diff --git a/src/mesa/drivers/dri/radeon/radeon_tex.c b/src/mesa/drivers/dri/radeon/radeon_tex.c
index b4964f1..da5d469 100644
--- a/src/mesa/drivers/dri/radeon/radeon_tex.c
+++ b/src/mesa/drivers/dri/radeon/radeon_tex.c
@@ -250,21 +250,22 @@  static void radeonSetTexBorderColor( radeonTexObjPtr t, const GLfloat color[4] )
 }
 
 #define SCALED_FLOAT_TO_BYTE( x, scale ) \
 		(((GLuint)((255.0F / scale) * (x))) / 2)
 
 static void radeonTexEnv( struct gl_context *ctx, GLenum target,
 			  GLenum pname, const GLfloat *param )
 {
    r100ContextPtr rmesa = R100_CONTEXT(ctx);
    GLuint unit = ctx->Texture.CurrentUnit;
-   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+   struct gl_fixedfunc_texture_unit *texUnit =
+      &ctx->Texture.FixedFuncUnit[unit];
 
    if ( RADEON_DEBUG & RADEON_STATE ) {
       fprintf( stderr, "%s( %s )\n",
 	       __func__, _mesa_enum_to_string( pname ) );
    }
 
    switch ( pname ) {
    case GL_TEXTURE_ENV_COLOR: {
       GLubyte c[4];
       GLuint envColor;
diff --git a/src/mesa/drivers/dri/radeon/radeon_texstate.c b/src/mesa/drivers/dri/radeon/radeon_texstate.c
index 5cabba1..47eac85 100644
--- a/src/mesa/drivers/dri/radeon/radeon_texstate.c
+++ b/src/mesa/drivers/dri/radeon/radeon_texstate.c
@@ -201,21 +201,23 @@  do {							\
 
 static GLenum
 texture_base_format(const struct gl_texture_object *t)
 {
 	return t->Image[0][t->BaseLevel]->_BaseFormat;
 }
 
 static GLboolean radeonUpdateTextureEnv( struct gl_context *ctx, int unit )
 {
    r100ContextPtr rmesa = R100_CONTEXT(ctx);
-   const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+   const struct gl_texture_unit *rtexUnit = &ctx->Texture.Unit[unit];
+   const struct gl_fixedfunc_texture_unit *texUnit =
+      &ctx->Texture.FixedFuncUnit[unit];
    GLuint color_combine, alpha_combine;
    const GLuint color_combine0 = RADEON_COLOR_ARG_A_ZERO | RADEON_COLOR_ARG_B_ZERO
          | RADEON_COLOR_ARG_C_CURRENT_COLOR | RADEON_BLEND_CTL_ADD
          | RADEON_SCALE_1X | RADEON_CLAMP_TX;
    const GLuint alpha_combine0 = RADEON_ALPHA_ARG_A_ZERO | RADEON_ALPHA_ARG_B_ZERO
          | RADEON_ALPHA_ARG_C_CURRENT_ALPHA | RADEON_BLEND_CTL_ADD
          | RADEON_SCALE_1X | RADEON_CLAMP_TX;
 
 
    if ( RADEON_DEBUG & RADEON_TEXTURE ) {
@@ -227,21 +229,21 @@  static GLboolean radeonUpdateTextureEnv( struct gl_context *ctx, int unit )
     * the texture format does not include an alpha component. This
     * reduces the amount of special-casing we have to do, alpha-only
     * textures being a notable exception. Doesn't work for luminance
     * textures realized with I8 and ALPHA_IN_MAP not set neither (on r100).
     */
     /* Don't cache these results.
     */
    rmesa->state.texture.unit[unit].format = 0;
    rmesa->state.texture.unit[unit].envMode = 0;
 
-   if ( !texUnit->_Current ) {
+   if ( !rtexUnit->_Current ) {
       color_combine = color_combine0;
       alpha_combine = alpha_combine0;
    }
    else {
       GLuint color_arg[3], alpha_arg[3];
       GLuint i;
       const GLuint numColorArgs = texUnit->_CurrentCombine->_NumArgsRGB;
       const GLuint numAlphaArgs = texUnit->_CurrentCombine->_NumArgsA;
       GLuint RGBshift = texUnit->_CurrentCombine->ScaleShiftRGB;
       GLuint Ashift = texUnit->_CurrentCombine->ScaleShiftA;
@@ -250,21 +252,21 @@  static GLboolean radeonUpdateTextureEnv( struct gl_context *ctx, int unit )
       /* Step 1:
        * Extract the color and alpha combine function arguments.
        */
       for ( i = 0 ; i < numColorArgs ; i++ ) {
 	 const GLint op = texUnit->_CurrentCombine->OperandRGB[i] - GL_SRC_COLOR;
 	 const GLuint srcRGBi = texUnit->_CurrentCombine->SourceRGB[i];
 	 assert(op >= 0);
 	 assert(op <= 3);
 	 switch ( srcRGBi ) {
 	 case GL_TEXTURE:
-	    if (texture_base_format(texUnit->_Current) == GL_ALPHA)
+	    if (texture_base_format(rtexUnit->_Current) == GL_ALPHA)
 	       color_arg[i] = radeon_zero_color[op];
 	    else
 	       color_arg[i] = radeon_texture_color[op][unit];
 	    break;
 	 case GL_CONSTANT:
 	    color_arg[i] = radeon_tfactor_color[op];
 	    break;
 	 case GL_PRIMARY_COLOR:
 	    color_arg[i] = radeon_primary_color[op];
 	    break;
@@ -295,21 +297,21 @@  static GLboolean radeonUpdateTextureEnv( struct gl_context *ctx, int unit )
 	 }
       }
 
       for ( i = 0 ; i < numAlphaArgs ; i++ ) {
 	 const GLint op = texUnit->_CurrentCombine->OperandA[i] - GL_SRC_ALPHA;
 	 const GLuint srcAi = texUnit->_CurrentCombine->SourceA[i];
 	 assert(op >= 0);
 	 assert(op <= 1);
 	 switch ( srcAi ) {
 	 case GL_TEXTURE:
-	    if (texture_base_format(texUnit->_Current) == GL_LUMINANCE)
+	    if (texture_base_format(rtexUnit->_Current) == GL_LUMINANCE)
 	       alpha_arg[i] = radeon_zero_alpha[op+1];
 	    else
 	       alpha_arg[i] = radeon_texture_alpha[op][unit];
 	    break;
 	 case GL_CONSTANT:
 	    alpha_arg[i] = radeon_tfactor_alpha[op];
 	    break;
 	 case GL_PRIMARY_COLOR:
 	    alpha_arg[i] = radeon_primary_alpha[op];
 	    break;
@@ -791,21 +793,22 @@  static void set_texgen_matrix( r100ContextPtr rmesa,
 
    rmesa->TexGenEnabled |= RADEON_TEXMAT_0_ENABLE << unit;
    rmesa->radeon.NewGLState |= _NEW_TEXTURE_MATRIX;
 }
 
 /* Returns GL_FALSE if fallback required.
  */
 static GLboolean radeon_validate_texgen( struct gl_context *ctx, GLuint unit )
 {
    r100ContextPtr rmesa = R100_CONTEXT(ctx);
-   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+   struct gl_fixedfunc_texture_unit *texUnit =
+      &ctx->Texture.FixedFuncUnit[unit];
    GLuint inputshift = RADEON_TEXGEN_0_INPUT_SHIFT + unit*4;
    GLuint tmp = rmesa->TexGenEnabled;
    static const GLfloat reflect[16] = {
       -1,  0,  0,  0,
        0, -1,  0,  0,
        0,  0,  -1, 0,
        0,  0,  0,  1 };
 
    rmesa->TexGenEnabled &= ~(RADEON_TEXGEN_TEXMAT_0_ENABLE << unit);
    rmesa->TexGenEnabled &= ~(RADEON_TEXMAT_0_ENABLE << unit);
diff --git a/src/mesa/main/attrib.c b/src/mesa/main/attrib.c
index 8ac5db0..398ff65 100644
--- a/src/mesa/main/attrib.c
+++ b/src/mesa/main/attrib.c
@@ -367,22 +367,22 @@  _mesa_PushAttrib(GLbitfield mask)
       attr->PolygonStipple = ctx->Polygon.StippleFlag;
       attr->RescaleNormals = ctx->Transform.RescaleNormals;
       attr->Scissor = ctx->Scissor.EnableFlags;
       attr->Stencil = ctx->Stencil.Enabled;
       attr->StencilTwoSide = ctx->Stencil.TestTwoSide;
       attr->MultisampleEnabled = ctx->Multisample.Enabled;
       attr->SampleAlphaToCoverage = ctx->Multisample.SampleAlphaToCoverage;
       attr->SampleAlphaToOne = ctx->Multisample.SampleAlphaToOne;
       attr->SampleCoverage = ctx->Multisample.SampleCoverage;
       for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
-         attr->Texture[i] = ctx->Texture.Unit[i].Enabled;
-         attr->TexGen[i] = ctx->Texture.Unit[i].TexGenEnabled;
+         attr->Texture[i] = ctx->Texture.FixedFuncUnit[i].Enabled;
+         attr->TexGen[i] = ctx->Texture.FixedFuncUnit[i].TexGenEnabled;
       }
       /* GL_ARB_vertex_program */
       attr->VertexProgram = ctx->VertexProgram.Enabled;
       attr->VertexProgramPointSize = ctx->VertexProgram.PointSizeEnabled;
       attr->VertexProgramTwoSide = ctx->VertexProgram.TwoSideEnabled;
 
       /* GL_ARB_fragment_program */
       attr->FragmentProgram = ctx->FragmentProgram.Enabled;
 
       if (!save_attrib_data(&head, GL_ENABLE_BIT, attr)) {
@@ -711,37 +711,37 @@  pop_enable_group(struct gl_context *ctx, const struct gl_enable_attrib *enable)
 
    /* GL_ARB_framebuffer_sRGB / GL_EXT_framebuffer_sRGB */
    TEST_AND_UPDATE(ctx->Color.sRGBEnabled, enable->sRGBEnabled,
                    GL_FRAMEBUFFER_SRGB);
 
    /* texture unit enables */
    for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
       const GLbitfield enabled = enable->Texture[i];
       const GLbitfield genEnabled = enable->TexGen[i];
 
-      if (ctx->Texture.Unit[i].Enabled != enabled) {
+      if (ctx->Texture.FixedFuncUnit[i].Enabled != enabled) {
          _mesa_ActiveTexture(GL_TEXTURE0 + i);
 
          _mesa_set_enable(ctx, GL_TEXTURE_1D, !!(enabled & TEXTURE_1D_BIT));
          _mesa_set_enable(ctx, GL_TEXTURE_2D, !!(enabled & TEXTURE_2D_BIT));
          _mesa_set_enable(ctx, GL_TEXTURE_3D, !!(enabled & TEXTURE_3D_BIT));
          if (ctx->Extensions.NV_texture_rectangle) {
             _mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE_ARB,
                              !!(enabled & TEXTURE_RECT_BIT));
          }
          if (ctx->Extensions.ARB_texture_cube_map) {
             _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP,
                              !!(enabled & TEXTURE_CUBE_BIT));
          }
       }
 
-      if (ctx->Texture.Unit[i].TexGenEnabled != genEnabled) {
+      if (ctx->Texture.FixedFuncUnit[i].TexGenEnabled != genEnabled) {
          _mesa_ActiveTexture(GL_TEXTURE0 + i);
          _mesa_set_enable(ctx, GL_TEXTURE_GEN_S, !!(genEnabled & S_BIT));
          _mesa_set_enable(ctx, GL_TEXTURE_GEN_T, !!(genEnabled & T_BIT));
          _mesa_set_enable(ctx, GL_TEXTURE_GEN_R, !!(genEnabled & R_BIT));
          _mesa_set_enable(ctx, GL_TEXTURE_GEN_Q, !!(genEnabled & Q_BIT));
       }
    }
 
    _mesa_ActiveTexture(GL_TEXTURE0 + curTexUnitSave);
 }
@@ -751,21 +751,22 @@  pop_enable_group(struct gl_context *ctx, const struct gl_enable_attrib *enable)
  * Pop/restore texture attribute/group state.
  */
 static void
 pop_texture_group(struct gl_context *ctx, struct texture_state *texstate)
 {
    GLuint u;
 
    _mesa_lock_context_textures(ctx);
 
    for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
-      const struct gl_texture_unit *unit = &texstate->Texture.Unit[u];
+      const struct gl_fixedfunc_texture_unit *unit =
+         &texstate->Texture.FixedFuncUnit[u];
       GLuint tgt;
 
       _mesa_ActiveTexture(GL_TEXTURE0_ARB + u);
       _mesa_set_enable(ctx, GL_TEXTURE_1D, !!(unit->Enabled & TEXTURE_1D_BIT));
       _mesa_set_enable(ctx, GL_TEXTURE_2D, !!(unit->Enabled & TEXTURE_2D_BIT));
       _mesa_set_enable(ctx, GL_TEXTURE_3D, !!(unit->Enabled & TEXTURE_3D_BIT));
       if (ctx->Extensions.ARB_texture_cube_map) {
          _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP,
                           !!(unit->Enabled & TEXTURE_CUBE_BIT));
       }
@@ -778,38 +779,40 @@  pop_texture_group(struct gl_context *ctx, struct texture_state *texstate)
       _mesa_TexGeni(GL_S, GL_TEXTURE_GEN_MODE, unit->GenS.Mode);
       _mesa_TexGeni(GL_T, GL_TEXTURE_GEN_MODE, unit->GenT.Mode);
       _mesa_TexGeni(GL_R, GL_TEXTURE_GEN_MODE, unit->GenR.Mode);
       _mesa_TexGeni(GL_Q, GL_TEXTURE_GEN_MODE, unit->GenQ.Mode);
       _mesa_TexGenfv(GL_S, GL_OBJECT_PLANE, unit->GenS.ObjectPlane);
       _mesa_TexGenfv(GL_T, GL_OBJECT_PLANE, unit->GenT.ObjectPlane);
       _mesa_TexGenfv(GL_R, GL_OBJECT_PLANE, unit->GenR.ObjectPlane);
       _mesa_TexGenfv(GL_Q, GL_OBJECT_PLANE, unit->GenQ.ObjectPlane);
       /* Eye plane done differently to avoid re-transformation */
       {
-         struct gl_texture_unit *destUnit = &ctx->Texture.Unit[u];
+         struct gl_fixedfunc_texture_unit *destUnit =
+            &ctx->Texture.FixedFuncUnit[u];
+
          COPY_4FV(destUnit->GenS.EyePlane, unit->GenS.EyePlane);
          COPY_4FV(destUnit->GenT.EyePlane, unit->GenT.EyePlane);
          COPY_4FV(destUnit->GenR.EyePlane, unit->GenR.EyePlane);
          COPY_4FV(destUnit->GenQ.EyePlane, unit->GenQ.EyePlane);
          if (ctx->Driver.TexGen) {
             ctx->Driver.TexGen(ctx, GL_S, GL_EYE_PLANE, unit->GenS.EyePlane);
             ctx->Driver.TexGen(ctx, GL_T, GL_EYE_PLANE, unit->GenT.EyePlane);
             ctx->Driver.TexGen(ctx, GL_R, GL_EYE_PLANE, unit->GenR.EyePlane);
             ctx->Driver.TexGen(ctx, GL_Q, GL_EYE_PLANE, unit->GenQ.EyePlane);
          }
       }
       _mesa_set_enable(ctx, GL_TEXTURE_GEN_S, !!(unit->TexGenEnabled & S_BIT));
       _mesa_set_enable(ctx, GL_TEXTURE_GEN_T, !!(unit->TexGenEnabled & T_BIT));
       _mesa_set_enable(ctx, GL_TEXTURE_GEN_R, !!(unit->TexGenEnabled & R_BIT));
       _mesa_set_enable(ctx, GL_TEXTURE_GEN_Q, !!(unit->TexGenEnabled & Q_BIT));
       _mesa_TexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS,
-                    unit->LodBias);
+		    texstate->Texture.Unit[u].LodBias);
       _mesa_TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB,
                     unit->Combine.ModeRGB);
       _mesa_TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA,
                     unit->Combine.ModeA);
       {
          const GLuint n = ctx->Extensions.NV_texture_env_combine4 ? 4 : 3;
          GLuint i;
          for (i = 0; i < n; i++) {
             _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB + i,
                           unit->Combine.SourceRGB[i]);
diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c
index 7dbf678..79d3e39 100644
--- a/src/mesa/main/context.c
+++ b/src/mesa/main/context.c
@@ -1257,22 +1257,24 @@  _mesa_initialize_context(struct gl_context *ctx,
          goto fail;
 
       /* fall-through */
    case API_OPENGL_CORE:
       break;
    case API_OPENGLES:
       /**
        * GL_OES_texture_cube_map says
        * "Initially all texture generation modes are set to REFLECTION_MAP_OES"
        */
-      for (i = 0; i < MAX_TEXTURE_UNITS; i++) {
-         struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
+      for (i = 0; i < ARRAY_SIZE(ctx->Texture.FixedFuncUnit); i++) {
+         struct gl_fixedfunc_texture_unit *texUnit =
+            &ctx->Texture.FixedFuncUnit[i];
+
          texUnit->GenS.Mode = GL_REFLECTION_MAP_NV;
          texUnit->GenT.Mode = GL_REFLECTION_MAP_NV;
          texUnit->GenR.Mode = GL_REFLECTION_MAP_NV;
          texUnit->GenS._ModeBit = TEXGEN_REFLECTION_MAP_NV;
          texUnit->GenT._ModeBit = TEXGEN_REFLECTION_MAP_NV;
          texUnit->GenR._ModeBit = TEXGEN_REFLECTION_MAP_NV;
       }
       break;
    case API_OPENGLES2:
       ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE;
diff --git a/src/mesa/main/enable.c b/src/mesa/main/enable.c
index 967d230..4c5f9dc 100644
--- a/src/mesa/main/enable.c
+++ b/src/mesa/main/enable.c
@@ -179,42 +179,44 @@  _mesa_DisableClientState( GLenum cap )
    if (!ctx->Extensions.EXT1 && !ctx->Extensions.EXT2) {		\
       goto invalid_enum_error;						\
    }
 
 /**
  * Return pointer to current texture unit for setting/getting coordinate
  * state.
  * Note that we'll set GL_INVALID_OPERATION and return NULL if the active
  * texture unit is higher than the number of supported coordinate units.
  */
-static struct gl_texture_unit *
+static struct gl_fixedfunc_texture_unit *
 get_texcoord_unit(struct gl_context *ctx)
 {
    if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "glEnable/Disable(texcoord unit)");
       return NULL;
    }
    else {
-      return &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+      return &ctx->Texture.FixedFuncUnit[ctx->Texture.CurrentUnit];
    }
 }
 
 
 /**
  * Helper function to enable or disable a texture target.
  * \param bit  one of the TEXTURE_x_BIT values
  * \return GL_TRUE if state is changing or GL_FALSE if no change
  */
 static GLboolean
 enable_texture(struct gl_context *ctx, GLboolean state, GLbitfield texBit)
 {
-   struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
+   struct gl_fixedfunc_texture_unit *texUnit =
+      _mesa_get_current_fixedfunc_tex_unit(ctx);
+
    const GLbitfield newenabled = state
       ? (texUnit->Enabled | texBit) : (texUnit->Enabled & ~texBit);
 
    if (texUnit->Enabled == newenabled)
        return GL_FALSE;
 
    FLUSH_VERTICES(ctx, _NEW_TEXTURE_STATE);
    texUnit->Enabled = newenabled;
    return GL_TRUE;
 }
@@ -741,42 +743,42 @@  _mesa_set_enable(struct gl_context *ctx, GLenum cap, GLboolean state)
             goto invalid_enum_error;
          if (!enable_texture(ctx, state, TEXTURE_3D_BIT)) {
             return;
          }
          break;
       case GL_TEXTURE_GEN_S:
       case GL_TEXTURE_GEN_T:
       case GL_TEXTURE_GEN_R:
       case GL_TEXTURE_GEN_Q:
          {
-            struct gl_texture_unit *texUnit = get_texcoord_unit(ctx);
+            struct gl_fixedfunc_texture_unit *texUnit = get_texcoord_unit(ctx);
 
             if (ctx->API != API_OPENGL_COMPAT)
                goto invalid_enum_error;
 
             if (texUnit) {
                GLbitfield coordBit = S_BIT << (cap - GL_TEXTURE_GEN_S);
                GLbitfield newenabled = texUnit->TexGenEnabled & ~coordBit;
                if (state)
                   newenabled |= coordBit;
                if (texUnit->TexGenEnabled == newenabled)
                   return;
                FLUSH_VERTICES(ctx, _NEW_TEXTURE_STATE);
                texUnit->TexGenEnabled = newenabled;
             }
          }
          break;
 
       case GL_TEXTURE_GEN_STR_OES:
          /* disable S, T, and R at the same time */
          {
-            struct gl_texture_unit *texUnit = get_texcoord_unit(ctx);
+            struct gl_fixedfunc_texture_unit *texUnit = get_texcoord_unit(ctx);
 
             if (ctx->API != API_OPENGLES)
                goto invalid_enum_error;
 
             if (texUnit) {
                GLuint newenabled =
                   texUnit->TexGenEnabled & ~STR_BITS;
                if (state)
                   newenabled |= STR_BITS;
                if (texUnit->TexGenEnabled == newenabled)
@@ -1281,22 +1283,23 @@  _mesa_IsEnabledi( GLenum cap, GLuint index )
       goto invalid_enum_error;					\
    }
 
 
 /**
  * Helper function to determine whether a texture target is enabled.
  */
 static GLboolean
 is_texture_enabled(struct gl_context *ctx, GLbitfield bit)
 {
-   const struct gl_texture_unit *const texUnit =
-       &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+   const struct gl_fixedfunc_texture_unit *const texUnit =
+      _mesa_get_current_fixedfunc_tex_unit(ctx);
+
    return (texUnit->Enabled & bit) ? GL_TRUE : GL_FALSE;
 }
 
 
 /**
  * Return simple enable/disable state.
  *
  * \param cap  state variable to query.
  *
  * Returns the state of the specified capability from the current GL context.
@@ -1499,34 +1502,36 @@  _mesa_IsEnabled( GLenum cap )
          return is_texture_enabled(ctx, TEXTURE_2D_BIT);
       case GL_TEXTURE_3D:
          if (ctx->API != API_OPENGL_COMPAT && ctx->API != API_OPENGLES)
             goto invalid_enum_error;
          return is_texture_enabled(ctx, TEXTURE_3D_BIT);
       case GL_TEXTURE_GEN_S:
       case GL_TEXTURE_GEN_T:
       case GL_TEXTURE_GEN_R:
       case GL_TEXTURE_GEN_Q:
          {
-            const struct gl_texture_unit *texUnit = get_texcoord_unit(ctx);
+            const struct gl_fixedfunc_texture_unit *texUnit =
+               get_texcoord_unit(ctx);
 
             if (ctx->API != API_OPENGL_COMPAT)
                goto invalid_enum_error;
 
             if (texUnit) {
                GLbitfield coordBit = S_BIT << (cap - GL_TEXTURE_GEN_S);
                return (texUnit->TexGenEnabled & coordBit) ? GL_TRUE : GL_FALSE;
             }
          }
          return GL_FALSE;
       case GL_TEXTURE_GEN_STR_OES:
          {
-            const struct gl_texture_unit *texUnit = get_texcoord_unit(ctx);
+            const struct gl_fixedfunc_texture_unit *texUnit =
+               get_texcoord_unit(ctx);
 
             if (ctx->API != API_OPENGLES)
                goto invalid_enum_error;
 
             if (texUnit) {
                return (texUnit->TexGenEnabled & STR_BITS) == STR_BITS
                   ? GL_TRUE : GL_FALSE;
             }
          }
 
diff --git a/src/mesa/main/ff_fragment_shader.cpp b/src/mesa/main/ff_fragment_shader.cpp
index 2be3ae3..a698931 100644
--- a/src/mesa/main/ff_fragment_shader.cpp
+++ b/src/mesa/main/ff_fragment_shader.cpp
@@ -261,21 +261,22 @@  static GLuint make_state_key( struct gl_context *ctx,  struct state_key *key )
 
    memset(key, 0, sizeof(*key));
 
    /* _NEW_TEXTURE_OBJECT */
    mask = ctx->Texture._EnabledCoordUnits;
    int i = -1;
    while (mask) {
       i = u_bit_scan(&mask);
       const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
       const struct gl_texture_object *texObj = texUnit->_Current;
-      const struct gl_tex_env_combine_packed *comb = &texUnit->_CurrentCombinePacked;
+      const struct gl_tex_env_combine_packed *comb =
+         &ctx->Texture.FixedFuncUnit[i]._CurrentCombinePacked;
 
       if (!texObj)
          continue;
 
       key->unit[i].enabled = 1;
       inputs_referenced |= VARYING_BIT_TEX(i);
 
       key->unit[i].source_index = texObj->TargetIndex;
 
       const struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, i);
diff --git a/src/mesa/main/ffvertex_prog.c b/src/mesa/main/ffvertex_prog.c
index 6a022b8..976b6f4 100644
--- a/src/mesa/main/ffvertex_prog.c
+++ b/src/mesa/main/ffvertex_prog.c
@@ -228,21 +228,22 @@  static void make_state_key( struct gl_context *ctx, struct state_key *key )
          translate_fog_distance_mode(ctx->Fog.FogCoordinateSource,
                                      ctx->Fog.FogDistanceMode);
 
    if (ctx->Point._Attenuated)
       key->point_attenuated = 1;
 
    mask = ctx->Texture._EnabledCoordUnits | ctx->Texture._TexGenEnabled
       | ctx->Texture._TexMatEnabled | ctx->Point.CoordReplace;
    while (mask) {
       const int i = u_bit_scan(&mask);
-      struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
+      struct gl_fixedfunc_texture_unit *texUnit =
+         &ctx->Texture.FixedFuncUnit[i];
 
       if (ctx->Point.PointSprite)
 	 if (ctx->Point.CoordReplace & (1u << i))
 	    key->unit[i].coord_replace = 1;
 
       if (ctx->Texture._TexMatEnabled & ENABLE_TEXMAT(i))
 	 key->unit[i].texmat_enabled = 1;
 
       if (texUnit->TexGenEnabled) {
 	 key->unit[i].texgen_enabled = 1;
diff --git a/src/mesa/main/get.c b/src/mesa/main/get.c
index 516e8d1..2188017 100644
--- a/src/mesa/main/get.c
+++ b/src/mesa/main/get.c
@@ -1383,21 +1383,20 @@  static const struct value_desc error_value =
  *
  * \return the struct value_desc corresponding to the enum or a struct
  *     value_desc of TYPE_INVALID if not found.  This lets the calling
  *     glGet*v() function jump right into a switch statement and
  *     handle errors there instead of having to check for NULL.
  */
 static const struct value_desc *
 find_value(const char *func, GLenum pname, void **p, union value *v)
 {
    GET_CURRENT_CONTEXT(ctx);
-   struct gl_texture_unit *unit;
    int mask, hash;
    const struct value_desc *d;
    int api;
 
    api = ctx->API;
    /* We index into the table_set[] list of per-API hash tables using the API's
     * value in the gl_api enum. Since GLES 3 doesn't have an API_OPENGL* enum
     * value since it's compatible with GLES2 its entry in table_set[] is at the
     * end.
     */
@@ -1438,22 +1437,24 @@  find_value(const char *func, GLenum pname, void **p, union value *v)
    case LOC_BUFFER:
       *p = ((char *) ctx->DrawBuffer + d->offset);
       return d;
    case LOC_CONTEXT:
       *p = ((char *) ctx + d->offset);
       return d;
    case LOC_ARRAY:
       *p = ((char *) ctx->Array.VAO + d->offset);
       return d;
    case LOC_TEXUNIT:
-      unit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
-      *p = ((char *) unit + d->offset);
+      if (ctx->Texture.CurrentUnit < ARRAY_SIZE(ctx->Texture.FixedFuncUnit)) {
+         unsigned index = ctx->Texture.CurrentUnit;
+         *p = ((char *)&ctx->Texture.FixedFuncUnit[index] + d->offset);
+      }
       return d;
    case LOC_CUSTOM:
       find_custom_value(ctx, d, v);
       *p = v;
       return d;
    default:
       assert(0);
       break;
    }
 
diff --git a/src/mesa/main/get_hash_params.py b/src/mesa/main/get_hash_params.py
index df082af..e127b6b 100644
--- a/src/mesa/main/get_hash_params.py
+++ b/src/mesa/main/get_hash_params.py
@@ -227,21 +227,21 @@  descriptor=[
   [ "TEXTURE_COORD_ARRAY_TYPE", "LOC_CUSTOM, TYPE_ENUM16, offsetof(struct gl_array_attributes, Type), NO_EXTRA" ],
   [ "TEXTURE_COORD_ARRAY_STRIDE", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_attributes, Stride), NO_EXTRA" ],
 
 # GL_ARB_multitexture
   [ "MAX_TEXTURE_UNITS", "CONTEXT_INT(Const.MaxTextureUnits), NO_EXTRA" ],
   [ "CLIENT_ACTIVE_TEXTURE", "LOC_CUSTOM, TYPE_INT, 0, NO_EXTRA" ],
 
 # GL_ARB_texture_cube_map
   [ "TEXTURE_CUBE_MAP_ARB", "LOC_CUSTOM, TYPE_BOOLEAN, 0, NO_EXTRA" ],
 # S, T, and R are always set at the same time
-  [ "TEXTURE_GEN_STR_OES", "LOC_TEXUNIT, TYPE_BIT_0, offsetof(struct gl_texture_unit, TexGenEnabled), NO_EXTRA" ],
+  [ "TEXTURE_GEN_STR_OES", "LOC_TEXUNIT, TYPE_BIT_0, offsetof(struct gl_fixedfunc_texture_unit, TexGenEnabled), NO_EXTRA" ],
 
 # GL_ARB_multisample
   [ "MULTISAMPLE_ARB", "CONTEXT_BOOL(Multisample.Enabled), NO_EXTRA" ],
   [ "SAMPLE_ALPHA_TO_ONE_ARB", "CONTEXT_BOOL(Multisample.SampleAlphaToOne), NO_EXTRA" ],
 
 # GL_ARB_vertex_buffer_object
   [ "VERTEX_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_vertex_array_object, BufferBinding[VERT_ATTRIB_POS].BufferObj), NO_EXTRA" ],
   [ "NORMAL_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_vertex_array_object, BufferBinding[VERT_ATTRIB_NORMAL].BufferObj), NO_EXTRA" ],
   [ "COLOR_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_vertex_array_object, BufferBinding[VERT_ATTRIB_COLOR0].BufferObj), NO_EXTRA" ],
   [ "TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, NO_OFFSET, NO_EXTRA" ],
@@ -753,24 +753,24 @@  descriptor=[
   [ "RED_BIAS", "CONTEXT_FLOAT(Pixel.RedBias), NO_EXTRA" ],
   [ "RED_SCALE", "CONTEXT_FLOAT(Pixel.RedScale), NO_EXTRA" ],
   [ "RENDER_MODE", "CONTEXT_ENUM16(RenderMode), NO_EXTRA" ],
   [ "RGBA_MODE", "CONST(1), NO_EXTRA" ],
   [ "SELECTION_BUFFER_SIZE", "CONTEXT_INT(Select.BufferSize), NO_EXTRA" ],
   [ "STEREO", "BUFFER_INT(Visual.stereoMode), NO_EXTRA" ],
   [ "TEXTURE_1D", "LOC_CUSTOM, TYPE_BOOLEAN, NO_OFFSET, NO_EXTRA" ],
   [ "TEXTURE_3D", "LOC_CUSTOM, TYPE_BOOLEAN, NO_OFFSET, NO_EXTRA" ],
   [ "TEXTURE_BINDING_1D", "LOC_CUSTOM, TYPE_INT, TEXTURE_1D_INDEX, NO_EXTRA" ],
   [ "TEXTURE_BINDING_1D_ARRAY", "LOC_CUSTOM, TYPE_INT, TEXTURE_1D_ARRAY_INDEX, extra_EXT_texture_array" ],
-  [ "TEXTURE_GEN_S", "LOC_TEXUNIT, TYPE_BIT_0, offsetof(struct gl_texture_unit, TexGenEnabled), NO_EXTRA" ],
-  [ "TEXTURE_GEN_T", "LOC_TEXUNIT, TYPE_BIT_1, offsetof(struct gl_texture_unit, TexGenEnabled), NO_EXTRA" ],
-  [ "TEXTURE_GEN_R", "LOC_TEXUNIT, TYPE_BIT_2, offsetof(struct gl_texture_unit, TexGenEnabled), NO_EXTRA" ],
-  [ "TEXTURE_GEN_Q", "LOC_TEXUNIT, TYPE_BIT_3, offsetof(struct gl_texture_unit, TexGenEnabled), NO_EXTRA" ],
+  [ "TEXTURE_GEN_S", "LOC_TEXUNIT, TYPE_BIT_0, offsetof(struct gl_fixedfunc_texture_unit, TexGenEnabled), NO_EXTRA" ],
+  [ "TEXTURE_GEN_T", "LOC_TEXUNIT, TYPE_BIT_1, offsetof(struct gl_fixedfunc_texture_unit, TexGenEnabled), NO_EXTRA" ],
+  [ "TEXTURE_GEN_R", "LOC_TEXUNIT, TYPE_BIT_2, offsetof(struct gl_fixedfunc_texture_unit, TexGenEnabled), NO_EXTRA" ],
+  [ "TEXTURE_GEN_Q", "LOC_TEXUNIT, TYPE_BIT_3, offsetof(struct gl_fixedfunc_texture_unit, TexGenEnabled), NO_EXTRA" ],
   [ "UNPACK_LSB_FIRST", "CONTEXT_BOOL(Unpack.LsbFirst), NO_EXTRA" ],
   [ "UNPACK_SWAP_BYTES", "CONTEXT_BOOL(Unpack.SwapBytes), NO_EXTRA" ],
   [ "ZOOM_X", "CONTEXT_FLOAT(Pixel.ZoomX), NO_EXTRA" ],
   [ "ZOOM_Y", "CONTEXT_FLOAT(Pixel.ZoomY), NO_EXTRA" ],
 
 # Vertex arrays
   [ "VERTEX_ARRAY_COUNT_EXT", "CONST(0), NO_EXTRA" ],
   [ "NORMAL_ARRAY_COUNT_EXT", "CONST(0), NO_EXTRA" ],
   [ "COLOR_ARRAY_COUNT_EXT", "CONST(0), NO_EXTRA" ],
   [ "INDEX_ARRAY", "ARRAY_BOOL(VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Enabled), NO_EXTRA" ],
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 46137f5..562fb17 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -1268,69 +1268,76 @@  struct gl_tex_env_combine_packed
 struct gl_texgen
 {
    GLenum16 Mode;       /**< GL_EYE_LINEAR, GL_SPHERE_MAP, etc */
    GLbitfield _ModeBit; /**< TEXGEN_x bit corresponding to Mode */
    GLfloat ObjectPlane[4];
    GLfloat EyePlane[4];
 };
 
 
 /**
- * Texture unit state.  Contains enable flags, texture environment/function/
- * combiners, texgen state, and pointers to current texture objects.
+ * Sampler-related subset of a texture unit, like current texture objects.
  */
 struct gl_texture_unit
 {
+   GLfloat LodBias;		/**< for biasing mipmap levels */
+
+   /** Texture targets that have a non-default texture bound */
+   GLbitfield _BoundTextures;
+
+   /** Current sampler object (GL_ARB_sampler_objects) */
+   struct gl_sampler_object *Sampler;
+
+   /** Current texture object pointers */
+   struct gl_texture_object *CurrentTex[NUM_TEXTURE_TARGETS];
+
+   /** Points to highest priority, complete and enabled texture object */
+   struct gl_texture_object *_Current;
+};
+
+
+/**
+ * Fixed-function-related subset of a texture unit, like enable flags,
+ * texture environment/function/combiners, and texgen state.
+ */
+struct gl_fixedfunc_texture_unit
+{
    GLbitfield Enabled;          /**< bitmask of TEXTURE_*_BIT flags */
 
    GLenum16 EnvMode;            /**< GL_MODULATE, GL_DECAL, GL_BLEND, etc. */
    GLclampf EnvColor[4];
    GLfloat EnvColorUnclamped[4];
 
    struct gl_texgen GenS;
    struct gl_texgen GenT;
    struct gl_texgen GenR;
    struct gl_texgen GenQ;
    GLbitfield TexGenEnabled;	/**< Bitwise-OR of [STRQ]_BIT values */
    GLbitfield _GenFlags;	/**< Bitwise-OR of Gen[STRQ]._ModeBit */
 
-   GLfloat LodBias;		/**< for biasing mipmap levels */
-
-   /** Texture targets that have a non-default texture bound */
-   GLbitfield _BoundTextures;
-
-   /** Current sampler object (GL_ARB_sampler_objects) */
-   struct gl_sampler_object *Sampler;
-
    /**
     * \name GL_EXT_texture_env_combine
     */
    struct gl_tex_env_combine_state Combine;
 
    /**
     * Derived state based on \c EnvMode and the \c BaseFormat of the
     * currently enabled texture.
     */
    struct gl_tex_env_combine_state _EnvMode;
 
    /**
     * Currently enabled combiner state.  This will point to either
     * \c Combine or \c _EnvMode.
     */
    struct gl_tex_env_combine_state *_CurrentCombine;
 
-   /** Current texture object pointers */
-   struct gl_texture_object *CurrentTex[NUM_TEXTURE_TARGETS];
-
-   /** Points to highest priority, complete and enabled texture object */
-   struct gl_texture_object *_Current;
-
    /** Current compressed TexEnv & Combine state */
    struct gl_tex_env_combine_packed _CurrentCombinePacked;
 };
 
 
 /**
  * Texture attribute group (GL_TEXTURE_BIT).
  */
 struct gl_texture_attrib
 {
@@ -1356,20 +1363,21 @@  struct gl_texture_attrib
    /** Bitwise-OR of all Texture.Unit[i]._GenFlags */
    GLbitfield _GenFlags;
 
    /** Largest index of a texture unit with _Current != NULL. */
    GLint _MaxEnabledTexImageUnit;
 
    /** Largest index + 1 of texture units that have had any CurrentTex set. */
    GLint NumCurrentTexUsed;
 
    struct gl_texture_unit Unit[MAX_COMBINED_TEXTURE_IMAGE_UNITS];
+   struct gl_fixedfunc_texture_unit FixedFuncUnit[MAX_COMBINED_TEXTURE_IMAGE_UNITS];
 };
 
 
 /**
  * Data structure representing a single clip plane (e.g. one of the elements
  * of the ctx->Transform.EyeUserPlane or ctx->Transform._ClipUserPlane array).
  */
 typedef GLfloat gl_clip_plane[4];
 
 
diff --git a/src/mesa/main/rastpos.c b/src/mesa/main/rastpos.c
index 43f6759..dd1042f 100644
--- a/src/mesa/main/rastpos.c
+++ b/src/mesa/main/rastpos.c
@@ -259,21 +259,22 @@  shade_rastpos(struct gl_context *ctx,
  * \param vObj  object-space vertex coordinate
  * \param vEye  eye-space vertex coordinate
  * \param normal  vertex normal
  * \param unit  texture unit number
  * \param texcoord  incoming texcoord and resulting texcoord
  */
 static void
 compute_texgen(struct gl_context *ctx, const GLfloat vObj[4], const GLfloat vEye[4],
                const GLfloat normal[3], GLuint unit, GLfloat texcoord[4])
 {
-   const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+   const struct gl_fixedfunc_texture_unit *texUnit =
+      &ctx->Texture.FixedFuncUnit[unit];
 
    /* always compute sphere map terms, just in case */
    GLfloat u[3], two_nu, rx, ry, rz, m, mInv;
    COPY_3V(u, vEye);
    NORMALIZE_3FV(u);
    two_nu = 2.0F * DOT3(normal, u);
    rx = u[0] - normal[0] * two_nu;
    ry = u[1] - normal[1] * two_nu;
    rz = u[2] - normal[2] * two_nu;
    m = rx * rx + ry * ry + (rz + 1.0F) * (rz + 1.0F);
@@ -457,21 +458,21 @@  _mesa_RasterPos(struct gl_context *ctx, const GLfloat vObj[4])
 	 COPY_4FV(ctx->Current.RasterSecondaryColor,
 		  ctx->Current.Attrib[VERT_ATTRIB_COLOR1]);
       }
 
       /* texture coords */
       {
          GLuint u;
          for (u = 0; u < ctx->Const.MaxTextureCoordUnits; u++) {
             GLfloat tc[4];
             COPY_4V(tc, ctx->Current.Attrib[VERT_ATTRIB_TEX0 + u]);
-            if (ctx->Texture.Unit[u].TexGenEnabled) {
+            if (ctx->Texture.FixedFuncUnit[u].TexGenEnabled) {
                compute_texgen(ctx, vObj, eye, norm, u, tc);
             }
             TRANSFORM_POINT(ctx->Current.RasterTexCoords[u],
                             ctx->TextureMatrixStack[u].Top->m, tc);
          }
       }
 
       ctx->Current.RasterPosValid = GL_TRUE;
    }
 
diff --git a/src/mesa/main/texenv.c b/src/mesa/main/texenv.c
index 2fcaf7c..9018ce9 100644
--- a/src/mesa/main/texenv.c
+++ b/src/mesa/main/texenv.c
@@ -41,21 +41,21 @@ 
 #include "main/texstate.h"
 
 
 #define TE_ERROR(errCode, msg, value)				\
    _mesa_error(ctx, errCode, msg, _mesa_enum_to_string(value));
 
 
 /** Set texture env mode */
 static void
 set_env_mode(struct gl_context *ctx,
-             struct gl_texture_unit *texUnit,
+             struct gl_fixedfunc_texture_unit *texUnit,
              GLenum mode)
 {
    GLboolean legal;
 
    if (texUnit->EnvMode == mode)
       return;
 
    switch (mode) {
    case GL_MODULATE:
    case GL_BLEND:
@@ -81,38 +81,38 @@  set_env_mode(struct gl_context *ctx,
       texUnit->EnvMode = mode;
    }
    else {
       TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
    }
 }
 
 
 static void
 set_env_color(struct gl_context *ctx,
-              struct gl_texture_unit *texUnit,
+              struct gl_fixedfunc_texture_unit *texUnit,
               const GLfloat *color)
 {
    if (TEST_EQ_4V(color, texUnit->EnvColorUnclamped))
       return;
    FLUSH_VERTICES(ctx, _NEW_TEXTURE_STATE);
    COPY_4FV(texUnit->EnvColorUnclamped, color);
    texUnit->EnvColor[0] = CLAMP(color[0], 0.0F, 1.0F);
    texUnit->EnvColor[1] = CLAMP(color[1], 0.0F, 1.0F);
    texUnit->EnvColor[2] = CLAMP(color[2], 0.0F, 1.0F);
    texUnit->EnvColor[3] = CLAMP(color[3], 0.0F, 1.0F);
 }
 
 
 /** Set an RGB or A combiner mode/function */
 static void
 set_combiner_mode(struct gl_context *ctx,
-                  struct gl_texture_unit *texUnit,
+                  struct gl_fixedfunc_texture_unit *texUnit,
                   GLenum pname, GLenum mode)
 {
    GLboolean legal;
 
    switch (mode) {
    case GL_REPLACE:
    case GL_MODULATE:
    case GL_ADD:
    case GL_ADD_SIGNED:
    case GL_INTERPOLATE:
@@ -164,21 +164,21 @@  set_combiner_mode(struct gl_context *ctx,
    default:
       TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
    }
 }
 
 
 
 /** Set an RGB or A combiner source term */
 static void
 set_combiner_source(struct gl_context *ctx,
-                    struct gl_texture_unit *texUnit,
+                    struct gl_fixedfunc_texture_unit *texUnit,
                     GLenum pname, GLenum param)
 {
    GLuint term;
    GLboolean alpha, legal;
 
    /*
     * Translate pname to (term, alpha).
     *
     * The enums were given sequential values for a reason.
     */
@@ -254,21 +254,21 @@  set_combiner_source(struct gl_context *ctx,
    if (alpha)
       texUnit->Combine.SourceA[term] = param;
    else
       texUnit->Combine.SourceRGB[term] = param;
 }
 
 
 /** Set an RGB or A combiner operand term */
 static void
 set_combiner_operand(struct gl_context *ctx,
-                     struct gl_texture_unit *texUnit,
+                     struct gl_fixedfunc_texture_unit *texUnit,
                      GLenum pname, GLenum param)
 {
    GLuint term;
    GLboolean alpha, legal;
 
    /* The enums were given sequential values for a reason.
     */
    switch (pname) {
    case GL_OPERAND0_RGB:
    case GL_OPERAND1_RGB:
@@ -335,21 +335,21 @@  set_combiner_operand(struct gl_context *ctx,
 
    if (alpha)
       texUnit->Combine.OperandA[term] = param;
    else
       texUnit->Combine.OperandRGB[term] = param;
 }
 
 
 static void
 set_combiner_scale(struct gl_context *ctx,
-                   struct gl_texture_unit *texUnit,
+                   struct gl_fixedfunc_texture_unit *texUnit,
                    GLenum pname, GLfloat scale)
 {
    GLuint shift;
 
    if (scale == 1.0F) {
       shift = 0;
    }
    else if (scale == 2.0F) {
       shift = 1;
    }
@@ -379,34 +379,34 @@  set_combiner_scale(struct gl_context *ctx,
       TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
    }
 }
 
 
 
 void GLAPIENTRY
 _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param )
 {
    const GLint iparam0 = (GLint) param[0];
-   struct gl_texture_unit *texUnit;
    GLuint maxUnit;
    GET_CURRENT_CONTEXT(ctx);
 
    maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV)
       ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxCombinedTextureImageUnits;
    if (ctx->Texture.CurrentUnit >= maxUnit) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "glTexEnvfv(current unit)");
       return;
    }
 
-   texUnit = _mesa_get_current_tex_unit(ctx);
-
    if (target == GL_TEXTURE_ENV) {
+      struct gl_fixedfunc_texture_unit *texUnit =
+         _mesa_get_current_fixedfunc_tex_unit(ctx);
+
       switch (pname) {
       case GL_TEXTURE_ENV_MODE:
          set_env_mode(ctx, texUnit, (GLenum) iparam0);
          break;
       case GL_TEXTURE_ENV_COLOR:
          set_env_color(ctx, texUnit, param);
          break;
       case GL_COMBINE_RGB:
       case GL_COMBINE_ALPHA:
          set_combiner_mode(ctx, texUnit, pname, (GLenum) iparam0);
@@ -434,20 +434,23 @@  _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param )
       case GL_RGB_SCALE:
       case GL_ALPHA_SCALE:
          set_combiner_scale(ctx, texUnit, pname, param[0]);
 	 break;
       default:
 	 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname)" );
 	 return;
       }
    }
    else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) {
+      struct gl_texture_unit *texUnit =
+         _mesa_get_current_tex_unit(ctx);
+
       if (pname == GL_TEXTURE_LOD_BIAS_EXT) {
 	 if (texUnit->LodBias == param[0])
 	    return;
 	 FLUSH_VERTICES(ctx, _NEW_TEXTURE_OBJECT);
          texUnit->LodBias = param[0];
       }
       else {
          TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
 	 return;
       }
@@ -540,21 +543,22 @@  _mesa_TexEnviv( GLenum target, GLenum pname, const GLint *param )
    _mesa_TexEnvfv( target, pname, p );
 }
 
 
 
 /**
  * Helper for glGetTexEnvi/f()
  * \return  value of queried pname or -1 if error.
  */
 static GLint
-get_texenvi(struct gl_context *ctx, const struct gl_texture_unit *texUnit,
+get_texenvi(struct gl_context *ctx,
+            const struct gl_fixedfunc_texture_unit *texUnit,
             GLenum pname)
 {
    switch (pname) {
    case GL_TEXTURE_ENV_MODE:
       return texUnit->EnvMode;
       break;
    case GL_COMBINE_RGB:
       return texUnit->Combine.ModeRGB;
    case GL_COMBINE_ALPHA:
       return texUnit->Combine.ModeA;
@@ -625,49 +629,51 @@  get_texenvi(struct gl_context *ctx, const struct gl_texture_unit *texUnit,
 
    return -1; /* error */
 }
 
 
 
 void GLAPIENTRY
 _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
 {
    GLuint maxUnit;
-   const struct gl_texture_unit *texUnit;
    GET_CURRENT_CONTEXT(ctx);
 
    maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV)
       ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxCombinedTextureImageUnits;
    if (ctx->Texture.CurrentUnit >= maxUnit) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexEnvfv(current unit)");
       return;
    }
 
-   texUnit = _mesa_get_current_tex_unit(ctx);
-
    if (target == GL_TEXTURE_ENV) {
+      struct gl_fixedfunc_texture_unit *texUnit =
+         _mesa_get_current_fixedfunc_tex_unit(ctx);
+
       if (pname == GL_TEXTURE_ENV_COLOR) {
          if(ctx->NewState & (_NEW_BUFFERS | _NEW_FRAG_CLAMP))
             _mesa_update_state(ctx);
          if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer))
             COPY_4FV( params, texUnit->EnvColor );
          else
             COPY_4FV( params, texUnit->EnvColorUnclamped );
       }
       else {
          GLint val = get_texenvi(ctx, texUnit, pname);
          if (val >= 0) {
             *params = (GLfloat) val;
          }
       }
    }
    else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) {
+      const struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
+
       if (pname == GL_TEXTURE_LOD_BIAS_EXT) {
          *params = texUnit->LodBias;
       }
       else {
          _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)" );
 	 return;
       }
    }
    else if (target == GL_POINT_SPRITE_NV) {
       /* GL_ARB_point_sprite / GL_NV_point_sprite */
@@ -691,47 +697,49 @@  _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
       _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" );
       return;
    }
 }
 
 
 void GLAPIENTRY
 _mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params )
 {
    GLuint maxUnit;
-   const struct gl_texture_unit *texUnit;
    GET_CURRENT_CONTEXT(ctx);
 
    maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV)
       ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxCombinedTextureImageUnits;
    if (ctx->Texture.CurrentUnit >= maxUnit) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexEnviv(current unit)");
       return;
    }
 
-   texUnit = _mesa_get_current_tex_unit(ctx);
-
    if (target == GL_TEXTURE_ENV) {
+      struct gl_fixedfunc_texture_unit *texUnit =
+         _mesa_get_current_fixedfunc_tex_unit(ctx);
+
       if (pname == GL_TEXTURE_ENV_COLOR) {
          params[0] = FLOAT_TO_INT( texUnit->EnvColor[0] );
          params[1] = FLOAT_TO_INT( texUnit->EnvColor[1] );
          params[2] = FLOAT_TO_INT( texUnit->EnvColor[2] );
          params[3] = FLOAT_TO_INT( texUnit->EnvColor[3] );
       }
       else {
          GLint val = get_texenvi(ctx, texUnit, pname);
          if (val >= 0) {
             *params = val;
          }
       }
    }
    else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) {
+      const struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
+
       if (pname == GL_TEXTURE_LOD_BIAS_EXT) {
          *params = (GLint) texUnit->LodBias;
       }
       else {
          _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)" );
 	 return;
       }
    }
    else if (target == GL_POINT_SPRITE_NV) {
       /* GL_ARB_point_sprite / GL_NV_point_sprite */
diff --git a/src/mesa/main/texgen.c b/src/mesa/main/texgen.c
index 1b8d187..45f86fd 100644
--- a/src/mesa/main/texgen.c
+++ b/src/mesa/main/texgen.c
@@ -37,21 +37,21 @@ 
 #include "main/texgen.h"
 #include "main/texstate.h"
 #include "math/m_matrix.h"
 #include "main/dispatch.h"
 
 
 /**
  * Return texgen state for given coordinate
  */
 static struct gl_texgen *
-get_texgen(struct gl_context *ctx, struct gl_texture_unit *texUnit,
+get_texgen(struct gl_context *ctx, struct gl_fixedfunc_texture_unit *texUnit,
            GLenum coord)
 {
    if (ctx->API == API_OPENGLES) {
       return (coord == GL_TEXTURE_GEN_STR_OES)
          ? &texUnit->GenS : NULL;
    }
 
    switch (coord) {
    case GL_S:
       return &texUnit->GenS;
@@ -63,37 +63,37 @@  get_texgen(struct gl_context *ctx, struct gl_texture_unit *texUnit,
       return &texUnit->GenQ;
    default:
       return NULL;
    }
 }
 
 
 void GLAPIENTRY
 _mesa_TexGenfv( GLenum coord, GLenum pname, const GLfloat *params )
 {
-   struct gl_texture_unit *texUnit;
+   struct gl_fixedfunc_texture_unit *texUnit;
    struct gl_texgen *texgen;
    GET_CURRENT_CONTEXT(ctx);
 
    if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE))
       _mesa_debug(ctx, "glTexGen %s %s %.1f(%s)...\n",
                   _mesa_enum_to_string(coord),
                   _mesa_enum_to_string(pname),
                   *params,
 		  _mesa_enum_to_string((GLenum) (GLint) *params));
 
    if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "glTexGen(current unit)");
       return;
    }
 
-   texUnit = _mesa_get_current_tex_unit(ctx);
+   texUnit = _mesa_get_current_fixedfunc_tex_unit(ctx);
 
    texgen = get_texgen(ctx, texUnit, coord);
    if (!texgen) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glTexGen(coord)");
       return;
    }
 
    switch (pname) {
    case GL_TEXTURE_GEN_MODE:
       {
@@ -282,30 +282,30 @@  _mesa_TexGeni( GLenum coord, GLenum pname, GLint param )
    p[0] = param;
    p[1] = p[2] = p[3] = 0;
    _mesa_TexGeniv( coord, pname, p );
 }
 
 
 
 void GLAPIENTRY
 _mesa_GetTexGendv( GLenum coord, GLenum pname, GLdouble *params )
 {
-   struct gl_texture_unit *texUnit;
+   struct gl_fixedfunc_texture_unit *texUnit;
    struct gl_texgen *texgen;
    GET_CURRENT_CONTEXT(ctx);
 
    if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexGendv(current unit)");
       return;
    }
 
-   texUnit = _mesa_get_current_tex_unit(ctx);
+   texUnit = _mesa_get_current_fixedfunc_tex_unit(ctx);
 
    texgen = get_texgen(ctx, texUnit, coord);
    if (!texgen) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexGendv(coord)");
       return;
    }
 
    switch (pname) {
    case GL_TEXTURE_GEN_MODE:
       params[0] = ENUM_TO_DOUBLE(texgen->Mode);
@@ -319,30 +319,30 @@  _mesa_GetTexGendv( GLenum coord, GLenum pname, GLdouble *params )
    default:
       _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGendv(pname)" );
    }
 }
 
 
 
 void GLAPIENTRY
 _mesa_GetTexGenfv( GLenum coord, GLenum pname, GLfloat *params )
 {
-   struct gl_texture_unit *texUnit;
+   struct gl_fixedfunc_texture_unit *texUnit;
    struct gl_texgen *texgen;
    GET_CURRENT_CONTEXT(ctx);
 
    if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexGenfv(current unit)");
       return;
    }
 
-   texUnit = _mesa_get_current_tex_unit(ctx);
+   texUnit = _mesa_get_current_fixedfunc_tex_unit(ctx);
 
    texgen = get_texgen(ctx, texUnit, coord);
    if (!texgen) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexGenfv(coord)");
       return;
    }
 
    switch (pname) {
    case GL_TEXTURE_GEN_MODE:
       params[0] = ENUM_TO_FLOAT(texgen->Mode);
@@ -364,30 +364,30 @@  _mesa_GetTexGenfv( GLenum coord, GLenum pname, GLfloat *params )
    default:
       _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(pname)" );
    }
 }
 
 
 
 void GLAPIENTRY
 _mesa_GetTexGeniv( GLenum coord, GLenum pname, GLint *params )
 {
-   struct gl_texture_unit *texUnit;
+   struct gl_fixedfunc_texture_unit *texUnit;
    struct gl_texgen *texgen;
    GET_CURRENT_CONTEXT(ctx);
 
    if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexGeniv(current unit)");
       return;
    }
 
-   texUnit = _mesa_get_current_tex_unit(ctx);
+   texUnit = _mesa_get_current_fixedfunc_tex_unit(ctx);
 
    texgen = get_texgen(ctx, texUnit, coord);
    if (!texgen) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexGeniv(coord)");
       return;
    }
 
    switch (pname) {
    case GL_TEXTURE_GEN_MODE:
       params[0] = texgen->Mode;
diff --git a/src/mesa/main/texstate.c b/src/mesa/main/texstate.c
index e24b3c4..2b05630 100644
--- a/src/mesa/main/texstate.c
+++ b/src/mesa/main/texstate.c
@@ -71,33 +71,22 @@  _mesa_copy_texture_state( const struct gl_context *src, struct gl_context *dst )
    assert(src);
    assert(dst);
 
    dst->Texture.CurrentUnit = src->Texture.CurrentUnit;
    dst->Texture._GenFlags = src->Texture._GenFlags;
    dst->Texture._TexGenEnabled = src->Texture._TexGenEnabled;
    dst->Texture._TexMatEnabled = src->Texture._TexMatEnabled;
 
    /* per-unit state */
    for (u = 0; u < src->Const.MaxCombinedTextureImageUnits; 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[u].Combine = src->Texture.Unit[u].Combine;
-
       /*
        * XXX strictly speaking, we should compare texture names/ids and
        * bind textures in the dest context according to id.  For now, only
        * copy bindings if the contexts share the same pool of textures to
        * avoid refcounting bugs.
        */
       if (dst->Shared == src->Shared) {
          /* copy texture object bindings, not contents of texture objects */
          _mesa_lock_context_textures(dst);
 
@@ -106,30 +95,44 @@  _mesa_copy_texture_state( const struct gl_context *src, struct gl_context *dst )
                                    src->Texture.Unit[u].CurrentTex[tex]);
             if (src->Texture.Unit[u].CurrentTex[tex]) {
                dst->Texture.NumCurrentTexUsed =
                   MAX2(dst->Texture.NumCurrentTexUsed, u + 1);
             }
          }
          dst->Texture.Unit[u]._BoundTextures = src->Texture.Unit[u]._BoundTextures;
          _mesa_unlock_context_textures(dst);
       }
    }
+
+   for (u = 0; u < src->Const.MaxCombinedTextureImageUnits; u++) {
+      dst->Texture.FixedFuncUnit[u].Enabled = src->Texture.FixedFuncUnit[u].Enabled;
+      dst->Texture.FixedFuncUnit[u].EnvMode = src->Texture.FixedFuncUnit[u].EnvMode;
+      COPY_4V(dst->Texture.FixedFuncUnit[u].EnvColor, src->Texture.FixedFuncUnit[u].EnvColor);
+      dst->Texture.FixedFuncUnit[u].TexGenEnabled = src->Texture.FixedFuncUnit[u].TexGenEnabled;
+      dst->Texture.FixedFuncUnit[u].GenS = src->Texture.FixedFuncUnit[u].GenS;
+      dst->Texture.FixedFuncUnit[u].GenT = src->Texture.FixedFuncUnit[u].GenT;
+      dst->Texture.FixedFuncUnit[u].GenR = src->Texture.FixedFuncUnit[u].GenR;
+      dst->Texture.FixedFuncUnit[u].GenQ = src->Texture.FixedFuncUnit[u].GenQ;
+
+      /* GL_EXT_texture_env_combine */
+      dst->Texture.FixedFuncUnit[u].Combine = src->Texture.FixedFuncUnit[u].Combine;
+   }
 }
 
 
 /*
  * For debugging
  */
 void
 _mesa_print_texunit_state( struct gl_context *ctx, GLuint unit )
 {
-   const struct gl_texture_unit *texUnit = ctx->Texture.Unit + unit;
+   const struct gl_fixedfunc_texture_unit *texUnit = ctx->Texture.FixedFuncUnit + unit;
    printf("Texture Unit %d\n", unit);
    printf("  GL_TEXTURE_ENV_MODE = %s\n", _mesa_enum_to_string(texUnit->EnvMode));
    printf("  GL_COMBINE_RGB = %s\n", _mesa_enum_to_string(texUnit->Combine.ModeRGB));
    printf("  GL_COMBINE_ALPHA = %s\n", _mesa_enum_to_string(texUnit->Combine.ModeA));
    printf("  GL_SOURCE0_RGB = %s\n", _mesa_enum_to_string(texUnit->Combine.SourceRGB[0]));
    printf("  GL_SOURCE1_RGB = %s\n", _mesa_enum_to_string(texUnit->Combine.SourceRGB[1]));
    printf("  GL_SOURCE2_RGB = %s\n", _mesa_enum_to_string(texUnit->Combine.SourceRGB[2]));
    printf("  GL_SOURCE0_ALPHA = %s\n", _mesa_enum_to_string(texUnit->Combine.SourceA[0]));
    printf("  GL_SOURCE1_ALPHA = %s\n", _mesa_enum_to_string(texUnit->Combine.SourceA[1]));
    printf("  GL_SOURCE2_ALPHA = %s\n", _mesa_enum_to_string(texUnit->Combine.SourceA[2]));
@@ -454,21 +457,21 @@  tex_combine_translate_operand(GLenum operand)
    case GL_ONE_MINUS_SRC_COLOR: return TEXENV_OPR_ONE_MINUS_COLOR;
    case GL_SRC_ALPHA: return TEXENV_OPR_ALPHA;
    case GL_ONE_MINUS_SRC_ALPHA: return TEXENV_OPR_ONE_MINUS_ALPHA;
    default:
       unreachable("Invalid TexEnv Combine argument source");
    }
 }
 
 
 static void
-pack_tex_combine(struct gl_texture_unit *texUnit)
+pack_tex_combine(struct gl_fixedfunc_texture_unit *texUnit)
 {
    struct gl_tex_env_combine_state *state = texUnit->_CurrentCombine;
    struct gl_tex_env_combine_packed *packed = &texUnit->_CurrentCombinePacked;
 
    memset(packed, 0, sizeof *packed);
 
    packed->ModeRGB = tex_combine_translate_mode(texUnit->EnvMode, state->ModeRGB);
    packed->ModeA = tex_combine_translate_mode(texUnit->EnvMode, state->ModeA);
    packed->ScaleShiftRGB = state->ScaleShiftRGB;
    packed->ScaleShiftA = state->ScaleShiftA;
@@ -486,57 +489,59 @@  pack_tex_combine(struct gl_texture_unit *texUnit)
       packed->ArgsA[i].Source = tex_combine_translate_source(state->SourceA[i]);
       packed->ArgsA[i].Operand = tex_combine_translate_operand(state->OperandA[i]);
    }
 }
 
 
 /**
  * Examine texture unit's combine/env state to update derived state.
  */
 static void
-update_tex_combine(struct gl_context *ctx, struct gl_texture_unit *texUnit)
+update_tex_combine(struct gl_context *ctx,
+                   struct gl_texture_unit *texUnit,
+                   struct gl_fixedfunc_texture_unit *fftexUnit)
 {
    struct gl_tex_env_combine_state *combine;
 
    /* No combiners will apply to this. */
    if (texUnit->_Current->Target == GL_TEXTURE_BUFFER)
       return;
 
    /* 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 (texUnit->EnvMode == GL_COMBINE ||
-       texUnit->EnvMode == GL_COMBINE4_NV) {
-      texUnit->_CurrentCombine = & texUnit->Combine;
+   if (fftexUnit->EnvMode == GL_COMBINE ||
+       fftexUnit->EnvMode == GL_COMBINE4_NV) {
+      fftexUnit->_CurrentCombine = & fftexUnit->Combine;
    }
    else {
       const struct gl_texture_object *texObj = texUnit->_Current;
       GLenum format = texObj->Image[0][texObj->BaseLevel]->_BaseFormat;
 
       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;
+      calculate_derived_texenv(&fftexUnit->_EnvMode, fftexUnit->EnvMode, format);
+      fftexUnit->_CurrentCombine = & fftexUnit->_EnvMode;
    }
 
-   combine = texUnit->_CurrentCombine;
+   combine = fftexUnit->_CurrentCombine;
 
    /* 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)
+      if (fftexUnit->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:
@@ -554,52 +559,53 @@  update_tex_combine(struct gl_context *ctx, struct gl_texture_unit *texUnit)
       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)
+      if (fftexUnit->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;
    }
 
-   pack_tex_combine(texUnit);
+   pack_tex_combine(fftexUnit);
 }
 
 static void
 update_texgen(struct gl_context *ctx)
 {
    GLuint unit;
 
    /* 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];
+      struct gl_fixedfunc_texture_unit *texUnit =
+         &ctx->Texture.FixedFuncUnit[unit];
 
       texUnit->_GenFlags = 0x0;
 
       if (!(ctx->Texture._EnabledCoordUnits & (1 << unit)))
 	 continue;
 
       if (texUnit->TexGenEnabled) {
 	 if (texUnit->TexGenEnabled & S_BIT) {
 	    texUnit->_GenFlags |= texUnit->GenS._ModeBit;
 	 }
@@ -741,24 +747,26 @@  update_program_texture_state(struct gl_context *ctx, struct gl_program **prog,
 }
 
 static void
 update_ff_texture_state(struct gl_context *ctx,
                         BITSET_WORD *enabled_texture_units)
 {
    int unit;
 
    for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
       struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+      struct gl_fixedfunc_texture_unit *fftexUnit =
+         &ctx->Texture.FixedFuncUnit[unit];
       GLbitfield mask;
       bool complete;
 
-      if (texUnit->Enabled == 0x0)
+      if (fftexUnit->Enabled == 0x0)
          continue;
 
       /* If a shader already dictated what texture target was used for this
        * unit, just go along with it.
        */
       if (BITSET_TEST(enabled_texture_units, unit))
          continue;
 
       /* From the GL 4.4 compat specification, section 16.2 ("Texture Application"):
        *
@@ -781,21 +789,21 @@  update_ff_texture_state(struct gl_context *ctx,
        *
        *     "If a texture unit is disabled or has an invalid or incomplete
        *      texture (as defined in section 8.17) bound to it, then blending
        *      is disabled for that texture unit. If the texture environment
        *      for a given enabled texture unit references a disabled texture
        *      unit, or an invalid or incomplete texture that is bound to
        *      another unit, then the results of texture blending are
        *      undefined."
        */
       complete = false;
-      mask = texUnit->Enabled;
+      mask = fftexUnit->Enabled;
       while (mask) {
          const int texIndex = u_bit_scan(&mask);
          struct gl_texture_object *texObj = texUnit->CurrentTex[texIndex];
          struct gl_sampler_object *sampler = texUnit->Sampler ?
             texUnit->Sampler : &texObj->Sampler;
 
          if (!_mesa_is_texture_complete(texObj, sampler)) {
             _mesa_test_texobj_completeness(ctx, texObj);
          }
          if (_mesa_is_texture_complete(texObj, sampler)) {
@@ -808,21 +816,21 @@  update_ff_texture_state(struct gl_context *ctx,
       if (!complete)
          continue;
 
       /* if we get here, we know this texture unit is enabled */
       BITSET_SET(enabled_texture_units, unit);
       ctx->Texture._MaxEnabledTexImageUnit =
          MAX2(ctx->Texture._MaxEnabledTexImageUnit, (int)unit);
 
       ctx->Texture._EnabledCoordUnits |= 1 << unit;
 
-      update_tex_combine(ctx, texUnit);
+      update_tex_combine(ctx, texUnit, fftexUnit);
    }
 }
 
 static void
 fix_missing_textures_for_atifs(struct gl_context *ctx,
                                struct gl_program *prog,
                                BITSET_WORD *enabled_texture_units)
 {
    GLbitfield mask = prog->SamplersUsed;
 
@@ -991,20 +999,33 @@  _mesa_init_texture(struct gl_context *ctx)
     * enable seamless cubemaps by default since GLES2. This should work
     * for most implementations and drivers that don't support seamless
     * cubemaps for GLES2 can still disable it.
     */
    ctx->Texture.CubeMapSeamless = ctx->API == API_OPENGLES2;
 
    for (u = 0; u < ARRAY_SIZE(ctx->Texture.Unit); u++) {
       struct gl_texture_unit *texUnit = &ctx->Texture.Unit[u];
       GLuint tex;
 
+      /* initialize current texture object ptrs to the shared default objects */
+      for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
+         _mesa_reference_texobj(&texUnit->CurrentTex[tex],
+                                ctx->Shared->DefaultTex[tex]);
+      }
+
+      texUnit->_BoundTextures = 0;
+   }
+
+   for (u = 0; u < ARRAY_SIZE(ctx->Texture.FixedFuncUnit); u++) {
+      struct gl_fixedfunc_texture_unit *texUnit =
+         &ctx->Texture.FixedFuncUnit[u];
+
       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 = 0x0;
       texUnit->GenS.Mode = GL_EYE_LINEAR;
       texUnit->GenT.Mode = GL_EYE_LINEAR;
@@ -1017,28 +1038,20 @@  _mesa_init_texture(struct gl_context *ctx)
 
       /* Yes, these plane coefficients are correct! */
       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 );
-
-      /* initialize current texture object ptrs to the shared default objects */
-      for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
-         _mesa_reference_texobj(&texUnit->CurrentTex[tex],
-                                ctx->Shared->DefaultTex[tex]);
-      }
-
-      texUnit->_BoundTextures = 0;
    }
 
    /* After we're done initializing the context's texture state the default
     * texture objects' refcounts should be at least
     * MAX_COMBINED_TEXTURE_IMAGE_UNITS + 1.
     */
    assert(ctx->Shared->DefaultTex[TEXTURE_1D_INDEX]->RefCount
           >= MAX_COMBINED_TEXTURE_IMAGE_UNITS + 1);
 
    /* Allocate proxy textures */
diff --git a/src/mesa/main/texstate.h b/src/mesa/main/texstate.h
index 4f515e4..cf3f7e5 100644
--- a/src/mesa/main/texstate.h
+++ b/src/mesa/main/texstate.h
@@ -47,20 +47,35 @@  _mesa_get_tex_unit(struct gl_context *ctx, GLuint unit)
 /**
  * Return pointer to current texture unit.
  * This the texture unit set by glActiveTexture(), not glClientActiveTexture().
  */
 static inline struct gl_texture_unit *
 _mesa_get_current_tex_unit(struct gl_context *ctx)
 {
    return _mesa_get_tex_unit(ctx, ctx->Texture.CurrentUnit);
 }
 
+
+/**
+ * Return pointer to current fixed-func texture unit.
+ * This the texture unit set by glActiveTexture(), not glClientActiveTexture().
+ * \return NULL if the current unit is not a fixed-func texture unit
+ */
+static inline struct gl_fixedfunc_texture_unit *
+_mesa_get_current_fixedfunc_tex_unit(struct gl_context *ctx)
+{
+   unsigned unit = ctx->Texture.CurrentUnit;
+
+   return &ctx->Texture.FixedFuncUnit[unit];
+}
+
+
 static inline GLuint
 _mesa_max_tex_unit(struct gl_context *ctx)
 {
    /* See OpenGL spec for glActiveTexture: */
    return MAX2(ctx->Const.MaxCombinedTextureImageUnits,
                ctx->Const.MaxTextureCoordUnits);
 }
 
 
 extern void
diff --git a/src/mesa/program/prog_statevars.c b/src/mesa/program/prog_statevars.c
index 481123a..78f7005 100644
--- a/src/mesa/program/prog_statevars.c
+++ b/src/mesa/program/prog_statevars.c
@@ -208,56 +208,56 @@  _mesa_fetch_state(struct gl_context *ctx, const gl_state_index state[],
                return;
          }
       }
    case STATE_TEXGEN:
       {
          /* state[1] is the texture unit */
          const GLuint unit = (GLuint) state[1];
          /* state[2] is the texgen attribute */
          switch (state[2]) {
          case STATE_TEXGEN_EYE_S:
-            COPY_4V(value, ctx->Texture.Unit[unit].GenS.EyePlane);
+            COPY_4V(value, ctx->Texture.FixedFuncUnit[unit].GenS.EyePlane);
             return;
          case STATE_TEXGEN_EYE_T:
-            COPY_4V(value, ctx->Texture.Unit[unit].GenT.EyePlane);
+            COPY_4V(value, ctx->Texture.FixedFuncUnit[unit].GenT.EyePlane);
             return;
          case STATE_TEXGEN_EYE_R:
-            COPY_4V(value, ctx->Texture.Unit[unit].GenR.EyePlane);
+            COPY_4V(value, ctx->Texture.FixedFuncUnit[unit].GenR.EyePlane);
             return;
          case STATE_TEXGEN_EYE_Q:
-            COPY_4V(value, ctx->Texture.Unit[unit].GenQ.EyePlane);
+            COPY_4V(value, ctx->Texture.FixedFuncUnit[unit].GenQ.EyePlane);
             return;
          case STATE_TEXGEN_OBJECT_S:
-            COPY_4V(value, ctx->Texture.Unit[unit].GenS.ObjectPlane);
+            COPY_4V(value, ctx->Texture.FixedFuncUnit[unit].GenS.ObjectPlane);
             return;
          case STATE_TEXGEN_OBJECT_T:
-            COPY_4V(value, ctx->Texture.Unit[unit].GenT.ObjectPlane);
+            COPY_4V(value, ctx->Texture.FixedFuncUnit[unit].GenT.ObjectPlane);
             return;
          case STATE_TEXGEN_OBJECT_R:
-            COPY_4V(value, ctx->Texture.Unit[unit].GenR.ObjectPlane);
+            COPY_4V(value, ctx->Texture.FixedFuncUnit[unit].GenR.ObjectPlane);
             return;
          case STATE_TEXGEN_OBJECT_Q:
-            COPY_4V(value, ctx->Texture.Unit[unit].GenQ.ObjectPlane);
+            COPY_4V(value, ctx->Texture.FixedFuncUnit[unit].GenQ.ObjectPlane);
             return;
          default:
             _mesa_problem(ctx, "Invalid texgen state in fetch_state");
             return;
          }
       }
    case STATE_TEXENV_COLOR:
       {
          /* state[1] is the texture unit */
          const GLuint unit = (GLuint) state[1];
          if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer))
-            COPY_4V(value, ctx->Texture.Unit[unit].EnvColor);
+            COPY_4V(value, ctx->Texture.FixedFuncUnit[unit].EnvColor);
          else
-            COPY_4V(value, ctx->Texture.Unit[unit].EnvColorUnclamped);
+            COPY_4V(value, ctx->Texture.FixedFuncUnit[unit].EnvColorUnclamped);
       }
       return;
    case STATE_FOG_COLOR:
       if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer))
          COPY_4V(value, ctx->Fog.Color);
       else
          COPY_4V(value, ctx->Fog.ColorUnclamped);
       return;
    case STATE_FOG_PARAMS:
       value[0] = ctx->Fog.Density;
diff --git a/src/mesa/swrast/s_context.c b/src/mesa/swrast/s_context.c
index f7f08b1..0c12a63 100644
--- a/src/mesa/swrast/s_context.c
+++ b/src/mesa/swrast/s_context.c
@@ -178,21 +178,21 @@  _swrast_update_fog_hint( struct gl_context *ctx )
 static void
 _swrast_update_texture_env( struct gl_context *ctx )
 {
    SWcontext *swrast = SWRAST_CONTEXT(ctx);
    GLuint i;
 
    swrast->_TextureCombinePrimary = GL_FALSE;
 
    for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
       const struct gl_tex_env_combine_state *combine =
-         ctx->Texture.Unit[i]._CurrentCombine;
+         ctx->Texture.FixedFuncUnit[i]._CurrentCombine;
       GLuint term;
       for (term = 0; term < combine->_NumArgsRGB; term++) {
          if (combine->SourceRGB[term] == GL_PRIMARY_COLOR) {
             swrast->_TextureCombinePrimary = GL_TRUE;
             return;
          }
          if (combine->SourceA[term] == GL_PRIMARY_COLOR) {
             swrast->_TextureCombinePrimary = GL_TRUE;
             return;
          }
diff --git a/src/mesa/swrast/s_texcombine.c b/src/mesa/swrast/s_texcombine.c
index da4a013..743ee40 100644
--- a/src/mesa/swrast/s_texcombine.c
+++ b/src/mesa/swrast/s_texcombine.c
@@ -77,21 +77,22 @@  get_texel_array(SWcontext *swrast, GLuint unit)
  *                       span->end: number of fragments to process
  *                       span->array->rgba: incoming/result fragment colors
  */
 static void
 texture_combine( struct gl_context *ctx, GLuint unit,
                  const float4_array primary_rgba,
                  const GLfloat *texelBuffer,
                  SWspan *span )
 {
    SWcontext *swrast = SWRAST_CONTEXT(ctx);
-   const struct gl_texture_unit *textureUnit = &(ctx->Texture.Unit[unit]);
+   const struct gl_fixedfunc_texture_unit *textureUnit =
+      &ctx->Texture.FixedFuncUnit[unit];
    const struct gl_tex_env_combine_state *combine = textureUnit->_CurrentCombine;
    float4_array argRGB[MAX_COMBINER_TERMS];
    float4_array argA[MAX_COMBINER_TERMS];
    const GLfloat scaleRGB = (GLfloat) (1 << combine->ScaleShiftRGB);
    const GLfloat scaleA = (GLfloat) (1 << combine->ScaleShiftA);
    const GLuint numArgsRGB = combine->_NumArgsRGB;
    const GLuint numArgsA = combine->_NumArgsA;
    float4_array ccolor[4], rgba;
    GLuint i, term;
    GLuint n = span->end;
diff --git a/src/mesa/swrast/s_triangle.c b/src/mesa/swrast/s_triangle.c
index c84cfec..d80ab18 100644
--- a/src/mesa/swrast/s_triangle.c
+++ b/src/mesa/swrast/s_triangle.c
@@ -532,21 +532,21 @@  affine_span(struct gl_context *ctx, SWspan *span,
 #define NAME affine_textured_triangle
 #define INTERP_Z 1
 #define INTERP_RGB 1
 #define INTERP_ALPHA 1
 #define INTERP_INT_TEX 1
 #define S_SCALE twidth
 #define T_SCALE theight
 
 #define SETUP_CODE							\
    struct affine_info info;						\
-   struct gl_texture_unit *unit = ctx->Texture.Unit+0;			\
+   struct gl_fixedfunc_texture_unit *unit = ctx->Texture.FixedFuncUnit+0; \
    const struct gl_texture_object *obj = 				\
       ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX];		\
    const struct gl_texture_image *texImg = 				\
       _mesa_base_tex_image(obj);					\
    const struct swrast_texture_image *swImg =				\
       swrast_texture_image_const(texImg);				\
    const GLfloat twidth = (GLfloat) texImg->Width;			\
    const GLfloat theight = (GLfloat) texImg->Height;			\
    info.texture = (const GLchan *) swImg->ImageSlices[0];		\
    info.twidth_log2 = texImg->WidthLog2;				\
@@ -801,21 +801,21 @@  fast_persp_span(struct gl_context *ctx, SWspan *span,
  *
  */
 #define NAME persp_textured_triangle
 #define INTERP_Z 1
 #define INTERP_RGB 1
 #define INTERP_ALPHA 1
 #define INTERP_ATTRIBS 1
 
 #define SETUP_CODE							\
    struct persp_info info;						\
-   const struct gl_texture_unit *unit = ctx->Texture.Unit+0;		\
+   const struct gl_fixedfunc_texture_unit *unit = ctx->Texture.FixedFuncUnit+0; \
    const struct gl_texture_object *obj = 				\
       ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX];		\
    const struct gl_texture_image *texImg = 				\
       _mesa_base_tex_image(obj);					\
    const struct swrast_texture_image *swImg =				\
       swrast_texture_image_const(texImg);				\
    info.texture = (const GLchan *) swImg->ImageSlices[0];		\
    info.twidth_log2 = texImg->WidthLog2;				\
    info.smask = texImg->Width - 1;					\
    info.tmask = texImg->Height - 1;					\
@@ -1059,41 +1059,41 @@  _swrast_choose_triangle( struct gl_context *ctx )
             samp = &texObj2D->Sampler;
          else
             samp = NULL;
 
          texImg = texObj2D ? _mesa_base_tex_image(texObj2D) : NULL;
          swImg = swrast_texture_image_const(texImg);
 
          format = texImg ? texImg->TexFormat : MESA_FORMAT_NONE;
          minFilter = texObj2D ? samp->MinFilter : GL_NONE;
          magFilter = texObj2D ? samp->MagFilter : GL_NONE;
-         envMode = ctx->Texture.Unit[0].EnvMode;
+         envMode = ctx->Texture.FixedFuncUnit[0].EnvMode;
 
          /* First see if we can use an optimized 2-D texture function */
          if (ctx->Texture._EnabledCoordUnits == 0x1
              && !_swrast_use_fragment_program(ctx)
              && !_mesa_ati_fragment_shader_enabled(ctx)
              && ctx->Texture._MaxEnabledTexImageUnit == 0
              && ctx->Texture.Unit[0]._Current->Target == GL_TEXTURE_2D
              && samp->WrapS == GL_REPEAT
              && samp->WrapT == GL_REPEAT
              && texObj2D->_Swizzle == SWIZZLE_NOOP
              && swImg->_IsPowerOfTwo
              && texImg->Border == 0
              && (_mesa_format_row_stride(format, texImg->Width) ==
                  swImg->RowStride)
              && (format == MESA_FORMAT_BGR_UNORM8 || format == MESA_FORMAT_A8B8G8R8_UNORM)
              && minFilter == magFilter
              && ctx->Light.Model.ColorControl == GL_SINGLE_COLOR
              && !swrast->_FogEnabled
-             && ctx->Texture.Unit[0].EnvMode != GL_COMBINE_EXT
-             && ctx->Texture.Unit[0].EnvMode != GL_COMBINE4_NV) {
+             && ctx->Texture.FixedFuncUnit[0].EnvMode != GL_COMBINE_EXT
+             && ctx->Texture.FixedFuncUnit[0].EnvMode != GL_COMBINE4_NV) {
 	    if (ctx->Hint.PerspectiveCorrection==GL_FASTEST) {
 	       if (minFilter == GL_NEAREST
 		   && format == MESA_FORMAT_BGR_UNORM8
 		   && (envMode == GL_REPLACE || envMode == GL_DECAL)
 		   && ((swrast->_RasterMask == (DEPTH_BIT | TEXTURE_BIT)
 			&& ctx->Depth.Func == GL_LESS
 			&& ctx->Depth.Mask == GL_TRUE)
 		       || swrast->_RasterMask == TEXTURE_BIT)
 		   && ctx->Polygon.StippleFlag == GL_FALSE
                    && ctx->DrawBuffer->Visual.depthBits <= 16) {
diff --git a/src/mesa/tnl/t_vb_texgen.c b/src/mesa/tnl/t_vb_texgen.c
index 94066f4..a13262d 100644
--- a/src/mesa/tnl/t_vb_texgen.c
+++ b/src/mesa/tnl/t_vb_texgen.c
@@ -330,21 +330,22 @@  static void texgen_sphere_map( struct gl_context *ctx,
 
 
 static void texgen( struct gl_context *ctx,
 		    struct texgen_stage_data *store,
 		    GLuint unit )
 {
    TNLcontext *tnl = TNL_CONTEXT(ctx);
    struct vertex_buffer *VB = &tnl->vb;
    GLvector4f *in = VB->AttribPtr[VERT_ATTRIB_TEX0 + unit];
    GLvector4f *out = &store->texcoord[unit];
-   const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+   const struct gl_fixedfunc_texture_unit *texUnit =
+      &ctx->Texture.FixedFuncUnit[unit];
    const GLvector4f *obj = VB->AttribPtr[_TNL_ATTRIB_POS];
    const GLvector4f *eye = VB->EyePtr;
    const GLvector4f *normal = VB->AttribPtr[_TNL_ATTRIB_NORMAL];
    const GLfloat *m = store->tmp_m;
    const GLuint count = VB->Count;
    GLfloat (*texcoord)[4] = (GLfloat (*)[4])out->data;
    GLfloat (*f)[3] = store->tmp_f;
    GLuint copy;
 
    if (texUnit->_GenFlags & TEXGEN_NEED_M) {
@@ -482,45 +483,46 @@  static GLboolean run_texgen_stage( struct gl_context *ctx,
 				   struct tnl_pipeline_stage *stage )
 {
    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
    struct texgen_stage_data *store = TEXGEN_STAGE_DATA(stage);
    GLuint i;
 
    if (!ctx->Texture._TexGenEnabled || ctx->VertexProgram._Current) 
       return GL_TRUE;
 
    for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++) {
-      struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
+      struct gl_fixedfunc_texture_unit *texUnit =
+         &ctx->Texture.FixedFuncUnit[i];
 
       if (texUnit->TexGenEnabled) {
-
 	 store->TexgenFunc[i]( ctx, store, i );
 
          VB->AttribPtr[VERT_ATTRIB_TEX0 + i] = &store->texcoord[i];
       }
    }
 
    return GL_TRUE;
 }
 
 
 static void validate_texgen_stage( struct gl_context *ctx,
 				   struct tnl_pipeline_stage *stage )
 {
    struct texgen_stage_data *store = TEXGEN_STAGE_DATA(stage);
    GLuint i;
 
    if (!ctx->Texture._TexGenEnabled || ctx->VertexProgram._Current) 
       return;
 
    for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++) {
-      struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
+      struct gl_fixedfunc_texture_unit *texUnit =
+         &ctx->Texture.FixedFuncUnit[i];
 
       if (texUnit->TexGenEnabled) {
 	 GLuint sz;
 
 	 if (texUnit->TexGenEnabled & Q_BIT)
 	    sz = 4;
 	 else if (texUnit->TexGenEnabled & R_BIT)
 	    sz = 3;
 	 else if (texUnit->TexGenEnabled & T_BIT)
 	    sz = 2;