fixed pointer arithmetic error in glCopyPixels
[mesa.git] / src / mesa / main / matrix.c
index 6573a46c02f62891a3e7877d4687eee5117ba2d3..eaec178b0a1df2493933ad29b30f2ca11669938d 100644 (file)
@@ -1,10 +1,10 @@
-/* $Id: matrix.c,v 1.27 2000/11/22 07:32:17 joukj Exp $ */
+/* $Id: matrix.c,v 1.39 2002/02/15 16:24:37 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-2001  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"),
 #endif
 
 
-/**********************************************************************/
-/*                        API functions                               */
-/**********************************************************************/
-
-
-#define GET_ACTIVE_MATRIX(ctx, mat, flags, where)                      \
-do {                                                                   \
-   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, where);                      \
-   if (MESA_VERBOSE&VERBOSE_API) fprintf(stderr, "%s\n", where);        \
-   switch (ctx->Transform.MatrixMode) {                                        \
-      case GL_MODELVIEW:                                               \
-        mat = &ctx->ModelView;                                         \
-        flags |= _NEW_MODELVIEW;                                       \
-        break;                                                         \
-      case GL_PROJECTION:                                              \
-        mat = &ctx->ProjectionMatrix;                                  \
-        flags |= _NEW_PROJECTION;                                      \
-        break;                                                         \
-      case GL_TEXTURE:                                                 \
-        mat = &ctx->TextureMatrix[ctx->Texture.CurrentTransformUnit];  \
-        flags |= _NEW_TEXTURE_MATRIX;                                  \
-        break;                                                         \
-      case GL_COLOR:                                                   \
-        mat = &ctx->ColorMatrix;                                       \
-        flags |= _NEW_COLOR_MATRIX;                                    \
-        break;                                                         \
-      default:                                                         \
-         gl_problem(ctx, where);                                       \
-   }                                                                   \
-} while (0)
-
-
 void
 _mesa_Frustum( GLdouble left, GLdouble right,
                GLdouble bottom, GLdouble top,
                GLdouble nearval, GLdouble farval )
 {
    GET_CURRENT_CONTEXT(ctx);
-   GLmatrix *mat = 0;
-
-   GET_ACTIVE_MATRIX( ctx,  mat, ctx->NewState, "glFrustrum" );
+   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
 
    if (nearval <= 0.0 ||
        farval <= 0.0 ||
@@ -100,11 +66,15 @@ _mesa_Frustum( GLdouble left, GLdouble right,
        left == right ||
        top == bottom)
    {
-      gl_error( ctx,  GL_INVALID_VALUE, "glFrustum" );
+      _mesa_error( ctx,  GL_INVALID_VALUE, "glFrustum" );
       return;
    }
 
-   _math_matrix_frustrum( mat, left, right, bottom, top, nearval, farval );
+   _math_matrix_frustum( ctx->CurrentStack->Top,
+                         (GLfloat) left, (GLfloat) right, 
+                        (GLfloat) bottom, (GLfloat) top, 
+                        (GLfloat) nearval, (GLfloat) farval );
+   ctx->NewState |= ctx->CurrentStack->DirtyFlag;
 }
 
 
@@ -114,19 +84,21 @@ _mesa_Ortho( GLdouble left, GLdouble right,
              GLdouble nearval, GLdouble farval )
 {
    GET_CURRENT_CONTEXT(ctx);
-   GLmatrix *mat = 0;
-
-   GET_ACTIVE_MATRIX( ctx,  mat, ctx->NewState, "glOrtho" );
+   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
 
    if (left == right ||
        bottom == top ||
        nearval == farval)
    {
-      gl_error( ctx,  GL_INVALID_VALUE, "gl_Ortho" );
+      _mesa_error( ctx,  GL_INVALID_VALUE, "glOrtho" );
       return;
    }
 
-   _math_matrix_ortho( mat, left, right, bottom, top, nearval, farval );
+   _math_matrix_ortho( ctx->CurrentStack->Top,
+                       (GLfloat) left, (GLfloat) right, 
+                      (GLfloat) bottom, (GLfloat) top, 
+                      (GLfloat) nearval, (GLfloat) farval );
+   ctx->NewState |= ctx->CurrentStack->DirtyFlag;
 }
 
 
@@ -134,17 +106,45 @@ void
 _mesa_MatrixMode( GLenum mode )
 {
    GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glMatrixMode");
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (ctx->Transform.MatrixMode == mode && mode != GL_TEXTURE)
+      return;
+   FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
+
    switch (mode) {
-      case GL_MODELVIEW:
-      case GL_PROJECTION:
-      case GL_TEXTURE:
-      case GL_COLOR:
-         ctx->Transform.MatrixMode = mode;
-         break;
-      default:
-         gl_error( ctx,  GL_INVALID_ENUM, "glMatrixMode" );
+   case GL_MODELVIEW:
+      ctx->CurrentStack = &ctx->ModelviewMatrixStack;
+      break;
+   case GL_PROJECTION:
+      ctx->CurrentStack = &ctx->ProjectionMatrixStack;
+      break;
+   case GL_TEXTURE:
+      ctx->CurrentStack = &ctx->TextureMatrixStack[ctx->Texture.CurrentUnit];
+      break;
+   case GL_COLOR:
+      ctx->CurrentStack = &ctx->ColorMatrixStack;
+      break;
+   case GL_MATRIX0_NV:
+   case GL_MATRIX1_NV:
+   case GL_MATRIX2_NV:
+   case GL_MATRIX3_NV:
+   case GL_MATRIX4_NV:
+   case GL_MATRIX5_NV:
+   case GL_MATRIX6_NV:
+   case GL_MATRIX7_NV:
+      if (!ctx->Extensions.NV_vertex_program) {
+         _mesa_error( ctx,  GL_INVALID_ENUM, "glMatrixMode" );
+         return;
+      }
+      ctx->CurrentStack = &ctx->ProgramMatrixStack[mode - GL_MATRIX0_NV];
+      break;
+   default:
+      _mesa_error( ctx,  GL_INVALID_ENUM, "glMatrixMode" );
+      return;
    }
+
+   ctx->Transform.MatrixMode = mode;
 }
 
 
@@ -153,51 +153,22 @@ void
 _mesa_PushMatrix( void )
 {
    GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPushMatrix");
+   struct matrix_stack *stack = ctx->CurrentStack;
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (MESA_VERBOSE&VERBOSE_API)
       fprintf(stderr, "glPushMatrix %s\n",
-             gl_lookup_enum_by_nr(ctx->Transform.MatrixMode));
-
-   switch (ctx->Transform.MatrixMode) {
-      case GL_MODELVIEW:
-         if (ctx->ModelViewStackDepth >= MAX_MODELVIEW_STACK_DEPTH - 1) {
-            gl_error( ctx,  GL_STACK_OVERFLOW, "glPushMatrix");
-            return;
-         }
-         _math_matrix_copy( &ctx->ModelViewStack[ctx->ModelViewStackDepth++],
-                      &ctx->ModelView );
-         break;
-      case GL_PROJECTION:
-         if (ctx->ProjectionStackDepth >= MAX_PROJECTION_STACK_DEPTH - 1) {
-            gl_error( ctx,  GL_STACK_OVERFLOW, "glPushMatrix");
-            return;
-         }
-         _math_matrix_copy( &ctx->ProjectionStack[ctx->ProjectionStackDepth++],
-                      &ctx->ProjectionMatrix );
-         break;
-      case GL_TEXTURE:
-         {
-            GLuint t = ctx->Texture.CurrentTransformUnit;
-            if (ctx->TextureStackDepth[t] >= MAX_TEXTURE_STACK_DEPTH - 1) {
-               gl_error( ctx,  GL_STACK_OVERFLOW, "glPushMatrix");
-               return;
-            }
-           _math_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;
-         }
-         _math_matrix_copy( &ctx->ColorStack[ctx->ColorStackDepth++],
-                      &ctx->ColorMatrix );
-         break;
-      default:
-         gl_problem(ctx, "Bad matrix mode in gl_PushMatrix");
+             _mesa_lookup_enum_by_nr(ctx->Transform.MatrixMode));
+
+   if (stack->Depth + 1 >= stack->MaxDepth) {
+      _mesa_error( ctx,  GL_STACK_OVERFLOW, "glPushMatrix" );
+      return;
    }
+   _math_matrix_copy( &stack->Stack[stack->Depth + 1],
+                      &stack->Stack[stack->Depth] );
+   stack->Depth++;
+   stack->Top = &(stack->Stack[stack->Depth]);
+   ctx->NewState |= stack->DirtyFlag;
 }
 
 
@@ -206,56 +177,20 @@ void
 _mesa_PopMatrix( void )
 {
    GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPopMatrix");
+   struct matrix_stack *stack = ctx->CurrentStack;
+   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
 
    if (MESA_VERBOSE&VERBOSE_API)
       fprintf(stderr, "glPopMatrix %s\n",
-             gl_lookup_enum_by_nr(ctx->Transform.MatrixMode));
-
-   switch (ctx->Transform.MatrixMode) {
-      case GL_MODELVIEW:
-         if (ctx->ModelViewStackDepth==0) {
-            gl_error( ctx,  GL_STACK_UNDERFLOW, "glPopMatrix");
-            return;
-         }
-         _math_matrix_copy( &ctx->ModelView,
-                           &ctx->ModelViewStack[--ctx->ModelViewStackDepth] );
-        ctx->NewState |= _NEW_MODELVIEW;
-         break;
-      case GL_PROJECTION:
-         if (ctx->ProjectionStackDepth==0) {
-            gl_error( ctx,  GL_STACK_UNDERFLOW, "glPopMatrix");
-            return;
-         }
-
-         _math_matrix_copy( &ctx->ProjectionMatrix,
-                           &ctx->ProjectionStack[--ctx->ProjectionStackDepth] );
-        ctx->NewState |= _NEW_PROJECTION;
-         break;
-      case GL_TEXTURE:
-         {
-            GLuint t = ctx->Texture.CurrentTransformUnit;
-            if (ctx->TextureStackDepth[t]==0) {
-               gl_error( ctx,  GL_STACK_UNDERFLOW, "glPopMatrix");
-               return;
-            }
-           _math_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;
-         }
-         _math_matrix_copy(&ctx->ColorMatrix,
-                          &ctx->ColorStack[--ctx->ColorStackDepth]);
-        ctx->NewState |= _NEW_COLOR_MATRIX;
-         break;
-      default:
-         gl_problem(ctx, "Bad matrix mode in gl_PopMatrix");
+             _mesa_lookup_enum_by_nr(ctx->Transform.MatrixMode));
+
+   if (stack->Depth == 0) {
+      _mesa_error( ctx,  GL_STACK_UNDERFLOW, "glPopMatrix" );
+      return;
    }
+   stack->Depth--;
+   stack->Top = &(stack->Stack[stack->Depth]);
+   ctx->NewState |= stack->DirtyFlag;
 }
 
 
@@ -264,9 +199,9 @@ void
 _mesa_LoadIdentity( void )
 {
    GET_CURRENT_CONTEXT(ctx);
-   GLmatrix *mat = 0;
-   GET_ACTIVE_MATRIX(ctx, mat, ctx->NewState, "glLoadIdentity");
-   _math_matrix_set_identity( mat );
+   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+   _math_matrix_set_identity( ctx->CurrentStack->Top );
+   ctx->NewState |= ctx->CurrentStack->DirtyFlag;
 }
 
 
@@ -274,9 +209,9 @@ void
 _mesa_LoadMatrixf( const GLfloat *m )
 {
    GET_CURRENT_CONTEXT(ctx);
-   GLmatrix *mat = 0;
-   GET_ACTIVE_MATRIX(ctx, mat, ctx->NewState, "glLoadMatrix");
-   _math_matrix_loadf( mat, m );
+   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+   _math_matrix_loadf( ctx->CurrentStack->Top, m );
+   ctx->NewState |= ctx->CurrentStack->DirtyFlag;
 }
 
 
@@ -286,7 +221,7 @@ _mesa_LoadMatrixd( const GLdouble *m )
    GLint i;
    GLfloat f[16];
    for (i = 0; i < 16; i++)
-      f[i] = m[i];
+      f[i] = (GLfloat) m[i];
    _mesa_LoadMatrixf(f);
 }
 
@@ -299,9 +234,9 @@ void
 _mesa_MultMatrixf( const GLfloat *m )
 {
    GET_CURRENT_CONTEXT(ctx);
-   GLmatrix *mat = 0;
-   GET_ACTIVE_MATRIX( ctx,  mat, ctx->NewState, "glMultMatrix" );
-   _math_matrix_mul_floats( mat, m );
+   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+   _math_matrix_mul_floats( ctx->CurrentStack->Top, m );
+   ctx->NewState |= ctx->CurrentStack->DirtyFlag;
 }
 
 
@@ -314,7 +249,7 @@ _mesa_MultMatrixd( const GLdouble *m )
    GLint i;
    GLfloat f[16];
    for (i = 0; i < 16; i++)
-      f[i] = m[i];
+      f[i] = (GLfloat) m[i];
    _mesa_MultMatrixf( f );
 }
 
@@ -328,17 +263,17 @@ void
 _mesa_Rotatef( GLfloat angle, GLfloat x, GLfloat y, GLfloat z )
 {
    GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
    if (angle != 0.0F) {
-      GLmatrix *mat = 0;
-      GET_ACTIVE_MATRIX( ctx,  mat, ctx->NewState, "glRotate" );
-      _math_matrix_rotate( mat, angle, x, y, z );
+      _math_matrix_rotate( ctx->CurrentStack->Top, angle, x, y, z);
+      ctx->NewState |= ctx->CurrentStack->DirtyFlag;
    }
 }
 
 void
 _mesa_Rotated( GLdouble angle, GLdouble x, GLdouble y, GLdouble z )
 {
-   _mesa_Rotatef(angle, x, y, z);
+   _mesa_Rotatef((GLfloat) angle, (GLfloat) x, (GLfloat) y, (GLfloat) z);
 }
 
 
@@ -349,16 +284,16 @@ void
 _mesa_Scalef( GLfloat x, GLfloat y, GLfloat z )
 {
    GET_CURRENT_CONTEXT(ctx);
-   GLmatrix *mat = 0;
-   GET_ACTIVE_MATRIX(ctx, mat, ctx->NewState, "glScale");
-   _math_matrix_scale( mat, x, y, z );
+   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+   _math_matrix_scale( ctx->CurrentStack->Top, x, y, z);
+   ctx->NewState |= ctx->CurrentStack->DirtyFlag;
 }
 
 
 void
 _mesa_Scaled( GLdouble x, GLdouble y, GLdouble z )
 {
-   _mesa_Scalef(x, y, z);
+   _mesa_Scalef((GLfloat) x, (GLfloat) y, (GLfloat) z);
 }
 
 
@@ -369,16 +304,16 @@ void
 _mesa_Translatef( GLfloat x, GLfloat y, GLfloat z )
 {
    GET_CURRENT_CONTEXT(ctx);
-   GLmatrix *mat = 0;
-   GET_ACTIVE_MATRIX(ctx, mat, ctx->NewState, "glTranslate");
-   _math_matrix_translate( mat, x, y, z );
+   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+   _math_matrix_translate( ctx->CurrentStack->Top, x, y, z);
+   ctx->NewState |= ctx->CurrentStack->DirtyFlag;
 }
 
 
 void
 _mesa_Translated( GLdouble x, GLdouble y, GLdouble z )
 {
-   _mesa_Translatef(x, y, z);
+   _mesa_Translatef((GLfloat) x, (GLfloat) y, (GLfloat) z);
 }
 
 
@@ -425,26 +360,24 @@ void
 _mesa_Viewport( GLint x, GLint y, GLsizei width, GLsizei height )
 {
    GET_CURRENT_CONTEXT(ctx);
-   gl_Viewport(ctx, x, y, width, height);
+   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+   _mesa_set_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 )
+_mesa_set_viewport( GLcontext *ctx, GLint x, GLint y,
+                    GLsizei width, GLsizei height )
 {
-   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glViewport");
+   const GLfloat n = ctx->Viewport.Near;
+   const GLfloat f = ctx->Viewport.Far;
 
-   if (width<0 || height<0) {
-      gl_error( ctx,  GL_INVALID_VALUE, "glViewport" );
+   if (width < 0 || height < 0) {
+      _mesa_error( ctx,  GL_INVALID_VALUE, "glViewport" );
       return;
    }
 
@@ -461,13 +394,15 @@ gl_Viewport( GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height )
    ctx->Viewport.Y = y;
    ctx->Viewport.Height = height;
 
-   /* compute scale and bias values */
+   /* compute scale and bias values :: This is really driver-specific
+    * and should be maintained elsewhere if at all.
+    */
    ctx->Viewport._WindowMap.m[MAT_SX] = (GLfloat) width / 2.0F;
    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 * ctx->Visual.DepthMaxF;
-   ctx->Viewport._WindowMap.m[MAT_TZ] = 0.5 * ctx->Visual.DepthMaxF;
+   ctx->Viewport._WindowMap.m[MAT_SZ] = ctx->DepthMaxF * ((f - n) / 2.0F);
+   ctx->Viewport._WindowMap.m[MAT_TZ] = ctx->DepthMaxF * ((f - n) / 2.0F + n);
    ctx->Viewport._WindowMap.flags = MAT_FLAG_GENERAL_SCALE|MAT_FLAG_TRANSLATION;
    ctx->Viewport._WindowMap.type = MATRIX_3D_NO_ROT;
    ctx->NewState |= _NEW_VIEWPORT;
@@ -500,7 +435,7 @@ _mesa_DepthRange( GLclampd nearval, GLclampd farval )
     */
    GLfloat n, f;
    GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDepthRange");
+   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
 
    if (MESA_VERBOSE&VERBOSE_API)
       fprintf(stderr, "glDepthRange %f %f\n", nearval, farval);
@@ -510,8 +445,8 @@ _mesa_DepthRange( GLclampd nearval, GLclampd farval )
 
    ctx->Viewport.Near = n;
    ctx->Viewport.Far = f;
-   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->Viewport._WindowMap.m[MAT_SZ] = ctx->DepthMaxF * ((f - n) / 2.0F);
+   ctx->Viewport._WindowMap.m[MAT_TZ] = ctx->DepthMaxF * ((f - n) / 2.0F + n);
    ctx->NewState |= _NEW_VIEWPORT;
 
    if (ctx->Driver.DepthRange) {