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 257117f1b4Smrg 2601e04c3fSmrg#include "c99_math.h" 27c1f859d4Smrg#include "main/glheader.h" 28c1f859d4Smrg#include "main/light.h" 29c1f859d4Smrg#include "main/macros.h" 307ec681f3Smrg 3101e04c3fSmrg#include "util/simple_list.h" 32c1f859d4Smrg#include "main/mtypes.h" 337117f1b4Smrg 347117f1b4Smrg#include "math/m_translate.h" 357117f1b4Smrg 3601e04c3fSmrg#include "util/bitscan.h" 3701e04c3fSmrg 387117f1b4Smrg#include "t_context.h" 397117f1b4Smrg#include "t_pipeline.h" 40af69d88dSmrg#include "tnl.h" 417117f1b4Smrg 427117f1b4Smrg#define LIGHT_TWOSIDE 0x1 437117f1b4Smrg#define LIGHT_MATERIAL 0x2 447117f1b4Smrg#define MAX_LIGHT_FUNC 0x4 457117f1b4Smrg 463464ebd5Sriastradhtypedef void (*light_func)( struct gl_context *ctx, 477117f1b4Smrg struct vertex_buffer *VB, 487117f1b4Smrg struct tnl_pipeline_stage *stage, 497117f1b4Smrg GLvector4f *input ); 507117f1b4Smrg 517117f1b4Smrg/** 527117f1b4Smrg * Information for updating current material attributes from vertex color, 537117f1b4Smrg * for GL_COLOR_MATERIAL. 547117f1b4Smrg */ 557117f1b4Smrgstruct material_cursor { 567117f1b4Smrg const GLfloat *ptr; /* points to src vertex color (in VB array) */ 577117f1b4Smrg GLuint stride; /* stride to next vertex color (bytes) */ 587117f1b4Smrg GLfloat *current; /* points to material attribute to update */ 597117f1b4Smrg GLuint size; /* vertex/color size: 1, 2, 3 or 4 */ 607117f1b4Smrg}; 617117f1b4Smrg 627117f1b4Smrg/** 637117f1b4Smrg * Data private to this pipeline stage. 647117f1b4Smrg */ 657117f1b4Smrgstruct light_stage_data { 667117f1b4Smrg GLvector4f Input; 677117f1b4Smrg GLvector4f LitColor[2]; 687117f1b4Smrg GLvector4f LitSecondary[2]; 697117f1b4Smrg light_func *light_func_tab; 707117f1b4Smrg 717117f1b4Smrg struct material_cursor mat[MAT_ATTRIB_MAX]; 727117f1b4Smrg GLuint mat_count; 737117f1b4Smrg GLuint mat_bitmask; 747117f1b4Smrg}; 757117f1b4Smrg 767117f1b4Smrg 777117f1b4Smrg#define LIGHT_STAGE_DATA(stage) ((struct light_stage_data *)(stage->privatePtr)) 787117f1b4Smrg 797117f1b4Smrg 807117f1b4Smrg 81af69d88dSmrg/**********************************************************************/ 82af69d88dSmrg/***** Lighting computation *****/ 83af69d88dSmrg/**********************************************************************/ 84af69d88dSmrg 85af69d88dSmrg 86af69d88dSmrg/* 87af69d88dSmrg * Notes: 88af69d88dSmrg * When two-sided lighting is enabled we compute the color (or index) 89af69d88dSmrg * for both the front and back side of the primitive. Then, when the 90af69d88dSmrg * orientation of the facet is later learned, we can determine which 91af69d88dSmrg * color (or index) to use for rendering. 92af69d88dSmrg * 93af69d88dSmrg * KW: We now know orientation in advance and only shade for 94af69d88dSmrg * the side or sides which are actually required. 95af69d88dSmrg * 96af69d88dSmrg * Variables: 97af69d88dSmrg * n = normal vector 98af69d88dSmrg * V = vertex position 99af69d88dSmrg * P = light source position 100af69d88dSmrg * Pe = (0,0,0,1) 101af69d88dSmrg * 102af69d88dSmrg * Precomputed: 103af69d88dSmrg * IF P[3]==0 THEN 104af69d88dSmrg * // light at infinity 105af69d88dSmrg * IF local_viewer THEN 106af69d88dSmrg * _VP_inf_norm = unit vector from V to P // Precompute 107af69d88dSmrg * ELSE 108af69d88dSmrg * // eye at infinity 109af69d88dSmrg * _h_inf_norm = Normalize( VP + <0,0,1> ) // Precompute 110af69d88dSmrg * ENDIF 111af69d88dSmrg * ENDIF 112af69d88dSmrg * 113af69d88dSmrg * Functions: 114af69d88dSmrg * Normalize( v ) = normalized vector v 115af69d88dSmrg * Magnitude( v ) = length of vector v 116af69d88dSmrg */ 117af69d88dSmrg 118af69d88dSmrg 119af69d88dSmrg 120af69d88dSmrgstatic void 121af69d88dSmrgvalidate_shine_table( struct gl_context *ctx, GLuint side, GLfloat shininess ) 122af69d88dSmrg{ 123af69d88dSmrg TNLcontext *tnl = TNL_CONTEXT(ctx); 124af69d88dSmrg struct tnl_shine_tab *list = tnl->_ShineTabList; 125af69d88dSmrg struct tnl_shine_tab *s; 126af69d88dSmrg 12701e04c3fSmrg assert(side < 2); 128af69d88dSmrg 129af69d88dSmrg foreach(s, list) 130af69d88dSmrg if ( s->shininess == shininess ) 131af69d88dSmrg break; 132af69d88dSmrg 133af69d88dSmrg if (s == list) { 134af69d88dSmrg GLint j; 135af69d88dSmrg GLfloat *m; 136af69d88dSmrg 137af69d88dSmrg foreach(s, list) 138af69d88dSmrg if (s->refcount == 0) 139af69d88dSmrg break; 140af69d88dSmrg 141af69d88dSmrg m = s->tab; 14201e04c3fSmrg m[0] = 0.0F; 14301e04c3fSmrg if (shininess == 0.0F) { 144af69d88dSmrg for (j = 1 ; j <= SHINE_TABLE_SIZE ; j++) 14501e04c3fSmrg m[j] = 1.0F; 146af69d88dSmrg } 147af69d88dSmrg else { 148af69d88dSmrg for (j = 1 ; j < SHINE_TABLE_SIZE ; j++) { 14901e04c3fSmrg GLfloat t, x = j / (GLfloat) (SHINE_TABLE_SIZE - 1); 15001e04c3fSmrg if (x < 0.005F) /* underflow check */ 15101e04c3fSmrg x = 0.005F; 15201e04c3fSmrg t = powf(x, shininess); 15301e04c3fSmrg if (t > 1e-20F) 15401e04c3fSmrg m[j] = t; 155af69d88dSmrg else 15601e04c3fSmrg m[j] = 0.0F; 157af69d88dSmrg } 15801e04c3fSmrg m[SHINE_TABLE_SIZE] = 1.0F; 159af69d88dSmrg } 160af69d88dSmrg 161af69d88dSmrg s->shininess = shininess; 162af69d88dSmrg } 163af69d88dSmrg 164af69d88dSmrg if (tnl->_ShineTable[side]) 165af69d88dSmrg tnl->_ShineTable[side]->refcount--; 166af69d88dSmrg 167af69d88dSmrg tnl->_ShineTable[side] = s; 168af69d88dSmrg move_to_tail( list, s ); 169af69d88dSmrg s->refcount++; 170af69d88dSmrg} 171af69d88dSmrg 172af69d88dSmrg 173af69d88dSmrgvoid 174af69d88dSmrg_tnl_validate_shine_tables( struct gl_context *ctx ) 175af69d88dSmrg{ 176af69d88dSmrg TNLcontext *tnl = TNL_CONTEXT(ctx); 177af69d88dSmrg GLfloat shininess; 1787ec681f3Smrg 179af69d88dSmrg shininess = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SHININESS][0]; 180af69d88dSmrg if (!tnl->_ShineTable[0] || tnl->_ShineTable[0]->shininess != shininess) 181af69d88dSmrg validate_shine_table( ctx, 0, shininess ); 182af69d88dSmrg 183af69d88dSmrg shininess = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_SHININESS][0]; 184af69d88dSmrg if (!tnl->_ShineTable[1] || tnl->_ShineTable[1]->shininess != shininess) 185af69d88dSmrg validate_shine_table( ctx, 1, shininess ); 186af69d88dSmrg} 187af69d88dSmrg 188af69d88dSmrg 1897117f1b4Smrg/** 1907117f1b4Smrg * In the case of colormaterial, the effected material attributes 1917117f1b4Smrg * should already have been bound to point to the incoming color data, 1927117f1b4Smrg * prior to running the pipeline. 1937117f1b4Smrg * This function copies the vertex's color to the material attributes 1947117f1b4Smrg * which are tracking glColor. 1957117f1b4Smrg * It's called per-vertex in the lighting loop. 1967117f1b4Smrg */ 1977117f1b4Smrgstatic void 1983464ebd5Sriastradhupdate_materials(struct gl_context *ctx, struct light_stage_data *store) 1997117f1b4Smrg{ 2007117f1b4Smrg GLuint i; 2017117f1b4Smrg 2027117f1b4Smrg for (i = 0 ; i < store->mat_count ; i++) { 2037117f1b4Smrg /* update the material */ 2047117f1b4Smrg COPY_CLEAN_4V(store->mat[i].current, store->mat[i].size, store->mat[i].ptr); 2057117f1b4Smrg /* increment src vertex color pointer */ 2067117f1b4Smrg STRIDE_F(store->mat[i].ptr, store->mat[i].stride); 2077117f1b4Smrg } 2087ec681f3Smrg 2097117f1b4Smrg /* recompute derived light/material values */ 2107117f1b4Smrg _mesa_update_material( ctx, store->mat_bitmask ); 2117117f1b4Smrg /* XXX we should only call this if we're tracking/changing the specular 2127117f1b4Smrg * exponent. 2137117f1b4Smrg */ 214af69d88dSmrg _tnl_validate_shine_tables( ctx ); 2157117f1b4Smrg} 2167117f1b4Smrg 2177117f1b4Smrg 2187117f1b4Smrg/** 2197117f1b4Smrg * Prepare things prior to running the lighting stage. 2207117f1b4Smrg * Return number of material attributes which will track vertex color. 2217117f1b4Smrg */ 2227117f1b4Smrgstatic GLuint 2233464ebd5Sriastradhprepare_materials(struct gl_context *ctx, 2247117f1b4Smrg struct vertex_buffer *VB, struct light_stage_data *store) 2257117f1b4Smrg{ 2267117f1b4Smrg GLuint i; 2277ec681f3Smrg 2287117f1b4Smrg store->mat_count = 0; 2297117f1b4Smrg store->mat_bitmask = 0; 2307117f1b4Smrg 231af69d88dSmrg /* Examine the _ColorMaterialBitmask to determine which materials 2327117f1b4Smrg * track vertex color. Override the material attribute's pointer 2337117f1b4Smrg * with the color pointer for each one. 2347117f1b4Smrg */ 2357117f1b4Smrg if (ctx->Light.ColorMaterialEnabled) { 23601e04c3fSmrg GLbitfield bitmask = ctx->Light._ColorMaterialBitmask; 23701e04c3fSmrg while (bitmask) { 23801e04c3fSmrg const int i = u_bit_scan(&bitmask); 23901e04c3fSmrg VB->AttribPtr[_TNL_ATTRIB_MAT_FRONT_AMBIENT + i] = 24001e04c3fSmrg VB->AttribPtr[_TNL_ATTRIB_COLOR0]; 24101e04c3fSmrg } 2427117f1b4Smrg } 2437117f1b4Smrg 2447117f1b4Smrg /* Now, for each material attribute that's tracking vertex color, save 2457117f1b4Smrg * some values (ptr, stride, size, current) that we'll need in 2467117f1b4Smrg * update_materials(), above, that'll actually copy the vertex color to 2477117f1b4Smrg * the material attribute(s). 2487117f1b4Smrg */ 2497117f1b4Smrg for (i = _TNL_FIRST_MAT; i <= _TNL_LAST_MAT; i++) { 2507117f1b4Smrg if (VB->AttribPtr[i]->stride) { 2517117f1b4Smrg const GLuint j = store->mat_count++; 2527117f1b4Smrg const GLuint attr = i - _TNL_ATTRIB_MAT_FRONT_AMBIENT; 2537117f1b4Smrg store->mat[j].ptr = VB->AttribPtr[i]->start; 2547117f1b4Smrg store->mat[j].stride = VB->AttribPtr[i]->stride; 2557117f1b4Smrg store->mat[j].size = VB->AttribPtr[i]->size; 2567117f1b4Smrg store->mat[j].current = ctx->Light.Material.Attrib[attr]; 2577117f1b4Smrg store->mat_bitmask |= (1<<attr); 2587117f1b4Smrg } 2597117f1b4Smrg } 2607117f1b4Smrg 2617117f1b4Smrg /* FIXME: Is this already done? 2627117f1b4Smrg */ 2637117f1b4Smrg _mesa_update_material( ctx, ~0 ); 264af69d88dSmrg 265af69d88dSmrg _tnl_validate_shine_tables( ctx ); 2667117f1b4Smrg 2677117f1b4Smrg return store->mat_count; 2687117f1b4Smrg} 2697117f1b4Smrg 270af69d88dSmrg/* 271af69d88dSmrg * Compute dp ^ SpecularExponent. 272af69d88dSmrg * Lerp between adjacent values in the f(x) lookup table, giving a 273af69d88dSmrg * continuous function, with adequate overall accuracy. (Though still 274af69d88dSmrg * pretty good compared to a straight lookup). 275af69d88dSmrg */ 276af69d88dSmrgstatic inline GLfloat 277af69d88dSmrglookup_shininess(const struct gl_context *ctx, GLuint face, GLfloat dp) 278af69d88dSmrg{ 279af69d88dSmrg TNLcontext *tnl = TNL_CONTEXT(ctx); 280af69d88dSmrg const struct tnl_shine_tab *tab = tnl->_ShineTable[face]; 281af69d88dSmrg float f = dp * (SHINE_TABLE_SIZE - 1); 282af69d88dSmrg int k = (int) f; 283af69d88dSmrg if (k < 0 /* gcc may cast an overflow float value to negative int value */ 284af69d88dSmrg || k > SHINE_TABLE_SIZE - 2) 285af69d88dSmrg return powf(dp, tab->shininess); 286af69d88dSmrg else 287af69d88dSmrg return tab->tab[k] + (f - k) * (tab->tab[k+1] - tab->tab[k]); 288af69d88dSmrg} 289af69d88dSmrg 2907117f1b4Smrg/* Tables for all the shading functions. 2917117f1b4Smrg */ 2927117f1b4Smrgstatic light_func _tnl_light_tab[MAX_LIGHT_FUNC]; 2937117f1b4Smrgstatic light_func _tnl_light_fast_tab[MAX_LIGHT_FUNC]; 2947117f1b4Smrgstatic light_func _tnl_light_fast_single_tab[MAX_LIGHT_FUNC]; 2957117f1b4Smrgstatic light_func _tnl_light_spec_tab[MAX_LIGHT_FUNC]; 2967117f1b4Smrg 2977117f1b4Smrg#define TAG(x) x 2987117f1b4Smrg#define IDX (0) 2997117f1b4Smrg#include "t_vb_lighttmp.h" 3007117f1b4Smrg 3017117f1b4Smrg#define TAG(x) x##_twoside 3027117f1b4Smrg#define IDX (LIGHT_TWOSIDE) 3037117f1b4Smrg#include "t_vb_lighttmp.h" 3047117f1b4Smrg 3057117f1b4Smrg#define TAG(x) x##_material 3067117f1b4Smrg#define IDX (LIGHT_MATERIAL) 3077117f1b4Smrg#include "t_vb_lighttmp.h" 3087117f1b4Smrg 3097117f1b4Smrg#define TAG(x) x##_twoside_material 3107117f1b4Smrg#define IDX (LIGHT_TWOSIDE|LIGHT_MATERIAL) 3117117f1b4Smrg#include "t_vb_lighttmp.h" 3127117f1b4Smrg 3137117f1b4Smrg 3147117f1b4Smrgstatic void init_lighting_tables( void ) 3157117f1b4Smrg{ 3167117f1b4Smrg static int done; 3177117f1b4Smrg 3187117f1b4Smrg if (!done) { 3197117f1b4Smrg init_light_tab(); 3207117f1b4Smrg init_light_tab_twoside(); 3217117f1b4Smrg init_light_tab_material(); 3227117f1b4Smrg init_light_tab_twoside_material(); 3237117f1b4Smrg done = 1; 3247117f1b4Smrg } 3257117f1b4Smrg} 3267117f1b4Smrg 3277117f1b4Smrg 3287ec681f3Smrgstatic GLboolean run_lighting( struct gl_context *ctx, 3297117f1b4Smrg struct tnl_pipeline_stage *stage ) 3307117f1b4Smrg{ 3317117f1b4Smrg struct light_stage_data *store = LIGHT_STAGE_DATA(stage); 3327117f1b4Smrg TNLcontext *tnl = TNL_CONTEXT(ctx); 3337117f1b4Smrg struct vertex_buffer *VB = &tnl->vb; 334cdc920a0Smrg GLvector4f *input = ctx->_NeedEyeCoords ? VB->EyePtr : VB->AttribPtr[_TNL_ATTRIB_POS]; 3357117f1b4Smrg GLuint idx; 3367117f1b4Smrg 3377117f1b4Smrg if (!ctx->Light.Enabled || ctx->VertexProgram._Current) 3387117f1b4Smrg return GL_TRUE; 3397117f1b4Smrg 3407117f1b4Smrg /* Make sure we can talk about position x,y and z: 3417117f1b4Smrg */ 342cdc920a0Smrg if (input->size <= 2 && input == VB->AttribPtr[_TNL_ATTRIB_POS]) { 3437117f1b4Smrg 3447117f1b4Smrg _math_trans_4f( store->Input.data, 345cdc920a0Smrg VB->AttribPtr[_TNL_ATTRIB_POS]->data, 346cdc920a0Smrg VB->AttribPtr[_TNL_ATTRIB_POS]->stride, 3477117f1b4Smrg GL_FLOAT, 348cdc920a0Smrg VB->AttribPtr[_TNL_ATTRIB_POS]->size, 3497117f1b4Smrg 0, 3507117f1b4Smrg VB->Count ); 3517117f1b4Smrg 3527117f1b4Smrg if (input->size <= 2) { 3537117f1b4Smrg /* Clean z. 3547117f1b4Smrg */ 3557117f1b4Smrg _mesa_vector4f_clean_elem(&store->Input, VB->Count, 2); 3567117f1b4Smrg } 3577ec681f3Smrg 3587117f1b4Smrg if (input->size <= 1) { 3597117f1b4Smrg /* Clean y. 3607117f1b4Smrg */ 3617117f1b4Smrg _mesa_vector4f_clean_elem(&store->Input, VB->Count, 1); 3627117f1b4Smrg } 3637117f1b4Smrg 3647117f1b4Smrg input = &store->Input; 3657117f1b4Smrg } 3667ec681f3Smrg 3677117f1b4Smrg idx = 0; 3687117f1b4Smrg 3697117f1b4Smrg if (prepare_materials( ctx, VB, store )) 3707117f1b4Smrg idx |= LIGHT_MATERIAL; 3717117f1b4Smrg 3727117f1b4Smrg if (ctx->Light.Model.TwoSide) 3737117f1b4Smrg idx |= LIGHT_TWOSIDE; 3747117f1b4Smrg 3757117f1b4Smrg /* The individual functions know about replaying side-effects 3767ec681f3Smrg * vs. full re-execution. 3777117f1b4Smrg */ 3787117f1b4Smrg store->light_func_tab[idx]( ctx, VB, stage, input ); 3797117f1b4Smrg 3807117f1b4Smrg return GL_TRUE; 3817117f1b4Smrg} 3827117f1b4Smrg 3837117f1b4Smrg 3847117f1b4Smrg/* Called in place of do_lighting when the light table may have changed. 3857117f1b4Smrg */ 3863464ebd5Sriastradhstatic void validate_lighting( struct gl_context *ctx, 3877117f1b4Smrg struct tnl_pipeline_stage *stage ) 3887117f1b4Smrg{ 3897117f1b4Smrg light_func *tab; 3907117f1b4Smrg 3917117f1b4Smrg if (!ctx->Light.Enabled || ctx->VertexProgram._Current) 3927117f1b4Smrg return; 3937117f1b4Smrg 394cdc920a0Smrg if (ctx->Light._NeedVertices) { 395cdc920a0Smrg if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) 396cdc920a0Smrg tab = _tnl_light_spec_tab; 397cdc920a0Smrg else 398cdc920a0Smrg tab = _tnl_light_tab; 399cdc920a0Smrg } 400cdc920a0Smrg else { 40101e04c3fSmrg /* Power of two means only a single active light. */ 4027ec681f3Smrg if (util_is_power_of_two_or_zero(ctx->Light._EnabledLights)) 403cdc920a0Smrg tab = _tnl_light_fast_single_tab; 404cdc920a0Smrg else 405cdc920a0Smrg tab = _tnl_light_fast_tab; 4067117f1b4Smrg } 4077117f1b4Smrg 4087117f1b4Smrg 4097117f1b4Smrg LIGHT_STAGE_DATA(stage)->light_func_tab = tab; 4107117f1b4Smrg 4117117f1b4Smrg /* This and the above should only be done on _NEW_LIGHT: 4127117f1b4Smrg */ 4137117f1b4Smrg TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx ); 4147117f1b4Smrg} 4157117f1b4Smrg 4167117f1b4Smrg 4177117f1b4Smrg 4187117f1b4Smrg/* Called the first time stage->run is called. In effect, don't 4197117f1b4Smrg * allocate data until the first time the stage is run. 4207117f1b4Smrg */ 4213464ebd5Sriastradhstatic GLboolean init_lighting( struct gl_context *ctx, 4227117f1b4Smrg struct tnl_pipeline_stage *stage ) 4237117f1b4Smrg{ 4247117f1b4Smrg TNLcontext *tnl = TNL_CONTEXT(ctx); 4257117f1b4Smrg struct light_stage_data *store; 4267117f1b4Smrg GLuint size = tnl->vb.Size; 4277117f1b4Smrg 428af69d88dSmrg stage->privatePtr = malloc(sizeof(*store)); 4297117f1b4Smrg store = LIGHT_STAGE_DATA(stage); 4307117f1b4Smrg if (!store) 4317117f1b4Smrg return GL_FALSE; 4327117f1b4Smrg 4337117f1b4Smrg /* Do onetime init. 4347117f1b4Smrg */ 4357117f1b4Smrg init_lighting_tables(); 4367117f1b4Smrg 4377117f1b4Smrg _mesa_vector4f_alloc( &store->Input, 0, size, 32 ); 4387117f1b4Smrg _mesa_vector4f_alloc( &store->LitColor[0], 0, size, 32 ); 4397117f1b4Smrg _mesa_vector4f_alloc( &store->LitColor[1], 0, size, 32 ); 4407117f1b4Smrg _mesa_vector4f_alloc( &store->LitSecondary[0], 0, size, 32 ); 4417117f1b4Smrg _mesa_vector4f_alloc( &store->LitSecondary[1], 0, size, 32 ); 4427117f1b4Smrg 4437117f1b4Smrg store->LitColor[0].size = 4; 4447117f1b4Smrg store->LitColor[1].size = 4; 4457117f1b4Smrg store->LitSecondary[0].size = 3; 4467117f1b4Smrg store->LitSecondary[1].size = 3; 4477117f1b4Smrg 4487117f1b4Smrg return GL_TRUE; 4497117f1b4Smrg} 4507117f1b4Smrg 4517117f1b4Smrg 4527117f1b4Smrg 4537117f1b4Smrg 4547117f1b4Smrgstatic void dtr( struct tnl_pipeline_stage *stage ) 4557117f1b4Smrg{ 4567117f1b4Smrg struct light_stage_data *store = LIGHT_STAGE_DATA(stage); 4577117f1b4Smrg 4587117f1b4Smrg if (store) { 4597117f1b4Smrg _mesa_vector4f_free( &store->Input ); 4607117f1b4Smrg _mesa_vector4f_free( &store->LitColor[0] ); 4617117f1b4Smrg _mesa_vector4f_free( &store->LitColor[1] ); 4627117f1b4Smrg _mesa_vector4f_free( &store->LitSecondary[0] ); 4637117f1b4Smrg _mesa_vector4f_free( &store->LitSecondary[1] ); 464af69d88dSmrg free( store ); 4657117f1b4Smrg stage->privatePtr = NULL; 4667117f1b4Smrg } 4677117f1b4Smrg} 4687117f1b4Smrg 4697117f1b4Smrgconst struct tnl_pipeline_stage _tnl_lighting_stage = 4707117f1b4Smrg{ 4717117f1b4Smrg "lighting", /* name */ 4727117f1b4Smrg NULL, /* private_data */ 4737117f1b4Smrg init_lighting, 4747117f1b4Smrg dtr, /* destroy */ 4757117f1b4Smrg validate_lighting, 4767117f1b4Smrg run_lighting 4777117f1b4Smrg}; 478