17117f1b4Smrg/* 27117f1b4Smrg * Mesa 3-D graphics library 37117f1b4Smrg * 47117f1b4Smrg * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. 57117f1b4Smrg * 67117f1b4Smrg * Permission is hereby granted, free of charge, to any person obtaining a 77117f1b4Smrg * copy of this software and associated documentation files (the "Software"), 87117f1b4Smrg * to deal in the Software without restriction, including without limitation 97117f1b4Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 107117f1b4Smrg * and/or sell copies of the Software, and to permit persons to whom the 117117f1b4Smrg * Software is furnished to do so, subject to the following conditions: 127117f1b4Smrg * 137117f1b4Smrg * The above copyright notice and this permission notice shall be included 147117f1b4Smrg * in all copies or substantial portions of the Software. 157117f1b4Smrg * 167117f1b4Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 177117f1b4Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 187117f1b4Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22af69d88dSmrg * OTHER DEALINGS IN THE SOFTWARE. 237117f1b4Smrg * 247117f1b4Smrg * Authors: 25af69d88dSmrg * Brian Paul Keith Whitwell <keithw@vmware.com> 267117f1b4Smrg */ 277117f1b4Smrg 287117f1b4Smrg/* 297117f1b4Smrg * Regarding GL_NV_texgen_reflection: 307117f1b4Smrg * 317117f1b4Smrg * Portions of this software may use or implement intellectual 327117f1b4Smrg * property owned and licensed by NVIDIA Corporation. NVIDIA disclaims 337117f1b4Smrg * any and all warranties with respect to such intellectual property, 347117f1b4Smrg * including any use thereof or modifications thereto. 357117f1b4Smrg */ 367117f1b4Smrg 3701e04c3fSmrg#include "main/errors.h" 38c1f859d4Smrg#include "main/glheader.h" 39c1f859d4Smrg#include "main/macros.h" 407ec681f3Smrg 41c1f859d4Smrg#include "main/mtypes.h" 427117f1b4Smrg 437117f1b4Smrg#include "math/m_xform.h" 447117f1b4Smrg 457117f1b4Smrg#include "t_context.h" 467117f1b4Smrg#include "t_pipeline.h" 477117f1b4Smrg 487117f1b4Smrg 497117f1b4Smrg/*********************************************************************** 507117f1b4Smrg * Automatic texture coordinate generation (texgen) code. 517117f1b4Smrg */ 527117f1b4Smrg 537117f1b4Smrg 547117f1b4Smrgstruct texgen_stage_data; 557117f1b4Smrg 563464ebd5Sriastradhtypedef void (*texgen_func)( struct gl_context *ctx, 577117f1b4Smrg struct texgen_stage_data *store, 587117f1b4Smrg GLuint unit); 597117f1b4Smrg 607117f1b4Smrg 617117f1b4Smrgstruct texgen_stage_data { 627117f1b4Smrg 637117f1b4Smrg /* Per-texunit derived state. 647117f1b4Smrg */ 657117f1b4Smrg GLuint TexgenSize[MAX_TEXTURE_COORD_UNITS]; 667117f1b4Smrg texgen_func TexgenFunc[MAX_TEXTURE_COORD_UNITS]; 677117f1b4Smrg 687117f1b4Smrg /* Temporary values used in texgen. 697117f1b4Smrg */ 707117f1b4Smrg GLfloat (*tmp_f)[3]; 717117f1b4Smrg GLfloat *tmp_m; 727117f1b4Smrg 737117f1b4Smrg /* Buffered outputs of the stage. 747117f1b4Smrg */ 757117f1b4Smrg GLvector4f texcoord[MAX_TEXTURE_COORD_UNITS]; 767117f1b4Smrg}; 777117f1b4Smrg 787117f1b4Smrg 797117f1b4Smrg#define TEXGEN_STAGE_DATA(stage) ((struct texgen_stage_data *)stage->privatePtr) 807117f1b4Smrg 817117f1b4Smrg 827117f1b4Smrg 837117f1b4Smrgstatic GLuint all_bits[5] = { 847117f1b4Smrg 0, 857117f1b4Smrg VEC_SIZE_1, 867117f1b4Smrg VEC_SIZE_2, 877117f1b4Smrg VEC_SIZE_3, 887117f1b4Smrg VEC_SIZE_4, 897117f1b4Smrg}; 907117f1b4Smrg 917117f1b4Smrg#define VEC_SIZE_FLAGS (VEC_SIZE_1|VEC_SIZE_2|VEC_SIZE_3|VEC_SIZE_4) 927117f1b4Smrg 937117f1b4Smrg#define TEXGEN_NEED_M (TEXGEN_SPHERE_MAP) 947117f1b4Smrg#define TEXGEN_NEED_F (TEXGEN_SPHERE_MAP | \ 957117f1b4Smrg TEXGEN_REFLECTION_MAP_NV) 967117f1b4Smrg 977117f1b4Smrg 987117f1b4Smrg 997117f1b4Smrgstatic void build_m3( GLfloat f[][3], GLfloat m[], 1007117f1b4Smrg const GLvector4f *normal, 1017117f1b4Smrg const GLvector4f *eye ) 1027117f1b4Smrg{ 1037117f1b4Smrg GLuint stride = eye->stride; 1047117f1b4Smrg GLfloat *coord = (GLfloat *)eye->start; 1057117f1b4Smrg GLuint count = eye->count; 1067117f1b4Smrg const GLfloat *norm = normal->start; 1077117f1b4Smrg GLuint i; 1087117f1b4Smrg 1097117f1b4Smrg for (i=0;i<count;i++,STRIDE_F(coord,stride),STRIDE_F(norm,normal->stride)) { 1107117f1b4Smrg GLfloat u[3], two_nu, fx, fy, fz; 1117117f1b4Smrg COPY_3V( u, coord ); 1127117f1b4Smrg NORMALIZE_3FV( u ); 1137117f1b4Smrg two_nu = 2.0F * DOT3(norm,u); 1147117f1b4Smrg fx = f[i][0] = u[0] - norm[0] * two_nu; 1157117f1b4Smrg fy = f[i][1] = u[1] - norm[1] * two_nu; 1167117f1b4Smrg fz = f[i][2] = u[2] - norm[2] * two_nu; 1177117f1b4Smrg m[i] = fx * fx + fy * fy + (fz + 1.0F) * (fz + 1.0F); 1187117f1b4Smrg if (m[i] != 0.0F) { 11901e04c3fSmrg m[i] = 0.5F * (1.0f / sqrtf(m[i])); 1207117f1b4Smrg } 1217117f1b4Smrg } 1227117f1b4Smrg} 1237117f1b4Smrg 1247117f1b4Smrg 1257117f1b4Smrg 1267117f1b4Smrgstatic void build_m2( GLfloat f[][3], GLfloat m[], 1277117f1b4Smrg const GLvector4f *normal, 1287117f1b4Smrg const GLvector4f *eye ) 1297117f1b4Smrg{ 1307117f1b4Smrg GLuint stride = eye->stride; 1317117f1b4Smrg GLfloat *coord = eye->start; 1327117f1b4Smrg GLuint count = eye->count; 1337117f1b4Smrg 1347117f1b4Smrg GLfloat *norm = normal->start; 1357117f1b4Smrg GLuint i; 1367117f1b4Smrg 1377117f1b4Smrg for (i=0;i<count;i++,STRIDE_F(coord,stride),STRIDE_F(norm,normal->stride)) { 1387117f1b4Smrg GLfloat u[3], two_nu, fx, fy, fz; 1397117f1b4Smrg COPY_2V( u, coord ); 1407117f1b4Smrg u[2] = 0; 1417117f1b4Smrg NORMALIZE_3FV( u ); 1427117f1b4Smrg two_nu = 2.0F * DOT3(norm,u); 1437117f1b4Smrg fx = f[i][0] = u[0] - norm[0] * two_nu; 1447117f1b4Smrg fy = f[i][1] = u[1] - norm[1] * two_nu; 1457117f1b4Smrg fz = f[i][2] = u[2] - norm[2] * two_nu; 1467117f1b4Smrg m[i] = fx * fx + fy * fy + (fz + 1.0F) * (fz + 1.0F); 1477117f1b4Smrg if (m[i] != 0.0F) { 14801e04c3fSmrg m[i] = 0.5F * (1.0f / sqrtf(m[i])); 1497117f1b4Smrg } 1507117f1b4Smrg } 1517117f1b4Smrg} 1527117f1b4Smrg 1537117f1b4Smrg 1547117f1b4Smrg 1557117f1b4Smrgtypedef void (*build_m_func)( GLfloat f[][3], 1567117f1b4Smrg GLfloat m[], 1577117f1b4Smrg const GLvector4f *normal, 1587117f1b4Smrg const GLvector4f *eye ); 1597117f1b4Smrg 1607117f1b4Smrg 1617117f1b4Smrgstatic build_m_func build_m_tab[5] = { 1627117f1b4Smrg NULL, 1637117f1b4Smrg NULL, 1647117f1b4Smrg build_m2, 1657117f1b4Smrg build_m3, 1667117f1b4Smrg build_m3 1677117f1b4Smrg}; 1687117f1b4Smrg 1697117f1b4Smrg 1707117f1b4Smrg/* This is unusual in that we respect the stride of the output vector 1717117f1b4Smrg * (f). This allows us to pass in either a texcoord vector4f, or a 1727117f1b4Smrg * temporary vector3f. 1737117f1b4Smrg */ 1747117f1b4Smrgstatic void build_f3( GLfloat *f, 1757117f1b4Smrg GLuint fstride, 1767117f1b4Smrg const GLvector4f *normal, 1777117f1b4Smrg const GLvector4f *eye ) 1787117f1b4Smrg{ 1797117f1b4Smrg GLuint stride = eye->stride; 1807117f1b4Smrg GLfloat *coord = eye->start; 1817117f1b4Smrg GLuint count = eye->count; 1827117f1b4Smrg 1837117f1b4Smrg GLfloat *norm = normal->start; 1847117f1b4Smrg GLuint i; 1857117f1b4Smrg 1867117f1b4Smrg for (i=0;i<count;i++) { 1877117f1b4Smrg GLfloat u[3], two_nu; 1887117f1b4Smrg COPY_3V( u, coord ); 1897117f1b4Smrg NORMALIZE_3FV( u ); 1907117f1b4Smrg two_nu = 2.0F * DOT3(norm,u); 1917117f1b4Smrg f[0] = u[0] - norm[0] * two_nu; 1927117f1b4Smrg f[1] = u[1] - norm[1] * two_nu; 1937117f1b4Smrg f[2] = u[2] - norm[2] * two_nu; 1947117f1b4Smrg STRIDE_F(coord,stride); 1957117f1b4Smrg STRIDE_F(f,fstride); 1967117f1b4Smrg STRIDE_F(norm, normal->stride); 1977117f1b4Smrg } 1987117f1b4Smrg} 1997117f1b4Smrg 2007117f1b4Smrg 2017117f1b4Smrgstatic void build_f2( GLfloat *f, 2027117f1b4Smrg GLuint fstride, 2037117f1b4Smrg const GLvector4f *normal, 2047117f1b4Smrg const GLvector4f *eye ) 2057117f1b4Smrg{ 2067117f1b4Smrg GLuint stride = eye->stride; 2077117f1b4Smrg GLfloat *coord = eye->start; 2087117f1b4Smrg GLuint count = eye->count; 2097117f1b4Smrg GLfloat *norm = normal->start; 2107117f1b4Smrg GLuint i; 2117117f1b4Smrg 2127117f1b4Smrg for (i=0;i<count;i++) { 2137117f1b4Smrg 2147117f1b4Smrg GLfloat u[3], two_nu; 2157117f1b4Smrg COPY_2V( u, coord ); 2167117f1b4Smrg u[2] = 0; 2177117f1b4Smrg NORMALIZE_3FV( u ); 2187117f1b4Smrg two_nu = 2.0F * DOT3(norm,u); 2197117f1b4Smrg f[0] = u[0] - norm[0] * two_nu; 2207117f1b4Smrg f[1] = u[1] - norm[1] * two_nu; 2217117f1b4Smrg f[2] = u[2] - norm[2] * two_nu; 2227117f1b4Smrg 2237117f1b4Smrg STRIDE_F(coord,stride); 2247117f1b4Smrg STRIDE_F(f,fstride); 2257117f1b4Smrg STRIDE_F(norm, normal->stride); 2267117f1b4Smrg } 2277117f1b4Smrg} 2287117f1b4Smrg 2297117f1b4Smrgtypedef void (*build_f_func)( GLfloat *f, 2307117f1b4Smrg GLuint fstride, 2317117f1b4Smrg const GLvector4f *normal_vec, 2327117f1b4Smrg const GLvector4f *eye ); 2337117f1b4Smrg 2347117f1b4Smrg 2357117f1b4Smrg 2367117f1b4Smrg/* Just treat 4-vectors as 3-vectors. 2377117f1b4Smrg */ 2387117f1b4Smrgstatic build_f_func build_f_tab[5] = { 2397117f1b4Smrg NULL, 2407117f1b4Smrg NULL, 2417117f1b4Smrg build_f2, 2427117f1b4Smrg build_f3, 2437117f1b4Smrg build_f3 2447117f1b4Smrg}; 2457117f1b4Smrg 2467117f1b4Smrg 2477117f1b4Smrg 2487117f1b4Smrg/* Special case texgen functions. 2497117f1b4Smrg */ 2503464ebd5Sriastradhstatic void texgen_reflection_map_nv( struct gl_context *ctx, 2517117f1b4Smrg struct texgen_stage_data *store, 2527117f1b4Smrg GLuint unit ) 2537117f1b4Smrg{ 2547117f1b4Smrg struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; 2557117f1b4Smrg GLvector4f *in = VB->AttribPtr[VERT_ATTRIB_TEX0 + unit]; 2567117f1b4Smrg GLvector4f *out = &store->texcoord[unit]; 2577117f1b4Smrg 2587117f1b4Smrg build_f_tab[VB->EyePtr->size]( out->start, 2597117f1b4Smrg out->stride, 2607117f1b4Smrg VB->AttribPtr[_TNL_ATTRIB_NORMAL], 2617117f1b4Smrg VB->EyePtr ); 2627117f1b4Smrg 2637117f1b4Smrg out->flags |= (in->flags & VEC_SIZE_FLAGS) | VEC_SIZE_3; 2647117f1b4Smrg out->count = VB->Count; 2657117f1b4Smrg out->size = MAX2(in->size, 3); 2667ec681f3Smrg if (in->size == 4) 2677117f1b4Smrg _mesa_copy_tab[0x8]( out, in ); 2687117f1b4Smrg} 2697117f1b4Smrg 2707117f1b4Smrg 2717117f1b4Smrg 2723464ebd5Sriastradhstatic void texgen_normal_map_nv( struct gl_context *ctx, 2737117f1b4Smrg struct texgen_stage_data *store, 2747117f1b4Smrg GLuint unit ) 2757117f1b4Smrg{ 2767117f1b4Smrg struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; 2777117f1b4Smrg GLvector4f *in = VB->AttribPtr[VERT_ATTRIB_TEX0 + unit]; 2787117f1b4Smrg GLvector4f *out = &store->texcoord[unit]; 2797117f1b4Smrg GLvector4f *normal = VB->AttribPtr[_TNL_ATTRIB_NORMAL]; 2807117f1b4Smrg GLfloat (*texcoord)[4] = (GLfloat (*)[4])out->start; 2817117f1b4Smrg GLuint count = VB->Count; 2827117f1b4Smrg GLuint i; 2837117f1b4Smrg const GLfloat *norm = normal->start; 2847117f1b4Smrg 2857117f1b4Smrg for (i=0;i<count;i++, STRIDE_F(norm, normal->stride)) { 2867117f1b4Smrg texcoord[i][0] = norm[0]; 2877117f1b4Smrg texcoord[i][1] = norm[1]; 2887117f1b4Smrg texcoord[i][2] = norm[2]; 2897117f1b4Smrg } 2907117f1b4Smrg 2917117f1b4Smrg 2927117f1b4Smrg out->flags |= (in->flags & VEC_SIZE_FLAGS) | VEC_SIZE_3; 2937117f1b4Smrg out->count = count; 2947117f1b4Smrg out->size = MAX2(in->size, 3); 2957ec681f3Smrg if (in->size == 4) 2967117f1b4Smrg _mesa_copy_tab[0x8]( out, in ); 2977117f1b4Smrg} 2987117f1b4Smrg 2997117f1b4Smrg 3003464ebd5Sriastradhstatic void texgen_sphere_map( struct gl_context *ctx, 3017117f1b4Smrg struct texgen_stage_data *store, 3027117f1b4Smrg GLuint unit ) 3037117f1b4Smrg{ 3047117f1b4Smrg struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; 3057117f1b4Smrg GLvector4f *in = VB->AttribPtr[VERT_ATTRIB_TEX0 + unit]; 3067117f1b4Smrg GLvector4f *out = &store->texcoord[unit]; 3077117f1b4Smrg GLfloat (*texcoord)[4] = (GLfloat (*)[4]) out->start; 3087117f1b4Smrg GLuint count = VB->Count; 3097117f1b4Smrg GLuint i; 3107117f1b4Smrg GLfloat (*f)[3] = store->tmp_f; 3117117f1b4Smrg GLfloat *m = store->tmp_m; 3127117f1b4Smrg 3137117f1b4Smrg (build_m_tab[VB->EyePtr->size])( store->tmp_f, 3147117f1b4Smrg store->tmp_m, 3157117f1b4Smrg VB->AttribPtr[_TNL_ATTRIB_NORMAL], 3167117f1b4Smrg VB->EyePtr ); 3177117f1b4Smrg 3187117f1b4Smrg out->size = MAX2(in->size,2); 3197117f1b4Smrg 3207117f1b4Smrg for (i=0;i<count;i++) { 3217117f1b4Smrg texcoord[i][0] = f[i][0] * m[i] + 0.5F; 3227117f1b4Smrg texcoord[i][1] = f[i][1] * m[i] + 0.5F; 3237117f1b4Smrg } 3247117f1b4Smrg 3257117f1b4Smrg out->count = count; 3267117f1b4Smrg out->flags |= (in->flags & VEC_SIZE_FLAGS) | VEC_SIZE_2; 3277117f1b4Smrg if (in->size > 2) 3287117f1b4Smrg _mesa_copy_tab[all_bits[in->size] & ~0x3]( out, in ); 3297117f1b4Smrg} 3307117f1b4Smrg 3317117f1b4Smrg 3327117f1b4Smrg 3333464ebd5Sriastradhstatic void texgen( struct gl_context *ctx, 3347117f1b4Smrg struct texgen_stage_data *store, 3357117f1b4Smrg GLuint unit ) 3367117f1b4Smrg{ 3377117f1b4Smrg TNLcontext *tnl = TNL_CONTEXT(ctx); 3387117f1b4Smrg struct vertex_buffer *VB = &tnl->vb; 3397117f1b4Smrg GLvector4f *in = VB->AttribPtr[VERT_ATTRIB_TEX0 + unit]; 3407117f1b4Smrg GLvector4f *out = &store->texcoord[unit]; 34101e04c3fSmrg const struct gl_fixedfunc_texture_unit *texUnit = 34201e04c3fSmrg &ctx->Texture.FixedFuncUnit[unit]; 343cdc920a0Smrg const GLvector4f *obj = VB->AttribPtr[_TNL_ATTRIB_POS]; 3447117f1b4Smrg const GLvector4f *eye = VB->EyePtr; 3457117f1b4Smrg const GLvector4f *normal = VB->AttribPtr[_TNL_ATTRIB_NORMAL]; 3467117f1b4Smrg const GLfloat *m = store->tmp_m; 3477117f1b4Smrg const GLuint count = VB->Count; 3487117f1b4Smrg GLfloat (*texcoord)[4] = (GLfloat (*)[4])out->data; 3497117f1b4Smrg GLfloat (*f)[3] = store->tmp_f; 3507117f1b4Smrg GLuint copy; 3517117f1b4Smrg 3527117f1b4Smrg if (texUnit->_GenFlags & TEXGEN_NEED_M) { 3537117f1b4Smrg build_m_tab[eye->size]( store->tmp_f, store->tmp_m, normal, eye ); 3547117f1b4Smrg } else if (texUnit->_GenFlags & TEXGEN_NEED_F) { 3557117f1b4Smrg build_f_tab[eye->size]( (GLfloat *)store->tmp_f, 3, normal, eye ); 3567117f1b4Smrg } 3577117f1b4Smrg 3587117f1b4Smrg 3597117f1b4Smrg out->size = MAX2(in->size, store->TexgenSize[unit]); 3607117f1b4Smrg out->flags |= (in->flags & VEC_SIZE_FLAGS) | texUnit->TexGenEnabled; 3617117f1b4Smrg out->count = count; 3627117f1b4Smrg 3637117f1b4Smrg copy = (all_bits[in->size] & ~texUnit->TexGenEnabled); 3647117f1b4Smrg if (copy) 3657117f1b4Smrg _mesa_copy_tab[copy]( out, in ); 3667117f1b4Smrg 3677117f1b4Smrg if (texUnit->TexGenEnabled & S_BIT) { 3687117f1b4Smrg GLuint i; 3694a49301eSmrg switch (texUnit->GenS.Mode) { 3707117f1b4Smrg case GL_OBJECT_LINEAR: 3717117f1b4Smrg _mesa_dotprod_tab[obj->size]( (GLfloat *)out->data, 3727117f1b4Smrg sizeof(out->data[0]), obj, 3737ec681f3Smrg texUnit->ObjectPlane[GEN_S] ); 3747117f1b4Smrg break; 3757117f1b4Smrg case GL_EYE_LINEAR: 3767117f1b4Smrg _mesa_dotprod_tab[eye->size]( (GLfloat *)out->data, 3777117f1b4Smrg sizeof(out->data[0]), eye, 3787ec681f3Smrg texUnit->EyePlane[GEN_S] ); 3797117f1b4Smrg break; 3807117f1b4Smrg case GL_SPHERE_MAP: 3817117f1b4Smrg for (i = 0; i < count; i++) 3827117f1b4Smrg texcoord[i][0] = f[i][0] * m[i] + 0.5F; 3837117f1b4Smrg break; 3847117f1b4Smrg case GL_REFLECTION_MAP_NV: 3857117f1b4Smrg for (i=0;i<count;i++) 3867117f1b4Smrg texcoord[i][0] = f[i][0]; 3877117f1b4Smrg break; 3887117f1b4Smrg case GL_NORMAL_MAP_NV: { 3897117f1b4Smrg const GLfloat *norm = normal->start; 3907117f1b4Smrg for (i=0;i<count;i++, STRIDE_F(norm, normal->stride)) { 3917117f1b4Smrg texcoord[i][0] = norm[0]; 3927117f1b4Smrg } 3937117f1b4Smrg break; 3947117f1b4Smrg } 3957117f1b4Smrg default: 3967117f1b4Smrg _mesa_problem(ctx, "Bad S texgen"); 3977117f1b4Smrg } 3987117f1b4Smrg } 3997117f1b4Smrg 4007117f1b4Smrg if (texUnit->TexGenEnabled & T_BIT) { 4017117f1b4Smrg GLuint i; 4024a49301eSmrg switch (texUnit->GenT.Mode) { 4037117f1b4Smrg case GL_OBJECT_LINEAR: 4047117f1b4Smrg _mesa_dotprod_tab[obj->size]( &(out->data[0][1]), 4057117f1b4Smrg sizeof(out->data[0]), obj, 4067ec681f3Smrg texUnit->ObjectPlane[GEN_T] ); 4077117f1b4Smrg break; 4087117f1b4Smrg case GL_EYE_LINEAR: 4097117f1b4Smrg _mesa_dotprod_tab[eye->size]( &(out->data[0][1]), 4107117f1b4Smrg sizeof(out->data[0]), eye, 4117ec681f3Smrg texUnit->EyePlane[GEN_T] ); 4127117f1b4Smrg break; 4137117f1b4Smrg case GL_SPHERE_MAP: 4147117f1b4Smrg for (i = 0; i < count; i++) 4157117f1b4Smrg texcoord[i][1] = f[i][1] * m[i] + 0.5F; 4167117f1b4Smrg break; 4177117f1b4Smrg case GL_REFLECTION_MAP_NV: 4187117f1b4Smrg for (i=0;i<count;i++) 4197117f1b4Smrg texcoord[i][1] = f[i][1]; 4207117f1b4Smrg break; 4217117f1b4Smrg case GL_NORMAL_MAP_NV: { 4227117f1b4Smrg const GLfloat *norm = normal->start; 4237117f1b4Smrg for (i=0;i<count;i++, STRIDE_F(norm, normal->stride)) { 4247117f1b4Smrg texcoord[i][1] = norm[1]; 4257117f1b4Smrg } 4267117f1b4Smrg break; 4277117f1b4Smrg } 4287117f1b4Smrg default: 4297117f1b4Smrg _mesa_problem(ctx, "Bad T texgen"); 4307117f1b4Smrg } 4317117f1b4Smrg } 4327117f1b4Smrg 4337117f1b4Smrg if (texUnit->TexGenEnabled & R_BIT) { 4347117f1b4Smrg GLuint i; 4354a49301eSmrg switch (texUnit->GenR.Mode) { 4367117f1b4Smrg case GL_OBJECT_LINEAR: 4377117f1b4Smrg _mesa_dotprod_tab[obj->size]( &(out->data[0][2]), 4387117f1b4Smrg sizeof(out->data[0]), obj, 4397ec681f3Smrg texUnit->ObjectPlane[GEN_R] ); 4407117f1b4Smrg break; 4417117f1b4Smrg case GL_EYE_LINEAR: 4427117f1b4Smrg _mesa_dotprod_tab[eye->size]( &(out->data[0][2]), 4437117f1b4Smrg sizeof(out->data[0]), eye, 4447ec681f3Smrg texUnit->EyePlane[GEN_R] ); 4457117f1b4Smrg break; 4467117f1b4Smrg case GL_REFLECTION_MAP_NV: 4477117f1b4Smrg for (i=0;i<count;i++) 4487117f1b4Smrg texcoord[i][2] = f[i][2]; 4497117f1b4Smrg break; 4507117f1b4Smrg case GL_NORMAL_MAP_NV: { 4517117f1b4Smrg const GLfloat *norm = normal->start; 4527117f1b4Smrg for (i=0;i<count;i++,STRIDE_F(norm, normal->stride)) { 4537117f1b4Smrg texcoord[i][2] = norm[2]; 4547117f1b4Smrg } 4557117f1b4Smrg break; 4567117f1b4Smrg } 4577117f1b4Smrg default: 4587117f1b4Smrg _mesa_problem(ctx, "Bad R texgen"); 4597117f1b4Smrg } 4607117f1b4Smrg } 4617117f1b4Smrg 4627117f1b4Smrg if (texUnit->TexGenEnabled & Q_BIT) { 4634a49301eSmrg switch (texUnit->GenQ.Mode) { 4647117f1b4Smrg case GL_OBJECT_LINEAR: 4657117f1b4Smrg _mesa_dotprod_tab[obj->size]( &(out->data[0][3]), 4667117f1b4Smrg sizeof(out->data[0]), obj, 4677ec681f3Smrg texUnit->ObjectPlane[GEN_Q] ); 4687117f1b4Smrg break; 4697117f1b4Smrg case GL_EYE_LINEAR: 4707117f1b4Smrg _mesa_dotprod_tab[eye->size]( &(out->data[0][3]), 4717117f1b4Smrg sizeof(out->data[0]), eye, 4727ec681f3Smrg texUnit->EyePlane[GEN_Q] ); 4737117f1b4Smrg break; 4747117f1b4Smrg default: 4757117f1b4Smrg _mesa_problem(ctx, "Bad Q texgen"); 4767117f1b4Smrg } 4777117f1b4Smrg } 4787117f1b4Smrg} 4797117f1b4Smrg 4807117f1b4Smrg 4817117f1b4Smrg 4827117f1b4Smrg 4833464ebd5Sriastradhstatic GLboolean run_texgen_stage( struct gl_context *ctx, 4847117f1b4Smrg struct tnl_pipeline_stage *stage ) 4857117f1b4Smrg{ 4867117f1b4Smrg struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; 4877117f1b4Smrg struct texgen_stage_data *store = TEXGEN_STAGE_DATA(stage); 4887117f1b4Smrg GLuint i; 4897117f1b4Smrg 4907ec681f3Smrg if (!ctx->Texture._TexGenEnabled || ctx->VertexProgram._Current) 4917117f1b4Smrg return GL_TRUE; 4927117f1b4Smrg 4937117f1b4Smrg for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++) { 49401e04c3fSmrg struct gl_fixedfunc_texture_unit *texUnit = 49501e04c3fSmrg &ctx->Texture.FixedFuncUnit[i]; 4967117f1b4Smrg 4977117f1b4Smrg if (texUnit->TexGenEnabled) { 4987117f1b4Smrg store->TexgenFunc[i]( ctx, store, i ); 4997117f1b4Smrg 5007117f1b4Smrg VB->AttribPtr[VERT_ATTRIB_TEX0 + i] = &store->texcoord[i]; 5017117f1b4Smrg } 5027117f1b4Smrg } 5037117f1b4Smrg 5047117f1b4Smrg return GL_TRUE; 5057117f1b4Smrg} 5067117f1b4Smrg 5077117f1b4Smrg 5083464ebd5Sriastradhstatic void validate_texgen_stage( struct gl_context *ctx, 5097117f1b4Smrg struct tnl_pipeline_stage *stage ) 5107117f1b4Smrg{ 5117117f1b4Smrg struct texgen_stage_data *store = TEXGEN_STAGE_DATA(stage); 5127117f1b4Smrg GLuint i; 5137117f1b4Smrg 5147ec681f3Smrg if (!ctx->Texture._TexGenEnabled || ctx->VertexProgram._Current) 5157117f1b4Smrg return; 5167117f1b4Smrg 5177117f1b4Smrg for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++) { 51801e04c3fSmrg struct gl_fixedfunc_texture_unit *texUnit = 51901e04c3fSmrg &ctx->Texture.FixedFuncUnit[i]; 5207117f1b4Smrg 5217117f1b4Smrg if (texUnit->TexGenEnabled) { 5227117f1b4Smrg GLuint sz; 5237117f1b4Smrg 5247117f1b4Smrg if (texUnit->TexGenEnabled & Q_BIT) 5257117f1b4Smrg sz = 4; 5267117f1b4Smrg else if (texUnit->TexGenEnabled & R_BIT) 5277117f1b4Smrg sz = 3; 5287117f1b4Smrg else if (texUnit->TexGenEnabled & T_BIT) 5297117f1b4Smrg sz = 2; 5307117f1b4Smrg else 5317117f1b4Smrg sz = 1; 5327117f1b4Smrg 5337117f1b4Smrg store->TexgenSize[i] = sz; 5347117f1b4Smrg store->TexgenFunc[i] = texgen; /* general solution */ 5357117f1b4Smrg 5367117f1b4Smrg /* look for special texgen cases */ 5377117f1b4Smrg if (texUnit->TexGenEnabled == (S_BIT|T_BIT|R_BIT)) { 5387117f1b4Smrg if (texUnit->_GenFlags == TEXGEN_REFLECTION_MAP_NV) { 5397117f1b4Smrg store->TexgenFunc[i] = texgen_reflection_map_nv; 5407117f1b4Smrg } 5417117f1b4Smrg else if (texUnit->_GenFlags == TEXGEN_NORMAL_MAP_NV) { 5427117f1b4Smrg store->TexgenFunc[i] = texgen_normal_map_nv; 5437117f1b4Smrg } 5447117f1b4Smrg } 5457117f1b4Smrg else if (texUnit->TexGenEnabled == (S_BIT|T_BIT) && 5467117f1b4Smrg texUnit->_GenFlags == TEXGEN_SPHERE_MAP) { 5477117f1b4Smrg store->TexgenFunc[i] = texgen_sphere_map; 5487117f1b4Smrg } 5497117f1b4Smrg } 5507117f1b4Smrg } 5517117f1b4Smrg} 5527117f1b4Smrg 5537117f1b4Smrg 5547117f1b4Smrg 5557117f1b4Smrg 5567117f1b4Smrg 5577117f1b4Smrg/* Called the first time stage->run() is invoked. 5587117f1b4Smrg */ 5593464ebd5Sriastradhstatic GLboolean alloc_texgen_data( struct gl_context *ctx, 5607117f1b4Smrg struct tnl_pipeline_stage *stage ) 5617117f1b4Smrg{ 5627117f1b4Smrg struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; 5637117f1b4Smrg struct texgen_stage_data *store; 5647117f1b4Smrg GLuint i; 5657117f1b4Smrg 566af69d88dSmrg stage->privatePtr = calloc(1, sizeof(*store)); 5677117f1b4Smrg store = TEXGEN_STAGE_DATA(stage); 5687117f1b4Smrg if (!store) 5697117f1b4Smrg return GL_FALSE; 5707117f1b4Smrg 5717117f1b4Smrg for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++) 5727117f1b4Smrg _mesa_vector4f_alloc( &store->texcoord[i], 0, VB->Size, 32 ); 5737117f1b4Smrg 574af69d88dSmrg store->tmp_f = malloc(VB->Size * sizeof(GLfloat) * 3); 575af69d88dSmrg store->tmp_m = malloc(VB->Size * sizeof(GLfloat)); 5767117f1b4Smrg 5777117f1b4Smrg return GL_TRUE; 5787117f1b4Smrg} 5797117f1b4Smrg 5807117f1b4Smrg 5817117f1b4Smrgstatic void free_texgen_data( struct tnl_pipeline_stage *stage ) 5827117f1b4Smrg 5837117f1b4Smrg{ 5847117f1b4Smrg struct texgen_stage_data *store = TEXGEN_STAGE_DATA(stage); 5857117f1b4Smrg GLuint i; 5867117f1b4Smrg 5877117f1b4Smrg if (store) { 5887117f1b4Smrg for (i = 0 ; i < MAX_TEXTURE_COORD_UNITS ; i++) 5897117f1b4Smrg if (store->texcoord[i].data) 5907117f1b4Smrg _mesa_vector4f_free( &store->texcoord[i] ); 5917117f1b4Smrg 5927117f1b4Smrg 593af69d88dSmrg free( store->tmp_f ); 594af69d88dSmrg free( store->tmp_m ); 595af69d88dSmrg free( store ); 5967117f1b4Smrg stage->privatePtr = NULL; 5977117f1b4Smrg } 5987117f1b4Smrg} 5997117f1b4Smrg 6007117f1b4Smrg 6017117f1b4Smrg 6027117f1b4Smrgconst struct tnl_pipeline_stage _tnl_texgen_stage = 6037117f1b4Smrg{ 6047117f1b4Smrg "texgen", /* name */ 6057117f1b4Smrg NULL, /* private data */ 6067117f1b4Smrg alloc_texgen_data, /* destructor */ 6077117f1b4Smrg free_texgen_data, /* destructor */ 6087117f1b4Smrg validate_texgen_stage, /* check */ 6097117f1b4Smrg run_texgen_stage /* run -- initially set to alloc data */ 6107117f1b4Smrg}; 611