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