+#endif
+
+
+
+/**********************************************************************/
+/** \name State management */
+/*@{*/
+
+
+/**
+ * Update the projection matrix stack.
+ *
+ * \param ctx GL context.
+ *
+ * Calls _math_matrix_analyse() with the top-matrix of the projection matrix
+ * stack, and recomputes user clip positions if necessary.
+ *
+ * \note This routine references __GLcontextRec::Tranform attribute values to
+ * compute userclip positions in clip space, but is only called on
+ * _NEW_PROJECTION. The _mesa_ClipPlane() function keeps these values up to
+ * date across changes to the __GLcontextRec::Transform attributes.
+ */
+static void
+update_projection( GLcontext *ctx )
+{
+ _math_matrix_analyse( ctx->ProjectionMatrixStack.Top );
+
+#if FEATURE_userclip
+ /* Recompute clip plane positions in clipspace. This is also done
+ * in _mesa_ClipPlane().
+ */
+ if (ctx->Transform.ClipPlanesEnabled) {
+ GLuint p;
+ for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
+ if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
+ _mesa_transform_vector( ctx->Transform._ClipUserPlane[p],
+ ctx->Transform.EyeUserPlane[p],
+ ctx->ProjectionMatrixStack.Top->inv );
+ }
+ }
+ }
+#endif
+}
+
+
+/**
+ * Calculate the combined modelview-projection matrix.
+ *
+ * \param ctx GL context.
+ *
+ * Multiplies the top matrices of the projection and model view stacks into
+ * __GLcontextRec::_ModelProjectMatrix via _math_matrix_mul_matrix() and
+ * analyzes the resulting matrix via _math_matrix_analyse().
+ */
+static void
+calculate_model_project_matrix( GLcontext *ctx )
+{
+ _math_matrix_mul_matrix( &ctx->_ModelProjectMatrix,
+ ctx->ProjectionMatrixStack.Top,
+ ctx->ModelviewMatrixStack.Top );
+
+ _math_matrix_analyse( &ctx->_ModelProjectMatrix );
+}
+
+
+/**
+ * Updates the combined modelview-projection matrix.
+ *
+ * \param ctx GL context.
+ * \param new_state new state bit mask.
+ *
+ * If there is a new model view matrix then analyzes it. If there is a new
+ * projection matrix, updates it. Finally calls
+ * calculate_model_project_matrix() to recalculate the modelview-projection
+ * matrix.
+ */
+void _mesa_update_modelview_project( GLcontext *ctx, GLuint new_state )
+{
+ if (new_state & _NEW_MODELVIEW) {
+ _math_matrix_analyse( ctx->ModelviewMatrixStack.Top );
+
+ /* Bring cull position uptodate.
+ */
+ TRANSFORM_POINT3( ctx->Transform.CullObjPos,
+ ctx->ModelviewMatrixStack.Top->inv,
+ ctx->Transform.CullEyePos );
+ }
+
+
+ if (new_state & _NEW_PROJECTION)
+ update_projection( ctx );
+
+ /* Keep ModelviewProject uptodate always to allow tnl
+ * implementations that go model->clip even when eye is required.
+ */
+ calculate_model_project_matrix(ctx);
+}
+
+/*@}*/
+
+
+/**********************************************************************/
+/** Matrix stack initialization */
+/*@{*/
+
+
+/**
+ * Initialize a matrix stack.
+ *
+ * \param stack matrix stack.
+ * \param maxDepth maximum stack depth.
+ * \param dirtyFlag dirty flag.
+ *
+ * Allocates an array of \p maxDepth elements for the matrix stack and calls
+ * _math_matrix_ctr() and _math_matrix_alloc_inv() for each element to
+ * initialize it.
+ */
+static void
+init_matrix_stack( struct matrix_stack *stack,
+ GLuint maxDepth, GLuint dirtyFlag )
+{
+ GLuint i;
+
+ stack->Depth = 0;
+ stack->MaxDepth = maxDepth;
+ stack->DirtyFlag = dirtyFlag;
+ /* The stack */
+ stack->Stack = (GLmatrix *) CALLOC(maxDepth * sizeof(GLmatrix));
+ for (i = 0; i < maxDepth; i++) {
+ _math_matrix_ctr(&stack->Stack[i]);
+ _math_matrix_alloc_inv(&stack->Stack[i]);
+ }
+ stack->Top = stack->Stack;
+}
+
+/**
+ * Free matrix stack.
+ *
+ * \param stack matrix stack.
+ *
+ * Calls _math_matrix_dtr() for each element of the matrix stack and
+ * frees the array.
+ */
+static void
+free_matrix_stack( struct matrix_stack *stack )
+{
+ GLuint i;
+ for (i = 0; i < stack->MaxDepth; i++) {
+ _math_matrix_dtr(&stack->Stack[i]);
+ }
+ FREE(stack->Stack);
+ stack->Stack = stack->Top = NULL;
+}
+
+/*@}*/
+
+
+/**********************************************************************/
+/** \name Initialization */
+/*@{*/
+
+
+/**
+ * Initialize the context matrix data.
+ *
+ * \param ctx GL context.
+ *
+ * Initializes each of the matrix stacks and the combined modelview-projection
+ * matrix.
+ */
+void _mesa_init_matrix( GLcontext * ctx )
+{
+ GLint i;
+
+ /* Initialize matrix stacks */
+ init_matrix_stack(&ctx->ModelviewMatrixStack, MAX_MODELVIEW_STACK_DEPTH,
+ _NEW_MODELVIEW);
+ init_matrix_stack(&ctx->ProjectionMatrixStack, MAX_PROJECTION_STACK_DEPTH,
+ _NEW_PROJECTION);
+ init_matrix_stack(&ctx->ColorMatrixStack, MAX_COLOR_STACK_DEPTH,
+ _NEW_COLOR_MATRIX);
+ for (i = 0; i < MAX_TEXTURE_UNITS; i++)
+ init_matrix_stack(&ctx->TextureMatrixStack[i], MAX_TEXTURE_STACK_DEPTH,
+ _NEW_TEXTURE_MATRIX);
+ for (i = 0; i < MAX_PROGRAM_MATRICES; i++)
+ init_matrix_stack(&ctx->ProgramMatrixStack[i],
+ MAX_PROGRAM_MATRIX_STACK_DEPTH, _NEW_TRACK_MATRIX);
+ ctx->CurrentStack = &ctx->ModelviewMatrixStack;
+
+ /* Init combined Modelview*Projection matrix */
+ _math_matrix_ctr( &ctx->_ModelProjectMatrix );
+}
+
+
+/**
+ * Free the context matrix data.
+ *
+ * \param ctx GL context.
+ *
+ * Frees each of the matrix stacks and the combined modelview-projection
+ * matrix.
+ */
+void _mesa_free_matrix_data( GLcontext *ctx )
+{
+ GLint i;
+
+ free_matrix_stack(&ctx->ModelviewMatrixStack);
+ free_matrix_stack(&ctx->ProjectionMatrixStack);
+ free_matrix_stack(&ctx->ColorMatrixStack);
+ for (i = 0; i < MAX_TEXTURE_UNITS; i++)
+ free_matrix_stack(&ctx->TextureMatrixStack[i]);
+ for (i = 0; i < MAX_PROGRAM_MATRICES; i++)
+ free_matrix_stack(&ctx->ProgramMatrixStack[i]);
+ /* combined Modelview*Projection matrix */
+ _math_matrix_dtr( &ctx->_ModelProjectMatrix );
+
+}
+
+
+/**
+ * Initialize the context transform attribute group.
+ *
+ * \param ctx GL context.
+ *
+ * \todo Move this to a new file with other 'transform' routines.
+ */
+void _mesa_init_transform( GLcontext *ctx )
+{
+ GLint i;
+
+ /* Transformation group */
+ ctx->Transform.MatrixMode = GL_MODELVIEW;
+ ctx->Transform.Normalize = GL_FALSE;
+ ctx->Transform.RescaleNormals = GL_FALSE;
+ ctx->Transform.RasterPositionUnclipped = GL_FALSE;
+ for (i=0;i<MAX_CLIP_PLANES;i++) {
+ ASSIGN_4V( ctx->Transform.EyeUserPlane[i], 0.0, 0.0, 0.0, 0.0 );
+ }
+ ctx->Transform.ClipPlanesEnabled = 0;
+
+ ASSIGN_4V( ctx->Transform.CullObjPos, 0.0, 0.0, 1.0, 0.0 );
+ ASSIGN_4V( ctx->Transform.CullEyePos, 0.0, 0.0, 1.0, 0.0 );
+}
+
+
+/**
+ * Initialize the context viewport attribute group.
+ *
+ * \param ctx GL context.
+ *
+ * \todo Move this to a new file with other 'viewport' routines.
+ */
+void _mesa_init_viewport( GLcontext *ctx )
+{
+ GLfloat depthMax = 65535.0F; /* sorf of arbitrary */
+
+ /* Viewport group */
+ ctx->Viewport.X = 0;
+ ctx->Viewport.Y = 0;
+ ctx->Viewport.Width = 0;
+ ctx->Viewport.Height = 0;
+ ctx->Viewport.Near = 0.0;
+ ctx->Viewport.Far = 1.0;
+ _math_matrix_ctr(&ctx->Viewport._WindowMap);
+
+ _math_matrix_viewport(&ctx->Viewport._WindowMap, 0, 0, 0, 0,
+ 0.0F, 1.0F, depthMax);
+}
+
+
+/**
+ * Free the context viewport attribute group data.
+ *
+ * \param ctx GL context.
+ *
+ * \todo Move this to a new file with other 'viewport' routines.
+ */
+void _mesa_free_viewport_data( GLcontext *ctx )
+{
+ _math_matrix_dtr(&ctx->Viewport._WindowMap);
+}
+
+/*@}*/