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