Header file clean-up:
[mesa.git] / src / mesa / main / state.c
index e6513eb9f93b690d9f6b3296ebd432296d802323..6948c78e7d63e8887691386cf3bdbf471d40527d 100644 (file)
@@ -1,10 +1,10 @@
-/* $Id: state.c,v 1.54 2001/01/08 17:42:13 keithw 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 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 "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;
 }
@@ -123,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;
@@ -420,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;
@@ -436,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;
 
@@ -468,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;
@@ -478,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;
@@ -487,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 */
+
 }
 
 
@@ -496,6 +529,10 @@ _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 )
 {
@@ -505,44 +542,38 @@ update_polygon( GLcontext *ctx )
       ctx->_TriangleCaps |= DD_TRI_CULL_FRONT_BACK;
 
    /* Any Polygon offsets enabled? */
-   ctx->Polygon._OffsetAny = GL_FALSE;
-   ctx->_TriangleCaps &= ~DD_TRI_OFFSET;
-
    if (ctx->Polygon.OffsetPoint ||
        ctx->Polygon.OffsetLine ||
        ctx->Polygon.OffsetFill) {
       ctx->_TriangleCaps |= DD_TRI_OFFSET;
-      ctx->Polygon._OffsetAny = GL_TRUE;
    }
 }
 
 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);
    }
 }
 
@@ -559,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 );
@@ -569,16 +599,13 @@ update_tnl_spaces( GLcontext *ctx, GLuint oldneedeyecoords )
       GLuint new_state = ctx->NewState;
 
       /* Recalculate that same state only if it has been invalidated
-       * by other statechanges. 
+       * 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 );
    }
 }
 
@@ -610,23 +637,23 @@ 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 );
         }
       }
    }
@@ -676,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 ||
@@ -700,6 +727,169 @@ 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
@@ -715,27 +905,27 @@ update_image_transfer_state(GLcontext *ctx)
  * state references this value, and must be treated with care to
  * ensure that updates are done correctly.  All state dependent on
  * _NeedEyeCoords is calculated from within _mesa_update_tnl_spaces(),
- * and from nowhere else.  
+ * 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).
     */
@@ -745,7 +935,7 @@ void gl_update_state( GLcontext *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 );
@@ -756,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.
@@ -764,11 +954,29 @@ 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;
    }
 
 
+#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 this variable has changed, update for the
@@ -776,10 +984,9 @@ void gl_update_state( GLcontext *ctx )
     * normal transform.
     *
     * If the lighting space hasn't changed, may still need to recompute
-    * light positions & normal transforms for other reasons. 
+    * light positions & normal transforms for other reasons.
     */
    if (new_state & (_NEW_MODELVIEW |
-                   _NEW_PROJECTION |
                    _NEW_LIGHT |
                    _MESA_NEW_NEED_EYE_COORDS))
       update_tnl_spaces( ctx, oldneedeyecoords );
@@ -795,6 +1002,57 @@ void gl_update_state( GLcontext *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.
+                                */
 }