Added most of the infrastructure required to support
[mesa.git] / src / mesa / main / light.c
1
2 /*
3 * Mesa 3-D graphics library
4 * Version: 5.1
5 *
6 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26
27 #include "glheader.h"
28 #include "imports.h"
29 #include "colormac.h"
30 #include "context.h"
31 #include "enums.h"
32 #include "light.h"
33 #include "macros.h"
34 #include "simple_list.h"
35 #include "mtypes.h"
36 #include "math/m_xform.h"
37 #include "math/m_matrix.h"
38
39
40 /* XXX this is a bit of a hack needed for compilation within XFree86 */
41 #ifndef FLT_MIN
42 #define FLT_MIN 1e-37
43 #endif
44
45
46 void
47 _mesa_ShadeModel( GLenum mode )
48 {
49 GET_CURRENT_CONTEXT(ctx);
50 ASSERT_OUTSIDE_BEGIN_END(ctx);
51
52 if (MESA_VERBOSE & VERBOSE_API)
53 _mesa_debug(ctx, "glShadeModel %s\n", _mesa_lookup_enum_by_nr(mode));
54
55 if (mode != GL_FLAT && mode != GL_SMOOTH) {
56 _mesa_error( ctx, GL_INVALID_ENUM, "glShadeModel" );
57 return;
58 }
59
60 if (ctx->Light.ShadeModel == mode)
61 return;
62
63 FLUSH_VERTICES(ctx, _NEW_LIGHT);
64 ctx->Light.ShadeModel = mode;
65 ctx->_TriangleCaps ^= DD_FLATSHADE;
66 if (ctx->Driver.ShadeModel)
67 (*ctx->Driver.ShadeModel)( ctx, mode );
68 }
69
70
71
72 void
73 _mesa_Lightf( GLenum light, GLenum pname, GLfloat param )
74 {
75 _mesa_Lightfv( light, pname, &param );
76 }
77
78
79 void
80 _mesa_Lightfv( GLenum light, GLenum pname, const GLfloat *params )
81 {
82 GET_CURRENT_CONTEXT(ctx);
83 GLint i = (GLint) (light - GL_LIGHT0);
84 struct gl_light *l = &ctx->Light.Light[i];
85
86 if (i < 0 || i >= (GLint) ctx->Const.MaxLights) {
87 _mesa_error( ctx, GL_INVALID_ENUM, "glLight(light=0x%x)", light );
88 return;
89 }
90
91 switch (pname) {
92 case GL_AMBIENT:
93 if (TEST_EQ_4V(l->Ambient, params))
94 return;
95 FLUSH_VERTICES(ctx, _NEW_LIGHT);
96 COPY_4V( l->Ambient, params );
97 break;
98 case GL_DIFFUSE:
99 if (TEST_EQ_4V(l->Diffuse, params))
100 return;
101 FLUSH_VERTICES(ctx, _NEW_LIGHT);
102 COPY_4V( l->Diffuse, params );
103 break;
104 case GL_SPECULAR:
105 if (TEST_EQ_4V(l->Specular, params))
106 return;
107 FLUSH_VERTICES(ctx, _NEW_LIGHT);
108 COPY_4V( l->Specular, params );
109 break;
110 case GL_POSITION: {
111 GLfloat tmp[4];
112 /* transform position by ModelView matrix */
113 TRANSFORM_POINT( tmp, ctx->ModelviewMatrixStack.Top->m, params );
114 if (TEST_EQ_4V(l->EyePosition, tmp))
115 return;
116 FLUSH_VERTICES(ctx, _NEW_LIGHT);
117 COPY_4V(l->EyePosition, tmp);
118 if (l->EyePosition[3] != 0.0F)
119 l->_Flags |= LIGHT_POSITIONAL;
120 else
121 l->_Flags &= ~LIGHT_POSITIONAL;
122 break;
123 }
124 case GL_SPOT_DIRECTION: {
125 GLfloat tmp[4];
126 /* transform direction by inverse modelview */
127 if (ctx->ModelviewMatrixStack.Top->flags & MAT_DIRTY_INVERSE) {
128 _math_matrix_analyse( ctx->ModelviewMatrixStack.Top );
129 }
130 TRANSFORM_NORMAL( tmp, params, ctx->ModelviewMatrixStack.Top->inv );
131 if (TEST_EQ_3V(l->EyeDirection, tmp))
132 return;
133 FLUSH_VERTICES(ctx, _NEW_LIGHT);
134 COPY_3V(l->EyeDirection, tmp);
135 break;
136 }
137 case GL_SPOT_EXPONENT:
138 if (params[0]<0.0 || params[0]>ctx->Const.MaxSpotExponent) {
139 _mesa_error( ctx, GL_INVALID_VALUE, "glLight" );
140 return;
141 }
142 if (l->SpotExponent == params[0])
143 return;
144 FLUSH_VERTICES(ctx, _NEW_LIGHT);
145 l->SpotExponent = params[0];
146 _mesa_invalidate_spot_exp_table( l );
147 break;
148 case GL_SPOT_CUTOFF:
149 if ((params[0]<0.0 || params[0]>90.0) && params[0]!=180.0) {
150 _mesa_error( ctx, GL_INVALID_VALUE, "glLight" );
151 return;
152 }
153 if (l->SpotCutoff == params[0])
154 return;
155 FLUSH_VERTICES(ctx, _NEW_LIGHT);
156 l->SpotCutoff = params[0];
157 l->_CosCutoff = (GLfloat) _mesa_cos(params[0]*DEG2RAD);
158 if (l->_CosCutoff < 0)
159 l->_CosCutoff = 0;
160 if (l->SpotCutoff != 180.0F)
161 l->_Flags |= LIGHT_SPOT;
162 else
163 l->_Flags &= ~LIGHT_SPOT;
164 break;
165 case GL_CONSTANT_ATTENUATION:
166 if (params[0]<0.0) {
167 _mesa_error( ctx, GL_INVALID_VALUE, "glLight" );
168 return;
169 }
170 if (l->ConstantAttenuation == params[0])
171 return;
172 FLUSH_VERTICES(ctx, _NEW_LIGHT);
173 l->ConstantAttenuation = params[0];
174 break;
175 case GL_LINEAR_ATTENUATION:
176 if (params[0]<0.0) {
177 _mesa_error( ctx, GL_INVALID_VALUE, "glLight" );
178 return;
179 }
180 if (l->LinearAttenuation == params[0])
181 return;
182 FLUSH_VERTICES(ctx, _NEW_LIGHT);
183 l->LinearAttenuation = params[0];
184 break;
185 case GL_QUADRATIC_ATTENUATION:
186 if (params[0]<0.0) {
187 _mesa_error( ctx, GL_INVALID_VALUE, "glLight" );
188 return;
189 }
190 if (l->QuadraticAttenuation == params[0])
191 return;
192 FLUSH_VERTICES(ctx, _NEW_LIGHT);
193 l->QuadraticAttenuation = params[0];
194 break;
195 default:
196 _mesa_error( ctx, GL_INVALID_ENUM, "glLight(pname=0x%x)", pname );
197 return;
198 }
199
200 if (ctx->Driver.Lightfv)
201 ctx->Driver.Lightfv( ctx, light, pname, params );
202 }
203
204
205 void
206 _mesa_Lighti( GLenum light, GLenum pname, GLint param )
207 {
208 _mesa_Lightiv( light, pname, &param );
209 }
210
211
212 void
213 _mesa_Lightiv( GLenum light, GLenum pname, const GLint *params )
214 {
215 GLfloat fparam[4];
216
217 switch (pname) {
218 case GL_AMBIENT:
219 case GL_DIFFUSE:
220 case GL_SPECULAR:
221 fparam[0] = INT_TO_FLOAT( params[0] );
222 fparam[1] = INT_TO_FLOAT( params[1] );
223 fparam[2] = INT_TO_FLOAT( params[2] );
224 fparam[3] = INT_TO_FLOAT( params[3] );
225 break;
226 case GL_POSITION:
227 fparam[0] = (GLfloat) params[0];
228 fparam[1] = (GLfloat) params[1];
229 fparam[2] = (GLfloat) params[2];
230 fparam[3] = (GLfloat) params[3];
231 break;
232 case GL_SPOT_DIRECTION:
233 fparam[0] = (GLfloat) params[0];
234 fparam[1] = (GLfloat) params[1];
235 fparam[2] = (GLfloat) params[2];
236 break;
237 case GL_SPOT_EXPONENT:
238 case GL_SPOT_CUTOFF:
239 case GL_CONSTANT_ATTENUATION:
240 case GL_LINEAR_ATTENUATION:
241 case GL_QUADRATIC_ATTENUATION:
242 fparam[0] = (GLfloat) params[0];
243 break;
244 default:
245 /* error will be caught later in gl_Lightfv */
246 ;
247 }
248
249 _mesa_Lightfv( light, pname, fparam );
250 }
251
252
253
254 void
255 _mesa_GetLightfv( GLenum light, GLenum pname, GLfloat *params )
256 {
257 GET_CURRENT_CONTEXT(ctx);
258 GLint l = (GLint) (light - GL_LIGHT0);
259 ASSERT_OUTSIDE_BEGIN_END(ctx);
260
261 if (l < 0 || l >= (GLint) ctx->Const.MaxLights) {
262 _mesa_error( ctx, GL_INVALID_ENUM, "glGetLightfv" );
263 return;
264 }
265
266 switch (pname) {
267 case GL_AMBIENT:
268 COPY_4V( params, ctx->Light.Light[l].Ambient );
269 break;
270 case GL_DIFFUSE:
271 COPY_4V( params, ctx->Light.Light[l].Diffuse );
272 break;
273 case GL_SPECULAR:
274 COPY_4V( params, ctx->Light.Light[l].Specular );
275 break;
276 case GL_POSITION:
277 COPY_4V( params, ctx->Light.Light[l].EyePosition );
278 break;
279 case GL_SPOT_DIRECTION:
280 COPY_3V( params, ctx->Light.Light[l].EyeDirection );
281 break;
282 case GL_SPOT_EXPONENT:
283 params[0] = ctx->Light.Light[l].SpotExponent;
284 break;
285 case GL_SPOT_CUTOFF:
286 params[0] = ctx->Light.Light[l].SpotCutoff;
287 break;
288 case GL_CONSTANT_ATTENUATION:
289 params[0] = ctx->Light.Light[l].ConstantAttenuation;
290 break;
291 case GL_LINEAR_ATTENUATION:
292 params[0] = ctx->Light.Light[l].LinearAttenuation;
293 break;
294 case GL_QUADRATIC_ATTENUATION:
295 params[0] = ctx->Light.Light[l].QuadraticAttenuation;
296 break;
297 default:
298 _mesa_error( ctx, GL_INVALID_ENUM, "glGetLightfv" );
299 break;
300 }
301 }
302
303
304
305 void
306 _mesa_GetLightiv( GLenum light, GLenum pname, GLint *params )
307 {
308 GET_CURRENT_CONTEXT(ctx);
309 GLint l = (GLint) (light - GL_LIGHT0);
310 ASSERT_OUTSIDE_BEGIN_END(ctx);
311
312 if (l < 0 || l >= (GLint) ctx->Const.MaxLights) {
313 _mesa_error( ctx, GL_INVALID_ENUM, "glGetLightiv" );
314 return;
315 }
316
317 switch (pname) {
318 case GL_AMBIENT:
319 params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[0]);
320 params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[1]);
321 params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[2]);
322 params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[3]);
323 break;
324 case GL_DIFFUSE:
325 params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[0]);
326 params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[1]);
327 params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[2]);
328 params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[3]);
329 break;
330 case GL_SPECULAR:
331 params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[0]);
332 params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[1]);
333 params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[2]);
334 params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[3]);
335 break;
336 case GL_POSITION:
337 params[0] = (GLint) ctx->Light.Light[l].EyePosition[0];
338 params[1] = (GLint) ctx->Light.Light[l].EyePosition[1];
339 params[2] = (GLint) ctx->Light.Light[l].EyePosition[2];
340 params[3] = (GLint) ctx->Light.Light[l].EyePosition[3];
341 break;
342 case GL_SPOT_DIRECTION:
343 params[0] = (GLint) ctx->Light.Light[l].EyeDirection[0];
344 params[1] = (GLint) ctx->Light.Light[l].EyeDirection[1];
345 params[2] = (GLint) ctx->Light.Light[l].EyeDirection[2];
346 break;
347 case GL_SPOT_EXPONENT:
348 params[0] = (GLint) ctx->Light.Light[l].SpotExponent;
349 break;
350 case GL_SPOT_CUTOFF:
351 params[0] = (GLint) ctx->Light.Light[l].SpotCutoff;
352 break;
353 case GL_CONSTANT_ATTENUATION:
354 params[0] = (GLint) ctx->Light.Light[l].ConstantAttenuation;
355 break;
356 case GL_LINEAR_ATTENUATION:
357 params[0] = (GLint) ctx->Light.Light[l].LinearAttenuation;
358 break;
359 case GL_QUADRATIC_ATTENUATION:
360 params[0] = (GLint) ctx->Light.Light[l].QuadraticAttenuation;
361 break;
362 default:
363 _mesa_error( ctx, GL_INVALID_ENUM, "glGetLightiv" );
364 break;
365 }
366 }
367
368
369
370 /**********************************************************************/
371 /*** Light Model ***/
372 /**********************************************************************/
373
374
375 void
376 _mesa_LightModelfv( GLenum pname, const GLfloat *params )
377 {
378 GLenum newenum;
379 GLboolean newbool;
380 GET_CURRENT_CONTEXT(ctx);
381 ASSERT_OUTSIDE_BEGIN_END(ctx);
382
383 switch (pname) {
384 case GL_LIGHT_MODEL_AMBIENT:
385 if (TEST_EQ_4V( ctx->Light.Model.Ambient, params ))
386 return;
387 FLUSH_VERTICES(ctx, _NEW_LIGHT);
388 COPY_4V( ctx->Light.Model.Ambient, params );
389 break;
390 case GL_LIGHT_MODEL_LOCAL_VIEWER:
391 newbool = (params[0]!=0.0);
392 if (ctx->Light.Model.LocalViewer == newbool)
393 return;
394 FLUSH_VERTICES(ctx, _NEW_LIGHT);
395 ctx->Light.Model.LocalViewer = newbool;
396 break;
397 case GL_LIGHT_MODEL_TWO_SIDE:
398 newbool = (params[0]!=0.0);
399 if (ctx->Light.Model.TwoSide == newbool)
400 return;
401 FLUSH_VERTICES(ctx, _NEW_LIGHT);
402 ctx->Light.Model.TwoSide = newbool;
403
404 if (ctx->Light.Enabled && ctx->Light.Model.TwoSide)
405 ctx->_TriangleCaps |= DD_TRI_LIGHT_TWOSIDE;
406 else
407 ctx->_TriangleCaps &= ~DD_TRI_LIGHT_TWOSIDE;
408 break;
409 case GL_LIGHT_MODEL_COLOR_CONTROL:
410 if (params[0] == (GLfloat) GL_SINGLE_COLOR)
411 newenum = GL_SINGLE_COLOR;
412 else if (params[0] == (GLfloat) GL_SEPARATE_SPECULAR_COLOR)
413 newenum = GL_SEPARATE_SPECULAR_COLOR;
414 else {
415 _mesa_error( ctx, GL_INVALID_ENUM, "glLightModel(param=0x0%x)",
416 (GLint) params[0] );
417 return;
418 }
419 if (ctx->Light.Model.ColorControl == newenum)
420 return;
421 FLUSH_VERTICES(ctx, _NEW_LIGHT);
422 ctx->Light.Model.ColorControl = newenum;
423
424 if ((ctx->Light.Enabled &&
425 ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR)
426 || ctx->Fog.ColorSumEnabled)
427 ctx->_TriangleCaps |= DD_SEPARATE_SPECULAR;
428 else
429 ctx->_TriangleCaps &= ~DD_SEPARATE_SPECULAR;
430
431 break;
432 default:
433 _mesa_error( ctx, GL_INVALID_ENUM, "glLightModel(pname=0x%x)", pname );
434 break;
435 }
436
437 if (ctx->Driver.LightModelfv)
438 ctx->Driver.LightModelfv( ctx, pname, params );
439 }
440
441
442 void
443 _mesa_LightModeliv( GLenum pname, const GLint *params )
444 {
445 GLfloat fparam[4];
446
447 switch (pname) {
448 case GL_LIGHT_MODEL_AMBIENT:
449 fparam[0] = INT_TO_FLOAT( params[0] );
450 fparam[1] = INT_TO_FLOAT( params[1] );
451 fparam[2] = INT_TO_FLOAT( params[2] );
452 fparam[3] = INT_TO_FLOAT( params[3] );
453 break;
454 case GL_LIGHT_MODEL_LOCAL_VIEWER:
455 case GL_LIGHT_MODEL_TWO_SIDE:
456 case GL_LIGHT_MODEL_COLOR_CONTROL:
457 fparam[0] = (GLfloat) params[0];
458 break;
459 default:
460 /* Error will be caught later in gl_LightModelfv */
461 ;
462 }
463 _mesa_LightModelfv( pname, fparam );
464 }
465
466
467 void
468 _mesa_LightModeli( GLenum pname, GLint param )
469 {
470 _mesa_LightModeliv( pname, &param );
471 }
472
473
474 void
475 _mesa_LightModelf( GLenum pname, GLfloat param )
476 {
477 _mesa_LightModelfv( pname, &param );
478 }
479
480
481
482 /********** MATERIAL **********/
483
484
485 /*
486 * Given a face and pname value (ala glColorMaterial), compute a bitmask
487 * of the targeted material values.
488 */
489 GLuint
490 _mesa_material_bitmask( GLcontext *ctx, GLenum face, GLenum pname,
491 GLuint legal, const char *where )
492 {
493 GLuint bitmask = 0;
494
495 /* Make a bitmask indicating what material attribute(s) we're updating */
496 switch (pname) {
497 case GL_EMISSION:
498 bitmask |= MAT_BIT_FRONT_EMISSION | MAT_BIT_BACK_EMISSION;
499 break;
500 case GL_AMBIENT:
501 bitmask |= MAT_BIT_FRONT_AMBIENT | MAT_BIT_BACK_AMBIENT;
502 break;
503 case GL_DIFFUSE:
504 bitmask |= MAT_BIT_FRONT_DIFFUSE | MAT_BIT_BACK_DIFFUSE;
505 break;
506 case GL_SPECULAR:
507 bitmask |= MAT_BIT_FRONT_SPECULAR | MAT_BIT_BACK_SPECULAR;
508 break;
509 case GL_SHININESS:
510 bitmask |= MAT_BIT_FRONT_SHININESS | MAT_BIT_BACK_SHININESS;
511 break;
512 case GL_AMBIENT_AND_DIFFUSE:
513 bitmask |= MAT_BIT_FRONT_AMBIENT | MAT_BIT_BACK_AMBIENT;
514 bitmask |= MAT_BIT_FRONT_DIFFUSE | MAT_BIT_BACK_DIFFUSE;
515 break;
516 case GL_COLOR_INDEXES:
517 bitmask |= MAT_BIT_FRONT_INDEXES | MAT_BIT_BACK_INDEXES;
518 break;
519 default:
520 _mesa_error( ctx, GL_INVALID_ENUM, where );
521 return 0;
522 }
523
524 if (face==GL_FRONT) {
525 bitmask &= FRONT_MATERIAL_BITS;
526 }
527 else if (face==GL_BACK) {
528 bitmask &= BACK_MATERIAL_BITS;
529 }
530 else if (face != GL_FRONT_AND_BACK) {
531 _mesa_error( ctx, GL_INVALID_ENUM, where );
532 return 0;
533 }
534
535 if (bitmask & ~legal) {
536 _mesa_error( ctx, GL_INVALID_ENUM, where );
537 return 0;
538 }
539
540 return bitmask;
541 }
542
543
544
545 /* Perform a straight copy between materials.
546 */
547 void _mesa_copy_materials( struct gl_material *dst,
548 const struct gl_material *src,
549 GLuint bitmask )
550 {
551 int i;
552
553 for (i = 0 ; i < MAT_ATTRIB_MAX ; i++)
554 if (bitmask & (1<<i))
555 COPY_4FV( dst->Attrib[i], src->Attrib[i] );
556 }
557
558
559
560 /* Update derived values following a change in ctx->Light.Material
561 */
562 void _mesa_update_material( GLcontext *ctx, GLuint bitmask )
563 {
564 struct gl_light *light, *list = &ctx->Light.EnabledList;
565 GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
566
567 if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
568 _mesa_debug(ctx, "_mesa_update_material, mask 0x%x\n", bitmask);
569
570 if (!bitmask)
571 return;
572
573 /* update material ambience */
574 if (bitmask & MAT_BIT_FRONT_AMBIENT) {
575 foreach (light, list) {
576 SCALE_3V( light->_MatAmbient[0], light->Ambient,
577 mat[MAT_ATTRIB_FRONT_AMBIENT]);
578 }
579 }
580
581 if (bitmask & MAT_BIT_BACK_AMBIENT) {
582 foreach (light, list) {
583 SCALE_3V( light->_MatAmbient[1], light->Ambient,
584 mat[MAT_ATTRIB_BACK_AMBIENT]);
585 }
586 }
587
588 /* update BaseColor = emission + scene's ambience * material's ambience */
589 if (bitmask & (MAT_BIT_FRONT_EMISSION | MAT_BIT_FRONT_AMBIENT)) {
590 COPY_3V( ctx->Light._BaseColor[0], mat[MAT_ATTRIB_FRONT_EMISSION] );
591 ACC_SCALE_3V( ctx->Light._BaseColor[0], mat[MAT_ATTRIB_FRONT_AMBIENT],
592 ctx->Light.Model.Ambient );
593 }
594
595 if (bitmask & (MAT_BIT_BACK_EMISSION | MAT_BIT_BACK_AMBIENT)) {
596 COPY_3V( ctx->Light._BaseColor[1], mat[MAT_ATTRIB_BACK_EMISSION] );
597 ACC_SCALE_3V( ctx->Light._BaseColor[1], mat[MAT_ATTRIB_BACK_AMBIENT],
598 ctx->Light.Model.Ambient );
599 }
600
601 /* update material diffuse values */
602 if (bitmask & MAT_BIT_FRONT_DIFFUSE) {
603 foreach (light, list) {
604 SCALE_3V( light->_MatDiffuse[0], light->Diffuse,
605 mat[MAT_ATTRIB_FRONT_DIFFUSE] );
606 }
607 }
608
609 if (bitmask & MAT_BIT_BACK_DIFFUSE) {
610 foreach (light, list) {
611 SCALE_3V( light->_MatDiffuse[1], light->Diffuse,
612 mat[MAT_ATTRIB_BACK_DIFFUSE] );
613 }
614 }
615
616 /* update material specular values */
617 if (bitmask & MAT_BIT_FRONT_SPECULAR) {
618 foreach (light, list) {
619 SCALE_3V( light->_MatSpecular[0], light->Specular,
620 mat[MAT_ATTRIB_FRONT_SPECULAR]);
621 }
622 }
623
624 if (bitmask & MAT_BIT_BACK_SPECULAR) {
625 foreach (light, list) {
626 SCALE_3V( light->_MatSpecular[1], light->Specular,
627 mat[MAT_ATTRIB_BACK_SPECULAR]);
628 }
629 }
630
631 if (bitmask & MAT_BIT_FRONT_SHININESS) {
632 _mesa_invalidate_shine_table( ctx, 0 );
633 }
634
635 if (bitmask & MAT_BIT_BACK_SHININESS) {
636 _mesa_invalidate_shine_table( ctx, 1 );
637 }
638 }
639
640
641 /*
642 * Update the current materials from the given rgba color
643 * according to the bitmask in ColorMaterialBitmask, which is
644 * set by glColorMaterial().
645 */
646 void _mesa_update_color_material( GLcontext *ctx,
647 const GLfloat color[4] )
648 {
649 GLuint bitmask = ctx->Light.ColorMaterialBitmask;
650 struct gl_material *mat = &ctx->Light.Material;
651 int i;
652
653 for (i = 0 ; i < MAT_ATTRIB_MAX ; i++)
654 if (bitmask & (1<<i))
655 COPY_4FV( mat->Attrib[i], color );
656
657 _mesa_update_material( ctx, bitmask );
658 }
659
660
661
662
663 void
664 _mesa_ColorMaterial( GLenum face, GLenum mode )
665 {
666 GET_CURRENT_CONTEXT(ctx);
667 GLuint bitmask;
668 GLuint legal = (MAT_BIT_FRONT_EMISSION | MAT_BIT_BACK_EMISSION |
669 MAT_BIT_FRONT_SPECULAR | MAT_BIT_BACK_SPECULAR |
670 MAT_BIT_FRONT_DIFFUSE | MAT_BIT_BACK_DIFFUSE |
671 MAT_BIT_FRONT_AMBIENT | MAT_BIT_BACK_AMBIENT);
672 ASSERT_OUTSIDE_BEGIN_END(ctx);
673
674 if (MESA_VERBOSE&VERBOSE_API)
675 _mesa_debug(ctx, "glColorMaterial %s %s\n",
676 _mesa_lookup_enum_by_nr(face),
677 _mesa_lookup_enum_by_nr(mode));
678
679 bitmask = _mesa_material_bitmask(ctx, face, mode, legal, "glColorMaterial");
680
681 if (ctx->Light.ColorMaterialBitmask == bitmask &&
682 ctx->Light.ColorMaterialFace == face &&
683 ctx->Light.ColorMaterialMode == mode)
684 return;
685
686 FLUSH_VERTICES(ctx, _NEW_LIGHT);
687 ctx->Light.ColorMaterialBitmask = bitmask;
688 ctx->Light.ColorMaterialFace = face;
689 ctx->Light.ColorMaterialMode = mode;
690
691 if (ctx->Light.ColorMaterialEnabled) {
692 FLUSH_CURRENT( ctx, 0 );
693 _mesa_update_color_material(ctx,ctx->Current.Attrib[VERT_ATTRIB_COLOR0]);
694 }
695
696 if (ctx->Driver.ColorMaterial)
697 (*ctx->Driver.ColorMaterial)( ctx, face, mode );
698 }
699
700
701
702
703
704 void
705 _mesa_GetMaterialfv( GLenum face, GLenum pname, GLfloat *params )
706 {
707 GET_CURRENT_CONTEXT(ctx);
708 GLuint f;
709 GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
710 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* update materials */
711
712 if (face==GL_FRONT) {
713 f = 0;
714 }
715 else if (face==GL_BACK) {
716 f = 1;
717 }
718 else {
719 _mesa_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(face)" );
720 return;
721 }
722
723 switch (pname) {
724 case GL_AMBIENT:
725 COPY_4FV( params, mat[MAT_ATTRIB_AMBIENT(f)] );
726 break;
727 case GL_DIFFUSE:
728 COPY_4FV( params, mat[MAT_ATTRIB_DIFFUSE(f)] );
729 break;
730 case GL_SPECULAR:
731 COPY_4FV( params, mat[MAT_ATTRIB_SPECULAR(f)] );
732 break;
733 case GL_EMISSION:
734 COPY_4FV( params, mat[MAT_ATTRIB_EMISSION(f)] );
735 break;
736 case GL_SHININESS:
737 *params = mat[MAT_ATTRIB_SHININESS(f)][0];
738 break;
739 case GL_COLOR_INDEXES:
740 params[0] = mat[MAT_ATTRIB_INDEXES(f)][0];
741 params[1] = mat[MAT_ATTRIB_INDEXES(f)][1];
742 params[2] = mat[MAT_ATTRIB_INDEXES(f)][2];
743 break;
744 default:
745 _mesa_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" );
746 }
747 }
748
749
750
751 void
752 _mesa_GetMaterialiv( GLenum face, GLenum pname, GLint *params )
753 {
754 GET_CURRENT_CONTEXT(ctx);
755 GLuint f;
756 GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
757 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* update materials */
758
759 if (face==GL_FRONT) {
760 f = 0;
761 }
762 else if (face==GL_BACK) {
763 f = 1;
764 }
765 else {
766 _mesa_error( ctx, GL_INVALID_ENUM, "glGetMaterialiv(face)" );
767 return;
768 }
769 switch (pname) {
770 case GL_AMBIENT:
771 params[0] = FLOAT_TO_INT( mat[MAT_ATTRIB_AMBIENT(f)][0] );
772 params[1] = FLOAT_TO_INT( mat[MAT_ATTRIB_AMBIENT(f)][1] );
773 params[2] = FLOAT_TO_INT( mat[MAT_ATTRIB_AMBIENT(f)][2] );
774 params[3] = FLOAT_TO_INT( mat[MAT_ATTRIB_AMBIENT(f)][3] );
775 break;
776 case GL_DIFFUSE:
777 params[0] = FLOAT_TO_INT( mat[MAT_ATTRIB_DIFFUSE(f)][0] );
778 params[1] = FLOAT_TO_INT( mat[MAT_ATTRIB_DIFFUSE(f)][1] );
779 params[2] = FLOAT_TO_INT( mat[MAT_ATTRIB_DIFFUSE(f)][2] );
780 params[3] = FLOAT_TO_INT( mat[MAT_ATTRIB_DIFFUSE(f)][3] );
781 break;
782 case GL_SPECULAR:
783 params[0] = FLOAT_TO_INT( mat[MAT_ATTRIB_SPECULAR(f)][0] );
784 params[1] = FLOAT_TO_INT( mat[MAT_ATTRIB_SPECULAR(f)][1] );
785 params[2] = FLOAT_TO_INT( mat[MAT_ATTRIB_SPECULAR(f)][2] );
786 params[3] = FLOAT_TO_INT( mat[MAT_ATTRIB_SPECULAR(f)][3] );
787 break;
788 case GL_EMISSION:
789 params[0] = FLOAT_TO_INT( mat[MAT_ATTRIB_EMISSION(f)][0] );
790 params[1] = FLOAT_TO_INT( mat[MAT_ATTRIB_EMISSION(f)][1] );
791 params[2] = FLOAT_TO_INT( mat[MAT_ATTRIB_EMISSION(f)][2] );
792 params[3] = FLOAT_TO_INT( mat[MAT_ATTRIB_EMISSION(f)][3] );
793 break;
794 case GL_SHININESS:
795 *params = IROUND( mat[MAT_ATTRIB_SHININESS(f)][0] );
796 break;
797 case GL_COLOR_INDEXES:
798 params[0] = IROUND( mat[MAT_ATTRIB_INDEXES(f)][0] );
799 params[1] = IROUND( mat[MAT_ATTRIB_INDEXES(f)][1] );
800 params[2] = IROUND( mat[MAT_ATTRIB_INDEXES(f)][2] );
801 break;
802 default:
803 _mesa_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" );
804 }
805 }
806
807
808
809
810 /**********************************************************************/
811 /***** Lighting computation *****/
812 /**********************************************************************/
813
814
815 /*
816 * Notes:
817 * When two-sided lighting is enabled we compute the color (or index)
818 * for both the front and back side of the primitive. Then, when the
819 * orientation of the facet is later learned, we can determine which
820 * color (or index) to use for rendering.
821 *
822 * KW: We now know orientation in advance and only shade for
823 * the side or sides which are actually required.
824 *
825 * Variables:
826 * n = normal vector
827 * V = vertex position
828 * P = light source position
829 * Pe = (0,0,0,1)
830 *
831 * Precomputed:
832 * IF P[3]==0 THEN
833 * // light at infinity
834 * IF local_viewer THEN
835 * _VP_inf_norm = unit vector from V to P // Precompute
836 * ELSE
837 * // eye at infinity
838 * _h_inf_norm = Normalize( VP + <0,0,1> ) // Precompute
839 * ENDIF
840 * ENDIF
841 *
842 * Functions:
843 * Normalize( v ) = normalized vector v
844 * Magnitude( v ) = length of vector v
845 */
846
847
848
849 /*
850 * Whenever the spotlight exponent for a light changes we must call
851 * this function to recompute the exponent lookup table.
852 */
853 void
854 _mesa_invalidate_spot_exp_table( struct gl_light *l )
855 {
856 l->_SpotExpTable[0][0] = -1;
857 }
858
859 static void validate_spot_exp_table( struct gl_light *l )
860 {
861 GLint i;
862 GLdouble exponent = l->SpotExponent;
863 GLdouble tmp = 0;
864 GLint clamp = 0;
865
866 l->_SpotExpTable[0][0] = 0.0;
867
868 for (i = EXP_TABLE_SIZE - 1; i > 0 ;i--) {
869 if (clamp == 0) {
870 tmp = _mesa_pow(i / (GLdouble) (EXP_TABLE_SIZE - 1), exponent);
871 if (tmp < FLT_MIN * 100.0) {
872 tmp = 0.0;
873 clamp = 1;
874 }
875 }
876 l->_SpotExpTable[i][0] = (GLfloat) tmp;
877 }
878 for (i = 0; i < EXP_TABLE_SIZE - 1; i++) {
879 l->_SpotExpTable[i][1] = (l->_SpotExpTable[i+1][0] -
880 l->_SpotExpTable[i][0]);
881 }
882 l->_SpotExpTable[EXP_TABLE_SIZE-1][1] = 0.0;
883 }
884
885
886
887
888 /* Calculate a new shine table. Doing this here saves a branch in
889 * lighting, and the cost of doing it early may be partially offset
890 * by keeping a MRU cache of shine tables for various shine values.
891 */
892 void
893 _mesa_invalidate_shine_table( GLcontext *ctx, GLuint i )
894 {
895 if (ctx->_ShineTable[i])
896 ctx->_ShineTable[i]->refcount--;
897 ctx->_ShineTable[i] = 0;
898 }
899
900 static void validate_shine_table( GLcontext *ctx, GLuint i, GLfloat shininess )
901 {
902 struct gl_shine_tab *list = ctx->_ShineTabList;
903 struct gl_shine_tab *s;
904
905 foreach(s, list)
906 if ( s->shininess == shininess )
907 break;
908
909 if (s == list) {
910 GLint j;
911 GLfloat *m;
912
913 foreach(s, list)
914 if (s->refcount == 0)
915 break;
916
917 m = s->tab;
918 m[0] = 0.0;
919 if (shininess == 0.0) {
920 for (j = 1 ; j <= SHINE_TABLE_SIZE ; j++)
921 m[j] = 1.0;
922 }
923 else {
924 for (j = 1 ; j < SHINE_TABLE_SIZE ; j++) {
925 GLdouble t, x = j / (GLfloat) (SHINE_TABLE_SIZE - 1);
926 if (x < 0.005) /* underflow check */
927 x = 0.005;
928 t = _mesa_pow(x, shininess);
929 if (t > 1e-20)
930 m[j] = (GLfloat) t;
931 else
932 m[j] = 0.0;
933 }
934 m[SHINE_TABLE_SIZE] = 1.0;
935 }
936
937 s->shininess = shininess;
938 }
939
940 if (ctx->_ShineTable[i])
941 ctx->_ShineTable[i]->refcount--;
942
943 ctx->_ShineTable[i] = s;
944 move_to_tail( list, s );
945 s->refcount++;
946 }
947
948 void
949 _mesa_validate_all_lighting_tables( GLcontext *ctx )
950 {
951 GLint i;
952 GLfloat shininess;
953
954 shininess = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SHININESS][0];
955 if (!ctx->_ShineTable[0] || ctx->_ShineTable[0]->shininess != shininess)
956 validate_shine_table( ctx, 0, shininess );
957
958 shininess = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_SHININESS][0];
959 if (!ctx->_ShineTable[1] || ctx->_ShineTable[1]->shininess != shininess)
960 validate_shine_table( ctx, 1, shininess );
961
962 for (i = 0 ; i < MAX_LIGHTS ; i++)
963 if (ctx->Light.Light[i]._SpotExpTable[0][0] == -1)
964 validate_spot_exp_table( &ctx->Light.Light[i] );
965 }
966
967
968
969
970 /*
971 * Examine current lighting parameters to determine if the optimized lighting
972 * function can be used.
973 * Also, precompute some lighting values such as the products of light
974 * source and material ambient, diffuse and specular coefficients.
975 */
976 void
977 _mesa_update_lighting( GLcontext *ctx )
978 {
979 struct gl_light *light;
980 ctx->Light._NeedEyeCoords = 0;
981 ctx->Light._Flags = 0;
982
983 if (!ctx->Light.Enabled)
984 return;
985
986 foreach(light, &ctx->Light.EnabledList) {
987 ctx->Light._Flags |= light->_Flags;
988 }
989
990 ctx->Light._NeedVertices =
991 ((ctx->Light._Flags & (LIGHT_POSITIONAL|LIGHT_SPOT)) ||
992 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR ||
993 ctx->Light.Model.LocalViewer);
994
995 ctx->Light._NeedEyeCoords = ((ctx->Light._Flags & LIGHT_POSITIONAL) ||
996 ctx->Light.Model.LocalViewer);
997
998
999
1000 /* XXX: This test is overkill & needs to be fixed both for software and
1001 * hardware t&l drivers. The above should be sufficient & should
1002 * be tested to verify this.
1003 */
1004 if (ctx->Light._NeedVertices)
1005 ctx->Light._NeedEyeCoords = GL_TRUE;
1006
1007
1008 /* Precompute some shading values. Although we reference
1009 * Light.Material here, we can get away without flushing
1010 * FLUSH_UPDATE_CURRENT, as when any outstanding material changes
1011 * are flushed, they will update the derived state at that time.
1012 */
1013 if (ctx->Visual.rgbMode) {
1014 if (ctx->Light.Model.TwoSide)
1015 _mesa_update_material( ctx,
1016 MAT_BIT_FRONT_EMISSION |
1017 MAT_BIT_FRONT_AMBIENT |
1018 MAT_BIT_FRONT_DIFFUSE |
1019 MAT_BIT_FRONT_SPECULAR |
1020 MAT_BIT_BACK_EMISSION |
1021 MAT_BIT_BACK_AMBIENT |
1022 MAT_BIT_BACK_DIFFUSE |
1023 MAT_BIT_BACK_SPECULAR);
1024 else
1025 _mesa_update_material( ctx,
1026 MAT_BIT_FRONT_EMISSION |
1027 MAT_BIT_FRONT_AMBIENT |
1028 MAT_BIT_FRONT_DIFFUSE |
1029 MAT_BIT_FRONT_SPECULAR);
1030 }
1031 else {
1032 static const GLfloat ci[3] = { .30F, .59F, .11F };
1033 foreach(light, &ctx->Light.EnabledList) {
1034 light->_dli = DOT3(ci, light->Diffuse);
1035 light->_sli = DOT3(ci, light->Specular);
1036 }
1037 }
1038 }
1039
1040
1041 /* _NEW_MODELVIEW
1042 * _NEW_LIGHT
1043 * _TNL_NEW_NEED_EYE_COORDS
1044 *
1045 * Update on (_NEW_MODELVIEW | _NEW_LIGHT) when lighting is enabled.
1046 * Also update on lighting space changes.
1047 */
1048 static void
1049 _mesa_compute_light_positions( GLcontext *ctx )
1050 {
1051 struct gl_light *light;
1052 static const GLfloat eye_z[3] = { 0, 0, 1 };
1053
1054 if (!ctx->Light.Enabled)
1055 return;
1056
1057 if (ctx->_NeedEyeCoords) {
1058 COPY_3V( ctx->_EyeZDir, eye_z );
1059 }
1060 else {
1061 TRANSFORM_NORMAL( ctx->_EyeZDir, eye_z, ctx->ModelviewMatrixStack.Top->m );
1062 }
1063
1064 foreach (light, &ctx->Light.EnabledList) {
1065
1066 if (ctx->_NeedEyeCoords) {
1067 COPY_4FV( light->_Position, light->EyePosition );
1068 }
1069 else {
1070 TRANSFORM_POINT( light->_Position, ctx->ModelviewMatrixStack.Top->inv,
1071 light->EyePosition );
1072 }
1073
1074 if (!(light->_Flags & LIGHT_POSITIONAL)) {
1075 /* VP (VP) = Normalize( Position ) */
1076 COPY_3V( light->_VP_inf_norm, light->_Position );
1077 NORMALIZE_3FV( light->_VP_inf_norm );
1078
1079 if (!ctx->Light.Model.LocalViewer) {
1080 /* _h_inf_norm = Normalize( V_to_P + <0,0,1> ) */
1081 ADD_3V( light->_h_inf_norm, light->_VP_inf_norm, ctx->_EyeZDir);
1082 NORMALIZE_3FV( light->_h_inf_norm );
1083 }
1084 light->_VP_inf_spot_attenuation = 1.0;
1085 }
1086
1087 if (light->_Flags & LIGHT_SPOT) {
1088 if (ctx->_NeedEyeCoords) {
1089 COPY_3V( light->_NormDirection, light->EyeDirection );
1090 }
1091 else {
1092 TRANSFORM_NORMAL( light->_NormDirection,
1093 light->EyeDirection,
1094 ctx->ModelviewMatrixStack.Top->m);
1095 }
1096
1097 NORMALIZE_3FV( light->_NormDirection );
1098
1099 if (!(light->_Flags & LIGHT_POSITIONAL)) {
1100 GLfloat PV_dot_dir = - DOT3(light->_VP_inf_norm,
1101 light->_NormDirection);
1102
1103 if (PV_dot_dir > light->_CosCutoff) {
1104 double x = PV_dot_dir * (EXP_TABLE_SIZE-1);
1105 int k = (int) x;
1106 light->_VP_inf_spot_attenuation =
1107 (GLfloat) (light->_SpotExpTable[k][0] +
1108 (x-k)*light->_SpotExpTable[k][1]);
1109 }
1110 else {
1111 light->_VP_inf_spot_attenuation = 0;
1112 }
1113 }
1114 }
1115 }
1116 }
1117
1118
1119
1120
1121
1122 static void
1123 update_modelview_scale( GLcontext *ctx )
1124 {
1125 ctx->_ModelViewInvScale = 1.0F;
1126 if (ctx->ModelviewMatrixStack.Top->flags & (MAT_FLAG_UNIFORM_SCALE |
1127 MAT_FLAG_GENERAL_SCALE |
1128 MAT_FLAG_GENERAL_3D |
1129 MAT_FLAG_GENERAL) ) {
1130 const GLfloat *m = ctx->ModelviewMatrixStack.Top->inv;
1131 GLfloat f = m[2] * m[2] + m[6] * m[6] + m[10] * m[10];
1132 if (f < 1e-12) f = 1.0;
1133 if (ctx->_NeedEyeCoords)
1134 ctx->_ModelViewInvScale = (GLfloat) INV_SQRTF(f);
1135 else
1136 ctx->_ModelViewInvScale = (GLfloat) SQRTF(f);
1137 }
1138 }
1139
1140
1141 /* Bring uptodate any state that relies on _NeedEyeCoords.
1142 */
1143 void _mesa_update_tnl_spaces( GLcontext *ctx, GLuint new_state )
1144 {
1145 const GLuint oldneedeyecoords = ctx->_NeedEyeCoords;
1146
1147 ctx->_NeedEyeCoords = 0;
1148
1149 if (ctx->_ForceEyeCoords ||
1150 (ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD) ||
1151 ctx->Point._Attenuated ||
1152 ctx->Light._NeedEyeCoords)
1153 ctx->_NeedEyeCoords = 1;
1154
1155 if (ctx->Light.Enabled &&
1156 !TEST_MAT_FLAGS( ctx->ModelviewMatrixStack.Top,
1157 MAT_FLAGS_LENGTH_PRESERVING))
1158 ctx->_NeedEyeCoords = 1;
1159
1160
1161 /* Check if the truth-value interpretations of the bitfields have
1162 * changed:
1163 */
1164 if (oldneedeyecoords != ctx->_NeedEyeCoords) {
1165 /* Recalculate all state that depends on _NeedEyeCoords.
1166 */
1167 update_modelview_scale(ctx);
1168 _mesa_compute_light_positions( ctx );
1169
1170 if (ctx->Driver.LightingSpaceChange)
1171 ctx->Driver.LightingSpaceChange( ctx );
1172 }
1173 else {
1174 GLuint new_state = ctx->NewState;
1175
1176 /* Recalculate that same state only if it has been invalidated
1177 * by other statechanges.
1178 */
1179 if (new_state & _NEW_MODELVIEW)
1180 update_modelview_scale(ctx);
1181
1182 if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW))
1183 _mesa_compute_light_positions( ctx );
1184 }
1185 }
1186
1187
1188 /* Drivers may need this if the hardware tnl unit doesn't support the
1189 * light-in-modelspace optimization. It's also useful for debugging.
1190 */
1191 void
1192 _mesa_allow_light_in_model( GLcontext *ctx, GLboolean flag )
1193 {
1194 ctx->_ForceEyeCoords = flag;
1195 ctx->NewState |= _NEW_POINT; /* one of the bits from
1196 * _MESA_NEW_NEED_EYE_COORDS.
1197 */
1198 }
1199
1200
1201
1202 /**********************************************************************/
1203 /***** Initialization *****/
1204 /**********************************************************************/
1205
1206 /**
1207 * Initialize the n-th light data structure.
1208 *
1209 * \param l pointer to the gl_light structure to be initialized.
1210 * \param n number of the light.
1211 * \note The defaults for light 0 are different than the other lights.
1212 */
1213 static void
1214 init_light( struct gl_light *l, GLuint n )
1215 {
1216 make_empty_list( l );
1217
1218 ASSIGN_4V( l->Ambient, 0.0, 0.0, 0.0, 1.0 );
1219 if (n==0) {
1220 ASSIGN_4V( l->Diffuse, 1.0, 1.0, 1.0, 1.0 );
1221 ASSIGN_4V( l->Specular, 1.0, 1.0, 1.0, 1.0 );
1222 }
1223 else {
1224 ASSIGN_4V( l->Diffuse, 0.0, 0.0, 0.0, 1.0 );
1225 ASSIGN_4V( l->Specular, 0.0, 0.0, 0.0, 1.0 );
1226 }
1227 ASSIGN_4V( l->EyePosition, 0.0, 0.0, 1.0, 0.0 );
1228 ASSIGN_3V( l->EyeDirection, 0.0, 0.0, -1.0 );
1229 l->SpotExponent = 0.0;
1230 _mesa_invalidate_spot_exp_table( l );
1231 l->SpotCutoff = 180.0;
1232 l->_CosCutoff = 0.0; /* KW: -ve values not admitted */
1233 l->ConstantAttenuation = 1.0;
1234 l->LinearAttenuation = 0.0;
1235 l->QuadraticAttenuation = 0.0;
1236 l->Enabled = GL_FALSE;
1237 }
1238
1239 /**
1240 * Initialize the light model data structure.
1241 *
1242 * \param lm pointer to the gl_lightmodel structure to be initialized.
1243 */
1244 static void
1245 init_lightmodel( struct gl_lightmodel *lm )
1246 {
1247 ASSIGN_4V( lm->Ambient, 0.2F, 0.2F, 0.2F, 1.0F );
1248 lm->LocalViewer = GL_FALSE;
1249 lm->TwoSide = GL_FALSE;
1250 lm->ColorControl = GL_SINGLE_COLOR;
1251 }
1252
1253 /**
1254 * Initialize the material data structure.
1255 *
1256 * \param m pointer to the gl_material structure to be initialized.
1257 */
1258 static void
1259 init_material( struct gl_material *m )
1260 {
1261 ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_AMBIENT], 0.2F, 0.2F, 0.2F, 1.0F );
1262 ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_DIFFUSE], 0.8F, 0.8F, 0.8F, 1.0F );
1263 ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_SPECULAR], 0.0F, 0.0F, 0.0F, 1.0F );
1264 ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_EMISSION], 0.0F, 0.0F, 0.0F, 1.0F );
1265 ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_SHININESS], 0.0F, 0.0F, 0.0F, 0.0F );
1266 ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_INDEXES], 0.0F, 1.0F, 1.0F, 0.0F );
1267
1268 ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_AMBIENT], 0.2F, 0.2F, 0.2F, 1.0F );
1269 ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_DIFFUSE], 0.8F, 0.8F, 0.8F, 1.0F );
1270 ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_SPECULAR], 0.0F, 0.0F, 0.0F, 1.0F );
1271 ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_EMISSION], 0.0F, 0.0F, 0.0F, 1.0F );
1272 ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_SHININESS], 0.0F, 0.0F, 0.0F, 0.0F );
1273 ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_INDEXES], 0.0F, 1.0F, 1.0F, 0.0F );
1274 }
1275
1276
1277 void _mesa_init_lighting( GLcontext *ctx )
1278 {
1279 int i;
1280
1281 /* Lighting group */
1282 for (i=0;i<MAX_LIGHTS;i++) {
1283 init_light( &ctx->Light.Light[i], i );
1284 }
1285 make_empty_list( &ctx->Light.EnabledList );
1286
1287 init_lightmodel( &ctx->Light.Model );
1288 init_material( &ctx->Light.Material );
1289 ctx->Light.ShadeModel = GL_SMOOTH;
1290 ctx->Light.Enabled = GL_FALSE;
1291 ctx->Light.ColorMaterialFace = GL_FRONT_AND_BACK;
1292 ctx->Light.ColorMaterialMode = GL_AMBIENT_AND_DIFFUSE;
1293 ctx->Light.ColorMaterialBitmask = _mesa_material_bitmask( ctx,
1294 GL_FRONT_AND_BACK,
1295 GL_AMBIENT_AND_DIFFUSE, ~0, 0 );
1296
1297 ctx->Light.ColorMaterialEnabled = GL_FALSE;
1298
1299 /* Lighting miscellaneous */
1300 ctx->_ShineTabList = MALLOC_STRUCT( gl_shine_tab );
1301 make_empty_list( ctx->_ShineTabList );
1302 for (i = 0 ; i < 10 ; i++) {
1303 struct gl_shine_tab *s = MALLOC_STRUCT( gl_shine_tab );
1304 s->shininess = -1;
1305 s->refcount = 0;
1306 insert_at_tail( ctx->_ShineTabList, s );
1307 }
1308
1309
1310
1311 /* Miscellaneous */
1312 ctx->Light._NeedEyeCoords = 0;
1313 ctx->_NeedEyeCoords = 0;
1314 ctx->_ModelViewInvScale = 1.0;
1315 }
1316
1317
1318 void _mesa_free_lighting_data( GLcontext *ctx )
1319 {
1320 struct gl_shine_tab *s, *tmps;
1321
1322 /* Free lighting shininess exponentiation table */
1323 foreach_s( s, tmps, ctx->_ShineTabList ) {
1324 FREE( s );
1325 }
1326 FREE( ctx->_ShineTabList );
1327 }