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