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