• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
38 void GLAPIENTRY
_mesa_ShadeModel(GLenum mode)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  */
67 void GLAPIENTRY
_mesa_ProvokingVertex(GLenum mode)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  */
99 void
_mesa_light(struct gl_context * ctx,GLuint lnum,GLenum pname,const GLfloat * params)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 
258 void GLAPIENTRY
_mesa_Lightf(GLenum light,GLenum pname,GLfloat param)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 
268 void GLAPIENTRY
_mesa_Lightfv(GLenum light,GLenum pname,const GLfloat * params)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 
329 void GLAPIENTRY
_mesa_Lighti(GLenum light,GLenum pname,GLint param)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 
339 void GLAPIENTRY
_mesa_Lightiv(GLenum light,GLenum pname,const GLint * params)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 
381 void GLAPIENTRY
_mesa_GetLightfv(GLenum light,GLenum pname,GLfloat * params)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 
430 void GLAPIENTRY
_mesa_GetLightiv(GLenum light,GLenum pname,GLint * params)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 
499 void GLAPIENTRY
_mesa_LightModelfv(GLenum pname,const GLfloat * params)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 
558 invalid_pname:
559    _mesa_error( ctx, GL_INVALID_ENUM, "glLightModel(pname=0x%x)", pname );
560    return;
561 }
562 
563 
564 void GLAPIENTRY
_mesa_LightModeliv(GLenum pname,const GLint * params)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 
589 void GLAPIENTRY
_mesa_LightModeli(GLenum pname,GLint param)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 
599 void GLAPIENTRY
_mesa_LightModelf(GLenum pname,GLfloat param)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  */
617 GLuint
_mesa_material_bitmask(struct gl_context * ctx,GLenum face,GLenum pname,GLuint legal,const char * where)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  */
675 void
_mesa_update_material(struct gl_context * ctx,GLuint bitmask)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  */
775 void
_mesa_update_color_material(struct gl_context * ctx,const GLfloat color[4])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 
792 void GLAPIENTRY
_mesa_ColorMaterial(GLenum face,GLenum mode)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 
832 void GLAPIENTRY
_mesa_GetMaterialfv(GLenum face,GLenum pname,GLfloat * params)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 
884 void GLAPIENTRY
_mesa_GetMaterialiv(GLenum face,GLenum pname,GLint * params)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  */
952 GLbitfield
_mesa_update_lighting(struct gl_context * ctx)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 
990 void
_mesa_update_light_materials(struct gl_context * ctx)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  */
1027 static void
compute_light_positions(struct gl_context * ctx)1028 compute_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 
1114 static void
update_modelview_scale(struct gl_context * ctx)1115 update_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  */
1137 bool
_mesa_update_tnl_spaces(struct gl_context * ctx,GLuint new_state)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  */
1189 void
_mesa_allow_light_in_model(struct gl_context * ctx,GLboolean flag)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  */
1209 static void
init_light(struct gl_light * l,struct gl_light_uniforms * lu,GLuint n)1210 init_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  */
1238 static void
init_lightmodel(struct gl_lightmodel * lm)1239 init_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  */
1253 static void
init_material(struct gl_material * m)1254 init_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  */
1275 void
_mesa_init_lighting(struct gl_context * ctx)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