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