2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
6 * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 #include "simple_list.h"
35 #include "math/m_matrix.h"
39 _mesa_ShadeModel( GLenum mode
)
41 GET_CURRENT_CONTEXT(ctx
);
43 if (MESA_VERBOSE
& VERBOSE_API
)
44 _mesa_debug(ctx
, "glShadeModel %s\n", _mesa_lookup_enum_by_nr(mode
));
46 if (mode
!= GL_FLAT
&& mode
!= GL_SMOOTH
) {
47 _mesa_error(ctx
, GL_INVALID_ENUM
, "glShadeModel");
51 if (ctx
->Light
.ShadeModel
== mode
)
54 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
55 ctx
->Light
.ShadeModel
= mode
;
57 if (ctx
->Driver
.ShadeModel
)
58 ctx
->Driver
.ShadeModel( ctx
, mode
);
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
68 _mesa_ProvokingVertex(GLenum mode
)
70 GET_CURRENT_CONTEXT(ctx
);
72 if (MESA_VERBOSE
&VERBOSE_API
)
73 _mesa_debug(ctx
, "glProvokingVertexEXT 0x%x\n", mode
);
76 case GL_FIRST_VERTEX_CONVENTION_EXT
:
77 case GL_LAST_VERTEX_CONVENTION_EXT
:
80 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProvokingVertexEXT(0x%x)", mode
);
84 if (ctx
->Light
.ProvokingVertex
== mode
)
87 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
88 ctx
->Light
.ProvokingVertex
= mode
;
93 * Helper function called by _mesa_Lightfv and _mesa_PopAttrib to set
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.
100 _mesa_light(struct gl_context
*ctx
, GLuint lnum
, GLenum pname
, const GLfloat
*params
)
102 struct gl_light
*light
;
104 ASSERT(lnum
< MAX_LIGHTS
);
105 light
= &ctx
->Light
.Light
[lnum
];
109 if (TEST_EQ_4V(light
->Ambient
, params
))
111 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
112 COPY_4V( light
->Ambient
, params
);
115 if (TEST_EQ_4V(light
->Diffuse
, params
))
117 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
118 COPY_4V( light
->Diffuse
, params
);
121 if (TEST_EQ_4V(light
->Specular
, params
))
123 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
124 COPY_4V( light
->Specular
, params
);
127 /* NOTE: position has already been transformed by ModelView! */
128 if (TEST_EQ_4V(light
->EyePosition
, params
))
130 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
131 COPY_4V(light
->EyePosition
, params
);
132 if (light
->EyePosition
[3] != 0.0F
)
133 light
->_Flags
|= LIGHT_POSITIONAL
;
135 light
->_Flags
&= ~LIGHT_POSITIONAL
;
137 case GL_SPOT_DIRECTION
:
138 /* NOTE: Direction already transformed by inverse ModelView! */
139 if (TEST_EQ_3V(light
->SpotDirection
, params
))
141 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
142 COPY_3V(light
->SpotDirection
, params
);
144 case GL_SPOT_EXPONENT
:
145 ASSERT(params
[0] >= 0.0);
146 ASSERT(params
[0] <= ctx
->Const
.MaxSpotExponent
);
147 if (light
->SpotExponent
== params
[0])
149 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
150 light
->SpotExponent
= params
[0];
153 ASSERT(params
[0] == 180.0 || (params
[0] >= 0.0 && params
[0] <= 90.0));
154 if (light
->SpotCutoff
== params
[0])
156 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
157 light
->SpotCutoff
= params
[0];
158 light
->_CosCutoff
= (GLfloat
) (cos(light
->SpotCutoff
* DEG2RAD
));
159 if (light
->_CosCutoff
< 0)
160 light
->_CosCutoff
= 0;
161 if (light
->SpotCutoff
!= 180.0F
)
162 light
->_Flags
|= LIGHT_SPOT
;
164 light
->_Flags
&= ~LIGHT_SPOT
;
166 case GL_CONSTANT_ATTENUATION
:
167 ASSERT(params
[0] >= 0.0);
168 if (light
->ConstantAttenuation
== params
[0])
170 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
171 light
->ConstantAttenuation
= params
[0];
173 case GL_LINEAR_ATTENUATION
:
174 ASSERT(params
[0] >= 0.0);
175 if (light
->LinearAttenuation
== params
[0])
177 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
178 light
->LinearAttenuation
= params
[0];
180 case GL_QUADRATIC_ATTENUATION
:
181 ASSERT(params
[0] >= 0.0);
182 if (light
->QuadraticAttenuation
== params
[0])
184 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
185 light
->QuadraticAttenuation
= params
[0];
188 _mesa_problem(ctx
, "Unexpected pname in _mesa_light()");
192 if (ctx
->Driver
.Lightfv
)
193 ctx
->Driver
.Lightfv( ctx
, GL_LIGHT0
+ lnum
, pname
, params
);
198 _mesa_Lightf( GLenum light
, GLenum pname
, GLfloat param
)
202 fparam
[1] = fparam
[2] = fparam
[3] = 0.0F
;
203 _mesa_Lightfv( light
, pname
, fparam
);
208 _mesa_Lightfv( GLenum light
, GLenum pname
, const GLfloat
*params
)
210 GET_CURRENT_CONTEXT(ctx
);
211 GLint i
= (GLint
) (light
- GL_LIGHT0
);
214 if (i
< 0 || i
>= (GLint
) ctx
->Const
.MaxLights
) {
215 _mesa_error( ctx
, GL_INVALID_ENUM
, "glLight(light=0x%x)", light
);
219 /* do particular error checks, transformations */
227 /* transform position by ModelView matrix */
228 TRANSFORM_POINT(temp
, ctx
->ModelviewMatrixStack
.Top
->m
, params
);
231 case GL_SPOT_DIRECTION
:
232 /* transform direction by inverse modelview */
233 if (_math_matrix_is_dirty(ctx
->ModelviewMatrixStack
.Top
)) {
234 _math_matrix_analyse(ctx
->ModelviewMatrixStack
.Top
);
236 TRANSFORM_DIRECTION(temp
, params
, ctx
->ModelviewMatrixStack
.Top
->m
);
239 case GL_SPOT_EXPONENT
:
240 if (params
[0] < 0.0 || params
[0] > ctx
->Const
.MaxSpotExponent
) {
241 _mesa_error(ctx
, GL_INVALID_VALUE
, "glLight");
246 if ((params
[0] < 0.0 || params
[0] > 90.0) && params
[0] != 180.0) {
247 _mesa_error(ctx
, GL_INVALID_VALUE
, "glLight");
251 case GL_CONSTANT_ATTENUATION
:
252 if (params
[0] < 0.0) {
253 _mesa_error(ctx
, GL_INVALID_VALUE
, "glLight");
257 case GL_LINEAR_ATTENUATION
:
258 if (params
[0] < 0.0) {
259 _mesa_error(ctx
, GL_INVALID_VALUE
, "glLight");
263 case GL_QUADRATIC_ATTENUATION
:
264 if (params
[0] < 0.0) {
265 _mesa_error(ctx
, GL_INVALID_VALUE
, "glLight");
270 _mesa_error(ctx
, GL_INVALID_ENUM
, "glLight(pname=0x%x)", pname
);
274 _mesa_light(ctx
, i
, pname
, params
);
279 _mesa_Lighti( GLenum light
, GLenum pname
, GLint param
)
283 iparam
[1] = iparam
[2] = iparam
[3] = 0;
284 _mesa_Lightiv( light
, pname
, iparam
);
289 _mesa_Lightiv( GLenum light
, GLenum pname
, const GLint
*params
)
297 fparam
[0] = INT_TO_FLOAT( params
[0] );
298 fparam
[1] = INT_TO_FLOAT( params
[1] );
299 fparam
[2] = INT_TO_FLOAT( params
[2] );
300 fparam
[3] = INT_TO_FLOAT( params
[3] );
303 fparam
[0] = (GLfloat
) params
[0];
304 fparam
[1] = (GLfloat
) params
[1];
305 fparam
[2] = (GLfloat
) params
[2];
306 fparam
[3] = (GLfloat
) params
[3];
308 case GL_SPOT_DIRECTION
:
309 fparam
[0] = (GLfloat
) params
[0];
310 fparam
[1] = (GLfloat
) params
[1];
311 fparam
[2] = (GLfloat
) params
[2];
313 case GL_SPOT_EXPONENT
:
315 case GL_CONSTANT_ATTENUATION
:
316 case GL_LINEAR_ATTENUATION
:
317 case GL_QUADRATIC_ATTENUATION
:
318 fparam
[0] = (GLfloat
) params
[0];
321 /* error will be caught later in gl_Lightfv */
325 _mesa_Lightfv( light
, pname
, fparam
);
331 _mesa_GetLightfv( GLenum light
, GLenum pname
, GLfloat
*params
)
333 GET_CURRENT_CONTEXT(ctx
);
334 GLint l
= (GLint
) (light
- GL_LIGHT0
);
336 if (l
< 0 || l
>= (GLint
) ctx
->Const
.MaxLights
) {
337 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetLightfv" );
343 COPY_4V( params
, ctx
->Light
.Light
[l
].Ambient
);
346 COPY_4V( params
, ctx
->Light
.Light
[l
].Diffuse
);
349 COPY_4V( params
, ctx
->Light
.Light
[l
].Specular
);
352 COPY_4V( params
, ctx
->Light
.Light
[l
].EyePosition
);
354 case GL_SPOT_DIRECTION
:
355 COPY_3V( params
, ctx
->Light
.Light
[l
].SpotDirection
);
357 case GL_SPOT_EXPONENT
:
358 params
[0] = ctx
->Light
.Light
[l
].SpotExponent
;
361 params
[0] = ctx
->Light
.Light
[l
].SpotCutoff
;
363 case GL_CONSTANT_ATTENUATION
:
364 params
[0] = ctx
->Light
.Light
[l
].ConstantAttenuation
;
366 case GL_LINEAR_ATTENUATION
:
367 params
[0] = ctx
->Light
.Light
[l
].LinearAttenuation
;
369 case GL_QUADRATIC_ATTENUATION
:
370 params
[0] = ctx
->Light
.Light
[l
].QuadraticAttenuation
;
373 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetLightfv" );
380 _mesa_GetLightiv( GLenum light
, GLenum pname
, GLint
*params
)
382 GET_CURRENT_CONTEXT(ctx
);
383 GLint l
= (GLint
) (light
- GL_LIGHT0
);
385 if (l
< 0 || l
>= (GLint
) ctx
->Const
.MaxLights
) {
386 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetLightiv" );
392 params
[0] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Ambient
[0]);
393 params
[1] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Ambient
[1]);
394 params
[2] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Ambient
[2]);
395 params
[3] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Ambient
[3]);
398 params
[0] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Diffuse
[0]);
399 params
[1] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Diffuse
[1]);
400 params
[2] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Diffuse
[2]);
401 params
[3] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Diffuse
[3]);
404 params
[0] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Specular
[0]);
405 params
[1] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Specular
[1]);
406 params
[2] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Specular
[2]);
407 params
[3] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Specular
[3]);
410 params
[0] = (GLint
) ctx
->Light
.Light
[l
].EyePosition
[0];
411 params
[1] = (GLint
) ctx
->Light
.Light
[l
].EyePosition
[1];
412 params
[2] = (GLint
) ctx
->Light
.Light
[l
].EyePosition
[2];
413 params
[3] = (GLint
) ctx
->Light
.Light
[l
].EyePosition
[3];
415 case GL_SPOT_DIRECTION
:
416 params
[0] = (GLint
) ctx
->Light
.Light
[l
].SpotDirection
[0];
417 params
[1] = (GLint
) ctx
->Light
.Light
[l
].SpotDirection
[1];
418 params
[2] = (GLint
) ctx
->Light
.Light
[l
].SpotDirection
[2];
420 case GL_SPOT_EXPONENT
:
421 params
[0] = (GLint
) ctx
->Light
.Light
[l
].SpotExponent
;
424 params
[0] = (GLint
) ctx
->Light
.Light
[l
].SpotCutoff
;
426 case GL_CONSTANT_ATTENUATION
:
427 params
[0] = (GLint
) ctx
->Light
.Light
[l
].ConstantAttenuation
;
429 case GL_LINEAR_ATTENUATION
:
430 params
[0] = (GLint
) ctx
->Light
.Light
[l
].LinearAttenuation
;
432 case GL_QUADRATIC_ATTENUATION
:
433 params
[0] = (GLint
) ctx
->Light
.Light
[l
].QuadraticAttenuation
;
436 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetLightiv" );
443 /**********************************************************************/
444 /*** Light Model ***/
445 /**********************************************************************/
449 _mesa_LightModelfv( GLenum pname
, const GLfloat
*params
)
453 GET_CURRENT_CONTEXT(ctx
);
456 case GL_LIGHT_MODEL_AMBIENT
:
457 if (TEST_EQ_4V( ctx
->Light
.Model
.Ambient
, params
))
459 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
460 COPY_4V( ctx
->Light
.Model
.Ambient
, params
);
462 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
463 if (ctx
->API
!= API_OPENGL_COMPAT
)
465 newbool
= (params
[0]!=0.0);
466 if (ctx
->Light
.Model
.LocalViewer
== newbool
)
468 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
469 ctx
->Light
.Model
.LocalViewer
= newbool
;
471 case GL_LIGHT_MODEL_TWO_SIDE
:
472 newbool
= (params
[0]!=0.0);
473 if (ctx
->Light
.Model
.TwoSide
== newbool
)
475 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
476 ctx
->Light
.Model
.TwoSide
= newbool
;
477 if (ctx
->Light
.Enabled
&& ctx
->Light
.Model
.TwoSide
)
478 ctx
->_TriangleCaps
|= DD_TRI_LIGHT_TWOSIDE
;
480 ctx
->_TriangleCaps
&= ~DD_TRI_LIGHT_TWOSIDE
;
482 case GL_LIGHT_MODEL_COLOR_CONTROL
:
483 if (ctx
->API
!= API_OPENGL_COMPAT
)
485 if (params
[0] == (GLfloat
) GL_SINGLE_COLOR
)
486 newenum
= GL_SINGLE_COLOR
;
487 else if (params
[0] == (GLfloat
) GL_SEPARATE_SPECULAR_COLOR
)
488 newenum
= GL_SEPARATE_SPECULAR_COLOR
;
490 _mesa_error( ctx
, GL_INVALID_ENUM
, "glLightModel(param=0x0%x)",
494 if (ctx
->Light
.Model
.ColorControl
== newenum
)
496 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
497 ctx
->Light
.Model
.ColorControl
= newenum
;
503 if (ctx
->Driver
.LightModelfv
)
504 ctx
->Driver
.LightModelfv( ctx
, pname
, params
);
509 _mesa_error( ctx
, GL_INVALID_ENUM
, "glLightModel(pname=0x%x)", pname
);
515 _mesa_LightModeliv( GLenum pname
, const GLint
*params
)
520 case GL_LIGHT_MODEL_AMBIENT
:
521 fparam
[0] = INT_TO_FLOAT( params
[0] );
522 fparam
[1] = INT_TO_FLOAT( params
[1] );
523 fparam
[2] = INT_TO_FLOAT( params
[2] );
524 fparam
[3] = INT_TO_FLOAT( params
[3] );
526 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
527 case GL_LIGHT_MODEL_TWO_SIDE
:
528 case GL_LIGHT_MODEL_COLOR_CONTROL
:
529 fparam
[0] = (GLfloat
) params
[0];
532 /* Error will be caught later in gl_LightModelfv */
533 ASSIGN_4V(fparam
, 0.0F
, 0.0F
, 0.0F
, 0.0F
);
535 _mesa_LightModelfv( pname
, fparam
);
540 _mesa_LightModeli( GLenum pname
, GLint param
)
544 iparam
[1] = iparam
[2] = iparam
[3] = 0;
545 _mesa_LightModeliv( pname
, iparam
);
550 _mesa_LightModelf( GLenum pname
, GLfloat param
)
554 fparam
[1] = fparam
[2] = fparam
[3] = 0.0F
;
555 _mesa_LightModelfv( pname
, fparam
);
560 /********** MATERIAL **********/
564 * Given a face and pname value (ala glColorMaterial), compute a bitmask
565 * of the targeted material values.
568 _mesa_material_bitmask( struct gl_context
*ctx
, GLenum face
, GLenum pname
,
569 GLuint legal
, const char *where
)
573 /* Make a bitmask indicating what material attribute(s) we're updating */
576 bitmask
|= MAT_BIT_FRONT_EMISSION
| MAT_BIT_BACK_EMISSION
;
579 bitmask
|= MAT_BIT_FRONT_AMBIENT
| MAT_BIT_BACK_AMBIENT
;
582 bitmask
|= MAT_BIT_FRONT_DIFFUSE
| MAT_BIT_BACK_DIFFUSE
;
585 bitmask
|= MAT_BIT_FRONT_SPECULAR
| MAT_BIT_BACK_SPECULAR
;
588 bitmask
|= MAT_BIT_FRONT_SHININESS
| MAT_BIT_BACK_SHININESS
;
590 case GL_AMBIENT_AND_DIFFUSE
:
591 bitmask
|= MAT_BIT_FRONT_AMBIENT
| MAT_BIT_BACK_AMBIENT
;
592 bitmask
|= MAT_BIT_FRONT_DIFFUSE
| MAT_BIT_BACK_DIFFUSE
;
594 case GL_COLOR_INDEXES
:
595 bitmask
|= MAT_BIT_FRONT_INDEXES
| MAT_BIT_BACK_INDEXES
;
598 _mesa_error( ctx
, GL_INVALID_ENUM
, "%s", where
);
602 if (face
==GL_FRONT
) {
603 bitmask
&= FRONT_MATERIAL_BITS
;
605 else if (face
==GL_BACK
) {
606 bitmask
&= BACK_MATERIAL_BITS
;
608 else if (face
!= GL_FRONT_AND_BACK
) {
609 _mesa_error( ctx
, GL_INVALID_ENUM
, "%s", where
);
613 if (bitmask
& ~legal
) {
614 _mesa_error( ctx
, GL_INVALID_ENUM
, "%s", where
);
623 /* Update derived values following a change in ctx->Light.Material
626 _mesa_update_material( struct gl_context
*ctx
, GLuint bitmask
)
628 struct gl_light
*light
, *list
= &ctx
->Light
.EnabledList
;
629 GLfloat (*mat
)[4] = ctx
->Light
.Material
.Attrib
;
631 if (MESA_VERBOSE
& VERBOSE_MATERIAL
)
632 _mesa_debug(ctx
, "_mesa_update_material, mask 0x%x\n", bitmask
);
637 /* update material ambience */
638 if (bitmask
& MAT_BIT_FRONT_AMBIENT
) {
639 foreach (light
, list
) {
640 SCALE_3V( light
->_MatAmbient
[0], light
->Ambient
,
641 mat
[MAT_ATTRIB_FRONT_AMBIENT
]);
645 if (bitmask
& MAT_BIT_BACK_AMBIENT
) {
646 foreach (light
, list
) {
647 SCALE_3V( light
->_MatAmbient
[1], light
->Ambient
,
648 mat
[MAT_ATTRIB_BACK_AMBIENT
]);
652 /* update BaseColor = emission + scene's ambience * material's ambience */
653 if (bitmask
& (MAT_BIT_FRONT_EMISSION
| MAT_BIT_FRONT_AMBIENT
)) {
654 COPY_3V( ctx
->Light
._BaseColor
[0], mat
[MAT_ATTRIB_FRONT_EMISSION
] );
655 ACC_SCALE_3V( ctx
->Light
._BaseColor
[0], mat
[MAT_ATTRIB_FRONT_AMBIENT
],
656 ctx
->Light
.Model
.Ambient
);
659 if (bitmask
& (MAT_BIT_BACK_EMISSION
| MAT_BIT_BACK_AMBIENT
)) {
660 COPY_3V( ctx
->Light
._BaseColor
[1], mat
[MAT_ATTRIB_BACK_EMISSION
] );
661 ACC_SCALE_3V( ctx
->Light
._BaseColor
[1], mat
[MAT_ATTRIB_BACK_AMBIENT
],
662 ctx
->Light
.Model
.Ambient
);
665 /* update material diffuse values */
666 if (bitmask
& MAT_BIT_FRONT_DIFFUSE
) {
667 foreach (light
, list
) {
668 SCALE_3V( light
->_MatDiffuse
[0], light
->Diffuse
,
669 mat
[MAT_ATTRIB_FRONT_DIFFUSE
] );
673 if (bitmask
& MAT_BIT_BACK_DIFFUSE
) {
674 foreach (light
, list
) {
675 SCALE_3V( light
->_MatDiffuse
[1], light
->Diffuse
,
676 mat
[MAT_ATTRIB_BACK_DIFFUSE
] );
680 /* update material specular values */
681 if (bitmask
& MAT_BIT_FRONT_SPECULAR
) {
682 foreach (light
, list
) {
683 SCALE_3V( light
->_MatSpecular
[0], light
->Specular
,
684 mat
[MAT_ATTRIB_FRONT_SPECULAR
]);
688 if (bitmask
& MAT_BIT_BACK_SPECULAR
) {
689 foreach (light
, list
) {
690 SCALE_3V( light
->_MatSpecular
[1], light
->Specular
,
691 mat
[MAT_ATTRIB_BACK_SPECULAR
]);
698 * Update the current materials from the given rgba color
699 * according to the bitmask in _ColorMaterialBitmask, which is
700 * set by glColorMaterial().
703 _mesa_update_color_material( struct gl_context
*ctx
, const GLfloat color
[4] )
705 const GLbitfield bitmask
= ctx
->Light
._ColorMaterialBitmask
;
706 struct gl_material
*mat
= &ctx
->Light
.Material
;
709 for (i
= 0 ; i
< MAT_ATTRIB_MAX
; i
++)
710 if (bitmask
& (1<<i
))
711 COPY_4FV( mat
->Attrib
[i
], color
);
713 _mesa_update_material( ctx
, bitmask
);
718 _mesa_ColorMaterial( GLenum face
, GLenum mode
)
720 GET_CURRENT_CONTEXT(ctx
);
722 GLuint legal
= (MAT_BIT_FRONT_EMISSION
| MAT_BIT_BACK_EMISSION
|
723 MAT_BIT_FRONT_SPECULAR
| MAT_BIT_BACK_SPECULAR
|
724 MAT_BIT_FRONT_DIFFUSE
| MAT_BIT_BACK_DIFFUSE
|
725 MAT_BIT_FRONT_AMBIENT
| MAT_BIT_BACK_AMBIENT
);
727 if (MESA_VERBOSE
&VERBOSE_API
)
728 _mesa_debug(ctx
, "glColorMaterial %s %s\n",
729 _mesa_lookup_enum_by_nr(face
),
730 _mesa_lookup_enum_by_nr(mode
));
732 bitmask
= _mesa_material_bitmask(ctx
, face
, mode
, legal
, "glColorMaterial");
734 return; /* error was recorded */
736 if (ctx
->Light
._ColorMaterialBitmask
== bitmask
&&
737 ctx
->Light
.ColorMaterialFace
== face
&&
738 ctx
->Light
.ColorMaterialMode
== mode
)
741 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
742 ctx
->Light
._ColorMaterialBitmask
= bitmask
;
743 ctx
->Light
.ColorMaterialFace
= face
;
744 ctx
->Light
.ColorMaterialMode
= mode
;
746 if (ctx
->Light
.ColorMaterialEnabled
) {
747 FLUSH_CURRENT( ctx
, 0 );
748 _mesa_update_color_material(ctx
,ctx
->Current
.Attrib
[VERT_ATTRIB_COLOR0
]);
751 if (ctx
->Driver
.ColorMaterial
)
752 ctx
->Driver
.ColorMaterial( ctx
, face
, mode
);
757 _mesa_GetMaterialfv( GLenum face
, GLenum pname
, GLfloat
*params
)
759 GET_CURRENT_CONTEXT(ctx
);
761 GLfloat (*mat
)[4] = ctx
->Light
.Material
.Attrib
;
762 FLUSH_VERTICES(ctx
, 0); /* update materials */
764 FLUSH_CURRENT(ctx
, 0); /* update ctx->Light.Material from vertex buffer */
766 if (face
==GL_FRONT
) {
769 else if (face
==GL_BACK
) {
773 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetMaterialfv(face)" );
779 COPY_4FV( params
, mat
[MAT_ATTRIB_AMBIENT(f
)] );
782 COPY_4FV( params
, mat
[MAT_ATTRIB_DIFFUSE(f
)] );
785 COPY_4FV( params
, mat
[MAT_ATTRIB_SPECULAR(f
)] );
788 COPY_4FV( params
, mat
[MAT_ATTRIB_EMISSION(f
)] );
791 *params
= mat
[MAT_ATTRIB_SHININESS(f
)][0];
793 case GL_COLOR_INDEXES
:
794 if (ctx
->API
!= API_OPENGL_COMPAT
) {
795 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetMaterialfv(pname)" );
798 params
[0] = mat
[MAT_ATTRIB_INDEXES(f
)][0];
799 params
[1] = mat
[MAT_ATTRIB_INDEXES(f
)][1];
800 params
[2] = mat
[MAT_ATTRIB_INDEXES(f
)][2];
803 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetMaterialfv(pname)" );
809 _mesa_GetMaterialiv( GLenum face
, GLenum pname
, GLint
*params
)
811 GET_CURRENT_CONTEXT(ctx
);
813 GLfloat (*mat
)[4] = ctx
->Light
.Material
.Attrib
;
815 ASSERT(ctx
->API
== API_OPENGL_COMPAT
);
817 FLUSH_VERTICES(ctx
, 0); /* update materials */
818 FLUSH_CURRENT(ctx
, 0); /* update ctx->Light.Material from vertex buffer */
820 if (face
==GL_FRONT
) {
823 else if (face
==GL_BACK
) {
827 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetMaterialiv(face)" );
832 params
[0] = FLOAT_TO_INT( mat
[MAT_ATTRIB_AMBIENT(f
)][0] );
833 params
[1] = FLOAT_TO_INT( mat
[MAT_ATTRIB_AMBIENT(f
)][1] );
834 params
[2] = FLOAT_TO_INT( mat
[MAT_ATTRIB_AMBIENT(f
)][2] );
835 params
[3] = FLOAT_TO_INT( mat
[MAT_ATTRIB_AMBIENT(f
)][3] );
838 params
[0] = FLOAT_TO_INT( mat
[MAT_ATTRIB_DIFFUSE(f
)][0] );
839 params
[1] = FLOAT_TO_INT( mat
[MAT_ATTRIB_DIFFUSE(f
)][1] );
840 params
[2] = FLOAT_TO_INT( mat
[MAT_ATTRIB_DIFFUSE(f
)][2] );
841 params
[3] = FLOAT_TO_INT( mat
[MAT_ATTRIB_DIFFUSE(f
)][3] );
844 params
[0] = FLOAT_TO_INT( mat
[MAT_ATTRIB_SPECULAR(f
)][0] );
845 params
[1] = FLOAT_TO_INT( mat
[MAT_ATTRIB_SPECULAR(f
)][1] );
846 params
[2] = FLOAT_TO_INT( mat
[MAT_ATTRIB_SPECULAR(f
)][2] );
847 params
[3] = FLOAT_TO_INT( mat
[MAT_ATTRIB_SPECULAR(f
)][3] );
850 params
[0] = FLOAT_TO_INT( mat
[MAT_ATTRIB_EMISSION(f
)][0] );
851 params
[1] = FLOAT_TO_INT( mat
[MAT_ATTRIB_EMISSION(f
)][1] );
852 params
[2] = FLOAT_TO_INT( mat
[MAT_ATTRIB_EMISSION(f
)][2] );
853 params
[3] = FLOAT_TO_INT( mat
[MAT_ATTRIB_EMISSION(f
)][3] );
856 *params
= IROUND( mat
[MAT_ATTRIB_SHININESS(f
)][0] );
858 case GL_COLOR_INDEXES
:
859 params
[0] = IROUND( mat
[MAT_ATTRIB_INDEXES(f
)][0] );
860 params
[1] = IROUND( mat
[MAT_ATTRIB_INDEXES(f
)][1] );
861 params
[2] = IROUND( mat
[MAT_ATTRIB_INDEXES(f
)][2] );
864 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetMaterialfv(pname)" );
871 * Examine current lighting parameters to determine if the optimized lighting
872 * function can be used.
873 * Also, precompute some lighting values such as the products of light
874 * source and material ambient, diffuse and specular coefficients.
877 _mesa_update_lighting( struct gl_context
*ctx
)
879 GLbitfield flags
= 0;
880 struct gl_light
*light
;
881 ctx
->Light
._NeedEyeCoords
= GL_FALSE
;
883 if (!ctx
->Light
.Enabled
)
886 foreach(light
, &ctx
->Light
.EnabledList
) {
887 flags
|= light
->_Flags
;
890 ctx
->Light
._NeedVertices
=
891 ((flags
& (LIGHT_POSITIONAL
|LIGHT_SPOT
)) ||
892 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
||
893 ctx
->Light
.Model
.LocalViewer
);
895 ctx
->Light
._NeedEyeCoords
= ((flags
& LIGHT_POSITIONAL
) ||
896 ctx
->Light
.Model
.LocalViewer
);
898 /* XXX: This test is overkill & needs to be fixed both for software and
899 * hardware t&l drivers. The above should be sufficient & should
900 * be tested to verify this.
902 if (ctx
->Light
._NeedVertices
)
903 ctx
->Light
._NeedEyeCoords
= GL_TRUE
;
905 /* Precompute some shading values. Although we reference
906 * Light.Material here, we can get away without flushing
907 * FLUSH_UPDATE_CURRENT, as when any outstanding material changes
908 * are flushed, they will update the derived state at that time.
910 if (ctx
->Light
.Model
.TwoSide
)
911 _mesa_update_material(ctx
,
912 MAT_BIT_FRONT_EMISSION
|
913 MAT_BIT_FRONT_AMBIENT
|
914 MAT_BIT_FRONT_DIFFUSE
|
915 MAT_BIT_FRONT_SPECULAR
|
916 MAT_BIT_BACK_EMISSION
|
917 MAT_BIT_BACK_AMBIENT
|
918 MAT_BIT_BACK_DIFFUSE
|
919 MAT_BIT_BACK_SPECULAR
);
921 _mesa_update_material(ctx
,
922 MAT_BIT_FRONT_EMISSION
|
923 MAT_BIT_FRONT_AMBIENT
|
924 MAT_BIT_FRONT_DIFFUSE
|
925 MAT_BIT_FRONT_SPECULAR
);
930 * Update state derived from light position, spot direction.
934 * _TNL_NEW_NEED_EYE_COORDS
936 * Update on (_NEW_MODELVIEW | _NEW_LIGHT) when lighting is enabled.
937 * Also update on lighting space changes.
940 compute_light_positions( struct gl_context
*ctx
)
942 struct gl_light
*light
;
943 static const GLfloat eye_z
[3] = { 0, 0, 1 };
945 if (!ctx
->Light
.Enabled
)
948 if (ctx
->_NeedEyeCoords
) {
949 COPY_3V( ctx
->_EyeZDir
, eye_z
);
952 TRANSFORM_NORMAL( ctx
->_EyeZDir
, eye_z
, ctx
->ModelviewMatrixStack
.Top
->m
);
955 foreach (light
, &ctx
->Light
.EnabledList
) {
957 if (ctx
->_NeedEyeCoords
) {
958 /* _Position is in eye coordinate space */
959 COPY_4FV( light
->_Position
, light
->EyePosition
);
962 /* _Position is in object coordinate space */
963 TRANSFORM_POINT( light
->_Position
, ctx
->ModelviewMatrixStack
.Top
->inv
,
964 light
->EyePosition
);
967 if (!(light
->_Flags
& LIGHT_POSITIONAL
)) {
968 /* VP (VP) = Normalize( Position ) */
969 COPY_3V( light
->_VP_inf_norm
, light
->_Position
);
970 NORMALIZE_3FV( light
->_VP_inf_norm
);
972 if (!ctx
->Light
.Model
.LocalViewer
) {
973 /* _h_inf_norm = Normalize( V_to_P + <0,0,1> ) */
974 ADD_3V( light
->_h_inf_norm
, light
->_VP_inf_norm
, ctx
->_EyeZDir
);
975 NORMALIZE_3FV( light
->_h_inf_norm
);
977 light
->_VP_inf_spot_attenuation
= 1.0;
980 /* positional light w/ homogeneous coordinate, divide by W */
981 GLfloat wInv
= (GLfloat
)1.0 / light
->_Position
[3];
982 light
->_Position
[0] *= wInv
;
983 light
->_Position
[1] *= wInv
;
984 light
->_Position
[2] *= wInv
;
987 if (light
->_Flags
& LIGHT_SPOT
) {
988 /* Note: we normalize the spot direction now */
990 if (ctx
->_NeedEyeCoords
) {
991 COPY_3V( light
->_NormSpotDirection
, light
->SpotDirection
);
992 NORMALIZE_3FV( light
->_NormSpotDirection
);
996 COPY_3V(spotDir
, light
->SpotDirection
);
997 NORMALIZE_3FV(spotDir
);
998 TRANSFORM_NORMAL( light
->_NormSpotDirection
,
1000 ctx
->ModelviewMatrixStack
.Top
->m
);
1003 NORMALIZE_3FV( light
->_NormSpotDirection
);
1005 if (!(light
->_Flags
& LIGHT_POSITIONAL
)) {
1006 GLfloat PV_dot_dir
= - DOT3(light
->_VP_inf_norm
,
1007 light
->_NormSpotDirection
);
1009 if (PV_dot_dir
> light
->_CosCutoff
) {
1010 light
->_VP_inf_spot_attenuation
=
1011 powf(PV_dot_dir
, light
->SpotExponent
);
1014 light
->_VP_inf_spot_attenuation
= 0;
1024 update_modelview_scale( struct gl_context
*ctx
)
1026 ctx
->_ModelViewInvScale
= 1.0F
;
1027 if (!_math_matrix_is_length_preserving(ctx
->ModelviewMatrixStack
.Top
)) {
1028 const GLfloat
*m
= ctx
->ModelviewMatrixStack
.Top
->inv
;
1029 GLfloat f
= m
[2] * m
[2] + m
[6] * m
[6] + m
[10] * m
[10];
1030 if (f
< 1e-12) f
= 1.0;
1031 if (ctx
->_NeedEyeCoords
)
1032 ctx
->_ModelViewInvScale
= (GLfloat
) INV_SQRTF(f
);
1034 ctx
->_ModelViewInvScale
= (GLfloat
) sqrtf(f
);
1040 * Bring up to date any state that relies on _NeedEyeCoords.
1043 _mesa_update_tnl_spaces( struct gl_context
*ctx
, GLuint new_state
)
1045 const GLuint oldneedeyecoords
= ctx
->_NeedEyeCoords
;
1048 ctx
->_NeedEyeCoords
= GL_FALSE
;
1050 if (ctx
->_ForceEyeCoords
||
1051 (ctx
->Texture
._GenFlags
& TEXGEN_NEED_EYE_COORD
) ||
1052 ctx
->Point
._Attenuated
||
1053 ctx
->Light
._NeedEyeCoords
)
1054 ctx
->_NeedEyeCoords
= GL_TRUE
;
1056 if (ctx
->Light
.Enabled
&&
1057 !_math_matrix_is_length_preserving(ctx
->ModelviewMatrixStack
.Top
))
1058 ctx
->_NeedEyeCoords
= GL_TRUE
;
1060 /* Check if the truth-value interpretations of the bitfields have
1063 if (oldneedeyecoords
!= ctx
->_NeedEyeCoords
) {
1064 /* Recalculate all state that depends on _NeedEyeCoords.
1066 update_modelview_scale(ctx
);
1067 compute_light_positions( ctx
);
1069 if (ctx
->Driver
.LightingSpaceChange
)
1070 ctx
->Driver
.LightingSpaceChange( ctx
);
1073 GLuint new_state2
= ctx
->NewState
;
1075 /* Recalculate that same state only if it has been invalidated
1076 * by other statechanges.
1078 if (new_state2
& _NEW_MODELVIEW
)
1079 update_modelview_scale(ctx
);
1081 if (new_state2
& (_NEW_LIGHT
|_NEW_MODELVIEW
))
1082 compute_light_positions( ctx
);
1088 * Drivers may need this if the hardware tnl unit doesn't support the
1089 * light-in-modelspace optimization. It's also useful for debugging.
1092 _mesa_allow_light_in_model( struct gl_context
*ctx
, GLboolean flag
)
1094 ctx
->_ForceEyeCoords
= !flag
;
1095 ctx
->NewState
|= _NEW_POINT
; /* one of the bits from
1096 * _MESA_NEW_NEED_EYE_COORDS.
1102 /**********************************************************************/
1103 /***** Initialization *****/
1104 /**********************************************************************/
1107 * Initialize the n-th light data structure.
1109 * \param l pointer to the gl_light structure to be initialized.
1110 * \param n number of the light.
1111 * \note The defaults for light 0 are different than the other lights.
1114 init_light( struct gl_light
*l
, GLuint n
)
1116 make_empty_list( l
);
1118 ASSIGN_4V( l
->Ambient
, 0.0, 0.0, 0.0, 1.0 );
1120 ASSIGN_4V( l
->Diffuse
, 1.0, 1.0, 1.0, 1.0 );
1121 ASSIGN_4V( l
->Specular
, 1.0, 1.0, 1.0, 1.0 );
1124 ASSIGN_4V( l
->Diffuse
, 0.0, 0.0, 0.0, 1.0 );
1125 ASSIGN_4V( l
->Specular
, 0.0, 0.0, 0.0, 1.0 );
1127 ASSIGN_4V( l
->EyePosition
, 0.0, 0.0, 1.0, 0.0 );
1128 ASSIGN_3V( l
->SpotDirection
, 0.0, 0.0, -1.0 );
1129 l
->SpotExponent
= 0.0;
1130 l
->SpotCutoff
= 180.0;
1131 l
->_CosCutoff
= 0.0; /* KW: -ve values not admitted */
1132 l
->ConstantAttenuation
= 1.0;
1133 l
->LinearAttenuation
= 0.0;
1134 l
->QuadraticAttenuation
= 0.0;
1135 l
->Enabled
= GL_FALSE
;
1140 * Initialize the light model data structure.
1142 * \param lm pointer to the gl_lightmodel structure to be initialized.
1145 init_lightmodel( struct gl_lightmodel
*lm
)
1147 ASSIGN_4V( lm
->Ambient
, 0.2F
, 0.2F
, 0.2F
, 1.0F
);
1148 lm
->LocalViewer
= GL_FALSE
;
1149 lm
->TwoSide
= GL_FALSE
;
1150 lm
->ColorControl
= GL_SINGLE_COLOR
;
1155 * Initialize the material data structure.
1157 * \param m pointer to the gl_material structure to be initialized.
1160 init_material( struct gl_material
*m
)
1162 ASSIGN_4V( m
->Attrib
[MAT_ATTRIB_FRONT_AMBIENT
], 0.2F
, 0.2F
, 0.2F
, 1.0F
);
1163 ASSIGN_4V( m
->Attrib
[MAT_ATTRIB_FRONT_DIFFUSE
], 0.8F
, 0.8F
, 0.8F
, 1.0F
);
1164 ASSIGN_4V( m
->Attrib
[MAT_ATTRIB_FRONT_SPECULAR
], 0.0F
, 0.0F
, 0.0F
, 1.0F
);
1165 ASSIGN_4V( m
->Attrib
[MAT_ATTRIB_FRONT_EMISSION
], 0.0F
, 0.0F
, 0.0F
, 1.0F
);
1166 ASSIGN_4V( m
->Attrib
[MAT_ATTRIB_FRONT_SHININESS
], 0.0F
, 0.0F
, 0.0F
, 0.0F
);
1167 ASSIGN_4V( m
->Attrib
[MAT_ATTRIB_FRONT_INDEXES
], 0.0F
, 1.0F
, 1.0F
, 0.0F
);
1169 ASSIGN_4V( m
->Attrib
[MAT_ATTRIB_BACK_AMBIENT
], 0.2F
, 0.2F
, 0.2F
, 1.0F
);
1170 ASSIGN_4V( m
->Attrib
[MAT_ATTRIB_BACK_DIFFUSE
], 0.8F
, 0.8F
, 0.8F
, 1.0F
);
1171 ASSIGN_4V( m
->Attrib
[MAT_ATTRIB_BACK_SPECULAR
], 0.0F
, 0.0F
, 0.0F
, 1.0F
);
1172 ASSIGN_4V( m
->Attrib
[MAT_ATTRIB_BACK_EMISSION
], 0.0F
, 0.0F
, 0.0F
, 1.0F
);
1173 ASSIGN_4V( m
->Attrib
[MAT_ATTRIB_BACK_SHININESS
], 0.0F
, 0.0F
, 0.0F
, 0.0F
);
1174 ASSIGN_4V( m
->Attrib
[MAT_ATTRIB_BACK_INDEXES
], 0.0F
, 1.0F
, 1.0F
, 0.0F
);
1179 * Initialize all lighting state for the given context.
1182 _mesa_init_lighting( struct gl_context
*ctx
)
1186 /* Lighting group */
1187 for (i
= 0; i
< MAX_LIGHTS
; i
++) {
1188 init_light( &ctx
->Light
.Light
[i
], i
);
1190 make_empty_list( &ctx
->Light
.EnabledList
);
1192 init_lightmodel( &ctx
->Light
.Model
);
1193 init_material( &ctx
->Light
.Material
);
1194 ctx
->Light
.ShadeModel
= GL_SMOOTH
;
1195 ctx
->Light
.ProvokingVertex
= GL_LAST_VERTEX_CONVENTION_EXT
;
1196 ctx
->Light
.Enabled
= GL_FALSE
;
1197 ctx
->Light
.ColorMaterialFace
= GL_FRONT_AND_BACK
;
1198 ctx
->Light
.ColorMaterialMode
= GL_AMBIENT_AND_DIFFUSE
;
1199 ctx
->Light
._ColorMaterialBitmask
= _mesa_material_bitmask( ctx
,
1201 GL_AMBIENT_AND_DIFFUSE
, ~0,
1204 ctx
->Light
.ColorMaterialEnabled
= GL_FALSE
;
1205 ctx
->Light
.ClampVertexColor
= GL_TRUE
;
1208 ctx
->Light
._NeedEyeCoords
= GL_FALSE
;
1209 ctx
->_NeedEyeCoords
= GL_FALSE
;
1210 ctx
->_ForceEyeCoords
= GL_FALSE
;
1211 ctx
->_ModelViewInvScale
= 1.0;
1216 * Deallocate malloc'd lighting state attached to given context.
1219 _mesa_free_lighting_data( struct gl_context
*ctx
)