Subversion Repositories shark

Rev

Rev 56 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
56 pj 1
/* $Id: t_vb_light.c,v 1.1 2003-02-28 11:48:07 pj 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
 
27
 
28
 
29
#include "glheader.h"
30
#include "colormac.h"
31
#include "light.h"
32
#include "macros.h"
33
#include "imports.h"
34
#include "mmath.h"
35
#include "simple_list.h"
36
#include "mtypes.h"
37
 
38
#include "math/m_translate.h"
39
 
40
#include "t_context.h"
41
#include "t_pipeline.h"
42
 
43
#define LIGHT_FLAGS         0x1 /* must be first */
44
#define LIGHT_TWOSIDE       0x2
45
#define LIGHT_COLORMATERIAL 0x4
46
#define MAX_LIGHT_FUNC      0x8
47
 
48
typedef void (*light_func)( GLcontext *ctx,
49
                            struct vertex_buffer *VB,
50
                            struct gl_pipeline_stage *stage,
51
                            GLvector4f *input );
52
 
53
struct light_stage_data {
54
   struct gl_client_array FloatColor;
55
   struct gl_client_array LitColor[2];
56
   struct gl_client_array LitSecondary[2];
57
   GLvector1ui LitIndex[2];
58
   light_func *light_func_tab;
59
};
60
 
61
 
62
#define LIGHT_STAGE_DATA(stage) ((struct light_stage_data *)(stage->privatePtr))
63
 
64
 
65
static void import_color_material( GLcontext *ctx,
66
                                   struct gl_pipeline_stage *stage )
67
{
68
   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
69
   struct gl_client_array *to = &LIGHT_STAGE_DATA(stage)->FloatColor;
70
   struct gl_client_array *from = VB->ColorPtr[0];
71
   GLuint count = VB->Count;
72
 
73
   if (!to->Ptr) {
74
      to->Ptr = ALIGN_MALLOC( VB->Size * 4 * sizeof(GLfloat), 32 );
75
      to->Type = GL_FLOAT;
76
   }
77
 
78
   /* No need to transform the same value 3000 times.
79
    */
80
   if (!from->StrideB) {
81
      to->StrideB = 0;
82
      count = 1;
83
   }
84
   else
85
      to->StrideB = 4 * sizeof(GLfloat);
86
 
87
   _math_trans_4f( (GLfloat (*)[4]) to->Ptr,
88
                   from->Ptr,
89
                   from->StrideB,
90
                   from->Type,
91
                   from->Size,
92
                   0,
93
                   count);
94
 
95
   VB->ColorPtr[0] = to;
96
}
97
 
98
 
99
/* Tables for all the shading functions.
100
 */
101
static light_func _tnl_light_tab[MAX_LIGHT_FUNC];
102
static light_func _tnl_light_fast_tab[MAX_LIGHT_FUNC];
103
static light_func _tnl_light_fast_single_tab[MAX_LIGHT_FUNC];
104
static light_func _tnl_light_spec_tab[MAX_LIGHT_FUNC];
105
static light_func _tnl_light_ci_tab[MAX_LIGHT_FUNC];
106
 
107
#define TAG(x)           x
108
#define IDX              (0)
109
#include "t_vb_lighttmp.h"
110
 
111
#define TAG(x)           x##_tw
112
#define IDX              (LIGHT_TWOSIDE)
113
#include "t_vb_lighttmp.h"
114
 
115
#define TAG(x)           x##_fl
116
#define IDX              (LIGHT_FLAGS)
117
#include "t_vb_lighttmp.h"
118
 
119
#define TAG(x)           x##_tw_fl
120
#define IDX              (LIGHT_FLAGS|LIGHT_TWOSIDE)
121
#include "t_vb_lighttmp.h"
122
 
123
#define TAG(x)           x##_cm
124
#define IDX              (LIGHT_COLORMATERIAL)
125
#include "t_vb_lighttmp.h"
126
 
127
#define TAG(x)           x##_tw_cm
128
#define IDX              (LIGHT_TWOSIDE|LIGHT_COLORMATERIAL)
129
#include "t_vb_lighttmp.h"
130
 
131
#define TAG(x)           x##_fl_cm
132
#define IDX              (LIGHT_FLAGS|LIGHT_COLORMATERIAL)
133
#include "t_vb_lighttmp.h"
134
 
135
#define TAG(x)           x##_tw_fl_cm
136
#define IDX              (LIGHT_FLAGS|LIGHT_TWOSIDE|LIGHT_COLORMATERIAL)
137
#include "t_vb_lighttmp.h"
138
 
139
 
140
static void init_lighting( void )
141
{
142
   static int done;
143
 
144
   if (!done) {
145
      init_light_tab();
146
      init_light_tab_tw();
147
      init_light_tab_fl();
148
      init_light_tab_tw_fl();
149
      init_light_tab_cm();
150
      init_light_tab_tw_cm();
151
      init_light_tab_fl_cm();
152
      init_light_tab_tw_fl_cm();
153
      done = 1;
154
   }
155
}
156
 
157
 
158
static GLboolean run_lighting( GLcontext *ctx, struct gl_pipeline_stage *stage )
159
{
160
   struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
161
   TNLcontext *tnl = TNL_CONTEXT(ctx);
162
   struct vertex_buffer *VB = &tnl->vb;
163
   GLvector4f *input = ctx->_NeedEyeCoords ? VB->EyePtr : VB->ObjPtr;
164
   GLuint ind;
165
 
166
/*     _tnl_print_vert_flags( __FUNCTION__, stage->changed_inputs ); */
167
 
168
   /* Make sure we can talk about elements 0..2 in the vector we are
169
    * lighting.
170
    */
171
   if (stage->changed_inputs & (VERT_BIT_EYE|VERT_BIT_POS)) {
172
      if (input->size <= 2) {
173
         if (input->flags & VEC_NOT_WRITEABLE) {
174
            ASSERT(VB->importable_data & VERT_BIT_POS);
175
 
176
            VB->import_data( ctx, VERT_BIT_POS, VEC_NOT_WRITEABLE );
177
            input = ctx->_NeedEyeCoords ? VB->EyePtr : VB->ObjPtr;
178
 
179
            ASSERT((input->flags & VEC_NOT_WRITEABLE) == 0);
180
         }
181
 
182
         _mesa_vector4f_clean_elem(input, VB->Count, 2);
183
      }
184
   }
185
 
186
   if (VB->Flag)
187
      ind = LIGHT_FLAGS;
188
   else
189
      ind = 0;
190
 
191
   /* The individual functions know about replaying side-effects
192
    * vs. full re-execution.
193
    */
194
   store->light_func_tab[ind]( ctx, VB, stage, input );
195
 
196
   return GL_TRUE;
197
}
198
 
199
 
200
/* Called in place of do_lighting when the light table may have changed.
201
 */
202
static GLboolean run_validate_lighting( GLcontext *ctx,
203
                                        struct gl_pipeline_stage *stage )
204
{
205
   GLuint ind = 0;
206
   light_func *tab;
207
 
208
   if (ctx->Visual.rgbMode) {
209
      if (ctx->Light._NeedVertices) {
210
         if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
211
            tab = _tnl_light_spec_tab;
212
         else
213
            tab = _tnl_light_tab;
214
      }
215
      else {
216
         if (ctx->Light.EnabledList.next == ctx->Light.EnabledList.prev)
217
            tab = _tnl_light_fast_single_tab;
218
         else
219
            tab = _tnl_light_fast_tab;
220
      }
221
   }
222
   else
223
      tab = _tnl_light_ci_tab;
224
 
225
   if (ctx->Light.ColorMaterialEnabled)
226
      ind |= LIGHT_COLORMATERIAL;
227
 
228
   if (ctx->Light.Model.TwoSide)
229
      ind |= LIGHT_TWOSIDE;
230
 
231
   LIGHT_STAGE_DATA(stage)->light_func_tab = &tab[ind];
232
 
233
   /* This and the above should only be done on _NEW_LIGHT:
234
    */
235
   TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
236
 
237
   /* Now run the stage...
238
    */
239
   stage->run = run_lighting;
240
   return stage->run( ctx, stage );
241
}
242
 
243
static void alloc_4chan( struct gl_client_array *a, GLuint sz )
244
{
245
   a->Ptr = ALIGN_MALLOC( sz * sizeof(GLchan) * 4, 32 );
246
   a->Size = 4;
247
   a->Type = CHAN_TYPE;
248
   a->Stride = 0;
249
   a->StrideB = sizeof(GLchan) * 4;
250
   a->Enabled = 0;
251
   a->Flags = 0;
252
}
253
 
254
 
255
/* Called the first time stage->run is called.  In effect, don't
256
 * allocate data until the first time the stage is run.
257
 */
258
static GLboolean run_init_lighting( GLcontext *ctx,
259
                                    struct gl_pipeline_stage *stage )
260
{
261
   TNLcontext *tnl = TNL_CONTEXT(ctx);
262
   struct light_stage_data *store;
263
   GLuint size = tnl->vb.Size;
264
 
265
   stage->privatePtr = MALLOC(sizeof(*store));
266
   store = LIGHT_STAGE_DATA(stage);
267
   if (!store)
268
      return GL_FALSE;
269
 
270
   /* Do onetime init.
271
    */
272
   init_lighting();
273
 
274
   store->FloatColor.Ptr = 0;
275
 
276
   alloc_4chan( &store->LitColor[0], size );
277
   alloc_4chan( &store->LitColor[1], size );
278
   alloc_4chan( &store->LitSecondary[0], size );
279
   alloc_4chan( &store->LitSecondary[1], size );
280
 
281
   _mesa_vector1ui_alloc( &store->LitIndex[0], 0, size, 32 );
282
   _mesa_vector1ui_alloc( &store->LitIndex[1], 0, size, 32 );
283
 
284
   /* Now validate the stage derived data...
285
    */
286
   stage->run = run_validate_lighting;
287
   return stage->run( ctx, stage );
288
}
289
 
290
 
291
 
292
/*
293
 * Check if lighting is enabled.  If so, configure the pipeline stage's
294
 * type, inputs, and outputs.
295
 */
296
static void check_lighting( GLcontext *ctx, struct gl_pipeline_stage *stage )
297
{
298
   stage->active = ctx->Light.Enabled && !ctx->VertexProgram.Enabled;
299
   if (stage->active) {
300
      if (stage->privatePtr)
301
         stage->run = run_validate_lighting;
302
      stage->inputs = VERT_BIT_NORMAL|VERT_BIT_MATERIAL;
303
      if (ctx->Light._NeedVertices)
304
         stage->inputs |= VERT_BIT_EYE; /* effectively, even when lighting in obj */
305
      if (ctx->Light.ColorMaterialEnabled)
306
         stage->inputs |= VERT_BIT_COLOR0;
307
 
308
      stage->outputs = VERT_BIT_COLOR0;
309
      if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
310
         stage->outputs |= VERT_BIT_COLOR1;
311
   }
312
}
313
 
314
 
315
static void dtr( struct gl_pipeline_stage *stage )
316
{
317
   struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
318
 
319
   if (store) {
320
      ALIGN_FREE( store->LitColor[0].Ptr );
321
      ALIGN_FREE( store->LitColor[1].Ptr );
322
      ALIGN_FREE( store->LitSecondary[0].Ptr );
323
      ALIGN_FREE( store->LitSecondary[1].Ptr );
324
 
325
      if (store->FloatColor.Ptr)
326
         ALIGN_FREE( store->FloatColor.Ptr );
327
 
328
      _mesa_vector1ui_free( &store->LitIndex[0] );
329
      _mesa_vector1ui_free( &store->LitIndex[1] );
330
      FREE( store );
331
      stage->privatePtr = 0;
332
   }
333
}
334
 
335
const struct gl_pipeline_stage _tnl_lighting_stage =
336
{
337
   "lighting",                  /* name */
338
   _NEW_LIGHT,                  /* recheck */
339
   _NEW_LIGHT|_NEW_MODELVIEW,   /* recalc -- modelview dependency
340
                                 * otherwise not captured by inputs
341
                                 * (which may be VERT_BIT_POS) */
342
   GL_FALSE,                    /* active? */
343
   0,                           /* inputs */
344
   0,                           /* outputs */
345
   0,                           /* changed_inputs */
346
   NULL,                        /* private_data */
347
   dtr,                         /* destroy */
348
   check_lighting,              /* check */
349
   run_init_lighting            /* run -- initially set to ctr */
350
};