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