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