Header file clean-up:
[mesa.git] / src / mesa / main / state.c
index 5c4dda99e8d97db0e8c131f087bf6424368c9608..6948c78e7d63e8887691386cf3bdbf471d40527d 100644 (file)
@@ -1,10 +1,10 @@
-/* $Id: state.c,v 1.50 2000/11/28 00:07:51 brianp Exp $ */
+/* $Id: state.c,v 1.96 2002/10/24 23:57:21 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
- * Version:  3.5
+ * Version:  4.1
  *
- * Copyright (C) 1999-2000  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
 
 
 /*
- * This file initializes the immediate-mode dispatch table (which may
- * be state-dependant) and manages internal Mesa state update.
+ * This file manages recalculation of derived values in the
+ * __GLcontext.
  */
 
 
-#ifdef PC_HEADER
-#include "all.h"
-#else
 #include "glheader.h"
 #include "accum.h"
-#include "alpha.h"
 #include "api_loopback.h"
 #include "attrib.h"
-#include "bitmap.h"
 #include "blend.h"
 #include "buffers.h"
 #include "clip.h"
 #include "colortab.h"
 #include "context.h"
 #include "convolve.h"
-#include "copypix.h"
 #include "depth.h"
 #include "dlist.h"
 #include "drawpix.h"
 #include "histogram.h"
 #include "light.h"
 #include "lines.h"
-#include "logic.h"
-#include "masking.h"
 #include "matrix.h"
 #include "mmath.h"
 #include "pixel.h"
-#include "pixeltex.h"
 #include "points.h"
 #include "polygon.h"
 #include "rastpos.h"
-#include "readpix.h"
-#include "scissor.h"
 #include "state.h"
 #include "stencil.h"
 #include "teximage.h"
 #include "texobj.h"
 #include "texstate.h"
-#include "texture.h"
 #include "mtypes.h"
 #include "varray.h"
-#include "winpos.h"
+#if FEATURE_NV_vertex_program
+#include "vpstate.h"
+#endif
 
-#include "swrast/swrast.h"
 #include "math/m_matrix.h"
 #include "math/m_xform.h"
-#endif
-
 
 
 static int
 generic_noop(void)
 {
 #ifdef DEBUG
-   gl_problem(NULL, "undefined function dispatch");
+   _mesa_problem(NULL, "User called no-op dispatch function");
 #endif
    return 0;
 }
@@ -112,6 +99,7 @@ _mesa_init_no_op_table(struct _glapi_table *table, GLuint tableSize)
 }
 
 
+
 /*
  * Initialize the given dispatch table with pointers to Mesa's
  * immediate-mode commands.
@@ -125,7 +113,7 @@ _mesa_init_exec_table(struct _glapi_table *exec, GLuint tableSize)
    /* first initialize all dispatch slots to no-op */
    _mesa_init_no_op_table(exec, tableSize);
 
-   _mesa_loopback_init_api_table( exec, GL_FALSE );
+   _mesa_loopback_init_api_table( exec, GL_TRUE );
 
    /* load the dispatch slots we understand */
    exec->Accum = _mesa_Accum;
@@ -422,9 +410,6 @@ _mesa_init_exec_table(struct _glapi_table *exec, GLuint tableSize)
    exec->PointParameterfEXT = _mesa_PointParameterfEXT;
    exec->PointParameterfvEXT = _mesa_PointParameterfvEXT;
 
-   /* 77. GL_PGI_misc_hints */
-   exec->HintPGI = _mesa_HintPGI;
-
    /* 78. GL_EXT_paletted_texture */
 #if 0
    exec->ColorTableEXT = _mesa_ColorTableEXT;
@@ -438,6 +423,10 @@ _mesa_init_exec_table(struct _glapi_table *exec, GLuint tableSize)
    exec->LockArraysEXT = _mesa_LockArraysEXT;
    exec->UnlockArraysEXT = _mesa_UnlockArraysEXT;
 
+   /* 148. GL_EXT_multi_draw_arrays */
+   exec->MultiDrawArraysEXT = _mesa_MultiDrawArraysEXT;
+   exec->MultiDrawElementsEXT = _mesa_MultiDrawElementsEXT;
+
    /* 173. GL_INGR_blend_func_separate */
    exec->BlendFuncSeparateEXT = _mesa_BlendFuncSeparateEXT;
 
@@ -470,6 +459,42 @@ _mesa_init_exec_table(struct _glapi_table *exec, GLuint tableSize)
    exec->WindowPos4sMESA = _mesa_WindowPos4sMESA;
    exec->WindowPos4svMESA = _mesa_WindowPos4svMESA;
 
+   /* 233. GL_NV_vertex_program */
+#if FEATURE_NV_vertex_program
+   exec->BindProgramNV = _mesa_BindProgramNV;
+   exec->DeleteProgramsNV = _mesa_DeleteProgramsNV;
+   exec->ExecuteProgramNV = _mesa_ExecuteProgramNV;
+   exec->GenProgramsNV = _mesa_GenProgramsNV;
+   exec->AreProgramsResidentNV = _mesa_AreProgramsResidentNV;
+   exec->RequestResidentProgramsNV = _mesa_RequestResidentProgramsNV;
+   exec->GetProgramParameterfvNV = _mesa_GetProgramParameterfvNV;
+   exec->GetProgramParameterdvNV = _mesa_GetProgramParameterdvNV;
+   exec->GetProgramivNV = _mesa_GetProgramivNV;
+   exec->GetProgramStringNV = _mesa_GetProgramStringNV;
+   exec->GetTrackMatrixivNV = _mesa_GetTrackMatrixivNV;
+   exec->GetVertexAttribdvNV = _mesa_GetVertexAttribdvNV;
+   exec->GetVertexAttribfvNV = _mesa_GetVertexAttribfvNV;
+   exec->GetVertexAttribivNV = _mesa_GetVertexAttribivNV;
+   exec->GetVertexAttribPointervNV = _mesa_GetVertexAttribPointervNV;
+   exec->IsProgramNV = _mesa_IsProgramNV;
+   exec->LoadProgramNV = _mesa_LoadProgramNV;
+   exec->ProgramParameter4dNV = _mesa_ProgramParameter4dNV;
+   exec->ProgramParameter4dvNV = _mesa_ProgramParameter4dvNV;
+   exec->ProgramParameter4fNV = _mesa_ProgramParameter4fNV;
+   exec->ProgramParameter4fvNV = _mesa_ProgramParameter4fvNV;
+   exec->ProgramParameters4dvNV = _mesa_ProgramParameters4dvNV;
+   exec->ProgramParameters4fvNV = _mesa_ProgramParameters4fvNV;
+   exec->TrackMatrixNV = _mesa_TrackMatrixNV;
+   exec->VertexAttribPointerNV = _mesa_VertexAttribPointerNV;
+#endif
+
+   /* 262. GL_NV_point_sprite */
+   exec->PointParameteriNV = _mesa_PointParameteriNV;
+   exec->PointParameterivNV = _mesa_PointParameterivNV;
+
+   /* 268. GL_EXT_stencil_two_side */
+   exec->ActiveStencilFaceEXT = _mesa_ActiveStencilFaceEXT;
+
    /* ARB 1. GL_ARB_multitexture */
    exec->ActiveTextureARB = _mesa_ActiveTextureARB;
    exec->ClientActiveTextureARB = _mesa_ClientActiveTextureARB;
@@ -480,6 +505,9 @@ _mesa_init_exec_table(struct _glapi_table *exec, GLuint tableSize)
    exec->MultTransposeMatrixdARB = _mesa_MultTransposeMatrixdARB;
    exec->MultTransposeMatrixfARB = _mesa_MultTransposeMatrixfARB;
 
+   /* ARB 5. GL_ARB_multisample */
+   exec->SampleCoverageARB = _mesa_SampleCoverageARB;
+
    /* ARB 12. GL_ARB_texture_compression */
    exec->CompressedTexImage3DARB = _mesa_CompressedTexImage3DARB;
    exec->CompressedTexImage2DARB = _mesa_CompressedTexImage2DARB;
@@ -489,6 +517,9 @@ _mesa_init_exec_table(struct _glapi_table *exec, GLuint tableSize)
    exec->CompressedTexSubImage1DARB = _mesa_CompressedTexSubImage1DARB;
    exec->GetCompressedTexImageARB = _mesa_GetCompressedTexImageARB;
 
+   /* ARB 14. GL_ARB_point_parameters */
+   /* reuse EXT_point_parameters functions */
+
 }
 
 
@@ -498,67 +529,51 @@ _mesa_init_exec_table(struct _glapi_table *exec, GLuint tableSize)
 /**********************************************************************/
 
 
+/*
+ * Check polygon state and set DD_TRI_CULL_FRONT_BACK and/or DD_TRI_OFFSET
+ * in ctx->_TriangleCaps if needed.
+ */
 static void
 update_polygon( GLcontext *ctx )
 {
-   ctx->_TriangleCaps &= ~DD_TRI_CULL_FRONT_BACK;
-
-   /* Setup CullBits bitmask */
-   if (ctx->Polygon.CullFlag) {
-      switch(ctx->Polygon.CullFaceMode) {
-      case GL_BACK:
-        ctx->Polygon._CullBits = 1;
-        break;
-      case GL_FRONT:
-        ctx->Polygon._CullBits = 2;
-        break;
-      default:
-      case GL_FRONT_AND_BACK:
-        ctx->Polygon._CullBits = 0;
-        ctx->_TriangleCaps |= DD_TRI_CULL_FRONT_BACK;
-        break;
-      }
-   }
-   else {
-      ctx->Polygon._CullBits = 3;
-   }
+   ctx->_TriangleCaps &= ~(DD_TRI_CULL_FRONT_BACK | DD_TRI_OFFSET);
 
-   /* Any Polygon offsets enabled? */
-   ctx->_TriangleCaps &= ~DD_TRI_OFFSET;
+   if (ctx->Polygon.CullFlag && ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK)
+      ctx->_TriangleCaps |= DD_TRI_CULL_FRONT_BACK;
 
+   /* Any Polygon offsets enabled? */
    if (ctx->Polygon.OffsetPoint ||
        ctx->Polygon.OffsetLine ||
-       ctx->Polygon.OffsetFill)
+       ctx->Polygon.OffsetFill) {
       ctx->_TriangleCaps |= DD_TRI_OFFSET;
+   }
 }
 
 static void
 calculate_model_project_matrix( GLcontext *ctx )
 {
-   if (!ctx->_NeedEyeCoords) {
-      _math_matrix_mul_matrix( &ctx->_ModelProjectMatrix,
-                              &ctx->ProjectionMatrix,
-                              &ctx->ModelView );
+   _math_matrix_mul_matrix( &ctx->_ModelProjectMatrix,
+                            ctx->ProjectionMatrixStack.Top,
+                            ctx->ModelviewMatrixStack.Top );
 
-      _math_matrix_analyse( &ctx->_ModelProjectMatrix );
-   }
+   _math_matrix_analyse( &ctx->_ModelProjectMatrix );
 }
 
 static void
 update_modelview_scale( GLcontext *ctx )
 {
    ctx->_ModelViewInvScale = 1.0F;
-   if (ctx->ModelView.flags & (MAT_FLAG_UNIFORM_SCALE |
+   if (ctx->ModelviewMatrixStack.Top->flags & (MAT_FLAG_UNIFORM_SCALE |
                               MAT_FLAG_GENERAL_SCALE |
                               MAT_FLAG_GENERAL_3D |
                               MAT_FLAG_GENERAL) ) {
-      const GLfloat *m = ctx->ModelView.inv;
+      const GLfloat *m = ctx->ModelviewMatrixStack.Top->inv;
       GLfloat f = m[2] * m[2] + m[6] * m[6] + m[10] * m[10];
       if (f < 1e-12) f = 1.0;
       if (ctx->_NeedEyeCoords)
-        ctx->_ModelViewInvScale = 1.0/GL_SQRT(f);
+        ctx->_ModelViewInvScale = (GLfloat) (1.0/GL_SQRT(f));
       else
-        ctx->_ModelViewInvScale = GL_SQRT(f);
+        ctx->_ModelViewInvScale = (GLfloat) GL_SQRT(f);
    }
 }
 
@@ -575,8 +590,7 @@ update_tnl_spaces( GLcontext *ctx, GLuint oldneedeyecoords )
       /* Recalculate all state that depends on _NeedEyeCoords.
        */
       update_modelview_scale(ctx);
-      calculate_model_project_matrix(ctx);
-      gl_compute_light_positions( ctx );
+      _mesa_compute_light_positions( ctx );
 
       if (ctx->Driver.LightingSpaceChange)
         ctx->Driver.LightingSpaceChange( ctx );
@@ -584,17 +598,14 @@ update_tnl_spaces( GLcontext *ctx, GLuint oldneedeyecoords )
    else {
       GLuint new_state = ctx->NewState;
 
-      /* Recalculate that same state if and only if it has been
-       * invalidated by other statechanges.
+      /* Recalculate that same state only if it has been invalidated
+       * by other statechanges.
        */
       if (new_state & _NEW_MODELVIEW)
         update_modelview_scale(ctx);
 
-      if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
-        calculate_model_project_matrix(ctx);
-       
       if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW))
-        gl_compute_light_positions( ctx );
+        _mesa_compute_light_positions( ctx );
    }
 }
 
@@ -626,30 +637,29 @@ update_drawbuffer( GLcontext *ctx )
 /* NOTE: This routine references Tranform attribute values to compute
  * userclip positions in clip space, but is only called on
  * _NEW_PROJECTION.  The _mesa_ClipPlane() function keeps these values
- * uptodate across changes to the Transform attributes.
+ * up to date across changes to the Transform attributes.
  */
 static void
 update_projection( GLcontext *ctx )
 {
-   _math_matrix_analyse( &ctx->ProjectionMatrix );
-      
+   _math_matrix_analyse( ctx->ProjectionMatrixStack.Top );
+
    /* Recompute clip plane positions in clipspace.  This is also done
     * in _mesa_ClipPlane().
     */
-   if (ctx->Transform._AnyClip) {
+   if (ctx->Transform.ClipPlanesEnabled) {
       GLuint p;
       for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
-        if (ctx->Transform.ClipEnabled[p]) {
-           gl_transform_vector( ctx->Transform._ClipUserPlane[p],
+        if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
+           _mesa_transform_vector( ctx->Transform._ClipUserPlane[p],
                                 ctx->Transform.EyeUserPlane[p],
-                                ctx->ProjectionMatrix.inv );
+                                ctx->ProjectionMatrixStack.Top->inv );
         }
       }
    }
 }
 
 
-
 /*
  * Return a bitmask of IMAGE_*_BIT flags which to indicate which
  * pixel transfer operations are enabled.
@@ -693,7 +703,7 @@ update_image_transfer_state(GLcontext *ctx)
    if (ctx->Pixel.PostConvolutionColorTableEnabled)
       mask |= IMAGE_POST_CONVOLUTION_COLOR_TABLE_BIT;
 
-   if (ctx->ColorMatrix.type != MATRIX_IDENTITY ||
+   if (ctx->ColorMatrixStack.Top->type != MATRIX_IDENTITY ||
        ctx->Pixel.PostColorMatrixScale[0] != 1.0F ||
        ctx->Pixel.PostColorMatrixBias[0]  != 0.0F ||
        ctx->Pixel.PostColorMatrixScale[1] != 1.0F ||
@@ -717,12 +727,179 @@ update_image_transfer_state(GLcontext *ctx)
 }
 
 
+
+
+/* Note: This routine refers to derived texture attribute values to
+ * compute the ENABLE_TEXMAT flags, but is only called on
+ * _NEW_TEXTURE_MATRIX.  On changes to _NEW_TEXTURE, the ENABLE_TEXMAT
+ * flags are updated by _mesa_update_textures(), below.
+ *
+ * If both TEXTURE and TEXTURE_MATRIX change at once, these values
+ * will be computed twice.
+ */
+static void
+update_texture_matrices( GLcontext *ctx )
+{
+   GLuint i;
+
+   ctx->Texture._TexMatEnabled = 0;
+
+   for (i=0; i < ctx->Const.MaxTextureUnits; i++) {
+      if (ctx->TextureMatrixStack[i].Top->flags & MAT_DIRTY) {
+        _math_matrix_analyse( ctx->TextureMatrixStack[i].Top );
+
+        if (ctx->Texture.Unit[i]._ReallyEnabled &&
+            ctx->TextureMatrixStack[i].Top->type != MATRIX_IDENTITY)
+           ctx->Texture._TexMatEnabled |= ENABLE_TEXMAT(i);
+
+        if (ctx->Driver.TextureMatrix)
+           ctx->Driver.TextureMatrix( ctx, i, ctx->TextureMatrixStack[i].Top);
+      }
+   }
+}
+
+
+/* Note: This routine refers to derived texture matrix values to
+ * compute the ENABLE_TEXMAT flags, but is only called on
+ * _NEW_TEXTURE.  On changes to _NEW_TEXTURE_MATRIX, the ENABLE_TEXMAT
+ * flags are updated by _mesa_update_texture_matrices, above.
+ *
+ * If both TEXTURE and TEXTURE_MATRIX change at once, these values
+ * will be computed twice.
+ */
+static void
+update_texture_state( GLcontext *ctx )
+{
+   GLuint unit;
+
+   ctx->Texture._EnabledUnits = 0;
+   ctx->Texture._GenFlags = 0;
+   ctx->_NeedNormals &= ~NEED_NORMALS_TEXGEN;
+   ctx->_NeedEyeCoords &= ~NEED_EYE_TEXGEN;
+   ctx->Texture._TexMatEnabled = 0;
+   ctx->Texture._TexGenEnabled = 0;
+
+   /* Update texture unit state.
+    */
+   for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
+      struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+
+      texUnit->_ReallyEnabled = 0;
+      texUnit->_GenFlags = 0;
+
+      if (!texUnit->Enabled)
+        continue;
+
+      /* Look for the highest-priority texture target that's enabled and
+       * complete.  That's the one we'll use for texturing.
+       */
+      if (texUnit->Enabled & TEXTURE_CUBE_BIT) {
+         struct gl_texture_object *texObj = texUnit->CurrentCubeMap;
+         if (!texObj->Complete) {
+            _mesa_test_texobj_completeness(ctx, texObj);
+         }
+         if (texObj->Complete) {
+            texUnit->_ReallyEnabled = TEXTURE_CUBE_BIT;
+            texUnit->_Current = texObj;
+         }
+      }
+
+      if (!texUnit->_ReallyEnabled && (texUnit->Enabled & TEXTURE_3D_BIT)) {
+         struct gl_texture_object *texObj = texUnit->Current3D;
+         if (!texObj->Complete) {
+            _mesa_test_texobj_completeness(ctx, texObj);
+         }
+         if (texObj->Complete) {
+            texUnit->_ReallyEnabled = TEXTURE_3D_BIT;
+            texUnit->_Current = texObj;
+         }
+      }
+
+      if (!texUnit->_ReallyEnabled && (texUnit->Enabled & TEXTURE_RECT_BIT)) {
+         struct gl_texture_object *texObj = texUnit->CurrentRect;
+         if (!texObj->Complete) {
+            _mesa_test_texobj_completeness(ctx, texObj);
+         }
+         if (texObj->Complete) {
+            texUnit->_ReallyEnabled = TEXTURE_RECT_BIT;
+            texUnit->_Current = texObj;
+         }
+      }
+
+      if (!texUnit->_ReallyEnabled && (texUnit->Enabled & TEXTURE_2D_BIT)) {
+         struct gl_texture_object *texObj = texUnit->Current2D;
+         if (!texObj->Complete) {
+            _mesa_test_texobj_completeness(ctx, texObj);
+         }
+         if (texObj->Complete) {
+            texUnit->_ReallyEnabled = TEXTURE_2D_BIT;
+            texUnit->_Current = texObj;
+         }
+      }
+
+      if (!texUnit->_ReallyEnabled && (texUnit->Enabled & TEXTURE_1D_BIT)) {
+         struct gl_texture_object *texObj = texUnit->Current1D;
+         if (!texObj->Complete) {
+            _mesa_test_texobj_completeness(ctx, texObj);
+         }
+         if (texObj->Complete) {
+            texUnit->_ReallyEnabled = TEXTURE_1D_BIT;
+            texUnit->_Current = texObj;
+         }
+      }
+
+      if (!texUnit->_ReallyEnabled) {
+        texUnit->_Current = NULL;
+        continue;
+      }
+
+      if (texUnit->_ReallyEnabled)
+         ctx->Texture._EnabledUnits |= (1 << unit);
+
+      if (texUnit->TexGenEnabled) {
+        if (texUnit->TexGenEnabled & S_BIT) {
+           texUnit->_GenFlags |= texUnit->_GenBitS;
+        }
+        if (texUnit->TexGenEnabled & T_BIT) {
+           texUnit->_GenFlags |= texUnit->_GenBitT;
+        }
+        if (texUnit->TexGenEnabled & Q_BIT) {
+           texUnit->_GenFlags |= texUnit->_GenBitQ;
+        }
+        if (texUnit->TexGenEnabled & R_BIT) {
+           texUnit->_GenFlags |= texUnit->_GenBitR;
+        }
+
+        ctx->Texture._TexGenEnabled |= ENABLE_TEXGEN(unit);
+        ctx->Texture._GenFlags |= texUnit->_GenFlags;
+      }
+
+      if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY)
+        ctx->Texture._TexMatEnabled |= ENABLE_TEXMAT(unit);
+   }
+
+   if (ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS) {
+      ctx->_NeedNormals |= NEED_NORMALS_TEXGEN;
+      ctx->_NeedEyeCoords |= NEED_EYE_TEXGEN;
+   }
+
+   if (ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD) {
+      ctx->_NeedEyeCoords |= NEED_EYE_TEXGEN;
+   }
+}
+
+
+
 /*
  * If ctx->NewState is non-zero then this function MUST be called before
  * rendering any primitive.  Basically, function pointers and miscellaneous
  * flags are updated to reflect the current state of the state machine.
  *
- * Special care is taken with the derived value _NeedEyeCoords.  These
+ * The above constraint is now maintained largely by the two Exec
+ * dispatch tables, which trigger the appropriate flush on transition
+ * between State and Geometry modes.
+ *
+ * Special care is taken with the derived value _NeedEyeCoords.  This
  * is a bitflag which is updated with information from a number of
  * attribute groups (MODELVIEW, LIGHT, TEXTURE).  A lot of derived
  * state references this value, and must be treated with care to
@@ -730,35 +907,35 @@ update_image_transfer_state(GLcontext *ctx)
  * _NeedEyeCoords is calculated from within _mesa_update_tnl_spaces(),
  * and from nowhere else.
  */
-void gl_update_state( GLcontext *ctx )
+void _mesa_update_state( GLcontext *ctx )
 {
-   GLuint new_state = ctx->NewState;
-   GLuint oldneedeyecoords = ctx->_NeedEyeCoords;
+   const GLuint new_state = ctx->NewState;
+   const GLuint oldneedeyecoords = ctx->_NeedEyeCoords;
 
    if (MESA_VERBOSE & VERBOSE_STATE)
-      gl_print_state("", new_state);
+      _mesa_print_state("_mesa_update_state", new_state);
 
    if (new_state & _NEW_MODELVIEW)
-      _math_matrix_analyse( &ctx->ModelView );
+      _math_matrix_analyse( ctx->ModelviewMatrixStack.Top );
 
    if (new_state & _NEW_PROJECTION)
       update_projection( ctx );
 
    if (new_state & _NEW_TEXTURE_MATRIX)
-      _mesa_update_texture_matrices( ctx );
+      update_texture_matrices( ctx );
 
    if (new_state & _NEW_COLOR_MATRIX)
-      _math_matrix_analyse( &ctx->ColorMatrix );
+      _math_matrix_analyse( ctx->ColorMatrixStack.Top );
 
    /* References ColorMatrix.type (derived above).
     */
-   if (new_state & (_NEW_PIXEL|_NEW_COLOR_MATRIX))
+   if (new_state & _IMAGE_NEW_TRANSFER_STATE)
       update_image_transfer_state(ctx);
 
    /* Contributes to NeedEyeCoords, NeedNormals.
     */
    if (new_state & _NEW_TEXTURE)
-      _mesa_update_texture_state( ctx );
+      update_texture_state( ctx );
 
    if (new_state & (_NEW_BUFFERS|_NEW_SCISSOR))
       update_drawbuffer( ctx );
@@ -769,7 +946,7 @@ void gl_update_state( GLcontext *ctx )
    /* Contributes to NeedEyeCoords, NeedNormals.
     */
    if (new_state & _NEW_LIGHT)
-      gl_update_lighting( ctx );
+      _mesa_update_lighting( ctx );
 
    /* We can light in object space if the modelview matrix preserves
     * lengths and relative angles.
@@ -777,24 +954,41 @@ void gl_update_state( GLcontext *ctx )
    if (new_state & (_NEW_MODELVIEW|_NEW_LIGHT)) {
       ctx->_NeedEyeCoords &= ~NEED_EYE_LIGHT_MODELVIEW;
       if (ctx->Light.Enabled &&
-         !TEST_MAT_FLAGS( &ctx->ModelView, MAT_FLAGS_LENGTH_PRESERVING))
+         !TEST_MAT_FLAGS( ctx->ModelviewMatrixStack.Top, MAT_FLAGS_LENGTH_PRESERVING))
            ctx->_NeedEyeCoords |= NEED_EYE_LIGHT_MODELVIEW;
    }
 
-   /* ctx->_NeedEyeCoords and ctx->_NeedEyeNormals are now uptodate.
+
+#if 0
+   /* XXX this is a bit of a hack.  We should be checking elsewhere if
+    * vertex program mode is enabled.  We set _NeedEyeCoords to zero to
+    * ensure that the combined modelview/projection matrix is computed
+    * in calculate_model_project_matrix().
+    */
+   if (ctx->VertexProgram.Enabled)
+      ctx->_NeedEyeCoords = 0;
+   /* KW: it's now always computed.
+    */
+#endif
+
+   /* Keep ModelviewProject uptodate always to allow tnl
+    * implementations that go model->clip even when eye is required.
+    */
+   if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
+      calculate_model_project_matrix(ctx);
+
+   /* ctx->_NeedEyeCoords is now uptodate.
     *
-    * If the truth value of either has changed, update for the new
-    * lighting space and recompute the positions of lights and the
+    * If the truth value of this variable has changed, update for the
+    * new lighting space and recompute the positions of lights and the
     * normal transform.
     *
     * If the lighting space hasn't changed, may still need to recompute
     * light positions & normal transforms for other reasons.
     */
    if (new_state & (_NEW_MODELVIEW |
-                   _NEW_PROJECTION |
-                   _TNL_NEW_NORMAL_TRANSFORM |
                    _NEW_LIGHT |
-                   _TNL_NEW_NEED_EYE_COORDS))
+                   _MESA_NEW_NEED_EYE_COORDS))
       update_tnl_spaces( ctx, oldneedeyecoords );
 
    /*
@@ -802,7 +996,63 @@ void gl_update_state( GLcontext *ctx )
     * to it's specific, private functions, and performs any
     * internal state management necessary, including invalidating
     * state of active modules.
+    *
+    * Set ctx->NewState to zero to avoid recursion if
+    * Driver.UpdateState() has to call FLUSH_VERTICES().  (fixed?)
     */
-   ctx->Driver.UpdateState(ctx);
    ctx->NewState = 0;
+   ctx->Driver.UpdateState(ctx, new_state);
+   ctx->Array.NewState = 0;
+
+   /* At this point we can do some assertions to be sure the required
+    * device driver function pointers are all initialized.
+    */
+   ASSERT(ctx->Driver.GetString);
+   ASSERT(ctx->Driver.UpdateState);
+   ASSERT(ctx->Driver.Clear);
+   ASSERT(ctx->Driver.GetBufferSize);
+   if (ctx->Visual.accumRedBits > 0) {
+      ASSERT(ctx->Driver.Accum);
+   }
+   ASSERT(ctx->Driver.DrawPixels);
+   ASSERT(ctx->Driver.ReadPixels);
+   ASSERT(ctx->Driver.CopyPixels);
+   ASSERT(ctx->Driver.Bitmap);
+   ASSERT(ctx->Driver.ResizeBuffers);
+   ASSERT(ctx->Driver.TexImage1D);
+   ASSERT(ctx->Driver.TexImage2D);
+   ASSERT(ctx->Driver.TexImage3D);
+   ASSERT(ctx->Driver.TexSubImage1D);
+   ASSERT(ctx->Driver.TexSubImage2D);
+   ASSERT(ctx->Driver.TexSubImage3D);
+   ASSERT(ctx->Driver.CopyTexImage1D);
+   ASSERT(ctx->Driver.CopyTexImage2D);
+   ASSERT(ctx->Driver.CopyTexSubImage1D);
+   ASSERT(ctx->Driver.CopyTexSubImage2D);
+   ASSERT(ctx->Driver.CopyTexSubImage3D);
+   if (ctx->Extensions.ARB_texture_compression) {
+#if 0  /* HW drivers need these, but not SW rasterizers */
+      ASSERT(ctx->Driver.CompressedTexImage1D);
+      ASSERT(ctx->Driver.CompressedTexImage2D);
+      ASSERT(ctx->Driver.CompressedTexImage3D);
+      ASSERT(ctx->Driver.CompressedTexSubImage1D);
+      ASSERT(ctx->Driver.CompressedTexSubImage2D);
+      ASSERT(ctx->Driver.CompressedTexSubImage3D);
+#endif
+   }
+}
+
+/* Is this helpful?
+ */
+void
+_mesa_allow_light_in_model( GLcontext *ctx, GLboolean flag )
+{
+   if (flag) 
+      ctx->_NeedEyeCoords &= ~NEED_EYE_DRIVER;
+   else
+      ctx->_NeedEyeCoords |= NEED_EYE_DRIVER;
+
+   ctx->NewState |= _NEW_POINT;        /* one of the bits from
+                                * _MESA_NEW_NEED_EYE_COORDS.
+                                */
 }