t_vb_light.c revision b980b2eeb62dc48101a7481d02d196c80b9da397
1/* $Id: t_vb_light.c,v 1.3 2001/01/08 04:09:42 keithw Exp $ */ 2 3/* 4 * Mesa 3-D graphics library 5 * Version: 3.5 6 * 7 * Copyright (C) 1999-2000 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 27 28 29#include "glheader.h" 30#include "colormac.h" 31#include "light.h" 32#include "macros.h" 33#include "mem.h" 34#include "mmath.h" 35#include "simple_list.h" 36#include "mtypes.h" 37 38#include "t_context.h" 39#include "t_pipeline.h" 40 41#define LIGHT_FLAGS 0x1 /* must be first */ 42#define LIGHT_TWOSIDE 0x2 43#define LIGHT_COLORMATERIAL 0x4 44#define MAX_LIGHT_FUNC 0x8 45 46typedef void (*light_func)( GLcontext *ctx, 47 struct vertex_buffer *VB, 48 struct gl_pipeline_stage *stage, 49 GLvector4f *input ); 50 51struct light_stage_data { 52 GLvector4ub LitColor[2]; 53 GLvector1ui LitIndex[2]; 54 GLvector4ub LitSecondary[2]; 55 56 light_func *light_func_tab; 57}; 58 59#define LIGHT_STAGE_DATA(stage) ((struct light_stage_data *)(stage->private)) 60 61/* Tables for all the shading functions. 62 */ 63static light_func _tnl_light_tab[MAX_LIGHT_FUNC]; 64static light_func _tnl_light_fast_tab[MAX_LIGHT_FUNC]; 65static light_func _tnl_light_fast_single_tab[MAX_LIGHT_FUNC]; 66static light_func _tnl_light_spec_tab[MAX_LIGHT_FUNC]; 67static light_func _tnl_light_ci_tab[MAX_LIGHT_FUNC]; 68 69#define TAG(x) x 70#define IDX (0) 71#include "t_vb_lighttmp.h" 72 73#define TAG(x) x##_tw 74#define IDX (LIGHT_TWOSIDE) 75#include "t_vb_lighttmp.h" 76 77#define TAG(x) x##_fl 78#define IDX (LIGHT_FLAGS) 79#include "t_vb_lighttmp.h" 80 81#define TAG(x) x##_tw_fl 82#define IDX (LIGHT_FLAGS|LIGHT_TWOSIDE) 83#include "t_vb_lighttmp.h" 84 85#define TAG(x) x##_cm 86#define IDX (LIGHT_COLORMATERIAL) 87#include "t_vb_lighttmp.h" 88 89#define TAG(x) x##_tw_cm 90#define IDX (LIGHT_TWOSIDE|LIGHT_COLORMATERIAL) 91#include "t_vb_lighttmp.h" 92 93#define TAG(x) x##_fl_cm 94#define IDX (LIGHT_FLAGS|LIGHT_COLORMATERIAL) 95#include "t_vb_lighttmp.h" 96 97#define TAG(x) x##_tw_fl_cm 98#define IDX (LIGHT_FLAGS|LIGHT_TWOSIDE|LIGHT_COLORMATERIAL) 99#include "t_vb_lighttmp.h" 100 101 102static void init_lighting( void ) 103{ 104 static int done; 105 106 if (!done) { 107 init_light_tab(); 108 init_light_tab_tw(); 109 init_light_tab_fl(); 110 init_light_tab_tw_fl(); 111 init_light_tab_cm(); 112 init_light_tab_tw_cm(); 113 init_light_tab_fl_cm(); 114 init_light_tab_tw_fl_cm(); 115 done = 1; 116 } 117} 118 119 120static GLboolean run_lighting( GLcontext *ctx, struct gl_pipeline_stage *stage ) 121{ 122 struct light_stage_data *store = LIGHT_STAGE_DATA(stage); 123 TNLcontext *tnl = TNL_CONTEXT(ctx); 124 struct vertex_buffer *VB = &tnl->vb; 125 GLvector4f *input = ctx->_NeedEyeCoords ? VB->EyePtr : VB->ObjPtr; 126 GLuint ind; 127 128 /* Make sure we can talk about elements 0..2 in the vector we are 129 * lighting. TODO: Don't repeat this in CVA! 130 */ 131 if (input->size <= 2) { 132 if (input->flags & VEC_NOT_WRITEABLE) { 133 ASSERT(VB->importable_data & VERT_OBJ); 134 VB->import_data( ctx, VERT_OBJ, VEC_NOT_WRITEABLE ); 135 input = ctx->_NeedEyeCoords ? VB->EyePtr : VB->ObjPtr; 136 ASSERT((input->flags & VEC_NOT_WRITEABLE) == 0); 137 } 138 139 gl_vector4f_clean_elem(input, VB->Count, 2); 140 } 141 142 if (VB->Flag) 143 ind = LIGHT_FLAGS; 144 else 145 ind = 0; 146 147 /* The individual tabs know about replaying side-effects vs. full 148 * re-execution. 149 */ 150 store->light_func_tab[ind]( ctx, VB, stage, input ); 151 152 return GL_TRUE; 153} 154 155 156/* Called in place of do_lighting when the light table may have changed. 157 */ 158static GLboolean run_validate_lighting( GLcontext *ctx, 159 struct gl_pipeline_stage *stage ) 160{ 161 GLuint ind = 0; 162 light_func *tab; 163 164 if (ctx->Visual.RGBAflag) { 165 if (ctx->Light._NeedVertices) { 166 if (ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR) 167 tab = _tnl_light_spec_tab; 168 else 169 tab = _tnl_light_tab; 170 } 171 else { 172 if (ctx->Light.EnabledList.next == ctx->Light.EnabledList.prev) 173 tab = _tnl_light_fast_single_tab; 174 else 175 tab = _tnl_light_fast_tab; 176 } 177/* tab = _tnl_light_tab; */ 178 } 179 else 180 tab = _tnl_light_ci_tab; 181 182 if (ctx->Light.ColorMaterialEnabled) 183 ind |= LIGHT_COLORMATERIAL; 184 185 if (ctx->Light.Model.TwoSide) 186 ind |= LIGHT_TWOSIDE; 187 188 LIGHT_STAGE_DATA(stage)->light_func_tab = &tab[ind]; 189 190 /* This and the above should only be done on _NEW_LIGHT: 191 */ 192 gl_validate_all_lighting_tables( ctx ); 193 194 /* Now run the stage... 195 */ 196 stage->run = run_lighting; 197 return stage->run( ctx, stage ); 198} 199 200/* Called the first time stage->run is called. In effect, don't 201 * allocate data until the first time the stage is run. 202 */ 203static GLboolean run_init_lighting( GLcontext *ctx, 204 struct gl_pipeline_stage *stage ) 205{ 206 TNLcontext *tnl = TNL_CONTEXT(ctx); 207 struct light_stage_data *store; 208 GLuint size = tnl->vb.Size; 209 210 stage->private = MALLOC(sizeof(*store)); 211 store = LIGHT_STAGE_DATA(stage); 212 if (!store) 213 return GL_FALSE; 214 215 /* Do onetime init. 216 */ 217 init_lighting(); 218 219 gl_vector4ub_alloc( &store->LitColor[0], 0, size, 32 ); 220 gl_vector4ub_alloc( &store->LitColor[1], 0, size, 32 ); 221 gl_vector4ub_alloc( &store->LitSecondary[0], 0, size, 32 ); 222 gl_vector4ub_alloc( &store->LitSecondary[1], 0, size, 32 ); 223 gl_vector1ui_alloc( &store->LitIndex[0], 0, size, 32 ); 224 gl_vector1ui_alloc( &store->LitIndex[1], 0, size, 32 ); 225 226 /* Now validate the stage derived data... 227 */ 228 stage->run = run_validate_lighting; 229 return stage->run( ctx, stage ); 230} 231 232 233 234/* 235 * Check if lighting is enabled. If so, configure the pipeline stage's 236 * type, inputs, and outputs. 237 */ 238static void check_lighting( GLcontext *ctx, struct gl_pipeline_stage *stage ) 239{ 240 stage->active = ctx->Light.Enabled; 241 if (stage->active) { 242 if (stage->private) 243 stage->run = run_validate_lighting; 244 stage->inputs = VERT_NORM|VERT_MATERIAL; 245 if (ctx->Light._NeedVertices) 246 stage->inputs |= VERT_EYE; /* effectively, even when lighting in obj */ 247 if (ctx->Light.ColorMaterialEnabled) 248 stage->inputs |= VERT_RGBA; 249 250 stage->outputs = VERT_RGBA; 251 if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) 252 stage->outputs |= VERT_SPEC_RGB; 253 } 254} 255 256 257static void dtr( struct gl_pipeline_stage *stage ) 258{ 259 struct light_stage_data *store = LIGHT_STAGE_DATA(stage); 260 261 if (store) { 262 gl_vector4ub_free( &store->LitColor[0] ); 263 gl_vector4ub_free( &store->LitColor[1] ); 264 gl_vector1ui_free( &store->LitIndex[0] ); 265 gl_vector1ui_free( &store->LitIndex[1] ); 266 gl_vector4ub_free( &store->LitSecondary[0] ); 267 gl_vector4ub_free( &store->LitSecondary[1] ); 268 FREE( store ); 269 stage->private = 0; 270 } 271} 272 273const struct gl_pipeline_stage _tnl_lighting_stage = 274{ 275 "lighting", 276 _NEW_LIGHT, /* recheck */ 277 _NEW_LIGHT|_NEW_MODELVIEW, /* recalc -- modelview dependency 278 * otherwise not captured by inputs 279 * (which may be VERT_OBJ) */ 280 0,0,0, /* active, inputs, outputs */ 281 0,0, /* changed_inputs, private_data */ 282 dtr, /* destroy */ 283 check_lighting, /* check */ 284 run_init_lighting /* run -- initially set to ctr */ 285}; 286 287