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