Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

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