added _NEW_PROGRAM to check_state flags for pipeline stages (fixes vparray demo bug)
[mesa.git] / src / mesa / tnl / t_vb_texgen.c
index f04d36c41acf8cce7b36e36b09382205eeddd7d9..64d569a0192a5df8400b55869987cc0860ad52e9 100644 (file)
@@ -1,10 +1,8 @@
-/* $Id: t_vb_texgen.c,v 1.12 2002/01/22 14:35:17 brianp Exp $ */
-
 /*
  * Mesa 3-D graphics library
- * Version:  3.5
+ * Version:  6.0
  *
- * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2004  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"),
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  *
  * Authors:
- *    Brian Paul <brian@valinux.com>
- *    Keith Whitwell <keithw@valinux.com>
+ *    Brian Paul
+ *    Keith Whitwell <keith@tungstengraphics.com>
  */
 
+/*
+ * Regarding GL_NV_texgen_reflection:
+ *
+ * Portions of this software may use or implement intellectual
+ * property owned and licensed by NVIDIA Corporation. NVIDIA disclaims
+ * any and all warranties with respect to such intellectual property,
+ * including any use thereof or modifications thereto.
+ */
 
 #include "glheader.h"
 #include "colormac.h"
 #include "context.h"
 #include "macros.h"
-#include "mmath.h"
-#include "mem.h"
+#include "imports.h"
 #include "mtypes.h"
 
 #include "math/m_xform.h"
@@ -59,9 +64,9 @@ struct texgen_stage_data {
 
    /* Per-texunit derived state.
     */
-   GLuint TexgenSize[MAX_TEXTURE_UNITS];
-   GLuint TexgenHoles[MAX_TEXTURE_UNITS];
-   texgen_func TexgenFunc[MAX_TEXTURE_UNITS];
+   GLuint TexgenSize[MAX_TEXTURE_COORD_UNITS];
+   GLuint TexgenHoles[MAX_TEXTURE_COORD_UNITS];
+   texgen_func TexgenFunc[MAX_TEXTURE_COORD_UNITS];
 
    /* Temporary values used in texgen.
     */
@@ -70,7 +75,7 @@ struct texgen_stage_data {
 
    /* Buffered outputs of the stage.
     */
-   GLvector4f texcoord[MAX_TEXTURE_UNITS];
+   GLvector4f texcoord[MAX_TEXTURE_COORD_UNITS];
 };
 
 
@@ -114,7 +119,7 @@ static void build_m3( GLfloat f[][3], GLfloat m[],
       fz = f[i][2] = u[2] - norm[2] * two_nu;
       m[i] = fx * fx + fy * fy + (fz + 1.0F) * (fz + 1.0F);
       if (m[i] != 0.0F) {
-        m[i] = 0.5F / (GLfloat) GL_SQRT(m[i]);
+        m[i] = 0.5F * _mesa_inv_sqrtf(m[i]);
       }
    }
 }
@@ -143,7 +148,7 @@ static void build_m2( GLfloat f[][3], GLfloat m[],
       fz = f[i][2] = u[2] - norm[2] * two_nu;
       m[i] = fx * fx + fy * fy + (fz + 1.0F) * (fz + 1.0F);
       if (m[i] != 0.0F) {
-        m[i] = 0.5F / (GLfloat) GL_SQRT(m[i]);
+        m[i] = 0.5F * _mesa_inv_sqrtf(m[i]);
       }
    }
 }
@@ -322,10 +327,6 @@ static void texgen_sphere_map( GLcontext *ctx,
    GLfloat (*f)[3] = store->tmp_f;
    GLfloat *m = store->tmp_m;
 
-/*     fprintf(stderr, "%s normstride %d eyestride %d\n",  */
-/*        __FUNCTION__, VB->NormalPtr->stride, */
-/*        VB->EyePtr->stride); */
-
    (build_m_tab[VB->EyePtr->size])( store->tmp_f,
                                    store->tmp_m,
                                    VB->NormalPtr,
@@ -359,22 +360,20 @@ static void texgen( GLcontext *ctx,
    struct vertex_buffer *VB = &tnl->vb;
    GLvector4f *in = VB->TexCoordPtr[unit];
    GLvector4f *out = &store->texcoord[unit];
-   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+   const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
    const GLvector4f *obj = VB->ObjPtr;
    const GLvector4f *eye = VB->EyePtr;
    const GLvector4f *normal = VB->NormalPtr;
+   const GLfloat *m = store->tmp_m;
+   const GLuint count = VB->Count;
    GLfloat (*texcoord)[4] = (GLfloat (*)[4])out->data;
-   GLfloat *indata;
-   GLuint count = VB->Count;
    GLfloat (*f)[3] = store->tmp_f;
-   GLfloat *m = store->tmp_m;
-        GLuint holes = 0;
-
+   GLuint holes = 0;
 
    if (texUnit->_GenFlags & TEXGEN_NEED_M) {
-      build_m_tab[in->size]( store->tmp_f, store->tmp_m, normal, eye );
+      build_m_tab[eye->size]( store->tmp_f, store->tmp_m, normal, eye );
    } else if (texUnit->_GenFlags & TEXGEN_NEED_F) {
-      build_f_tab[in->size]( (GLfloat *)store->tmp_f, 3, normal, eye );
+      build_f_tab[eye->size]( (GLfloat *)store->tmp_f, 3, normal, eye );
    }
 
    if (!in) {
@@ -400,6 +399,7 @@ static void texgen( GLcontext *ctx,
    }
 
    if (holes) {
+      if (holes & VEC_DIRTY_3) _mesa_vector4f_clean_elem(out, count, 3);
       if (holes & VEC_DIRTY_2) _mesa_vector4f_clean_elem(out, count, 2);
       if (holes & VEC_DIRTY_1) _mesa_vector4f_clean_elem(out, count, 1);
       if (holes & VEC_DIRTY_0) _mesa_vector4f_clean_elem(out, count, 0);
@@ -419,8 +419,8 @@ static void texgen( GLcontext *ctx,
                                       texUnit->EyePlaneS );
         break;
       case GL_SPHERE_MAP:
-        for (indata=in->start,i=0 ; i<count ;i++, STRIDE_F(indata,in->stride))
-           texcoord[i][0] = indata[0] * m[i] + 0.5F;
+         for (i = 0; i < count; i++)
+            texcoord[i][0] = f[i][0] * m[i] + 0.5F;
         break;
       case GL_REFLECTION_MAP_NV:
         for (i=0;i<count;i++)
@@ -452,12 +452,12 @@ static void texgen( GLcontext *ctx,
                                       texUnit->EyePlaneT );
         break;
       case GL_SPHERE_MAP:
-        for (indata=in->start,i=0; i<count ;i++,STRIDE_F(indata,in->stride))
-            texcoord[i][1] = indata[1] * m[i] + 0.5F;
+         for (i = 0; i < count; i++)
+            texcoord[i][1] = f[i][1] * m[i] + 0.5F;
         break;
       case GL_REFLECTION_MAP_NV:
         for (i=0;i<count;i++)
-            texcoord[i][0] = f[i][0];
+            texcoord[i][1] = f[i][1];
         break;
       case GL_NORMAL_MAP_NV: {
         const GLfloat *norm = normal->start;
@@ -521,18 +521,19 @@ static void texgen( GLcontext *ctx,
 
 
 static GLboolean run_texgen_stage( GLcontext *ctx,
-                                  struct gl_pipeline_stage *stage )
+                                  struct tnl_pipeline_stage *stage )
 {
    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
    struct texgen_stage_data *store = TEXGEN_STAGE_DATA( stage );
    GLuint i;
 
-   for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++)
+   for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++)
       if (ctx->Texture._TexGenEnabled & ENABLE_TEXGEN(i)) {
-        if (stage->changed_inputs & (VERT_BIT_EYE | VERT_BIT_NORMAL | VERT_BIT_TEX(i)))
+        if (stage->changed_inputs & (_TNL_BIT_POS | _TNL_BIT_NORMAL | _TNL_BIT_TEX(i)))
            store->TexgenFunc[i]( ctx, store, i );
 
-        VB->TexCoordPtr[i] = &store->texcoord[i];
+        VB->AttribPtr[VERT_ATTRIB_TEX0+i] = 
+           VB->TexCoordPtr[i] = &store->texcoord[i];
       }
 
    return GL_TRUE;
@@ -542,20 +543,20 @@ static GLboolean run_texgen_stage( GLcontext *ctx,
 
 
 static GLboolean run_validate_texgen_stage( GLcontext *ctx,
-                                           struct gl_pipeline_stage *stage )
+                                           struct tnl_pipeline_stage *stage )
 {
    struct texgen_stage_data *store = TEXGEN_STAGE_DATA(stage);
    GLuint i;
 
-   for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) {
+   for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++) {
       struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
 
       if (texUnit->TexGenEnabled) {
         GLuint sz;
 
-        if (texUnit->TexGenEnabled & R_BIT)
+        if (texUnit->TexGenEnabled & Q_BIT)
            sz = 4;
-        else if (texUnit->TexGenEnabled & Q_BIT)
+        else if (texUnit->TexGenEnabled & R_BIT)
            sz = 3;
         else if (texUnit->TexGenEnabled & T_BIT)
            sz = 2;
@@ -564,8 +565,9 @@ static GLboolean run_validate_texgen_stage( GLcontext *ctx,
 
         store->TexgenSize[i] = sz;
         store->TexgenHoles[i] = (all_bits[sz] & ~texUnit->TexGenEnabled);
-        store->TexgenFunc[i] = texgen;
+        store->TexgenFunc[i] = texgen; /* general solution */
 
+         /* look for special texgen cases */
         if (texUnit->TexGenEnabled == (S_BIT|T_BIT|R_BIT)) {
            if (texUnit->_GenFlags == TEXGEN_REFLECTION_MAP_NV) {
               store->TexgenFunc[i] = texgen_reflection_map_nv;
@@ -586,7 +588,7 @@ static GLboolean run_validate_texgen_stage( GLcontext *ctx,
 }
 
 
-static void check_texgen( GLcontext *ctx, struct gl_pipeline_stage *stage )
+static void check_texgen( GLcontext *ctx, struct tnl_pipeline_stage *stage )
 {
    GLuint i;
    stage->active = 0;
@@ -595,24 +597,21 @@ static void check_texgen( GLcontext *ctx, struct gl_pipeline_stage *stage )
       GLuint inputs = 0;
       GLuint outputs = 0;
 
-      if (ctx->Texture._GenFlags & TEXGEN_OBJ_LINEAR)
-        inputs |= VERT_BIT_POS;
-
-      if (ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD)
-        inputs |= VERT_BIT_EYE;
+      if (ctx->Texture._GenFlags & (TEXGEN_OBJ_LINEAR | TEXGEN_NEED_EYE_COORD))
+        inputs |= _TNL_BIT_POS;
 
       if (ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS)
-        inputs |= VERT_BIT_NORMAL;
+        inputs |= _TNL_BIT_NORMAL;
 
-      for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++)
+      for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++)
         if (ctx->Texture._TexGenEnabled & ENABLE_TEXGEN(i))
         {
-           outputs |= VERT_BIT_TEX(i);
+           outputs |= _TNL_BIT_TEX(i);
 
            /* Need the original input in case it contains a Q coord:
             * (sigh)
             */
-           inputs |= VERT_BIT_TEX(i);
+           inputs |= _TNL_BIT_TEX(i);
 
            /* Something for Feedback? */
         }
@@ -631,7 +630,7 @@ static void check_texgen( GLcontext *ctx, struct gl_pipeline_stage *stage )
 /* Called the first time stage->run() is invoked.
  */
 static GLboolean alloc_texgen_data( GLcontext *ctx,
-                                   struct gl_pipeline_stage *stage )
+                                   struct tnl_pipeline_stage *stage )
 {
    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
    struct texgen_stage_data *store;
@@ -642,7 +641,7 @@ static GLboolean alloc_texgen_data( GLcontext *ctx,
    if (!store)
       return GL_FALSE;
 
-   for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++)
+   for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++)
       _mesa_vector4f_alloc( &store->texcoord[i], 0, VB->Size, 32 );
 
    store->tmp_f = (GLfloat (*)[3]) MALLOC(VB->Size * sizeof(GLfloat) * 3);
@@ -655,14 +654,14 @@ static GLboolean alloc_texgen_data( GLcontext *ctx,
 }
 
 
-static void free_texgen_data( struct gl_pipeline_stage *stage )
+static void free_texgen_data( struct tnl_pipeline_stage *stage )
 
 {
    struct texgen_stage_data *store = TEXGEN_STAGE_DATA(stage);
    GLuint i;
 
    if (store) {
-      for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++)
+      for (i = 0 ; i < MAX_TEXTURE_COORD_UNITS ; i++)
         if (store->texcoord[i].data)
            _mesa_vector4f_free( &store->texcoord[i] );
 
@@ -676,10 +675,10 @@ static void free_texgen_data( struct gl_pipeline_stage *stage )
 
 
 
-const struct gl_pipeline_stage _tnl_texgen_stage =
+const struct tnl_pipeline_stage _tnl_texgen_stage =
 {
    "texgen",                   /* name */
-   _NEW_TEXTURE,               /* when to call check() */
+   _NEW_TEXTURE|_NEW_PROGRAM,  /* when to call check() */
    _NEW_TEXTURE,               /* when to invalidate stored data */
    GL_FALSE,                   /* active? */
    0,                          /* inputs */