fixed pointer arithmetic error in glCopyPixels
[mesa.git] / src / mesa / main / texstate.c
index f2f021160664b5fe50989c21a49fbef4421d333f..19e8984ad96ef8b79690a3ee6dc13262caf7b503 100644 (file)
@@ -1,10 +1,10 @@
-/* $Id: texstate.c,v 1.58 2001/10/17 13:31:07 brianp Exp $ */
+/* $Id: texstate.c,v 1.64 2002/02/15 16:32:06 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
- * Version:  3.5
+ * Version:  4.1
  *
- * Copyright (C) 1999-2001  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"),
 #include "math/m_matrix.h"
 #endif
 
+/* TEMPORARY! */
+#ifndef GL_TEXTURE_COMPARE_MODE_ARB
+#define GL_TEXTURE_COMPARE_MODE_ARB    0x9990
+#define GL_TEXTURE_COMPARE_FUNC_ARB    0x9991
+#define GL_COMPARE_R_TO_TEXTURE_ARB    0x9993
+#endif
 
 
 #ifdef SPECIALCAST
@@ -413,7 +419,8 @@ _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param )
         if (texUnit->LodBias == param[0])
            return;
         FLUSH_VERTICES(ctx, _NEW_TEXTURE);
-        texUnit->LodBias = param[0];
+         texUnit->LodBias = CLAMP(param[0], -ctx->Const.MaxTextureLodBias,
+                                  ctx->Const.MaxTextureLodBias);
         break;
       default:
          TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
@@ -461,10 +468,16 @@ void
 _mesa_TexEnviv( GLenum target, GLenum pname, const GLint *param )
 {
    GLfloat p[4];
-   p[0] = INT_TO_FLOAT( param[0] );
-   p[1] = INT_TO_FLOAT( param[1] );
-   p[2] = INT_TO_FLOAT( param[2] );
-   p[3] = INT_TO_FLOAT( param[3] );
+   if (pname == GL_TEXTURE_ENV_COLOR) {
+      p[0] = INT_TO_FLOAT( param[0] );
+      p[1] = INT_TO_FLOAT( param[1] );
+      p[2] = INT_TO_FLOAT( param[2] );
+      p[3] = INT_TO_FLOAT( param[3] );
+   }
+   else {
+      p[0] = (GLint) param[0];
+      p[1] = p[2] = p[3] = 0;  /* init to zero, just to be safe */
+   }
    _mesa_TexEnvfv( target, pname, p );
 }
 
@@ -896,6 +909,7 @@ _mesa_TexParameterfv( GLenum target, GLenum pname, const GLfloat *params )
              || eparam==GL_LINEAR_MIPMAP_NEAREST
              || eparam==GL_NEAREST_MIPMAP_LINEAR
              || eparam==GL_LINEAR_MIPMAP_LINEAR) {
+            FLUSH_VERTICES(ctx, _NEW_TEXTURE);
             texObj->MinFilter = eparam;
          }
          else {
@@ -909,6 +923,7 @@ _mesa_TexParameterfv( GLenum target, GLenum pname, const GLfloat *params )
             return;
 
          if (eparam==GL_NEAREST || eparam==GL_LINEAR) {
+            FLUSH_VERTICES(ctx, _NEW_TEXTURE);
             texObj->MagFilter = eparam;
          }
          else {
@@ -926,6 +941,7 @@ _mesa_TexParameterfv( GLenum target, GLenum pname, const GLfloat *params )
               ctx->Extensions.ARB_texture_border_clamp) ||
              (eparam == GL_MIRRORED_REPEAT_ARB &&
               ctx->Extensions.ARB_texture_mirrored_repeat)) {
+            FLUSH_VERTICES(ctx, _NEW_TEXTURE);
             texObj->WrapS = eparam;
          }
          else {
@@ -943,6 +959,7 @@ _mesa_TexParameterfv( GLenum target, GLenum pname, const GLfloat *params )
               ctx->Extensions.ARB_texture_border_clamp) ||
              (eparam == GL_MIRRORED_REPEAT_ARB &&
               ctx->Extensions.ARB_texture_mirrored_repeat)) {
+            FLUSH_VERTICES(ctx, _NEW_TEXTURE);
             texObj->WrapT = eparam;
          }
          else {
@@ -960,22 +977,46 @@ _mesa_TexParameterfv( GLenum target, GLenum pname, const GLfloat *params )
               ctx->Extensions.ARB_texture_border_clamp) ||
              (eparam == GL_MIRRORED_REPEAT_ARB &&
               ctx->Extensions.ARB_texture_mirrored_repeat)) {
+            FLUSH_VERTICES(ctx, _NEW_TEXTURE);
             texObj->WrapR = eparam;
          }
          else {
             _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
          }
          break;
-      case GL_TEXTURE_BORDER_COLOR:
+#if 0 /* someday */
+      case GL_TEXTUER_BORDER_VALUES_NV:
+         /* don't clamp */
+         FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+         COPY_4V(texObj->BorderValues, params);
          UNCLAMPED_FLOAT_TO_CHAN(texObj->BorderColor[0], params[0]);
          UNCLAMPED_FLOAT_TO_CHAN(texObj->BorderColor[1], params[1]);
          UNCLAMPED_FLOAT_TO_CHAN(texObj->BorderColor[2], params[2]);
          UNCLAMPED_FLOAT_TO_CHAN(texObj->BorderColor[3], params[3]);
          break;
+#endif
+      case GL_TEXTURE_BORDER_COLOR:
+         /* clamp */
+         FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+         texObj->BorderValues[0] = CLAMP(params[0], 0.0F, 1.0F);
+         texObj->BorderValues[1] = CLAMP(params[1], 0.0F, 1.0F);
+         texObj->BorderValues[2] = CLAMP(params[2], 0.0F, 1.0F);
+         texObj->BorderValues[3] = CLAMP(params[3], 0.0F, 1.0F);
+         UNCLAMPED_FLOAT_TO_CHAN(texObj->BorderColor[0], texObj->BorderValues[0]);
+         UNCLAMPED_FLOAT_TO_CHAN(texObj->BorderColor[1], texObj->BorderValues[1]);
+         UNCLAMPED_FLOAT_TO_CHAN(texObj->BorderColor[2], texObj->BorderValues[2]);
+         UNCLAMPED_FLOAT_TO_CHAN(texObj->BorderColor[3], texObj->BorderValues[3]);
+         break;
       case GL_TEXTURE_MIN_LOD:
+         if (texObj->MinLod == params[0])
+            return;
+         FLUSH_VERTICES(ctx, _NEW_TEXTURE);
          texObj->MinLod = params[0];
          break;
       case GL_TEXTURE_MAX_LOD:
+         if (texObj->MaxLod == params[0])
+            return;
+         FLUSH_VERTICES(ctx, _NEW_TEXTURE);
          texObj->MaxLod = params[0];
          break;
       case GL_TEXTURE_BASE_LEVEL:
@@ -983,6 +1024,7 @@ _mesa_TexParameterfv( GLenum target, GLenum pname, const GLfloat *params )
             _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
             return;
          }
+         FLUSH_VERTICES(ctx, _NEW_TEXTURE);
          texObj->BaseLevel = (GLint) params[0];
          break;
       case GL_TEXTURE_MAX_LEVEL:
@@ -990,10 +1032,12 @@ _mesa_TexParameterfv( GLenum target, GLenum pname, const GLfloat *params )
             _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
             return;
          }
+         FLUSH_VERTICES(ctx, _NEW_TEXTURE);
          texObj->MaxLevel = (GLint) params[0];
          break;
       case GL_TEXTURE_PRIORITY:
          /* (keithh@netcomuk.co.uk) */
+         FLUSH_VERTICES(ctx, _NEW_TEXTURE);
          texObj->Priority = CLAMP( params[0], 0.0F, 1.0F );
          break;
       case GL_TEXTURE_MAX_ANISOTROPY_EXT:
@@ -1002,6 +1046,7 @@ _mesa_TexParameterfv( GLenum target, GLenum pname, const GLfloat *params )
               _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
               return;
            }
+            FLUSH_VERTICES(ctx, _NEW_TEXTURE);
             texObj->MaxAnisotropy = params[0];
          }
          else {
@@ -1012,6 +1057,7 @@ _mesa_TexParameterfv( GLenum target, GLenum pname, const GLfloat *params )
          break;
       case GL_TEXTURE_COMPARE_SGIX:
          if (ctx->Extensions.SGIX_shadow) {
+            FLUSH_VERTICES(ctx, _NEW_TEXTURE);
             texObj->CompareFlag = params[0] ? GL_TRUE : GL_FALSE;
          }
          else {
@@ -1025,6 +1071,7 @@ _mesa_TexParameterfv( GLenum target, GLenum pname, const GLfloat *params )
             GLenum op = (GLenum) params[0];
             if (op == GL_TEXTURE_LEQUAL_R_SGIX ||
                 op == GL_TEXTURE_GEQUAL_R_SGIX) {
+               FLUSH_VERTICES(ctx, _NEW_TEXTURE);
                texObj->CompareOperator = op;
             }
             else {
@@ -1037,8 +1084,9 @@ _mesa_TexParameterfv( GLenum target, GLenum pname, const GLfloat *params )
             return;
          }
          break;
-      case GL_SHADOW_AMBIENT_SGIX:
+      case GL_SHADOW_AMBIENT_SGIX: /* aka GL_TEXTURE_COMPARE_FAIL_VALUE_ARB */
          if (ctx->Extensions.SGIX_shadow_ambient) {
+            FLUSH_VERTICES(ctx, _NEW_TEXTURE);
             UNCLAMPED_FLOAT_TO_CHAN(texObj->ShadowAmbient, params[0]);
          }
          else {
@@ -1057,6 +1105,65 @@ _mesa_TexParameterfv( GLenum target, GLenum pname, const GLfloat *params )
             return;
          }
          break;
+      case GL_TEXTURE_COMPARE_MODE_ARB:
+         if (ctx->Extensions.ARB_shadow) {
+            const GLenum mode = (GLenum) params[0];
+            if (mode == GL_NONE || mode == GL_COMPARE_R_TO_TEXTURE_ARB) {
+               FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+               texObj->CompareMode = params[0];
+            }
+            else {
+               _mesa_error(ctx, GL_INVALID_ENUM,
+                           "glTexParameter(bad GL_TEXTURE_COMPARE_MODE_ARB)");
+               return;
+            }
+         }
+         else {
+            _mesa_error(ctx, GL_INVALID_ENUM,
+                        "glTexParameter(pname=GL_TEXTURE_COMPARE_MODE_ARB)");
+            return;
+         }
+         break;
+      case GL_TEXTURE_COMPARE_FUNC_ARB:
+         if (ctx->Extensions.ARB_shadow) {
+            const GLenum func = (GLenum) params[0];
+            if (func == GL_LEQUAL || func == GL_GEQUAL) {
+               FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+               texObj->CompareFunc = params[0];
+            }
+            else {
+               _mesa_error(ctx, GL_INVALID_ENUM,
+                           "glTexParameter(bad GL_TEXTURE_COMPARE_FUNC_ARB)");
+               return;
+            }
+         }
+         else {
+            _mesa_error(ctx, GL_INVALID_ENUM,
+                        "glTexParameter(pname=GL_TEXTURE_COMPARE_FUNC_ARB)");
+            return;
+         }
+         break;
+      case GL_DEPTH_TEXTURE_MODE_ARB:
+         if (ctx->Extensions.ARB_depth_texture) {
+            const GLenum result = (GLenum) params[0];
+            if (result == GL_LUMINANCE || result == GL_INTENSITY
+                || result == GL_ALPHA) {
+               FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+               texObj->DepthMode = params[0];
+            }
+            else {
+               _mesa_error(ctx, GL_INVALID_ENUM,
+                          "glTexParameter(bad GL_DEPTH_TEXTURE_MODE_ARB)");
+               return;
+            }
+         }
+         else {
+            _mesa_error(ctx, GL_INVALID_ENUM,
+                        "glTexParameter(pname=GL_DEPTH_TEXTURE_MODE_ARB)");
+            return;
+         }
+         break;
+
       default:
          {
             char s[100];
@@ -1066,7 +1173,6 @@ _mesa_TexParameterfv( GLenum target, GLenum pname, const GLfloat *params )
          return;
    }
 
-   ctx->NewState |= _NEW_TEXTURE;
    texObj->Complete = GL_FALSE;
 
    if (ctx->Driver.TexParameter) {
@@ -1320,7 +1426,17 @@ _mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params )
       case GL_TEXTURE_WRAP_R_EXT:
          *params = ENUM_TO_FLOAT(obj->WrapR);
          return;
+#if 0 /* someday */
+      case GL_TEXTURE_BORDER_VALUES_NV:
+         /* unclamped */
+         params[0] = obj->BorderValues[0];
+         params[1] = obj->BorderValues[1];
+         params[2] = obj->BorderValues[2];
+         params[3] = obj->BorderValues[3];
+         return;
+#endif
       case GL_TEXTURE_BORDER_COLOR:
+         /* clamped */
          params[0] = obj->BorderColor[0] / CHAN_MAXF;
          params[1] = obj->BorderColor[1] / CHAN_MAXF;
          params[2] = obj->BorderColor[2] / CHAN_MAXF;
@@ -1363,7 +1479,7 @@ _mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params )
             return;
          }
          break;
-      case GL_SHADOW_AMBIENT_SGIX:
+      case GL_SHADOW_AMBIENT_SGIX: /* aka GL_TEXTURE_COMPARE_FAIL_VALUE_ARB */
          if (ctx->Extensions.SGIX_shadow_ambient) {
             *params = CHAN_TO_FLOAT(obj->ShadowAmbient);
             return;
@@ -1375,6 +1491,24 @@ _mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params )
             return;
          }
          break;
+      case GL_TEXTURE_COMPARE_MODE_ARB:
+         if (ctx->Extensions.ARB_shadow) {
+            *params = (GLfloat) obj->CompareMode;
+            return;
+         }
+         break;
+      case GL_TEXTURE_COMPARE_FUNC_ARB:
+         if (ctx->Extensions.ARB_shadow) {
+            *params = (GLfloat) obj->CompareFunc;
+            return;
+         }
+         break;
+      case GL_DEPTH_TEXTURE_MODE_ARB:
+         if (ctx->Extensions.ARB_depth_texture) {
+            *params = (GLfloat) obj->DepthMode;
+            return;
+         }
+         break;
       default:
          ; /* silence warnings */
    }
@@ -1413,17 +1547,27 @@ _mesa_GetTexParameteriv( GLenum target, GLenum pname, GLint *params )
       case GL_TEXTURE_WRAP_R_EXT:
          *params = (GLint) obj->WrapR;
          return;
+#if 0 /* someday */
+      case GL_TEXTURE_BORDER_VALUES_NV:
+         /* unclamped */
+         params[0] = FLOAT_TO_INT(obj->BorderValues[0]);
+         params[1] = FLOAT_TO_INT(obj->BorderValues[1]);
+         params[2] = FLOAT_TO_INT(obj->BorderValues[2]);
+         params[3] = FLOAT_TO_INT(obj->BorderValues[3]);
+         return;
+#endif
       case GL_TEXTURE_BORDER_COLOR:
+         /* clamped */
          {
-            GLfloat color[4];
-            color[0] = obj->BorderColor[0] / CHAN_MAXF;
-            color[1] = obj->BorderColor[1] / CHAN_MAXF;
-            color[2] = obj->BorderColor[2] / CHAN_MAXF;
-            color[3] = obj->BorderColor[3] / CHAN_MAXF;
-            params[0] = FLOAT_TO_INT( color[0] );
-            params[1] = FLOAT_TO_INT( color[1] );
-            params[2] = FLOAT_TO_INT( color[2] );
-            params[3] = FLOAT_TO_INT( color[3] );
+            GLfloat b[4];
+            b[0] = CLAMP(obj->BorderValues[0], 0.0F, 1.0F);
+            b[1] = CLAMP(obj->BorderValues[1], 0.0F, 1.0F);
+            b[2] = CLAMP(obj->BorderValues[2], 0.0F, 1.0F);
+            b[3] = CLAMP(obj->BorderValues[3], 0.0F, 1.0F);
+            params[0] = FLOAT_TO_INT(b[0]);
+            params[1] = FLOAT_TO_INT(b[1]);
+            params[2] = FLOAT_TO_INT(b[2]);
+            params[3] = FLOAT_TO_INT(b[3]);
          }
          return;
       case GL_TEXTURE_RESIDENT:
@@ -1463,10 +1607,10 @@ _mesa_GetTexParameteriv( GLenum target, GLenum pname, GLint *params )
             return;
          }
          break;
-      case GL_SHADOW_AMBIENT_SGIX:
+      case GL_SHADOW_AMBIENT_SGIX: /* aka GL_TEXTURE_COMPARE_FAIL_VALUE_ARB */
          if (ctx->Extensions.SGIX_shadow_ambient) {
-            /* XXX range? */
-            *params = (GLint) CHAN_TO_FLOAT(obj->ShadowAmbient);
+            GLfloat a = CHAN_TO_FLOAT(obj->ShadowAmbient);
+            *params = (GLint) FLOAT_TO_INT(a);
             return;
          }
          break;
@@ -1476,6 +1620,24 @@ _mesa_GetTexParameteriv( GLenum target, GLenum pname, GLint *params )
             return;
          }
          break;
+      case GL_TEXTURE_COMPARE_MODE_ARB:
+         if (ctx->Extensions.ARB_shadow) {
+            *params = (GLint) obj->CompareMode;
+            return;
+         }
+         break;
+      case GL_TEXTURE_COMPARE_FUNC_ARB:
+         if (ctx->Extensions.ARB_shadow) {
+            *params = (GLint) obj->CompareFunc;
+            return;
+         }
+         break;
+      case GL_DEPTH_TEXTURE_MODE_ARB:
+         if (ctx->Extensions.ARB_depth_texture) {
+            *params = (GLint) obj->DepthMode;
+            return;
+         }
+         break;
       default:
          ; /* silence warnings */
    }
@@ -1549,10 +1711,10 @@ _mesa_TexGenfv( GLenum coord, GLenum pname, const GLfloat *params )
            GLfloat tmp[4];
 
             /* Transform plane equation by the inverse modelview matrix */
-            if (ctx->ModelView.flags & MAT_DIRTY_INVERSE) {
-               _math_matrix_analyse( &ctx->ModelView );
+            if (ctx->ModelviewMatrixStack.Top->flags & MAT_DIRTY_INVERSE) {
+               _math_matrix_analyse( ctx->ModelviewMatrixStack.Top );
             }
-            _mesa_transform_vector( tmp, params, ctx->ModelView.inv );
+            _mesa_transform_vector( tmp, params, ctx->ModelviewMatrixStack.Top->inv );
            if (TEST_EQ_4V(texUnit->EyePlaneS, tmp))
               return;
            FLUSH_VERTICES(ctx, _NEW_TEXTURE);
@@ -1605,10 +1767,10 @@ _mesa_TexGenfv( GLenum coord, GLenum pname, const GLfloat *params )
         else if (pname==GL_EYE_PLANE) {
            GLfloat tmp[4];
             /* Transform plane equation by the inverse modelview matrix */
-           if (ctx->ModelView.flags & MAT_DIRTY_INVERSE) {
-               _math_matrix_analyse( &ctx->ModelView );
+           if (ctx->ModelviewMatrixStack.Top->flags & MAT_DIRTY_INVERSE) {
+               _math_matrix_analyse( ctx->ModelviewMatrixStack.Top );
             }
-            _mesa_transform_vector( tmp, params, ctx->ModelView.inv );
+            _mesa_transform_vector( tmp, params, ctx->ModelviewMatrixStack.Top->inv );
            if (TEST_EQ_4V(texUnit->EyePlaneT, tmp))
                return;
            FLUSH_VERTICES(ctx, _NEW_TEXTURE);
@@ -1658,10 +1820,10 @@ _mesa_TexGenfv( GLenum coord, GLenum pname, const GLfloat *params )
         else if (pname==GL_EYE_PLANE) {
            GLfloat tmp[4];
             /* Transform plane equation by the inverse modelview matrix */
-            if (ctx->ModelView.flags & MAT_DIRTY_INVERSE) {
-               _math_matrix_analyse( &ctx->ModelView );
+            if (ctx->ModelviewMatrixStack.Top->flags & MAT_DIRTY_INVERSE) {
+               _math_matrix_analyse( ctx->ModelviewMatrixStack.Top );
             }
-            _mesa_transform_vector( tmp, params, ctx->ModelView.inv );
+            _mesa_transform_vector( tmp, params, ctx->ModelviewMatrixStack.Top->inv );
            if (TEST_EQ_4V(texUnit->EyePlaneR, tmp))
               return;
            FLUSH_VERTICES(ctx, _NEW_TEXTURE);
@@ -1705,10 +1867,10 @@ _mesa_TexGenfv( GLenum coord, GLenum pname, const GLfloat *params )
         else if (pname==GL_EYE_PLANE) {
            GLfloat tmp[4];
             /* Transform plane equation by the inverse modelview matrix */
-            if (ctx->ModelView.flags & MAT_DIRTY_INVERSE) {
-               _math_matrix_analyse( &ctx->ModelView );
+            if (ctx->ModelviewMatrixStack.Top->flags & MAT_DIRTY_INVERSE) {
+               _math_matrix_analyse( ctx->ModelviewMatrixStack.Top );
             }
-            _mesa_transform_vector( tmp, params, ctx->ModelView.inv );
+            _mesa_transform_vector( tmp, params, ctx->ModelviewMatrixStack.Top->inv );
            if (TEST_EQ_4V(texUnit->EyePlaneQ, tmp))
               return;
            FLUSH_VERTICES(ctx, _NEW_TEXTURE);