home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mesa5.zip / mesa5src.zip / tnl / t_vb_texgen.cpp < prev    next >
C/C++ Source or Header  |  2002-10-29  |  19KB  |  693 lines

  1. /* $Id: t_vb_texgen.c,v 1.15 2002/10/29 20:29:04 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  3.5
  6.  *
  7.  * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
  8.  *
  9.  * Permission is hereby granted, free of charge, to any person obtaining a
  10.  * copy of this software and associated documentation files (the "Software"),
  11.  * to deal in the Software without restriction, including without limitation
  12.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  13.  * and/or sell copies of the Software, and to permit persons to whom the
  14.  * Software is furnished to do so, subject to the following conditions:
  15.  *
  16.  * The above copyright notice and this permission notice shall be included
  17.  * in all copies or substantial portions of the Software.
  18.  *
  19.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  20.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  22.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  23.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  24.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  *
  26.  * Authors:
  27.  *    Brian Paul
  28.  *    Keith Whitwell <keith@tungstengraphics.com>
  29.  */
  30.  
  31.  
  32. #include "glheader.h"
  33. #include "colormac.h"
  34. #include "context.h"
  35. #include "macros.h"
  36. #include "mmath.h"
  37. #include "imports.h"
  38. #include "mtypes.h"
  39.  
  40. #include "math/m_xform.h"
  41.  
  42. #include "t_context.h"
  43. #include "t_pipeline.h"
  44.  
  45.  
  46. /***********************************************************************
  47.  * Automatic texture coordinate generation (texgen) code.
  48.  */
  49.  
  50.  
  51. struct texgen_stage_data;
  52.  
  53. typedef void (*texgen_func)( GLcontext *ctx,
  54.                  struct texgen_stage_data *store,
  55.                  GLuint unit);
  56.  
  57.  
  58. struct texgen_stage_data {
  59.  
  60.    /* Per-texunit derived state.
  61.     */
  62.    GLuint TexgenSize[MAX_TEXTURE_UNITS];
  63.    GLuint TexgenHoles[MAX_TEXTURE_UNITS];
  64.    texgen_func TexgenFunc[MAX_TEXTURE_UNITS];
  65.  
  66.    /* Temporary values used in texgen.
  67.     */
  68.    GLfloat (*tmp_f)[3];
  69.    GLfloat *tmp_m;
  70.  
  71.    /* Buffered outputs of the stage.
  72.     */
  73.    GLvector4f texcoord[MAX_TEXTURE_UNITS];
  74. };
  75.  
  76.  
  77. #define TEXGEN_STAGE_DATA(stage) ((struct texgen_stage_data *)stage->privatePtr)
  78.  
  79.  
  80.  
  81. static GLuint all_bits[5] = {
  82.    0,
  83.    VEC_SIZE_1,
  84.    VEC_SIZE_2,
  85.    VEC_SIZE_3,
  86.    VEC_SIZE_4,
  87. };
  88.  
  89. #define VEC_SIZE_FLAGS (VEC_SIZE_1|VEC_SIZE_2|VEC_SIZE_3|VEC_SIZE_4)
  90.  
  91. #define TEXGEN_NEED_M            (TEXGEN_SPHERE_MAP)
  92. #define TEXGEN_NEED_F            (TEXGEN_SPHERE_MAP        | \
  93.                   TEXGEN_REFLECTION_MAP_NV)
  94.  
  95.  
  96.  
  97. static void build_m3( GLfloat f[][3], GLfloat m[],
  98.               const GLvector4f *normal,
  99.               const GLvector4f *eye )
  100. {
  101.    GLuint stride = eye->stride;
  102.    GLfloat *coord = (GLfloat *)eye->start;
  103.    GLuint count = eye->count;
  104.    const GLfloat *norm = normal->start;
  105.    GLuint i;
  106.  
  107.    for (i=0;i<count;i++,STRIDE_F(coord,stride),STRIDE_F(norm,normal->stride)) {
  108.       GLfloat u[3], two_nu, fx, fy, fz;
  109.       COPY_3V( u, coord );
  110.       NORMALIZE_3FV( u );
  111.       two_nu = 2.0F * DOT3(norm,u);
  112.       fx = f[i][0] = u[0] - norm[0] * two_nu;
  113.       fy = f[i][1] = u[1] - norm[1] * two_nu;
  114.       fz = f[i][2] = u[2] - norm[2] * two_nu;
  115.       m[i] = fx * fx + fy * fy + (fz + 1.0F) * (fz + 1.0F);
  116.       if (m[i] != 0.0F) {
  117.      m[i] = 0.5F / (GLfloat) GL_SQRT(m[i]);
  118.       }
  119.    }
  120. }
  121.  
  122.  
  123.  
  124. static void build_m2( GLfloat f[][3], GLfloat m[],
  125.               const GLvector4f *normal,
  126.               const GLvector4f *eye )
  127. {
  128.    GLuint stride = eye->stride;
  129.    GLfloat *coord = eye->start;
  130.    GLuint count = eye->count;
  131.  
  132.    GLfloat *norm = normal->start;
  133.    GLuint i;
  134.  
  135.    for (i=0;i<count;i++,STRIDE_F(coord,stride),STRIDE_F(norm,normal->stride)) {
  136.       GLfloat u[3], two_nu, fx, fy, fz;
  137.       COPY_2V( u, coord );
  138.       u[2] = 0;
  139.       NORMALIZE_3FV( u );
  140.       two_nu = 2.0F * DOT3(norm,u);
  141.       fx = f[i][0] = u[0] - norm[0] * two_nu;
  142.       fy = f[i][1] = u[1] - norm[1] * two_nu;
  143.       fz = f[i][2] = u[2] - norm[2] * two_nu;
  144.       m[i] = fx * fx + fy * fy + (fz + 1.0F) * (fz + 1.0F);
  145.       if (m[i] != 0.0F) {
  146.      m[i] = 0.5F / (GLfloat) GL_SQRT(m[i]);
  147.       }
  148.    }
  149. }
  150.  
  151.  
  152.  
  153. typedef void (*build_m_func)( GLfloat f[][3],
  154.                   GLfloat m[],
  155.                   const GLvector4f *normal,
  156.                   const GLvector4f *eye );
  157.  
  158.  
  159. static build_m_func build_m_tab[5] = {
  160.    0,
  161.    0,
  162.    build_m2,
  163.    build_m3,
  164.    build_m3
  165. };
  166.  
  167.  
  168. /* This is unusual in that we respect the stride of the output vector
  169.  * (f).  This allows us to pass in either a texcoord vector4f, or a
  170.  * temporary vector3f.
  171.  */
  172. static void build_f3( GLfloat *f,
  173.               GLuint fstride,
  174.               const GLvector4f *normal,
  175.               const GLvector4f *eye )
  176. {
  177.    GLuint stride = eye->stride;
  178.    GLfloat *coord = eye->start;
  179.    GLuint count = eye->count;
  180.  
  181.    GLfloat *norm = normal->start;
  182.    GLuint i;
  183.  
  184.    for (i=0;i<count;i++) {
  185.       GLfloat u[3], two_nu;
  186.       COPY_3V( u, coord );
  187.       NORMALIZE_3FV( u );
  188.       two_nu = 2.0F * DOT3(norm,u);
  189.       f[0] = u[0] - norm[0] * two_nu;
  190.       f[1] = u[1] - norm[1] * two_nu;
  191.       f[2] = u[2] - norm[2] * two_nu;
  192.       STRIDE_F(coord,stride);
  193.       STRIDE_F(f,fstride);
  194.       STRIDE_F(norm, normal->stride);
  195.    }
  196. }
  197.  
  198.  
  199. static void build_f2( GLfloat *f,
  200.               GLuint fstride,
  201.               const GLvector4f *normal,
  202.               const GLvector4f *eye )
  203. {
  204.    GLuint stride = eye->stride;
  205.    GLfloat *coord = eye->start;
  206.    GLuint count = eye->count;
  207.    GLfloat *norm = normal->start;
  208.    GLuint i;
  209.  
  210.    for (i=0;i<count;i++) {
  211.  
  212.       GLfloat u[3], two_nu;
  213.       COPY_2V( u, coord );
  214.       u[2] = 0;
  215.       NORMALIZE_3FV( u );
  216.       two_nu = 2.0F * DOT3(norm,u);
  217.       f[0] = u[0] - norm[0] * two_nu;
  218.       f[1] = u[1] - norm[1] * two_nu;
  219.       f[2] = u[2] - norm[2] * two_nu;
  220.  
  221.       STRIDE_F(coord,stride);
  222.       STRIDE_F(f,fstride);
  223.       STRIDE_F(norm, normal->stride);
  224.    }
  225. }
  226.  
  227. typedef void (*build_f_func)( GLfloat *f,
  228.                   GLuint fstride,
  229.                   const GLvector4f *normal_vec,
  230.                   const GLvector4f *eye );
  231.  
  232.  
  233.  
  234. /* Just treat 4-vectors as 3-vectors.
  235.  */
  236. static build_f_func build_f_tab[5] = {
  237.    0,
  238.    0,
  239.    build_f2,
  240.    build_f3,
  241.    build_f3
  242. };
  243.  
  244.  
  245. /* Special case texgen functions.
  246.  */
  247. static void texgen_reflection_map_nv( GLcontext *ctx,
  248.                       struct texgen_stage_data *store,
  249.                       GLuint unit )
  250. {
  251.    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
  252.    GLvector4f *in = VB->TexCoordPtr[unit];
  253.    GLvector4f *out = &store->texcoord[unit];
  254.  
  255.    build_f_tab[VB->EyePtr->size]( out->start,
  256.                   out->stride,
  257.                   VB->NormalPtr,
  258.                   VB->EyePtr );
  259.  
  260.    if (in) {
  261.       out->flags |= (in->flags & VEC_SIZE_FLAGS) | VEC_SIZE_3;
  262.       out->count = in->count;
  263.       out->size = MAX2(in->size, 3);
  264.       if (in->size == 4)
  265.      _mesa_copy_tab[0x8]( out, in );
  266.    }
  267.    else {
  268.       out->flags |= VEC_SIZE_3;
  269.       out->size = 3;
  270.       out->count = in->count;
  271.    }
  272.  
  273. }
  274.  
  275.  
  276.  
  277. static void texgen_normal_map_nv( GLcontext *ctx,
  278.                   struct texgen_stage_data *store,
  279.                   GLuint unit )
  280. {
  281.    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
  282.    GLvector4f *in = VB->TexCoordPtr[unit];
  283.    GLvector4f *out = &store->texcoord[unit];
  284.    GLvector4f *normal = VB->NormalPtr;
  285.    GLfloat (*texcoord)[4] = (GLfloat (*)[4])out->start;
  286.    GLuint count = VB->Count;
  287.    GLuint i;
  288.    const GLfloat *norm = normal->start;
  289.  
  290.    for (i=0;i<count;i++, STRIDE_F(norm, normal->stride)) {
  291.       texcoord[i][0] = norm[0];
  292.       texcoord[i][1] = norm[1];
  293.       texcoord[i][2] = norm[2];
  294.    }
  295.  
  296.  
  297.    if (in) {
  298.       out->flags |= (in->flags & VEC_SIZE_FLAGS) | VEC_SIZE_3;
  299.       out->count = in->count;
  300.       out->size = MAX2(in->size, 3);
  301.       if (in->size == 4)
  302.      _mesa_copy_tab[0x8]( out, in );
  303.    }
  304.    else {
  305.       out->flags |= VEC_SIZE_3;
  306.       out->size = 3;
  307.       out->count = in->count;
  308.    }
  309. }
  310.  
  311.  
  312. static void texgen_sphere_map( GLcontext *ctx,
  313.                    struct texgen_stage_data *store,
  314.                    GLuint unit )
  315. {
  316.    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
  317.    GLvector4f *in = VB->TexCoordPtr[unit];
  318.    GLvector4f *out = &store->texcoord[unit];
  319.    GLfloat (*texcoord)[4] = (GLfloat (*)[4]) out->start;
  320.    GLuint count = VB->Count;
  321.    GLuint i;
  322.    GLfloat (*f)[3] = store->tmp_f;
  323.    GLfloat *m = store->tmp_m;
  324.  
  325. /*     _mesa_debug(NULL, "%s normstride %d eyestride %d\n",  */
  326. /*         __FUNCTION__, VB->NormalPtr->stride, */
  327. /*         VB->EyePtr->stride); */
  328.  
  329.    (build_m_tab[VB->EyePtr->size])( store->tmp_f,
  330.                     store->tmp_m,
  331.                     VB->NormalPtr,
  332.                     VB->EyePtr );
  333.  
  334.    for (i=0;i<count;i++) {
  335.       texcoord[i][0] = f[i][0] * m[i] + 0.5F;
  336.       texcoord[i][1] = f[i][1] * m[i] + 0.5F;
  337.    }
  338.  
  339.    if (in) {
  340.       out->size = MAX2(in->size,2);
  341.       out->count = in->count;
  342.       out->flags |= (in->flags & VEC_SIZE_FLAGS) | VEC_SIZE_2;
  343.       if (in->size > 2)
  344.      _mesa_copy_tab[all_bits[in->size] & ~0x3]( out, in );
  345.    } else {
  346.       out->size = 2;
  347.       out->flags |= VEC_SIZE_2;
  348.       out->count = in->count;
  349.    }
  350. }
  351.  
  352.  
  353.  
  354. static void texgen( GLcontext *ctx,
  355.             struct texgen_stage_data *store,
  356.             GLuint unit )
  357. {
  358.    TNLcontext *tnl = TNL_CONTEXT(ctx);
  359.    struct vertex_buffer *VB = &tnl->vb;
  360.    GLvector4f *in = VB->TexCoordPtr[unit];
  361.    GLvector4f *out = &store->texcoord[unit];
  362.    struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
  363.    const GLvector4f *obj = VB->ObjPtr;
  364.    const GLvector4f *eye = VB->EyePtr;
  365.    const GLvector4f *normal = VB->NormalPtr;
  366.    GLfloat (*texcoord)[4] = (GLfloat (*)[4])out->data;
  367.    GLfloat *indata;
  368.    GLuint count = VB->Count;
  369.    GLfloat (*f)[3] = store->tmp_f;
  370.    GLfloat *m = store->tmp_m;
  371.      GLuint holes = 0;
  372.  
  373.  
  374.    if (texUnit->_GenFlags & TEXGEN_NEED_M) {
  375.       build_m_tab[in->size]( store->tmp_f, store->tmp_m, normal, eye );
  376.    } else if (texUnit->_GenFlags & TEXGEN_NEED_F) {
  377.       build_f_tab[in->size]( (GLfloat *)store->tmp_f, 3, normal, eye );
  378.    }
  379.  
  380.    if (!in) {
  381.       ASSERT(0);
  382.       in = out;
  383.       in->count = VB->Count;
  384.  
  385.       out->size = store->TexgenSize[unit];
  386.       out->flags |= texUnit->TexGenEnabled;
  387.       out->count = VB->Count;
  388.       holes = store->TexgenHoles[unit];
  389.    }
  390.    else {
  391.       GLuint copy = (all_bits[in->size] & ~texUnit->TexGenEnabled);
  392.       if (copy)
  393.      _mesa_copy_tab[copy]( out, in );
  394.  
  395.       out->size = MAX2(in->size, store->TexgenSize[unit]);
  396.       out->flags |= (in->flags & VEC_SIZE_FLAGS) | texUnit->TexGenEnabled;
  397.       out->count = in->count;
  398.  
  399.       holes = ~all_bits[in->size] & store->TexgenHoles[unit];
  400.    }
  401.  
  402.    if (holes) {
  403.       if (holes & VEC_DIRTY_2) _mesa_vector4f_clean_elem(out, count, 2);
  404.       if (holes & VEC_DIRTY_1) _mesa_vector4f_clean_elem(out, count, 1);
  405.       if (holes & VEC_DIRTY_0) _mesa_vector4f_clean_elem(out, count, 0);
  406.    }
  407.  
  408.    if (texUnit->TexGenEnabled & S_BIT) {
  409.       GLuint i;
  410.       switch (texUnit->GenModeS) {
  411.       case GL_OBJECT_LINEAR:
  412.      _mesa_dotprod_tab[obj->size]( (GLfloat *)out->data,
  413.                        sizeof(out->data[0]), obj,
  414.                        texUnit->ObjectPlaneS );
  415.      break;
  416.       case GL_EYE_LINEAR:
  417.      _mesa_dotprod_tab[eye->size]( (GLfloat *)out->data,
  418.                        sizeof(out->data[0]), eye,
  419.                        texUnit->EyePlaneS );
  420.      break;
  421.       case GL_SPHERE_MAP:
  422.      for (indata=in->start,i=0 ; i<count ;i++, STRIDE_F(indata,in->stride))
  423.         texcoord[i][0] = indata[0] * m[i] + 0.5F;
  424.      break;
  425.       case GL_REFLECTION_MAP_NV:
  426.      for (i=0;i<count;i++)
  427.          texcoord[i][0] = f[i][0];
  428.      break;
  429.       case GL_NORMAL_MAP_NV: {
  430.      const GLfloat *norm = normal->start;
  431.      for (i=0;i<count;i++, STRIDE_F(norm, normal->stride)) {
  432.          texcoord[i][0] = norm[0];
  433.      }
  434.      break;
  435.       }
  436.       default:
  437.      _mesa_problem(ctx, "Bad S texgen");
  438.       }
  439.    }
  440.  
  441.    if (texUnit->TexGenEnabled & T_BIT) {
  442.       GLuint i;
  443.       switch (texUnit->GenModeT) {
  444.       case GL_OBJECT_LINEAR:
  445.      _mesa_dotprod_tab[obj->size]( &(out->data[0][1]),
  446.                        sizeof(out->data[0]), obj,
  447.                        texUnit->ObjectPlaneT );
  448.      break;
  449.       case GL_EYE_LINEAR:
  450.      _mesa_dotprod_tab[eye->size]( &(out->data[0][1]),
  451.                        sizeof(out->data[0]), eye,
  452.                        texUnit->EyePlaneT );
  453.      break;
  454.       case GL_SPHERE_MAP:
  455.      for (indata=in->start,i=0; i<count ;i++,STRIDE_F(indata,in->stride))
  456.          texcoord[i][1] = indata[1] * m[i] + 0.5F;
  457.      break;
  458.       case GL_REFLECTION_MAP_NV:
  459.      for (i=0;i<count;i++)
  460.          texcoord[i][0] = f[i][0];
  461.      break;
  462.       case GL_NORMAL_MAP_NV: {
  463.      const GLfloat *norm = normal->start;
  464.      for (i=0;i<count;i++, STRIDE_F(norm, normal->stride)) {
  465.          texcoord[i][1] = norm[1];
  466.      }
  467.      break;
  468.       }
  469.       default:
  470.      _mesa_problem(ctx, "Bad T texgen");
  471.       }
  472.    }
  473.  
  474.    if (texUnit->TexGenEnabled & R_BIT) {
  475.       GLuint i;
  476.       switch (texUnit->GenModeR) {
  477.       case GL_OBJECT_LINEAR:
  478.      _mesa_dotprod_tab[obj->size]( &(out->data[0][2]),
  479.                        sizeof(out->data[0]), obj,
  480.                        texUnit->ObjectPlaneR );
  481.      break;
  482.       case GL_EYE_LINEAR:
  483.      _mesa_dotprod_tab[eye->size]( &(out->data[0][2]),
  484.                        sizeof(out->data[0]), eye,
  485.                        texUnit->EyePlaneR );
  486.      break;
  487.       case GL_REFLECTION_MAP_NV:
  488.      for (i=0;i<count;i++)
  489.          texcoord[i][2] = f[i][2];
  490.      break;
  491.       case GL_NORMAL_MAP_NV: {
  492.      const GLfloat *norm = normal->start;
  493.      for (i=0;i<count;i++,STRIDE_F(norm, normal->stride)) {
  494.          texcoord[i][2] = norm[2];
  495.      }
  496.      break;
  497.       }
  498.       default:
  499.      _mesa_problem(ctx, "Bad R texgen");
  500.       }
  501.    }
  502.  
  503.    if (texUnit->TexGenEnabled & Q_BIT) {
  504.       switch (texUnit->GenModeQ) {
  505.       case GL_OBJECT_LINEAR:
  506.      _mesa_dotprod_tab[obj->size]( &(out->data[0][3]),
  507.                        sizeof(out->data[0]), obj,
  508.                        texUnit->ObjectPlaneQ );
  509.      break;
  510.       case GL_EYE_LINEAR:
  511.      _mesa_dotprod_tab[eye->size]( &(out->data[0][3]),
  512.                        sizeof(out->data[0]), eye,
  513.                        texUnit->EyePlaneQ );
  514.      break;
  515.       default:
  516.      _mesa_problem(ctx, "Bad Q texgen");
  517.       }
  518.    }
  519. }
  520.  
  521.  
  522.  
  523. static GLboolean run_texgen_stage( GLcontext *ctx,
  524.                    struct gl_pipeline_stage *stage )
  525. {
  526.    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
  527.    struct texgen_stage_data *store = TEXGEN_STAGE_DATA( stage );
  528.    GLuint i;
  529.  
  530.    for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++)
  531.       if (ctx->Texture._TexGenEnabled & ENABLE_TEXGEN(i)) {
  532.      if (stage->changed_inputs & (VERT_BIT_EYE | VERT_BIT_NORMAL | VERT_BIT_TEX(i)))
  533.         store->TexgenFunc[i]( ctx, store, i );
  534.  
  535.      VB->TexCoordPtr[i] = &store->texcoord[i];
  536.       }
  537.  
  538.    return GL_TRUE;
  539. }
  540.  
  541.  
  542.  
  543.  
  544. static GLboolean run_validate_texgen_stage( GLcontext *ctx,
  545.                         struct gl_pipeline_stage *stage )
  546. {
  547.    struct texgen_stage_data *store = TEXGEN_STAGE_DATA(stage);
  548.    GLuint i;
  549.  
  550.    for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) {
  551.       struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
  552.  
  553.       if (texUnit->TexGenEnabled) {
  554.      GLuint sz;
  555.  
  556.      if (texUnit->TexGenEnabled & R_BIT)
  557.         sz = 4;
  558.      else if (texUnit->TexGenEnabled & Q_BIT)
  559.         sz = 3;
  560.      else if (texUnit->TexGenEnabled & T_BIT)
  561.         sz = 2;
  562.      else
  563.         sz = 1;
  564.  
  565.      store->TexgenSize[i] = sz;
  566.      store->TexgenHoles[i] = (all_bits[sz] & ~texUnit->TexGenEnabled);
  567.      store->TexgenFunc[i] = texgen;
  568.  
  569.      if (texUnit->TexGenEnabled == (S_BIT|T_BIT|R_BIT)) {
  570.         if (texUnit->_GenFlags == TEXGEN_REFLECTION_MAP_NV) {
  571.            store->TexgenFunc[i] = texgen_reflection_map_nv;
  572.         }
  573.         else if (texUnit->_GenFlags == TEXGEN_NORMAL_MAP_NV) {
  574.            store->TexgenFunc[i] = texgen_normal_map_nv;
  575.         }
  576.      }
  577.      else if (texUnit->TexGenEnabled == (S_BIT|T_BIT) &&
  578.           texUnit->_GenFlags == TEXGEN_SPHERE_MAP) {
  579.         store->TexgenFunc[i] = texgen_sphere_map;
  580.      }
  581.       }
  582.    }
  583.  
  584.    stage->run = run_texgen_stage;
  585.    return stage->run( ctx, stage );
  586. }
  587.  
  588.  
  589. static void check_texgen( GLcontext *ctx, struct gl_pipeline_stage *stage )
  590. {
  591.    GLuint i;
  592.    stage->active = 0;
  593.  
  594.    if (ctx->Texture._TexGenEnabled && !ctx->VertexProgram.Enabled) {
  595.       GLuint inputs = 0;
  596.       GLuint outputs = 0;
  597.  
  598.       if (ctx->Texture._GenFlags & TEXGEN_OBJ_LINEAR)
  599.      inputs |= VERT_BIT_POS;
  600.  
  601.       if (ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD)
  602.      inputs |= VERT_BIT_EYE;
  603.  
  604.       if (ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS)
  605.      inputs |= VERT_BIT_NORMAL;
  606.  
  607.       for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++)
  608.      if (ctx->Texture._TexGenEnabled & ENABLE_TEXGEN(i))
  609.      {
  610.         outputs |= VERT_BIT_TEX(i);
  611.  
  612.         /* Need the original input in case it contains a Q coord:
  613.          * (sigh)
  614.          */
  615.         inputs |= VERT_BIT_TEX(i);
  616.  
  617.         /* Something for Feedback? */
  618.      }
  619.  
  620.       if (stage->privatePtr)
  621.      stage->run = run_validate_texgen_stage;
  622.       stage->active = 1;
  623.       stage->inputs = inputs;
  624.       stage->outputs = outputs;
  625.    }
  626. }
  627.  
  628.  
  629.  
  630.  
  631. /* Called the first time stage->run() is invoked.
  632.  */
  633. static GLboolean alloc_texgen_data( GLcontext *ctx,
  634.                     struct gl_pipeline_stage *stage )
  635. {
  636.    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
  637.    struct texgen_stage_data *store;
  638.    GLuint i;
  639.  
  640.    stage->privatePtr = CALLOC(sizeof(*store));
  641.    store = TEXGEN_STAGE_DATA(stage);
  642.    if (!store)
  643.       return GL_FALSE;
  644.  
  645.    for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++)
  646.       _mesa_vector4f_alloc( &store->texcoord[i], 0, VB->Size, 32 );
  647.  
  648.    store->tmp_f = (GLfloat (*)[3]) MALLOC(VB->Size * sizeof(GLfloat) * 3);
  649.    store->tmp_m = (GLfloat *) MALLOC(VB->Size * sizeof(GLfloat));
  650.  
  651.    /* Now validate and run the stage.
  652.     */
  653.    stage->run = run_validate_texgen_stage;
  654.    return stage->run( ctx, stage );
  655. }
  656.  
  657.  
  658. static void free_texgen_data( struct gl_pipeline_stage *stage )
  659.  
  660. {
  661.    struct texgen_stage_data *store = TEXGEN_STAGE_DATA(stage);
  662.    GLuint i;
  663.  
  664.    if (store) {
  665.       for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++)
  666.      if (store->texcoord[i].data)
  667.         _mesa_vector4f_free( &store->texcoord[i] );
  668.  
  669.  
  670.       if (store->tmp_f) FREE( store->tmp_f );
  671.       if (store->tmp_m) FREE( store->tmp_m );
  672.       FREE( store );
  673.       stage->privatePtr = NULL;
  674.    }
  675. }
  676.  
  677.  
  678.  
  679. const struct gl_pipeline_stage _tnl_texgen_stage =
  680. {
  681.    "texgen",            /* name */
  682.    _NEW_TEXTURE,        /* when to call check() */
  683.    _NEW_TEXTURE,        /* when to invalidate stored data */
  684.    GL_FALSE,            /* active? */
  685.    0,                /* inputs */
  686.    0,                /* outputs */
  687.    0,                /* changed_inputs */
  688.    NULL,            /* private data */
  689.    free_texgen_data,        /* destructor */
  690.    check_texgen,        /* check */
  691.    alloc_texgen_data        /* run -- initially set to alloc data */
  692. };
  693.