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