2 * Mesa 3-D graphics library
4 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
5 * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
35 #include "math/m_matrix.h"
36 #include "util/bitscan.h"
40 _mesa_ShadeModel( GLenum mode
)
42 GET_CURRENT_CONTEXT(ctx
);
44 if (MESA_VERBOSE
& VERBOSE_API
)
45 _mesa_debug(ctx
, "glShadeModel %s\n", _mesa_enum_to_string(mode
));
47 if (ctx
->Light
.ShadeModel
== mode
)
50 if (mode
!= GL_FLAT
&& mode
!= GL_SMOOTH
) {
51 _mesa_error(ctx
, GL_INVALID_ENUM
, "glShadeModel");
55 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
56 ctx
->Light
.ShadeModel
= mode
;
58 if (ctx
->Driver
.ShadeModel
)
59 ctx
->Driver
.ShadeModel( ctx
, mode
);
64 * Set the provoking vertex (the vertex which specifies the prim's
65 * color when flat shading) to either the first or last vertex of the
69 _mesa_ProvokingVertex(GLenum mode
)
71 GET_CURRENT_CONTEXT(ctx
);
73 if (MESA_VERBOSE
&VERBOSE_API
)
74 _mesa_debug(ctx
, "glProvokingVertexEXT 0x%x\n", mode
);
77 case GL_FIRST_VERTEX_CONVENTION_EXT
:
78 case GL_LAST_VERTEX_CONVENTION_EXT
:
81 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProvokingVertexEXT(0x%x)", mode
);
85 if (ctx
->Light
.ProvokingVertex
== mode
)
88 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
89 ctx
->Light
.ProvokingVertex
= mode
;
94 * Helper function called by _mesa_Lightfv and _mesa_PopAttrib to set
96 * For GL_POSITION and GL_SPOT_DIRECTION the params position/direction
97 * will have already been transformed by the modelview matrix!
98 * Also, all error checking should have already been done.
101 _mesa_light(struct gl_context
*ctx
, GLuint lnum
, GLenum pname
, const GLfloat
*params
)
103 struct gl_light
*light
;
105 assert(lnum
< MAX_LIGHTS
);
106 light
= &ctx
->Light
.Light
[lnum
];
110 if (TEST_EQ_4V(light
->Ambient
, params
))
112 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
113 COPY_4V( light
->Ambient
, params
);
116 if (TEST_EQ_4V(light
->Diffuse
, params
))
118 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
119 COPY_4V( light
->Diffuse
, params
);
122 if (TEST_EQ_4V(light
->Specular
, params
))
124 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
125 COPY_4V( light
->Specular
, params
);
128 /* NOTE: position has already been transformed by ModelView! */
129 if (TEST_EQ_4V(light
->EyePosition
, params
))
131 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
132 COPY_4V(light
->EyePosition
, params
);
133 if (light
->EyePosition
[3] != 0.0F
)
134 light
->_Flags
|= LIGHT_POSITIONAL
;
136 light
->_Flags
&= ~LIGHT_POSITIONAL
;
138 case GL_SPOT_DIRECTION
:
139 /* NOTE: Direction already transformed by inverse ModelView! */
140 if (TEST_EQ_3V(light
->SpotDirection
, params
))
142 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
143 COPY_3V(light
->SpotDirection
, params
);
145 case GL_SPOT_EXPONENT
:
146 assert(params
[0] >= 0.0F
);
147 assert(params
[0] <= ctx
->Const
.MaxSpotExponent
);
148 if (light
->SpotExponent
== params
[0])
150 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
151 light
->SpotExponent
= params
[0];
154 assert(params
[0] == 180.0F
|| (params
[0] >= 0.0F
&& params
[0] <= 90.0F
));
155 if (light
->SpotCutoff
== params
[0])
157 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
158 light
->SpotCutoff
= params
[0];
159 light
->_CosCutoff
= (cosf(light
->SpotCutoff
* M_PI
/ 180.0));
160 if (light
->_CosCutoff
< 0)
161 light
->_CosCutoff
= 0;
162 if (light
->SpotCutoff
!= 180.0F
)
163 light
->_Flags
|= LIGHT_SPOT
;
165 light
->_Flags
&= ~LIGHT_SPOT
;
167 case GL_CONSTANT_ATTENUATION
:
168 assert(params
[0] >= 0.0F
);
169 if (light
->ConstantAttenuation
== params
[0])
171 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
172 light
->ConstantAttenuation
= params
[0];
174 case GL_LINEAR_ATTENUATION
:
175 assert(params
[0] >= 0.0F
);
176 if (light
->LinearAttenuation
== params
[0])
178 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
179 light
->LinearAttenuation
= params
[0];
181 case GL_QUADRATIC_ATTENUATION
:
182 assert(params
[0] >= 0.0F
);
183 if (light
->QuadraticAttenuation
== params
[0])
185 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
186 light
->QuadraticAttenuation
= params
[0];
189 unreachable("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.0F
|| params
[0] > ctx
->Const
.MaxSpotExponent
) {
241 _mesa_error(ctx
, GL_INVALID_VALUE
, "glLight");
246 if ((params
[0] < 0.0F
|| params
[0] > 90.0F
) && params
[0] != 180.0F
) {
247 _mesa_error(ctx
, GL_INVALID_VALUE
, "glLight");
251 case GL_CONSTANT_ATTENUATION
:
252 case GL_LINEAR_ATTENUATION
:
253 case GL_QUADRATIC_ATTENUATION
:
254 if (params
[0] < 0.0F
) {
255 _mesa_error(ctx
, GL_INVALID_VALUE
, "glLight");
260 _mesa_error(ctx
, GL_INVALID_ENUM
, "glLight(pname=0x%x)", pname
);
264 _mesa_light(ctx
, i
, pname
, params
);
269 _mesa_Lighti( GLenum light
, GLenum pname
, GLint param
)
273 iparam
[1] = iparam
[2] = iparam
[3] = 0;
274 _mesa_Lightiv( light
, pname
, iparam
);
279 _mesa_Lightiv( GLenum light
, GLenum pname
, const GLint
*params
)
287 fparam
[0] = INT_TO_FLOAT( params
[0] );
288 fparam
[1] = INT_TO_FLOAT( params
[1] );
289 fparam
[2] = INT_TO_FLOAT( params
[2] );
290 fparam
[3] = INT_TO_FLOAT( params
[3] );
293 fparam
[0] = (GLfloat
) params
[0];
294 fparam
[1] = (GLfloat
) params
[1];
295 fparam
[2] = (GLfloat
) params
[2];
296 fparam
[3] = (GLfloat
) params
[3];
298 case GL_SPOT_DIRECTION
:
299 fparam
[0] = (GLfloat
) params
[0];
300 fparam
[1] = (GLfloat
) params
[1];
301 fparam
[2] = (GLfloat
) params
[2];
303 case GL_SPOT_EXPONENT
:
305 case GL_CONSTANT_ATTENUATION
:
306 case GL_LINEAR_ATTENUATION
:
307 case GL_QUADRATIC_ATTENUATION
:
308 fparam
[0] = (GLfloat
) params
[0];
311 /* error will be caught later in gl_Lightfv */
315 _mesa_Lightfv( light
, pname
, fparam
);
321 _mesa_GetLightfv( GLenum light
, GLenum pname
, GLfloat
*params
)
323 GET_CURRENT_CONTEXT(ctx
);
324 GLint l
= (GLint
) (light
- GL_LIGHT0
);
326 if (l
< 0 || l
>= (GLint
) ctx
->Const
.MaxLights
) {
327 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetLightfv" );
333 COPY_4V( params
, ctx
->Light
.Light
[l
].Ambient
);
336 COPY_4V( params
, ctx
->Light
.Light
[l
].Diffuse
);
339 COPY_4V( params
, ctx
->Light
.Light
[l
].Specular
);
342 COPY_4V( params
, ctx
->Light
.Light
[l
].EyePosition
);
344 case GL_SPOT_DIRECTION
:
345 COPY_3V( params
, ctx
->Light
.Light
[l
].SpotDirection
);
347 case GL_SPOT_EXPONENT
:
348 params
[0] = ctx
->Light
.Light
[l
].SpotExponent
;
351 params
[0] = ctx
->Light
.Light
[l
].SpotCutoff
;
353 case GL_CONSTANT_ATTENUATION
:
354 params
[0] = ctx
->Light
.Light
[l
].ConstantAttenuation
;
356 case GL_LINEAR_ATTENUATION
:
357 params
[0] = ctx
->Light
.Light
[l
].LinearAttenuation
;
359 case GL_QUADRATIC_ATTENUATION
:
360 params
[0] = ctx
->Light
.Light
[l
].QuadraticAttenuation
;
363 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetLightfv" );
370 _mesa_GetLightiv( GLenum light
, GLenum pname
, GLint
*params
)
372 GET_CURRENT_CONTEXT(ctx
);
373 GLint l
= (GLint
) (light
- GL_LIGHT0
);
375 if (l
< 0 || l
>= (GLint
) ctx
->Const
.MaxLights
) {
376 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetLightiv" );
382 params
[0] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Ambient
[0]);
383 params
[1] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Ambient
[1]);
384 params
[2] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Ambient
[2]);
385 params
[3] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Ambient
[3]);
388 params
[0] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Diffuse
[0]);
389 params
[1] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Diffuse
[1]);
390 params
[2] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Diffuse
[2]);
391 params
[3] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Diffuse
[3]);
394 params
[0] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Specular
[0]);
395 params
[1] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Specular
[1]);
396 params
[2] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Specular
[2]);
397 params
[3] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Specular
[3]);
400 params
[0] = (GLint
) ctx
->Light
.Light
[l
].EyePosition
[0];
401 params
[1] = (GLint
) ctx
->Light
.Light
[l
].EyePosition
[1];
402 params
[2] = (GLint
) ctx
->Light
.Light
[l
].EyePosition
[2];
403 params
[3] = (GLint
) ctx
->Light
.Light
[l
].EyePosition
[3];
405 case GL_SPOT_DIRECTION
:
406 params
[0] = (GLint
) ctx
->Light
.Light
[l
].SpotDirection
[0];
407 params
[1] = (GLint
) ctx
->Light
.Light
[l
].SpotDirection
[1];
408 params
[2] = (GLint
) ctx
->Light
.Light
[l
].SpotDirection
[2];
410 case GL_SPOT_EXPONENT
:
411 params
[0] = (GLint
) ctx
->Light
.Light
[l
].SpotExponent
;
414 params
[0] = (GLint
) ctx
->Light
.Light
[l
].SpotCutoff
;
416 case GL_CONSTANT_ATTENUATION
:
417 params
[0] = (GLint
) ctx
->Light
.Light
[l
].ConstantAttenuation
;
419 case GL_LINEAR_ATTENUATION
:
420 params
[0] = (GLint
) ctx
->Light
.Light
[l
].LinearAttenuation
;
422 case GL_QUADRATIC_ATTENUATION
:
423 params
[0] = (GLint
) ctx
->Light
.Light
[l
].QuadraticAttenuation
;
426 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetLightiv" );
433 /**********************************************************************/
434 /*** Light Model ***/
435 /**********************************************************************/
439 _mesa_LightModelfv( GLenum pname
, const GLfloat
*params
)
443 GET_CURRENT_CONTEXT(ctx
);
446 case GL_LIGHT_MODEL_AMBIENT
:
447 if (TEST_EQ_4V( ctx
->Light
.Model
.Ambient
, params
))
449 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
450 COPY_4V( ctx
->Light
.Model
.Ambient
, params
);
452 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
453 if (ctx
->API
!= API_OPENGL_COMPAT
)
455 newbool
= (params
[0] != 0.0F
);
456 if (ctx
->Light
.Model
.LocalViewer
== newbool
)
458 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
459 ctx
->Light
.Model
.LocalViewer
= newbool
;
461 case GL_LIGHT_MODEL_TWO_SIDE
:
462 newbool
= (params
[0] != 0.0F
);
463 if (ctx
->Light
.Model
.TwoSide
== newbool
)
465 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
466 ctx
->Light
.Model
.TwoSide
= newbool
;
468 case GL_LIGHT_MODEL_COLOR_CONTROL
:
469 if (ctx
->API
!= API_OPENGL_COMPAT
)
471 if (params
[0] == (GLfloat
) GL_SINGLE_COLOR
)
472 newenum
= GL_SINGLE_COLOR
;
473 else if (params
[0] == (GLfloat
) GL_SEPARATE_SPECULAR_COLOR
)
474 newenum
= GL_SEPARATE_SPECULAR_COLOR
;
476 _mesa_error( ctx
, GL_INVALID_ENUM
, "glLightModel(param=0x0%x)",
480 if (ctx
->Light
.Model
.ColorControl
== newenum
)
482 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
483 ctx
->Light
.Model
.ColorControl
= newenum
;
489 if (ctx
->Driver
.LightModelfv
)
490 ctx
->Driver
.LightModelfv( ctx
, pname
, params
);
495 _mesa_error( ctx
, GL_INVALID_ENUM
, "glLightModel(pname=0x%x)", pname
);
501 _mesa_LightModeliv( GLenum pname
, const GLint
*params
)
506 case GL_LIGHT_MODEL_AMBIENT
:
507 fparam
[0] = INT_TO_FLOAT( params
[0] );
508 fparam
[1] = INT_TO_FLOAT( params
[1] );
509 fparam
[2] = INT_TO_FLOAT( params
[2] );
510 fparam
[3] = INT_TO_FLOAT( params
[3] );
512 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
513 case GL_LIGHT_MODEL_TWO_SIDE
:
514 case GL_LIGHT_MODEL_COLOR_CONTROL
:
515 fparam
[0] = (GLfloat
) params
[0];
518 /* Error will be caught later in gl_LightModelfv */
519 ASSIGN_4V(fparam
, 0.0F
, 0.0F
, 0.0F
, 0.0F
);
521 _mesa_LightModelfv( pname
, fparam
);
526 _mesa_LightModeli( GLenum pname
, GLint param
)
530 iparam
[1] = iparam
[2] = iparam
[3] = 0;
531 _mesa_LightModeliv( pname
, iparam
);
536 _mesa_LightModelf( GLenum pname
, GLfloat param
)
540 fparam
[1] = fparam
[2] = fparam
[3] = 0.0F
;
541 _mesa_LightModelfv( pname
, fparam
);
546 /********** MATERIAL **********/
550 * Given a face and pname value (ala glColorMaterial), compute a bitmask
551 * of the targeted material values.
554 _mesa_material_bitmask( struct gl_context
*ctx
, GLenum face
, GLenum pname
,
555 GLuint legal
, const char *where
)
559 /* Make a bitmask indicating what material attribute(s) we're updating */
562 bitmask
|= MAT_BIT_FRONT_EMISSION
| MAT_BIT_BACK_EMISSION
;
565 bitmask
|= MAT_BIT_FRONT_AMBIENT
| MAT_BIT_BACK_AMBIENT
;
568 bitmask
|= MAT_BIT_FRONT_DIFFUSE
| MAT_BIT_BACK_DIFFUSE
;
571 bitmask
|= MAT_BIT_FRONT_SPECULAR
| MAT_BIT_BACK_SPECULAR
;
574 bitmask
|= MAT_BIT_FRONT_SHININESS
| MAT_BIT_BACK_SHININESS
;
576 case GL_AMBIENT_AND_DIFFUSE
:
577 bitmask
|= MAT_BIT_FRONT_AMBIENT
| MAT_BIT_BACK_AMBIENT
;
578 bitmask
|= MAT_BIT_FRONT_DIFFUSE
| MAT_BIT_BACK_DIFFUSE
;
580 case GL_COLOR_INDEXES
:
581 bitmask
|= MAT_BIT_FRONT_INDEXES
| MAT_BIT_BACK_INDEXES
;
584 _mesa_error( ctx
, GL_INVALID_ENUM
, "%s", where
);
588 if (face
==GL_FRONT
) {
589 bitmask
&= FRONT_MATERIAL_BITS
;
591 else if (face
==GL_BACK
) {
592 bitmask
&= BACK_MATERIAL_BITS
;
594 else if (face
!= GL_FRONT_AND_BACK
) {
595 _mesa_error( ctx
, GL_INVALID_ENUM
, "%s", where
);
599 if (bitmask
& ~legal
) {
600 _mesa_error( ctx
, GL_INVALID_ENUM
, "%s", where
);
609 /* Update derived values following a change in ctx->Light.Material
612 _mesa_update_material( struct gl_context
*ctx
, GLuint bitmask
)
614 GLfloat (*mat
)[4] = ctx
->Light
.Material
.Attrib
;
616 if (MESA_VERBOSE
& VERBOSE_MATERIAL
)
617 _mesa_debug(ctx
, "_mesa_update_material, mask 0x%x\n", bitmask
);
622 /* update material ambience */
623 if (bitmask
& MAT_BIT_FRONT_AMBIENT
) {
624 GLbitfield mask
= ctx
->Light
._EnabledLights
;
626 const int i
= u_bit_scan(&mask
);
627 struct gl_light
*light
= &ctx
->Light
.Light
[i
];
628 SCALE_3V( light
->_MatAmbient
[0], light
->Ambient
,
629 mat
[MAT_ATTRIB_FRONT_AMBIENT
]);
633 if (bitmask
& MAT_BIT_BACK_AMBIENT
) {
634 GLbitfield mask
= ctx
->Light
._EnabledLights
;
636 const int i
= u_bit_scan(&mask
);
637 struct gl_light
*light
= &ctx
->Light
.Light
[i
];
638 SCALE_3V( light
->_MatAmbient
[1], light
->Ambient
,
639 mat
[MAT_ATTRIB_BACK_AMBIENT
]);
643 /* update BaseColor = emission + scene's ambience * material's ambience */
644 if (bitmask
& (MAT_BIT_FRONT_EMISSION
| MAT_BIT_FRONT_AMBIENT
)) {
645 COPY_3V( ctx
->Light
._BaseColor
[0], mat
[MAT_ATTRIB_FRONT_EMISSION
] );
646 ACC_SCALE_3V( ctx
->Light
._BaseColor
[0], mat
[MAT_ATTRIB_FRONT_AMBIENT
],
647 ctx
->Light
.Model
.Ambient
);
650 if (bitmask
& (MAT_BIT_BACK_EMISSION
| MAT_BIT_BACK_AMBIENT
)) {
651 COPY_3V( ctx
->Light
._BaseColor
[1], mat
[MAT_ATTRIB_BACK_EMISSION
] );
652 ACC_SCALE_3V( ctx
->Light
._BaseColor
[1], mat
[MAT_ATTRIB_BACK_AMBIENT
],
653 ctx
->Light
.Model
.Ambient
);
656 /* update material diffuse values */
657 if (bitmask
& MAT_BIT_FRONT_DIFFUSE
) {
658 GLbitfield mask
= ctx
->Light
._EnabledLights
;
660 const int i
= u_bit_scan(&mask
);
661 struct gl_light
*light
= &ctx
->Light
.Light
[i
];
662 SCALE_3V( light
->_MatDiffuse
[0], light
->Diffuse
,
663 mat
[MAT_ATTRIB_FRONT_DIFFUSE
] );
667 if (bitmask
& MAT_BIT_BACK_DIFFUSE
) {
668 GLbitfield mask
= ctx
->Light
._EnabledLights
;
670 const int i
= u_bit_scan(&mask
);
671 struct gl_light
*light
= &ctx
->Light
.Light
[i
];
672 SCALE_3V( light
->_MatDiffuse
[1], light
->Diffuse
,
673 mat
[MAT_ATTRIB_BACK_DIFFUSE
] );
677 /* update material specular values */
678 if (bitmask
& MAT_BIT_FRONT_SPECULAR
) {
679 GLbitfield mask
= ctx
->Light
._EnabledLights
;
681 const int i
= u_bit_scan(&mask
);
682 struct gl_light
*light
= &ctx
->Light
.Light
[i
];
683 SCALE_3V( light
->_MatSpecular
[0], light
->Specular
,
684 mat
[MAT_ATTRIB_FRONT_SPECULAR
]);
688 if (bitmask
& MAT_BIT_BACK_SPECULAR
) {
689 GLbitfield mask
= ctx
->Light
._EnabledLights
;
691 const int i
= u_bit_scan(&mask
);
692 struct gl_light
*light
= &ctx
->Light
.Light
[i
];
693 SCALE_3V( light
->_MatSpecular
[1], light
->Specular
,
694 mat
[MAT_ATTRIB_BACK_SPECULAR
]);
701 * Update the current materials from the given rgba color
702 * according to the bitmask in _ColorMaterialBitmask, which is
703 * set by glColorMaterial().
706 _mesa_update_color_material( struct gl_context
*ctx
, const GLfloat color
[4] )
708 GLbitfield bitmask
= ctx
->Light
._ColorMaterialBitmask
;
709 struct gl_material
*mat
= &ctx
->Light
.Material
;
712 const int i
= u_bit_scan(&bitmask
);
714 COPY_4FV( mat
->Attrib
[i
], color
);
717 _mesa_update_material( ctx
, bitmask
);
722 _mesa_ColorMaterial( GLenum face
, GLenum mode
)
724 GET_CURRENT_CONTEXT(ctx
);
726 GLuint legal
= (MAT_BIT_FRONT_EMISSION
| MAT_BIT_BACK_EMISSION
|
727 MAT_BIT_FRONT_SPECULAR
| MAT_BIT_BACK_SPECULAR
|
728 MAT_BIT_FRONT_DIFFUSE
| MAT_BIT_BACK_DIFFUSE
|
729 MAT_BIT_FRONT_AMBIENT
| MAT_BIT_BACK_AMBIENT
);
731 if (MESA_VERBOSE
&VERBOSE_API
)
732 _mesa_debug(ctx
, "glColorMaterial %s %s\n",
733 _mesa_enum_to_string(face
),
734 _mesa_enum_to_string(mode
));
736 bitmask
= _mesa_material_bitmask(ctx
, face
, mode
, legal
, "glColorMaterial");
738 return; /* error was recorded */
740 if (ctx
->Light
._ColorMaterialBitmask
== bitmask
&&
741 ctx
->Light
.ColorMaterialFace
== face
&&
742 ctx
->Light
.ColorMaterialMode
== mode
)
745 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
746 ctx
->Light
._ColorMaterialBitmask
= bitmask
;
747 ctx
->Light
.ColorMaterialFace
= face
;
748 ctx
->Light
.ColorMaterialMode
= mode
;
750 if (ctx
->Light
.ColorMaterialEnabled
) {
751 FLUSH_CURRENT( ctx
, 0 );
752 _mesa_update_color_material(ctx
,ctx
->Current
.Attrib
[VERT_ATTRIB_COLOR0
]);
755 if (ctx
->Driver
.ColorMaterial
)
756 ctx
->Driver
.ColorMaterial( ctx
, face
, mode
);
761 _mesa_GetMaterialfv( GLenum face
, GLenum pname
, GLfloat
*params
)
763 GET_CURRENT_CONTEXT(ctx
);
765 GLfloat (*mat
)[4] = ctx
->Light
.Material
.Attrib
;
766 FLUSH_VERTICES(ctx
, 0); /* update materials */
768 FLUSH_CURRENT(ctx
, 0); /* update ctx->Light.Material from vertex buffer */
770 if (face
==GL_FRONT
) {
773 else if (face
==GL_BACK
) {
777 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetMaterialfv(face)" );
783 COPY_4FV( params
, mat
[MAT_ATTRIB_AMBIENT(f
)] );
786 COPY_4FV( params
, mat
[MAT_ATTRIB_DIFFUSE(f
)] );
789 COPY_4FV( params
, mat
[MAT_ATTRIB_SPECULAR(f
)] );
792 COPY_4FV( params
, mat
[MAT_ATTRIB_EMISSION(f
)] );
795 *params
= mat
[MAT_ATTRIB_SHININESS(f
)][0];
797 case GL_COLOR_INDEXES
:
798 if (ctx
->API
!= API_OPENGL_COMPAT
) {
799 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetMaterialfv(pname)" );
802 params
[0] = mat
[MAT_ATTRIB_INDEXES(f
)][0];
803 params
[1] = mat
[MAT_ATTRIB_INDEXES(f
)][1];
804 params
[2] = mat
[MAT_ATTRIB_INDEXES(f
)][2];
807 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetMaterialfv(pname)" );
813 _mesa_GetMaterialiv( GLenum face
, GLenum pname
, GLint
*params
)
815 GET_CURRENT_CONTEXT(ctx
);
817 GLfloat (*mat
)[4] = ctx
->Light
.Material
.Attrib
;
819 assert(ctx
->API
== API_OPENGL_COMPAT
);
821 FLUSH_VERTICES(ctx
, 0); /* update materials */
822 FLUSH_CURRENT(ctx
, 0); /* update ctx->Light.Material from vertex buffer */
824 if (face
==GL_FRONT
) {
827 else if (face
==GL_BACK
) {
831 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetMaterialiv(face)" );
836 params
[0] = FLOAT_TO_INT( mat
[MAT_ATTRIB_AMBIENT(f
)][0] );
837 params
[1] = FLOAT_TO_INT( mat
[MAT_ATTRIB_AMBIENT(f
)][1] );
838 params
[2] = FLOAT_TO_INT( mat
[MAT_ATTRIB_AMBIENT(f
)][2] );
839 params
[3] = FLOAT_TO_INT( mat
[MAT_ATTRIB_AMBIENT(f
)][3] );
842 params
[0] = FLOAT_TO_INT( mat
[MAT_ATTRIB_DIFFUSE(f
)][0] );
843 params
[1] = FLOAT_TO_INT( mat
[MAT_ATTRIB_DIFFUSE(f
)][1] );
844 params
[2] = FLOAT_TO_INT( mat
[MAT_ATTRIB_DIFFUSE(f
)][2] );
845 params
[3] = FLOAT_TO_INT( mat
[MAT_ATTRIB_DIFFUSE(f
)][3] );
848 params
[0] = FLOAT_TO_INT( mat
[MAT_ATTRIB_SPECULAR(f
)][0] );
849 params
[1] = FLOAT_TO_INT( mat
[MAT_ATTRIB_SPECULAR(f
)][1] );
850 params
[2] = FLOAT_TO_INT( mat
[MAT_ATTRIB_SPECULAR(f
)][2] );
851 params
[3] = FLOAT_TO_INT( mat
[MAT_ATTRIB_SPECULAR(f
)][3] );
854 params
[0] = FLOAT_TO_INT( mat
[MAT_ATTRIB_EMISSION(f
)][0] );
855 params
[1] = FLOAT_TO_INT( mat
[MAT_ATTRIB_EMISSION(f
)][1] );
856 params
[2] = FLOAT_TO_INT( mat
[MAT_ATTRIB_EMISSION(f
)][2] );
857 params
[3] = FLOAT_TO_INT( mat
[MAT_ATTRIB_EMISSION(f
)][3] );
860 *params
= IROUND( mat
[MAT_ATTRIB_SHININESS(f
)][0] );
862 case GL_COLOR_INDEXES
:
863 params
[0] = IROUND( mat
[MAT_ATTRIB_INDEXES(f
)][0] );
864 params
[1] = IROUND( mat
[MAT_ATTRIB_INDEXES(f
)][1] );
865 params
[2] = IROUND( mat
[MAT_ATTRIB_INDEXES(f
)][2] );
868 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetMaterialfv(pname)" );
875 * Examine current lighting parameters to determine if the optimized lighting
876 * function can be used.
877 * Also, precompute some lighting values such as the products of light
878 * source and material ambient, diffuse and specular coefficients.
881 _mesa_update_lighting( struct gl_context
*ctx
)
883 GLbitfield flags
= 0;
884 ctx
->Light
._NeedEyeCoords
= GL_FALSE
;
886 if (!ctx
->Light
.Enabled
)
889 GLbitfield mask
= ctx
->Light
._EnabledLights
;
891 const int i
= u_bit_scan(&mask
);
892 struct gl_light
*light
= &ctx
->Light
.Light
[i
];
893 flags
|= light
->_Flags
;
896 ctx
->Light
._NeedVertices
=
897 ((flags
& (LIGHT_POSITIONAL
|LIGHT_SPOT
)) ||
898 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
||
899 ctx
->Light
.Model
.LocalViewer
);
901 ctx
->Light
._NeedEyeCoords
= ((flags
& LIGHT_POSITIONAL
) ||
902 ctx
->Light
.Model
.LocalViewer
);
904 /* XXX: This test is overkill & needs to be fixed both for software and
905 * hardware t&l drivers. The above should be sufficient & should
906 * be tested to verify this.
908 if (ctx
->Light
._NeedVertices
)
909 ctx
->Light
._NeedEyeCoords
= GL_TRUE
;
911 /* Precompute some shading values. Although we reference
912 * Light.Material here, we can get away without flushing
913 * FLUSH_UPDATE_CURRENT, as when any outstanding material changes
914 * are flushed, they will update the derived state at that time.
916 if (ctx
->Light
.Model
.TwoSide
)
917 _mesa_update_material(ctx
,
918 MAT_BIT_FRONT_EMISSION
|
919 MAT_BIT_FRONT_AMBIENT
|
920 MAT_BIT_FRONT_DIFFUSE
|
921 MAT_BIT_FRONT_SPECULAR
|
922 MAT_BIT_BACK_EMISSION
|
923 MAT_BIT_BACK_AMBIENT
|
924 MAT_BIT_BACK_DIFFUSE
|
925 MAT_BIT_BACK_SPECULAR
);
927 _mesa_update_material(ctx
,
928 MAT_BIT_FRONT_EMISSION
|
929 MAT_BIT_FRONT_AMBIENT
|
930 MAT_BIT_FRONT_DIFFUSE
|
931 MAT_BIT_FRONT_SPECULAR
);
936 * Update state derived from light position, spot direction.
940 * _TNL_NEW_NEED_EYE_COORDS
942 * Update on (_NEW_MODELVIEW | _NEW_LIGHT) when lighting is enabled.
943 * Also update on lighting space changes.
946 compute_light_positions( struct gl_context
*ctx
)
948 static const GLfloat eye_z
[3] = { 0, 0, 1 };
950 if (!ctx
->Light
.Enabled
)
953 if (ctx
->_NeedEyeCoords
) {
954 COPY_3V( ctx
->_EyeZDir
, eye_z
);
957 TRANSFORM_NORMAL( ctx
->_EyeZDir
, eye_z
, ctx
->ModelviewMatrixStack
.Top
->m
);
960 GLbitfield mask
= ctx
->Light
._EnabledLights
;
962 const int i
= u_bit_scan(&mask
);
963 struct gl_light
*light
= &ctx
->Light
.Light
[i
];
965 if (ctx
->_NeedEyeCoords
) {
966 /* _Position is in eye coordinate space */
967 COPY_4FV( light
->_Position
, light
->EyePosition
);
970 /* _Position is in object coordinate space */
971 TRANSFORM_POINT( light
->_Position
, ctx
->ModelviewMatrixStack
.Top
->inv
,
972 light
->EyePosition
);
975 if (!(light
->_Flags
& LIGHT_POSITIONAL
)) {
976 /* VP (VP) = Normalize( Position ) */
977 COPY_3V( light
->_VP_inf_norm
, light
->_Position
);
978 NORMALIZE_3FV( light
->_VP_inf_norm
);
980 if (!ctx
->Light
.Model
.LocalViewer
) {
981 /* _h_inf_norm = Normalize( V_to_P + <0,0,1> ) */
982 ADD_3V( light
->_h_inf_norm
, light
->_VP_inf_norm
, ctx
->_EyeZDir
);
983 NORMALIZE_3FV( light
->_h_inf_norm
);
985 light
->_VP_inf_spot_attenuation
= 1.0;
988 /* positional light w/ homogeneous coordinate, divide by W */
989 GLfloat wInv
= 1.0F
/ light
->_Position
[3];
990 light
->_Position
[0] *= wInv
;
991 light
->_Position
[1] *= wInv
;
992 light
->_Position
[2] *= wInv
;
995 if (light
->_Flags
& LIGHT_SPOT
) {
996 /* Note: we normalize the spot direction now */
998 if (ctx
->_NeedEyeCoords
) {
999 COPY_3V( light
->_NormSpotDirection
, light
->SpotDirection
);
1000 NORMALIZE_3FV( light
->_NormSpotDirection
);
1004 COPY_3V(spotDir
, light
->SpotDirection
);
1005 NORMALIZE_3FV(spotDir
);
1006 TRANSFORM_NORMAL( light
->_NormSpotDirection
,
1008 ctx
->ModelviewMatrixStack
.Top
->m
);
1011 NORMALIZE_3FV( light
->_NormSpotDirection
);
1013 if (!(light
->_Flags
& LIGHT_POSITIONAL
)) {
1014 GLfloat PV_dot_dir
= - DOT3(light
->_VP_inf_norm
,
1015 light
->_NormSpotDirection
);
1017 if (PV_dot_dir
> light
->_CosCutoff
) {
1018 light
->_VP_inf_spot_attenuation
=
1019 powf(PV_dot_dir
, light
->SpotExponent
);
1022 light
->_VP_inf_spot_attenuation
= 0;
1032 update_modelview_scale( struct gl_context
*ctx
)
1034 ctx
->_ModelViewInvScale
= 1.0F
;
1035 if (!_math_matrix_is_length_preserving(ctx
->ModelviewMatrixStack
.Top
)) {
1036 const GLfloat
*m
= ctx
->ModelviewMatrixStack
.Top
->inv
;
1037 GLfloat f
= m
[2] * m
[2] + m
[6] * m
[6] + m
[10] * m
[10];
1038 if (f
< 1e-12f
) f
= 1.0f
;
1039 if (ctx
->_NeedEyeCoords
)
1040 ctx
->_ModelViewInvScale
= 1.0f
/ sqrtf(f
);
1042 ctx
->_ModelViewInvScale
= sqrtf(f
);
1048 * Bring up to date any state that relies on _NeedEyeCoords.
1051 _mesa_update_tnl_spaces( struct gl_context
*ctx
, GLuint new_state
)
1053 const GLuint oldneedeyecoords
= ctx
->_NeedEyeCoords
;
1056 ctx
->_NeedEyeCoords
= GL_FALSE
;
1058 if (ctx
->_ForceEyeCoords
||
1059 (ctx
->Texture
._GenFlags
& TEXGEN_NEED_EYE_COORD
) ||
1060 ctx
->Point
._Attenuated
||
1061 ctx
->Light
._NeedEyeCoords
)
1062 ctx
->_NeedEyeCoords
= GL_TRUE
;
1064 if (ctx
->Light
.Enabled
&&
1065 !_math_matrix_is_length_preserving(ctx
->ModelviewMatrixStack
.Top
))
1066 ctx
->_NeedEyeCoords
= GL_TRUE
;
1068 /* Check if the truth-value interpretations of the bitfields have
1071 if (oldneedeyecoords
!= ctx
->_NeedEyeCoords
) {
1072 /* Recalculate all state that depends on _NeedEyeCoords.
1074 update_modelview_scale(ctx
);
1075 compute_light_positions( ctx
);
1077 if (ctx
->Driver
.LightingSpaceChange
)
1078 ctx
->Driver
.LightingSpaceChange( ctx
);
1081 GLuint new_state2
= ctx
->NewState
;
1083 /* Recalculate that same state only if it has been invalidated
1084 * by other statechanges.
1086 if (new_state2
& _NEW_MODELVIEW
)
1087 update_modelview_scale(ctx
);
1089 if (new_state2
& (_NEW_LIGHT
|_NEW_MODELVIEW
))
1090 compute_light_positions( ctx
);
1096 * Drivers may need this if the hardware tnl unit doesn't support the
1097 * light-in-modelspace optimization. It's also useful for debugging.
1100 _mesa_allow_light_in_model( struct gl_context
*ctx
, GLboolean flag
)
1102 ctx
->_ForceEyeCoords
= !flag
;
1103 ctx
->NewState
|= _NEW_POINT
; /* one of the bits from
1104 * _MESA_NEW_NEED_EYE_COORDS.
1110 /**********************************************************************/
1111 /***** Initialization *****/
1112 /**********************************************************************/
1115 * Initialize the n-th light data structure.
1117 * \param l pointer to the gl_light structure to be initialized.
1118 * \param n number of the light.
1119 * \note The defaults for light 0 are different than the other lights.
1122 init_light( struct gl_light
*l
, GLuint n
)
1124 ASSIGN_4V( l
->Ambient
, 0.0, 0.0, 0.0, 1.0 );
1126 ASSIGN_4V( l
->Diffuse
, 1.0, 1.0, 1.0, 1.0 );
1127 ASSIGN_4V( l
->Specular
, 1.0, 1.0, 1.0, 1.0 );
1130 ASSIGN_4V( l
->Diffuse
, 0.0, 0.0, 0.0, 1.0 );
1131 ASSIGN_4V( l
->Specular
, 0.0, 0.0, 0.0, 1.0 );
1133 ASSIGN_4V( l
->EyePosition
, 0.0, 0.0, 1.0, 0.0 );
1134 ASSIGN_3V( l
->SpotDirection
, 0.0, 0.0, -1.0 );
1135 l
->SpotExponent
= 0.0;
1136 l
->SpotCutoff
= 180.0;
1137 l
->_CosCutoff
= 0.0; /* KW: -ve values not admitted */
1138 l
->ConstantAttenuation
= 1.0;
1139 l
->LinearAttenuation
= 0.0;
1140 l
->QuadraticAttenuation
= 0.0;
1141 l
->Enabled
= GL_FALSE
;
1146 * Initialize the light model data structure.
1148 * \param lm pointer to the gl_lightmodel structure to be initialized.
1151 init_lightmodel( struct gl_lightmodel
*lm
)
1153 ASSIGN_4V( lm
->Ambient
, 0.2F
, 0.2F
, 0.2F
, 1.0F
);
1154 lm
->LocalViewer
= GL_FALSE
;
1155 lm
->TwoSide
= GL_FALSE
;
1156 lm
->ColorControl
= GL_SINGLE_COLOR
;
1161 * Initialize the material data structure.
1163 * \param m pointer to the gl_material structure to be initialized.
1166 init_material( struct gl_material
*m
)
1168 ASSIGN_4V( m
->Attrib
[MAT_ATTRIB_FRONT_AMBIENT
], 0.2F
, 0.2F
, 0.2F
, 1.0F
);
1169 ASSIGN_4V( m
->Attrib
[MAT_ATTRIB_FRONT_DIFFUSE
], 0.8F
, 0.8F
, 0.8F
, 1.0F
);
1170 ASSIGN_4V( m
->Attrib
[MAT_ATTRIB_FRONT_SPECULAR
], 0.0F
, 0.0F
, 0.0F
, 1.0F
);
1171 ASSIGN_4V( m
->Attrib
[MAT_ATTRIB_FRONT_EMISSION
], 0.0F
, 0.0F
, 0.0F
, 1.0F
);
1172 ASSIGN_4V( m
->Attrib
[MAT_ATTRIB_FRONT_SHININESS
], 0.0F
, 0.0F
, 0.0F
, 0.0F
);
1173 ASSIGN_4V( m
->Attrib
[MAT_ATTRIB_FRONT_INDEXES
], 0.0F
, 1.0F
, 1.0F
, 0.0F
);
1175 ASSIGN_4V( m
->Attrib
[MAT_ATTRIB_BACK_AMBIENT
], 0.2F
, 0.2F
, 0.2F
, 1.0F
);
1176 ASSIGN_4V( m
->Attrib
[MAT_ATTRIB_BACK_DIFFUSE
], 0.8F
, 0.8F
, 0.8F
, 1.0F
);
1177 ASSIGN_4V( m
->Attrib
[MAT_ATTRIB_BACK_SPECULAR
], 0.0F
, 0.0F
, 0.0F
, 1.0F
);
1178 ASSIGN_4V( m
->Attrib
[MAT_ATTRIB_BACK_EMISSION
], 0.0F
, 0.0F
, 0.0F
, 1.0F
);
1179 ASSIGN_4V( m
->Attrib
[MAT_ATTRIB_BACK_SHININESS
], 0.0F
, 0.0F
, 0.0F
, 0.0F
);
1180 ASSIGN_4V( m
->Attrib
[MAT_ATTRIB_BACK_INDEXES
], 0.0F
, 1.0F
, 1.0F
, 0.0F
);
1185 * Initialize all lighting state for the given context.
1188 _mesa_init_lighting( struct gl_context
*ctx
)
1192 /* Lighting group */
1193 ctx
->Light
._EnabledLights
= 0;
1194 for (i
= 0; i
< MAX_LIGHTS
; i
++) {
1195 init_light( &ctx
->Light
.Light
[i
], i
);
1198 init_lightmodel( &ctx
->Light
.Model
);
1199 init_material( &ctx
->Light
.Material
);
1200 ctx
->Light
.ShadeModel
= GL_SMOOTH
;
1201 ctx
->Light
.ProvokingVertex
= GL_LAST_VERTEX_CONVENTION_EXT
;
1202 ctx
->Light
.Enabled
= GL_FALSE
;
1203 ctx
->Light
.ColorMaterialFace
= GL_FRONT_AND_BACK
;
1204 ctx
->Light
.ColorMaterialMode
= GL_AMBIENT_AND_DIFFUSE
;
1205 ctx
->Light
._ColorMaterialBitmask
= _mesa_material_bitmask( ctx
,
1207 GL_AMBIENT_AND_DIFFUSE
, ~0,
1210 ctx
->Light
.ColorMaterialEnabled
= GL_FALSE
;
1211 ctx
->Light
.ClampVertexColor
= ctx
->API
== API_OPENGL_COMPAT
;
1212 ctx
->Light
._ClampVertexColor
= ctx
->API
== API_OPENGL_COMPAT
;
1215 ctx
->Light
._NeedEyeCoords
= GL_FALSE
;
1216 ctx
->_NeedEyeCoords
= GL_FALSE
;
1217 ctx
->_ForceEyeCoords
= GL_FALSE
;
1218 ctx
->_ModelViewInvScale
= 1.0;