Replace the flags Mesa was using for ctx->NewState with a new set
[mesa.git] / src / mesa / main / matrix.c
index 154a038b92332de2145cc97a24a8910375bfbdbc..df21d154fd2a67d0a8b68c10eb744fc49689452d 100644 (file)
@@ -1,10 +1,10 @@
-/* $Id: matrix.c,v 1.5 1999/10/08 09:27:11 keithw Exp $ */
+/* $Id: matrix.c,v 1.23 2000/10/30 13:32:00 keithw Exp $ */
 
 /*
  * Mesa 3-D graphics library
- * Version:  3.1
+ * Version:  3.5
  * 
- * Copyright (C) 1999  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2000  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"),
  */
 
 
-
-
-
 /*
  * Matrix operations
  *
- *
  * NOTES:
  * 1. 4x4 transformation matrices are stored in memory in column major order.
  * 2. Points/vertices are to be thought of as column vectors.
  * 3. Transformation of a point p by a matrix M is: p' = M * p
- *
  */
 
 
 #ifdef PC_HEADER
 #include "all.h"
 #else
-#ifndef XFree86Server
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#else
-#include "GL/xf86glx.h"
-#endif
+#include "glheader.h"
+#include "buffers.h"
 #include "context.h"
 #include "enums.h"
 #include "macros.h"
 #include "matrix.h"
+#include "mem.h"
 #include "mmath.h"
 #include "types.h"
-#ifdef XFree86Server
-#include "GL/xf86glx.h"
-#endif
 #endif
 
 
@@ -72,7 +59,6 @@ static const char *types[] = {
    "MATRIX_2D_NO_ROT",
    "MATRIX_3D"
 };
-static void matmul4( GLfloat *product, const GLfloat *a, const GLfloat *b );
 
 
 static GLfloat Identity[16] = {
@@ -83,6 +69,10 @@ static GLfloat Identity[16] = {
 };
 
 
+
+static void matmul4( GLfloat *product, const GLfloat *a, const GLfloat *b );
+
+
 static void print_matrix_floats( const GLfloat m[16] )
 {
    int i;
@@ -95,7 +85,6 @@ void gl_print_matrix( const GLmatrix *m )
 {
    fprintf(stderr, "Matrix type: %s, flags: %x\n", types[m->type], m->flags);
    print_matrix_floats(m->m);
-#if 1
    fprintf(stderr, "Inverse: \n");
    if (m->inv) {
       GLfloat prod[16];
@@ -103,9 +92,10 @@ void gl_print_matrix( const GLmatrix *m )
       matmul4(prod, m->m, m->inv);
       fprintf(stderr, "Mat * Inverse:\n");
       print_matrix_floats(prod);
-  } else 
+   }
+   else {
       fprintf(stderr, "  - not available\n");
-#endif
+   }
 }
 
 
@@ -129,7 +119,7 @@ static void matmul4( GLfloat *product, const GLfloat *a, const GLfloat *b )
 {
    GLint i;
    for (i = 0; i < 4; i++) {
-      GLfloat ai0=A(i,0),  ai1=A(i,1),  ai2=A(i,2),  ai3=A(i,3);
+      const GLfloat ai0=A(i,0),  ai1=A(i,1),  ai2=A(i,2),  ai3=A(i,3);
       P(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0) + ai3 * B(3,0);
       P(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1) + ai3 * B(3,1);
       P(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2) + ai3 * B(3,2);
@@ -138,18 +128,14 @@ static void matmul4( GLfloat *product, const GLfloat *a, const GLfloat *b )
 }
 
 
-
-
 /* Multiply two matrices known to occupy only the top three rows,
  * such as typical modelling matrices, and ortho matrices.
- *
- * KW: 3*9 = 27 muls
  */
 static void matmul34( GLfloat *product, const GLfloat *a, const GLfloat *b )
 {
    GLint i;
    for (i = 0; i < 3; i++) {
-      GLfloat ai0=A(i,0),  ai1=A(i,1),  ai2=A(i,2),  ai3=A(i,3);
+      const GLfloat ai0=A(i,0),  ai1=A(i,1),  ai2=A(i,2),  ai3=A(i,3);
       P(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0);
       P(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1);
       P(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2);
@@ -165,7 +151,7 @@ static void matmul4fd( GLfloat *product, const GLfloat *a, const GLdouble *b )
 {
    GLint i;
    for (i = 0; i < 4; i++) {
-      GLfloat ai0=A(i,0),  ai1=A(i,1),  ai2=A(i,2),  ai3=A(i,3);
+      const GLfloat ai0=A(i,0),  ai1=A(i,1),  ai2=A(i,2),  ai3=A(i,3);
       P(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0) + ai3 * B(3,0);
       P(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1) + ai3 * B(3,1);
       P(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2) + ai3 * B(3,2);
@@ -178,7 +164,6 @@ static void matmul4fd( GLfloat *product, const GLfloat *a, const GLdouble *b )
 #undef P
 
 
-
 #define SWAP_ROWS(a, b) { GLfloat *_tmp = a; (a)=(b); (b)=_tmp; }
 #define MAT(m,r,c) (m)[(c)*4+(r)]
 
@@ -300,6 +285,7 @@ static GLboolean invert_matrix_general( GLmatrix *mat )
 }
 #undef SWAP_ROWS
 
+
 /* Adapted from graphics gems II.
  */  
 static GLboolean invert_matrix_3d_general( GLmatrix *mat )
@@ -367,16 +353,14 @@ static GLboolean invert_matrix_3d( GLmatrix *mat )
    const GLfloat *in = mat->m;
    GLfloat *out = mat->inv;
 
-   if (!TEST_MAT_FLAGS(mat, MAT_FLAGS_ANGLE_PRESERVING))
-   {
+   if (!TEST_MAT_FLAGS(mat, MAT_FLAGS_ANGLE_PRESERVING)) {
       return invert_matrix_3d_general( mat );
    }
    
-   if (mat->flags & MAT_FLAG_UNIFORM_SCALE)
-   {
-      GLfloat  scale = (MAT(in,0,0) * MAT(in,0,0) +
-                       MAT(in,0,1) * MAT(in,0,1) +
-                       MAT(in,0,2) * MAT(in,0,2));
+   if (mat->flags & MAT_FLAG_UNIFORM_SCALE) {
+      GLfloat scale = (MAT(in,0,0) * MAT(in,0,0) +
+                       MAT(in,0,1) * MAT(in,0,1) +
+                       MAT(in,0,2) * MAT(in,0,2));
 
       if (scale == 0.0) 
          return GL_FALSE;
@@ -394,8 +378,7 @@ static GLboolean invert_matrix_3d( GLmatrix *mat )
       MAT(out,1,2) = scale * MAT(in,2,1);
       MAT(out,2,2) = scale * MAT(in,2,2);
    }
-   else if (mat->flags & MAT_FLAG_ROTATION)
-   {
+   else if (mat->flags & MAT_FLAG_ROTATION) {
       /* Transpose the 3 by 3 upper-left submatrix. */
       MAT(out,0,0) = MAT(in,0,0);
       MAT(out,1,0) = MAT(in,0,1);
@@ -407,8 +390,8 @@ static GLboolean invert_matrix_3d( GLmatrix *mat )
       MAT(out,1,2) = MAT(in,2,1);
       MAT(out,2,2) = MAT(in,2,2);
    }
-   else /* pure translation */
-   {
+   else {
+      /* pure translation */
       MEMCPY( out, Identity, sizeof(Identity) );
       MAT(out,0,3) = - MAT(in,0,3);
       MAT(out,1,3) = - MAT(in,1,3);
@@ -416,8 +399,7 @@ static GLboolean invert_matrix_3d( GLmatrix *mat )
       return GL_TRUE;
    }
     
-   if (mat->flags & MAT_FLAG_TRANSLATION)
-   {
+   if (mat->flags & MAT_FLAG_TRANSLATION) {
       /* Do the translation part */
       MAT(out,0,3) = - (MAT(in,0,3) * MAT(out,0,0) +
                        MAT(in,1,3) * MAT(out,0,1) +
@@ -429,8 +411,7 @@ static GLboolean invert_matrix_3d( GLmatrix *mat )
                        MAT(in,1,3) * MAT(out,2,1) +
                        MAT(in,2,3) * MAT(out,2,2) );
    }
-   else 
-   {
+   else {
       MAT(out,0,3) = MAT(out,1,3) = MAT(out,2,3) = 0.0;
    }
     
@@ -459,8 +440,7 @@ static GLboolean invert_matrix_3d_no_rot( GLmatrix *mat )
    MAT(out,1,1) = 1.0 / MAT(in,1,1);
    MAT(out,2,2) = 1.0 / MAT(in,2,2);
 
-   if (mat->flags & MAT_FLAG_TRANSLATION)
-   {
+   if (mat->flags & MAT_FLAG_TRANSLATION) {
       MAT(out,0,3) = - (MAT(in,0,3) * MAT(out,0,0));
       MAT(out,1,3) = - (MAT(in,1,3) * MAT(out,1,1));
       MAT(out,2,3) = - (MAT(in,2,3) * MAT(out,2,2));
@@ -482,8 +462,7 @@ static GLboolean invert_matrix_2d_no_rot( GLmatrix *mat )
    MAT(out,0,0) = 1.0 / MAT(in,0,0);
    MAT(out,1,1) = 1.0 / MAT(in,1,1);
 
-   if (mat->flags & MAT_FLAG_TRANSLATION)
-   {
+   if (mat->flags & MAT_FLAG_TRANSLATION) {
       MAT(out,0,3) = - (MAT(in,0,3) * MAT(out,0,0));
       MAT(out,1,3) = - (MAT(in,1,3) * MAT(out,1,1));
    }
@@ -520,6 +499,7 @@ static GLboolean invert_matrix_perspective( GLmatrix *mat )
 
 typedef GLboolean (*inv_mat_func)( GLmatrix *mat );
 
+
 static inv_mat_func inv_mat_tab[7] = {
    invert_matrix_general,
    invert_matrix_identity,
@@ -531,16 +511,9 @@ static inv_mat_func inv_mat_tab[7] = {
 };
 
 
-GLboolean gl_matrix_invert( GLmatrix *mat )
+static GLboolean matrix_invert( GLmatrix *mat )
 {
    if (inv_mat_tab[mat->type](mat)) {
-#if 0
-      GLmatrix m; m.inv = 0; m.type = 0; m.flags = 0;
-      matmul4( m.m, mat->m, mat->inv );
-      printf("inverted matrix of type %s:\n", types[mat->type]);
-      gl_print_matrix( mat );
-      gl_print_matrix( &m );
-#endif
       return GL_TRUE;
    } else {
       MEMCPY( mat->inv, Identity, sizeof(Identity) );
@@ -550,6 +523,50 @@ GLboolean gl_matrix_invert( GLmatrix *mat )
 
 
 
+void gl_matrix_transposef( GLfloat to[16], const GLfloat from[16] )
+{
+   to[0] = from[0];
+   to[1] = from[4];
+   to[2] = from[8];
+   to[3] = from[12];
+   to[4] = from[1];
+   to[5] = from[5];
+   to[6] = from[9];
+   to[7] = from[13];
+   to[8] = from[2];
+   to[9] = from[6];
+   to[10] = from[10];
+   to[11] = from[14];
+   to[12] = from[3];
+   to[13] = from[7];
+   to[14] = from[11];
+   to[15] = from[15];
+}
+
+
+
+void gl_matrix_transposed( GLdouble to[16], const GLdouble from[16] )
+{
+   to[0] = from[0];
+   to[1] = from[4];
+   to[2] = from[8];
+   to[3] = from[12];
+   to[4] = from[1];
+   to[5] = from[5];
+   to[6] = from[9];
+   to[7] = from[13];
+   to[8] = from[2];
+   to[9] = from[6];
+   to[10] = from[10];
+   to[11] = from[14];
+   to[12] = from[3];
+   to[13] = from[7];
+   to[14] = from[11];
+   to[15] = from[15];
+}
+
+
+
 /*
  * Generate a 4x4 transformation matrix from glRotate parameters.
  */
@@ -565,7 +582,7 @@ void gl_rotation_matrix( GLfloat angle, GLfloat x, GLfloat y, GLfloat z,
 
    mag = GL_SQRT( x*x + y*y + z*z );
 
-   if (mag == 0.0) {
+   if (mag <= 1.0e-4) {
       /* generate an identity matrix and return */
       MEMCPY(m, Identity, sizeof(GLfloat)*16);
       return;
@@ -713,8 +730,7 @@ static void analyze_from_scratch( GLmatrix *mat )
    GLuint mask = 0;
    GLuint i;
 
-   for (i = 0 ; i < 16 ; i++) 
-   {
+   for (i = 0 ; i < 16 ; i++) {
       if (m[i] == 0.0) mask |= (1<<i);
    }
    
@@ -735,15 +751,13 @@ static void analyze_from_scratch( GLmatrix *mat )
    if (mask == MASK_IDENTITY) {
       mat->type = MATRIX_IDENTITY;
    }
-   else if ((mask & MASK_2D_NO_ROT) == MASK_2D_NO_ROT)  
-   {
+   else if ((mask & MASK_2D_NO_ROT) == MASK_2D_NO_ROT) {
       mat->type = MATRIX_2D_NO_ROT;
       
       if ((mask & MASK_NO_2D_SCALE) != MASK_NO_2D_SCALE)
         mat->flags = MAT_FLAG_GENERAL_SCALE;
    }
-   else if ((mask & MASK_2D) == MASK_2D)  
-   {
+   else if ((mask & MASK_2D) == MASK_2D) {
       GLfloat mm = DOT2(m, m);
       GLfloat m4m4 = DOT2(m+4,m+4);
       GLfloat mm4 = DOT2(m,m+4);
@@ -762,20 +776,21 @@ static void analyze_from_scratch( GLmatrix *mat )
         mat->flags |= MAT_FLAG_ROTATION;
 
    }
-   else if ((mask & MASK_3D_NO_ROT) == MASK_3D_NO_ROT)
-   {
+   else if ((mask & MASK_3D_NO_ROT) == MASK_3D_NO_ROT) {
       mat->type = MATRIX_3D_NO_ROT;
 
       /* Check for scale */
       if (SQ(m[0]-m[5]) < SQ(1e-6) && 
          SQ(m[0]-m[10]) < SQ(1e-6)) {
-        if (SQ(m[0]-1.0) > SQ(1e-6))
+        if (SQ(m[0]-1.0) > SQ(1e-6)) {
            mat->flags |= MAT_FLAG_UNIFORM_SCALE;
-      } else
+         }
+      }
+      else {
         mat->flags |= MAT_FLAG_GENERAL_SCALE;
+      }
    }
-   else if ((mask & MASK_3D) == MASK_3D)
-   {
+   else if ((mask & MASK_3D) == MASK_3D) {
       GLfloat c1 = DOT3(m,m);
       GLfloat c2 = DOT3(m+4,m+4);
       GLfloat c3 = DOT3(m+8,m+8);
@@ -789,8 +804,10 @@ static void analyze_from_scratch( GLmatrix *mat )
         if (SQ(c1-1.0) > SQ(1e-6))
            mat->flags |= MAT_FLAG_UNIFORM_SCALE;
         /* else no scale at all */
-      } else 
+      }
+      else {
         mat->flags |= MAT_FLAG_GENERAL_SCALE;
+      }
 
       /* Check for rotation */
       if (SQ(d1) < SQ(1e-6)) {
@@ -801,11 +818,11 @@ static void analyze_from_scratch( GLmatrix *mat )
         else
            mat->flags |= MAT_FLAG_GENERAL_3D;
       }
-      else
+      else {
         mat->flags |= MAT_FLAG_GENERAL_3D; /* shear, etc */
+      }
    }
-   else if ((mask & MASK_PERSPECTIVE) == MASK_PERSPECTIVE && m[11]==-1.0F) 
-   {
+   else if ((mask & MASK_PERSPECTIVE) == MASK_PERSPECTIVE && m[11]==-1.0F) {
       mat->type = MATRIX_PERSPECTIVE;
       mat->flags |= MAT_FLAG_GENERAL;
    }
@@ -828,8 +845,7 @@ static void analyze_from_flags( GLmatrix *mat )
    }
    else if (TEST_MAT_FLAGS(mat, (MAT_FLAG_TRANSLATION |
                                 MAT_FLAG_UNIFORM_SCALE |
-                                MAT_FLAG_GENERAL_SCALE)))
-   {
+                                MAT_FLAG_GENERAL_SCALE))) {
       if ( m[10]==1.0F && m[14]==0.0F ) {
         mat->type = MATRIX_2D_NO_ROT;
       }
@@ -840,26 +856,22 @@ static void analyze_from_flags( GLmatrix *mat )
    else if (TEST_MAT_FLAGS(mat, MAT_FLAGS_3D)) {
       if (                                 m[ 8]==0.0F               
             &&                             m[ 9]==0.0F
-            && m[2]==0.0F && m[6]==0.0F && m[10]==1.0F && m[14]==0.0F)
-      {
+            && m[2]==0.0F && m[6]==0.0F && m[10]==1.0F && m[14]==0.0F) {
         mat->type = MATRIX_2D;
       }
-      else 
-      {
+      else {
         mat->type = MATRIX_3D;
       }
    }
    else if (                 m[4]==0.0F                 && m[12]==0.0F
             && m[1]==0.0F                               && m[13]==0.0F
             && m[2]==0.0F && m[6]==0.0F
-            && m[3]==0.0F && m[7]==0.0F && m[11]==-1.0F && m[15]==0.0F) 
-   {
+            && m[3]==0.0F && m[7]==0.0F && m[11]==-1.0F && m[15]==0.0F) {
       mat->type = MATRIX_PERSPECTIVE;
    }
    else {
       mat->type = MATRIX_GENERAL;
    }
-
 }
 
 
@@ -873,7 +885,7 @@ void gl_matrix_analyze( GLmatrix *mat )
    }
 
    if (mat->inv && (mat->flags & MAT_DIRTY_INVERSE)) {
-      gl_matrix_invert( mat );
+      matrix_invert( mat );
    }
 
    mat->flags &= ~(MAT_DIRTY_FLAGS|
@@ -882,6 +894,104 @@ void gl_matrix_analyze( GLmatrix *mat )
 }
 
 
+static void matrix_copy( GLmatrix *to, const GLmatrix *from )
+{
+   MEMCPY( to->m, from->m, sizeof(Identity) );
+   to->flags = from->flags | MAT_DIRTY_DEPENDENTS;
+   to->type = from->type;
+
+   if (to->inv != 0) {
+      if (from->inv == 0) {
+        matrix_invert( to );
+      }
+      else {
+        MEMCPY(to->inv, from->inv, sizeof(GLfloat)*16);
+      }
+   }
+}
+
+/*
+ * Multiply a matrix by an array of floats with known properties.
+ */
+static void mat_mul_floats( GLmatrix *mat, const GLfloat *m, GLuint flags )
+{
+   mat->flags |= (flags |
+                 MAT_DIRTY_TYPE | 
+                 MAT_DIRTY_INVERSE | 
+                 MAT_DIRTY_DEPENDENTS);
+
+   if (TEST_MAT_FLAGS(mat, MAT_FLAGS_3D))
+      matmul34( mat->m, mat->m, m );
+   else 
+      matmul4( mat->m, mat->m, m );      
+
+}
+
+
+void gl_calculate_model_project_matrix( GLcontext *ctx )
+{
+   gl_matrix_mul( &ctx->ModelProjectMatrix,
+                 &ctx->ProjectionMatrix,
+                 &ctx->ModelView );
+
+   gl_matrix_analyze( &ctx->ModelProjectMatrix );
+}
+
+
+void gl_matrix_ctr( GLmatrix *m )
+{
+   if ( m->m == 0 ) {
+      m->m = (GLfloat *) ALIGN_MALLOC( 16 * sizeof(GLfloat), 16 );
+   }
+   MEMCPY( m->m, Identity, sizeof(Identity) );
+   m->inv = 0;
+   m->type = MATRIX_IDENTITY;
+   m->flags = MAT_DIRTY_DEPENDENTS;
+}
+
+void gl_matrix_dtr( GLmatrix *m )
+{
+   if ( m->m != 0 ) {
+      ALIGN_FREE( m->m );
+      m->m = 0;
+   }
+   if ( m->inv != 0 ) {
+      ALIGN_FREE( m->inv );
+      m->inv = 0;
+   }
+}
+
+
+void gl_matrix_alloc_inv( GLmatrix *m )
+{
+   if ( m->inv == 0 ) {
+      m->inv = (GLfloat *) ALIGN_MALLOC( 16 * sizeof(GLfloat), 16 );
+      MEMCPY( m->inv, Identity, 16 * sizeof(GLfloat) );
+   }
+}
+
+
+void gl_matrix_mul( GLmatrix *dest, const GLmatrix *a, const GLmatrix *b )
+{
+   dest->flags = (a->flags |
+                 b->flags |
+                 MAT_DIRTY_TYPE | 
+                 MAT_DIRTY_INVERSE | 
+                 MAT_DIRTY_DEPENDENTS);
+
+   if (TEST_MAT_FLAGS(dest, MAT_FLAGS_3D))
+      matmul34( dest->m, a->m, b->m );
+   else 
+      matmul4( dest->m, a->m, b->m );
+}
+
+
+
+/**********************************************************************/
+/*                        API functions                               */
+/**********************************************************************/
+
+
 #define GET_ACTIVE_MATRIX(ctx, mat, flags, where)                      \
 do {                                                                   \
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, where);                      \
@@ -889,15 +999,19 @@ do {                                                                      \
    switch (ctx->Transform.MatrixMode) {                                        \
       case GL_MODELVIEW:                                               \
         mat = &ctx->ModelView;                                         \
-        flags |= NEW_MODELVIEW;                                        \
+        flags |= _NEW_MODELVIEW;                                       \
         break;                                                         \
       case GL_PROJECTION:                                              \
         mat = &ctx->ProjectionMatrix;                                  \
-        flags |= NEW_PROJECTION;                                       \
+        flags |= _NEW_PROJECTION;                                      \
         break;                                                         \
       case GL_TEXTURE:                                                 \
         mat = &ctx->TextureMatrix[ctx->Texture.CurrentTransformUnit];  \
-        flags |= NEW_TEXTURE_MATRIX;                                   \
+        flags |= _NEW_TEXTURE_MATRIX;                                  \
+        break;                                                         \
+      case GL_COLOR:                                                   \
+        mat = &ctx->ColorMatrix;                                       \
+        flags |= _NEW_COLOR_MATRIX;                                    \
         break;                                                         \
       default:                                                         \
          gl_problem(ctx, where);                                       \
@@ -905,11 +1019,12 @@ do {                                                                     \
 } while (0)
 
 
-void gl_Frustum( GLcontext *ctx,
-                 GLdouble left, GLdouble right,
-                GLdouble bottom, GLdouble top,
-                GLdouble nearval, GLdouble farval )
+void
+_mesa_Frustum( GLdouble left, GLdouble right,
+               GLdouble bottom, GLdouble top,
+               GLdouble nearval, GLdouble farval )
 {
+   GET_CURRENT_CONTEXT(ctx);
    GLfloat x, y, a, b, c, d;
    GLfloat m[16];
    GLmatrix *mat = 0;
@@ -935,12 +1050,9 @@ void gl_Frustum( GLcontext *ctx,
    M(3,0) = 0.0F;  M(3,1) = 0.0F;  M(3,2) = -1.0F;  M(3,3) = 0.0F;
 #undef M
 
+   mat_mul_floats( mat, m, MAT_FLAG_PERSPECTIVE );
 
-   gl_mat_mul_floats( mat, m, MAT_FLAG_PERSPECTIVE );
-
-
-   if (ctx->Transform.MatrixMode == GL_PROJECTION)
-   {
+   if (ctx->Transform.MatrixMode == GL_PROJECTION) {
       /* Need to keep a stack of near/far values in case the user push/pops
        * the projection matrix stack so that we can call Driver.NearFar()
        * after a pop.
@@ -955,11 +1067,12 @@ void gl_Frustum( GLcontext *ctx,
 }
 
 
-void gl_Ortho( GLcontext *ctx,
-               GLdouble left, GLdouble right,
-               GLdouble bottom, GLdouble top,
-               GLdouble nearval, GLdouble farval )
+void
+_mesa_Ortho( GLdouble left, GLdouble right,
+             GLdouble bottom, GLdouble top,
+             GLdouble nearval, GLdouble farval )
 {
+   GET_CURRENT_CONTEXT(ctx);
    GLfloat x, y, z;
    GLfloat tx, ty, tz;
    GLfloat m[16];
@@ -968,7 +1081,8 @@ void gl_Ortho( GLcontext *ctx,
    GET_ACTIVE_MATRIX( ctx,  mat, ctx->NewState, "glOrtho" );
    
    if ((left == right) || (bottom == top) || (nearval == farval)) {
-      gl_error( ctx,  GL_INVALID_VALUE, "gl_Ortho((l = r) or (b = top) or (n=f)" );
+      gl_error( ctx,  GL_INVALID_VALUE,
+                "gl_Ortho((l = r) or (b = top) or (n=f)" );
       return;
    }
 
@@ -986,7 +1100,7 @@ void gl_Ortho( GLcontext *ctx,
    M(3,0) = 0.0F;  M(3,1) = 0.0F;  M(3,2) = 0.0F;  M(3,3) = 1.0F;
 #undef M
 
-   gl_mat_mul_floats( mat, m, (MAT_FLAG_GENERAL_SCALE|MAT_FLAG_TRANSLATION));
+   mat_mul_floats( mat, m, (MAT_FLAG_GENERAL_SCALE|MAT_FLAG_TRANSLATION));
 
    if (ctx->Driver.NearFar) {
       (*ctx->Driver.NearFar)( ctx, nearval, farval );
@@ -994,13 +1108,16 @@ void gl_Ortho( GLcontext *ctx,
 }
 
 
-void gl_MatrixMode( GLcontext *ctx, GLenum mode )
+void
+_mesa_MatrixMode( GLenum mode )
 {
+   GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glMatrixMode");
    switch (mode) {
       case GL_MODELVIEW:
       case GL_PROJECTION:
       case GL_TEXTURE:
+      case GL_COLOR:
          ctx->Transform.MatrixMode = mode;
          break;
       default:
@@ -1010,8 +1127,10 @@ void gl_MatrixMode( GLcontext *ctx, GLenum mode )
 
 
 
-void gl_PushMatrix( GLcontext *ctx )
+void
+_mesa_PushMatrix( void )
 {
+   GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPushMatrix");
 
    if (MESA_VERBOSE&VERBOSE_API)
@@ -1020,20 +1139,20 @@ void gl_PushMatrix( GLcontext *ctx )
 
    switch (ctx->Transform.MatrixMode) {
       case GL_MODELVIEW:
-         if (ctx->ModelViewStackDepth>=MAX_MODELVIEW_STACK_DEPTH-1) {
+         if (ctx->ModelViewStackDepth >= MAX_MODELVIEW_STACK_DEPTH - 1) {
             gl_error( ctx,  GL_STACK_OVERFLOW, "glPushMatrix");
             return;
          }
-         gl_matrix_copy( &ctx->ModelViewStack[ctx->ModelViewStackDepth++],
-                        &ctx->ModelView );
+         matrix_copy( &ctx->ModelViewStack[ctx->ModelViewStackDepth++],
+                      &ctx->ModelView );
          break;
       case GL_PROJECTION:
-         if (ctx->ProjectionStackDepth>=MAX_PROJECTION_STACK_DEPTH) {
+         if (ctx->ProjectionStackDepth >= MAX_PROJECTION_STACK_DEPTH - 1) {
             gl_error( ctx,  GL_STACK_OVERFLOW, "glPushMatrix");
             return;
          }
-         gl_matrix_copy( &ctx->ProjectionStack[ctx->ProjectionStackDepth++],
-                        &ctx->ProjectionMatrix );
+         matrix_copy( &ctx->ProjectionStack[ctx->ProjectionStackDepth++],
+                      &ctx->ProjectionMatrix );
 
          /* Save near and far projection values */
          ctx->NearFarStack[ctx->ProjectionStackDepth][0]
@@ -1044,13 +1163,21 @@ void gl_PushMatrix( GLcontext *ctx )
       case GL_TEXTURE:
          {
             GLuint t = ctx->Texture.CurrentTransformUnit;
-            if (ctx->TextureStackDepth[t] >= MAX_TEXTURE_STACK_DEPTH) {
+            if (ctx->TextureStackDepth[t] >= MAX_TEXTURE_STACK_DEPTH - 1) {
                gl_error( ctx,  GL_STACK_OVERFLOW, "glPushMatrix");
                return;
             }
-           gl_matrix_copy( &ctx->TextureStack[t][ctx->TextureStackDepth[t]++],
-                           &ctx->TextureMatrix[t] );
+           matrix_copy( &ctx->TextureStack[t][ctx->TextureStackDepth[t]++],
+                         &ctx->TextureMatrix[t] );
+         }
+         break;
+      case GL_COLOR:
+         if (ctx->ColorStackDepth >= MAX_COLOR_STACK_DEPTH - 1) {
+            gl_error( ctx,  GL_STACK_OVERFLOW, "glPushMatrix");
+            return;
          }
+         matrix_copy( &ctx->ColorStack[ctx->ColorStackDepth++],
+                      &ctx->ColorMatrix );
          break;
       default:
          gl_problem(ctx, "Bad matrix mode in gl_PushMatrix");
@@ -1059,8 +1186,10 @@ void gl_PushMatrix( GLcontext *ctx )
 
 
 
-void gl_PopMatrix( GLcontext *ctx )
+void
+_mesa_PopMatrix( void )
 {
+   GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPopMatrix");
 
    if (MESA_VERBOSE&VERBOSE_API)
@@ -1073,9 +1202,9 @@ void gl_PopMatrix( GLcontext *ctx )
             gl_error( ctx,  GL_STACK_UNDERFLOW, "glPopMatrix");
             return;
          }
-         gl_matrix_copy( &ctx->ModelView,
-                        &ctx->ModelViewStack[--ctx->ModelViewStackDepth] );
-        ctx->NewState |= NEW_MODELVIEW;
+         matrix_copy( &ctx->ModelView,
+                      &ctx->ModelViewStack[--ctx->ModelViewStackDepth] );
+        ctx->NewState |= _NEW_MODELVIEW;
          break;
       case GL_PROJECTION:
          if (ctx->ProjectionStackDepth==0) {
@@ -1083,9 +1212,9 @@ void gl_PopMatrix( GLcontext *ctx )
             return;
          }
 
-         gl_matrix_copy( &ctx->ProjectionMatrix,
-                        &ctx->ProjectionStack[--ctx->ProjectionStackDepth] );
-        ctx->NewState |= NEW_PROJECTION;
+         matrix_copy( &ctx->ProjectionMatrix,
+                      &ctx->ProjectionStack[--ctx->ProjectionStackDepth] );
+        ctx->NewState |= _NEW_PROJECTION;
 
          /* Device driver near/far values */
          {
@@ -1103,10 +1232,20 @@ void gl_PopMatrix( GLcontext *ctx )
                gl_error( ctx,  GL_STACK_UNDERFLOW, "glPopMatrix");
                return;
             }
-           gl_matrix_copy(&ctx->TextureMatrix[t],
-                          &ctx->TextureStack[t][--ctx->TextureStackDepth[t]]);
+           matrix_copy(&ctx->TextureMatrix[t],
+                        &ctx->TextureStack[t][--ctx->TextureStackDepth[t]]);
+           ctx->NewState |= _NEW_TEXTURE_MATRIX;
          }
          break;
+      case GL_COLOR:
+         if (ctx->ColorStackDepth==0) {
+            gl_error( ctx,  GL_STACK_UNDERFLOW, "glPopMatrix");
+            return;
+         }
+         matrix_copy(&ctx->ColorMatrix,
+                     &ctx->ColorStack[--ctx->ColorStackDepth]);
+        ctx->NewState |= _NEW_COLOR_MATRIX;
+         break;
       default:
          gl_problem(ctx, "Bad matrix mode in gl_PopMatrix");
    }
@@ -1114,8 +1253,10 @@ void gl_PopMatrix( GLcontext *ctx )
 
 
 
-void gl_LoadIdentity( GLcontext *ctx )
+void
+_mesa_LoadIdentity( void )
 {
+   GET_CURRENT_CONTEXT(ctx);
    GLmatrix *mat = 0;
    GET_ACTIVE_MATRIX(ctx, mat, ctx->NewState, "glLoadIdentity");
 
@@ -1134,8 +1275,10 @@ void gl_LoadIdentity( GLcontext *ctx )
 }
 
 
-void gl_LoadMatrixf( GLcontext *ctx, const GLfloat *m )
+void
+_mesa_LoadMatrixf( const GLfloat *m )
 {
+   GET_CURRENT_CONTEXT(ctx);
    GLmatrix *mat = 0;
    GET_ACTIVE_MATRIX(ctx, mat, ctx->NewState, "glLoadMatrix");
 
@@ -1165,12 +1308,25 @@ void gl_LoadMatrixf( GLcontext *ctx, const GLfloat *m )
 }
 
 
+void
+_mesa_LoadMatrixd( const GLdouble *m )
+{
+   GLfloat f[16];
+   GLint i;
+   for (i = 0; i < 16; i++)
+      f[i] = m[i];
+   _mesa_LoadMatrixf(f);
+}
+
+
 
 /*
  * Multiply the active matrix by an arbitary matrix.
  */
-void gl_MultMatrixf( GLcontext *ctx, const GLfloat *m )
+void
+_mesa_MultMatrixf( const GLfloat *m )
 {
+   GET_CURRENT_CONTEXT(ctx);
    GLmatrix *mat = 0;
    GET_ACTIVE_MATRIX( ctx,  mat, ctx->NewState, "glMultMatrix" );
    matmul4( mat->m, mat->m, m );
@@ -1181,8 +1337,10 @@ void gl_MultMatrixf( GLcontext *ctx, const GLfloat *m )
 /*
  * Multiply the active matrix by an arbitary matrix.  
  */
-void gl_MultMatrixd( GLcontext *ctx, const GLdouble *m )
+void
+_mesa_MultMatrixd( const GLdouble *m )
 {
+   GET_CURRENT_CONTEXT(ctx);
    GLmatrix *mat = 0;
    GET_ACTIVE_MATRIX( ctx,  mat, ctx->NewState, "glMultMatrix" );
    matmul4fd( mat->m, mat->m, m );
@@ -1192,62 +1350,37 @@ void gl_MultMatrixd( GLcontext *ctx, const GLdouble *m )
 
 
 
-/*
- * Multiply a matrix by an array of floats with known properties.
- */
-void gl_mat_mul_floats( GLmatrix *mat, const GLfloat *m, GLuint flags )
-{
-   mat->flags |= (flags |
-                 MAT_DIRTY_TYPE | 
-                 MAT_DIRTY_INVERSE | 
-                 MAT_DIRTY_DEPENDENTS);
-
-   if (TEST_MAT_FLAGS(mat, MAT_FLAGS_3D))
-      matmul34( mat->m, mat->m, m );
-   else 
-      matmul4( mat->m, mat->m, m );      
-
-}
-
-/*
- * Multiply a matrix by an array of floats with known properties.
- */
-void gl_mat_mul_mat( GLmatrix *mat, const GLmatrix *m )
-{
-   mat->flags |= (m->flags |
-                 MAT_DIRTY_TYPE | 
-                 MAT_DIRTY_INVERSE | 
-                 MAT_DIRTY_DEPENDENTS);
-
-   if (TEST_MAT_FLAGS(mat, MAT_FLAGS_3D))
-      matmul34( mat->m, mat->m, m->m );
-   else 
-      matmul4( mat->m, mat->m, m->m );      
-}
-
-
-
 /*
  * Execute a glRotate call
  */
-void gl_Rotatef( GLcontext *ctx,
-                 GLfloat angle, GLfloat x, GLfloat y, GLfloat z )
+void
+_mesa_Rotatef( GLfloat angle, GLfloat x, GLfloat y, GLfloat z )
 {
+   GET_CURRENT_CONTEXT(ctx);
    GLfloat m[16];
    if (angle != 0.0F) {
       GLmatrix *mat = 0;
       GET_ACTIVE_MATRIX( ctx,  mat, ctx->NewState, "glRotate" );
 
       gl_rotation_matrix( angle, x, y, z, m );
-      gl_mat_mul_floats( mat, m, MAT_FLAG_ROTATION );
+      mat_mul_floats( mat, m, MAT_FLAG_ROTATION );
    }
 }
 
+void
+_mesa_Rotated( GLdouble angle, GLdouble x, GLdouble y, GLdouble z )
+{
+   _mesa_Rotatef(angle, x, y, z);
+}
+
+
 /*
  * Execute a glScale call
  */
-void gl_Scalef( GLcontext *ctx, GLfloat x, GLfloat y, GLfloat z )
+void
+_mesa_Scalef( GLfloat x, GLfloat y, GLfloat z )
 {
+   GET_CURRENT_CONTEXT(ctx);
    GLmatrix *mat = 0;
    GLfloat *m;
    GET_ACTIVE_MATRIX(ctx, mat, ctx->NewState, "glScale");
@@ -1268,11 +1401,21 @@ void gl_Scalef( GLcontext *ctx, GLfloat x, GLfloat y, GLfloat z )
                  MAT_DIRTY_DEPENDENTS);
 }
 
+
+void
+_mesa_Scaled( GLdouble x, GLdouble y, GLdouble z )
+{
+   _mesa_Scalef(x, y, z);
+}
+
+
 /*
  * Execute a glTranslate call
  */
-void gl_Translatef( GLcontext *ctx, GLfloat x, GLfloat y, GLfloat z )
+void
+_mesa_Translatef( GLfloat x, GLfloat y, GLfloat z )
 {
+   GET_CURRENT_CONTEXT(ctx);
    GLmatrix *mat = 0;
    GLfloat *m;
    GET_ACTIVE_MATRIX(ctx, mat, ctx->NewState, "glTranslate");
@@ -1289,12 +1432,72 @@ void gl_Translatef( GLcontext *ctx, GLfloat x, GLfloat y, GLfloat z )
 }
 
 
+void
+_mesa_Translated( GLdouble x, GLdouble y, GLdouble z )
+{
+   _mesa_Translatef(x, y, z);
+}
+
+
+
+void
+_mesa_LoadTransposeMatrixfARB( const GLfloat *m )
+{
+   GLfloat tm[16];
+   gl_matrix_transposef(tm, m);
+   _mesa_LoadMatrixf(tm);
+}
+
+
+void
+_mesa_LoadTransposeMatrixdARB( const GLdouble *m )
+{
+   GLdouble tm[16];
+   gl_matrix_transposed(tm, m);
+   _mesa_LoadMatrixd(tm);
+}
+
+
+void
+_mesa_MultTransposeMatrixfARB( const GLfloat *m )
+{
+   GLfloat tm[16];
+   gl_matrix_transposef(tm, m);
+   _mesa_MultMatrixf(tm);
+}
+
+
+void
+_mesa_MultTransposeMatrixdARB( const GLdouble *m )
+{
+   GLdouble tm[16];
+   gl_matrix_transposed(tm, m);
+   _mesa_MultMatrixd(tm);
+}
+
+
+/*
+ * Called via glViewport or display list execution.
+ */
+void
+_mesa_Viewport( GLint x, GLint y, GLsizei width, GLsizei height )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   gl_Viewport(ctx, x, y, width, height);
+}
+
+
+
 /*
  * Define a new viewport and reallocate auxillary buffers if the size of
  * the window (color buffer) has changed.
+ *
+ * XXX This is directly called by device drivers, BUT this function
+ * may be renamed _mesa_Viewport (without ctx arg) in the future so
+ * use of _mesa_Viewport is encouraged.
  */
-void gl_Viewport( GLcontext *ctx,
-                  GLint x, GLint y, GLsizei width, GLsizei height )
+void
+gl_Viewport( GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height )
 {
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glViewport");
 
@@ -1321,27 +1524,25 @@ void gl_Viewport( GLcontext *ctx,
    ctx->Viewport.WindowMap.m[MAT_TX] = ctx->Viewport.WindowMap.m[MAT_SX] + x;
    ctx->Viewport.WindowMap.m[MAT_SY] = (GLfloat) height / 2.0F;
    ctx->Viewport.WindowMap.m[MAT_TY] = ctx->Viewport.WindowMap.m[MAT_SY] + y;
-   ctx->Viewport.WindowMap.m[MAT_SZ] = 0.5 * DEPTH_SCALE;
-   ctx->Viewport.WindowMap.m[MAT_TZ] = 0.5 * DEPTH_SCALE;
+   ctx->Viewport.WindowMap.m[MAT_SZ] = 0.5 * ctx->Visual.DepthMaxF;
+   ctx->Viewport.WindowMap.m[MAT_TZ] = 0.5 * ctx->Visual.DepthMaxF;
 
    ctx->Viewport.WindowMap.flags = MAT_FLAG_GENERAL_SCALE|MAT_FLAG_TRANSLATION;
    ctx->Viewport.WindowMap.type = MATRIX_3D_NO_ROT;
-
-   ctx->ModelProjectWinMatrixUptodate = GL_FALSE;
-   ctx->NewState |= NEW_VIEWPORT;
+   ctx->NewState |= _NEW_VIEWPORT;
 
    /* Check if window/buffer has been resized and if so, reallocate the
     * ancillary buffers.
     */
-   gl_ResizeBuffersMESA(ctx);
+   _mesa_ResizeBuffersMESA();
 
 
    ctx->RasterMask &= ~WINCLIP_BIT;
 
    if (   ctx->Viewport.X<0
-       || ctx->Viewport.X + ctx->Viewport.Width > ctx->Buffer->Width
+       || ctx->Viewport.X + ctx->Viewport.Width > ctx->DrawBuffer->Width
        || ctx->Viewport.Y<0
-       || ctx->Viewport.Y + ctx->Viewport.Height > ctx->Buffer->Height) {
+       || ctx->Viewport.Y + ctx->Viewport.Height > ctx->DrawBuffer->Height) {
       ctx->RasterMask |= WINCLIP_BIT;
    }
 
@@ -1353,7 +1554,8 @@ void gl_Viewport( GLcontext *ctx,
 
 
 
-void gl_DepthRange( GLcontext *ctx, GLclampd nearval, GLclampd farval )
+void
+_mesa_DepthRange( GLclampd nearval, GLclampd farval )
 {
    /*
     * nearval - specifies mapping of the near clipping plane to window
@@ -1367,7 +1569,7 @@ void gl_DepthRange( GLcontext *ctx, GLclampd nearval, GLclampd farval )
     * this range to window z coords.
     */
    GLfloat n, f;
-
+   GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDepthRange");
 
    if (MESA_VERBOSE&VERBOSE_API)
@@ -1378,84 +1580,11 @@ void gl_DepthRange( GLcontext *ctx, GLclampd nearval, GLclampd farval )
 
    ctx->Viewport.Near = n;
    ctx->Viewport.Far = f;
-   ctx->Viewport.WindowMap.m[MAT_SZ] = DEPTH_SCALE * ((f - n) / 2.0);
-   ctx->Viewport.WindowMap.m[MAT_TZ] = DEPTH_SCALE * ((f - n) / 2.0 + n);
-
-   ctx->ModelProjectWinMatrixUptodate = GL_FALSE;
+   ctx->Viewport.WindowMap.m[MAT_SZ] = ctx->Visual.DepthMaxF * ((f - n) / 2.0);
+   ctx->Viewport.WindowMap.m[MAT_TZ] = ctx->Visual.DepthMaxF * ((f - n) / 2.0 + n);
+   ctx->NewState |= _NEW_VIEWPORT;
 
    if (ctx->Driver.DepthRange) {
       (*ctx->Driver.DepthRange)( ctx, nearval, farval );
    }
 }
-
-
-void gl_calculate_model_project_matrix( GLcontext *ctx )
-{
-   gl_matrix_mul( &ctx->ModelProjectMatrix,
-                 &ctx->ProjectionMatrix,
-                 &ctx->ModelView );
-
-   gl_matrix_analyze( &ctx->ModelProjectMatrix );
-}
-
-
-void gl_matrix_ctr( GLmatrix *m )
-{
-   m->inv = 0;
-   MEMCPY( m->m, Identity, sizeof(Identity));
-   m->type = MATRIX_IDENTITY;
-   m->flags = MAT_DIRTY_DEPENDENTS;
-}
-
-void gl_matrix_dtr( GLmatrix *m )
-{
-   if (m->inv != 0) {
-      free(m->inv);
-      m->inv = 0;
-   }
-}
-
-void gl_matrix_set_identity( GLmatrix *m )
-{
-   MEMCPY( m->m, Identity, sizeof(Identity));
-   m->type = MATRIX_IDENTITY;
-   m->flags = MAT_DIRTY_DEPENDENTS;
-}
-
-
-void gl_matrix_alloc_inv( GLmatrix *m )
-{
-   if (m->inv == 0) {
-      m->inv = (GLfloat *)malloc(16*sizeof(GLfloat));
-      MEMCPY( m->inv, Identity, 16 * sizeof(GLfloat) );
-   }
-}
-
-void gl_matrix_copy( GLmatrix *to, const GLmatrix *from )
-{
-   MEMCPY( to->m, from->m, sizeof(Identity));
-   to->flags = from->flags | MAT_DIRTY_DEPENDENTS;
-   to->type = from->type;
-
-   if (to->inv != 0) {
-      if (from->inv == 0) {
-        gl_matrix_invert( to );
-      } else {
-        MEMCPY(to->inv, from->inv, sizeof(GLfloat)*16);
-      }
-   }
-}
-
-void gl_matrix_mul( GLmatrix *dest, const GLmatrix *a, const GLmatrix *b )
-{
-   dest->flags = (a->flags |
-                 b->flags |
-                 MAT_DIRTY_TYPE | 
-                 MAT_DIRTY_INVERSE | 
-                 MAT_DIRTY_DEPENDENTS);
-
-   if (TEST_MAT_FLAGS(dest, MAT_FLAGS_3D))
-      matmul34( dest->m, a->m, b->m );
-   else 
-      matmul4( dest->m, a->m, b->m );
-}