2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2005 Brian Paul 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 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 #include "simple_list.h"
34 #include "math/m_matrix.h"
38 _mesa_ShadeModel( GLenum mode
)
40 GET_CURRENT_CONTEXT(ctx
);
41 ASSERT_OUTSIDE_BEGIN_END(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
;
56 ctx
->_TriangleCaps
^= DD_FLATSHADE
;
57 if (ctx
->Driver
.ShadeModel
)
58 (*ctx
->Driver
.ShadeModel
)( ctx
, mode
);
63 _mesa_Lightf( GLenum light
, GLenum pname
, GLfloat param
)
65 _mesa_Lightfv( light
, pname
, ¶m
);
70 _mesa_Lightfv( GLenum light
, GLenum pname
, const GLfloat
*params
)
72 GET_CURRENT_CONTEXT(ctx
);
73 GLint i
= (GLint
) (light
- GL_LIGHT0
);
74 struct gl_light
*l
= &ctx
->Light
.Light
[i
];
76 if (i
< 0 || i
>= (GLint
) ctx
->Const
.MaxLights
) {
77 _mesa_error( ctx
, GL_INVALID_ENUM
, "glLight(light=0x%x)", light
);
83 if (TEST_EQ_4V(l
->Ambient
, params
))
85 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
86 COPY_4V( l
->Ambient
, params
);
89 if (TEST_EQ_4V(l
->Diffuse
, params
))
91 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
92 COPY_4V( l
->Diffuse
, params
);
95 if (TEST_EQ_4V(l
->Specular
, params
))
97 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
98 COPY_4V( l
->Specular
, params
);
102 /* transform position by ModelView matrix */
103 TRANSFORM_POINT( tmp
, ctx
->ModelviewMatrixStack
.Top
->m
, params
);
104 if (TEST_EQ_4V(l
->EyePosition
, tmp
))
106 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
107 COPY_4V(l
->EyePosition
, tmp
);
108 if (l
->EyePosition
[3] != 0.0F
)
109 l
->_Flags
|= LIGHT_POSITIONAL
;
111 l
->_Flags
&= ~LIGHT_POSITIONAL
;
114 case GL_SPOT_DIRECTION
: {
116 /* transform direction by inverse modelview */
117 if (_math_matrix_is_dirty(ctx
->ModelviewMatrixStack
.Top
)) {
118 _math_matrix_analyse( ctx
->ModelviewMatrixStack
.Top
);
120 TRANSFORM_NORMAL( tmp
, params
, ctx
->ModelviewMatrixStack
.Top
->inv
);
121 if (TEST_EQ_3V(l
->EyeDirection
, tmp
))
123 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
124 COPY_3V(l
->EyeDirection
, tmp
);
127 case GL_SPOT_EXPONENT
:
128 if (params
[0]<0.0 || params
[0]>ctx
->Const
.MaxSpotExponent
) {
129 _mesa_error( ctx
, GL_INVALID_VALUE
, "glLight" );
132 if (l
->SpotExponent
== params
[0])
134 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
135 l
->SpotExponent
= params
[0];
136 _mesa_invalidate_spot_exp_table( l
);
139 if ((params
[0]<0.0 || params
[0]>90.0) && params
[0]!=180.0) {
140 _mesa_error( ctx
, GL_INVALID_VALUE
, "glLight" );
143 if (l
->SpotCutoff
== params
[0])
145 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
146 l
->SpotCutoff
= params
[0];
147 l
->_CosCutoff
= (GLfloat
) _mesa_cos(params
[0]*DEG2RAD
);
148 if (l
->_CosCutoff
< 0)
150 if (l
->SpotCutoff
!= 180.0F
)
151 l
->_Flags
|= LIGHT_SPOT
;
153 l
->_Flags
&= ~LIGHT_SPOT
;
155 case GL_CONSTANT_ATTENUATION
:
157 _mesa_error( ctx
, GL_INVALID_VALUE
, "glLight" );
160 if (l
->ConstantAttenuation
== params
[0])
162 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
163 l
->ConstantAttenuation
= params
[0];
165 case GL_LINEAR_ATTENUATION
:
167 _mesa_error( ctx
, GL_INVALID_VALUE
, "glLight" );
170 if (l
->LinearAttenuation
== params
[0])
172 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
173 l
->LinearAttenuation
= params
[0];
175 case GL_QUADRATIC_ATTENUATION
:
177 _mesa_error( ctx
, GL_INVALID_VALUE
, "glLight" );
180 if (l
->QuadraticAttenuation
== params
[0])
182 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
183 l
->QuadraticAttenuation
= params
[0];
186 _mesa_error( ctx
, GL_INVALID_ENUM
, "glLight(pname=0x%x)", pname
);
190 if (ctx
->Driver
.Lightfv
)
191 ctx
->Driver
.Lightfv( ctx
, light
, pname
, params
);
196 _mesa_Lighti( GLenum light
, GLenum pname
, GLint param
)
198 _mesa_Lightiv( light
, pname
, ¶m
);
203 _mesa_Lightiv( GLenum light
, GLenum pname
, const GLint
*params
)
211 fparam
[0] = INT_TO_FLOAT( params
[0] );
212 fparam
[1] = INT_TO_FLOAT( params
[1] );
213 fparam
[2] = INT_TO_FLOAT( params
[2] );
214 fparam
[3] = INT_TO_FLOAT( params
[3] );
217 fparam
[0] = (GLfloat
) params
[0];
218 fparam
[1] = (GLfloat
) params
[1];
219 fparam
[2] = (GLfloat
) params
[2];
220 fparam
[3] = (GLfloat
) params
[3];
222 case GL_SPOT_DIRECTION
:
223 fparam
[0] = (GLfloat
) params
[0];
224 fparam
[1] = (GLfloat
) params
[1];
225 fparam
[2] = (GLfloat
) params
[2];
227 case GL_SPOT_EXPONENT
:
229 case GL_CONSTANT_ATTENUATION
:
230 case GL_LINEAR_ATTENUATION
:
231 case GL_QUADRATIC_ATTENUATION
:
232 fparam
[0] = (GLfloat
) params
[0];
235 /* error will be caught later in gl_Lightfv */
239 _mesa_Lightfv( light
, pname
, fparam
);
245 _mesa_GetLightfv( GLenum light
, GLenum pname
, GLfloat
*params
)
247 GET_CURRENT_CONTEXT(ctx
);
248 GLint l
= (GLint
) (light
- GL_LIGHT0
);
249 ASSERT_OUTSIDE_BEGIN_END(ctx
);
251 if (l
< 0 || l
>= (GLint
) ctx
->Const
.MaxLights
) {
252 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetLightfv" );
258 COPY_4V( params
, ctx
->Light
.Light
[l
].Ambient
);
261 COPY_4V( params
, ctx
->Light
.Light
[l
].Diffuse
);
264 COPY_4V( params
, ctx
->Light
.Light
[l
].Specular
);
267 COPY_4V( params
, ctx
->Light
.Light
[l
].EyePosition
);
269 case GL_SPOT_DIRECTION
:
270 COPY_3V( params
, ctx
->Light
.Light
[l
].EyeDirection
);
272 case GL_SPOT_EXPONENT
:
273 params
[0] = ctx
->Light
.Light
[l
].SpotExponent
;
276 params
[0] = ctx
->Light
.Light
[l
].SpotCutoff
;
278 case GL_CONSTANT_ATTENUATION
:
279 params
[0] = ctx
->Light
.Light
[l
].ConstantAttenuation
;
281 case GL_LINEAR_ATTENUATION
:
282 params
[0] = ctx
->Light
.Light
[l
].LinearAttenuation
;
284 case GL_QUADRATIC_ATTENUATION
:
285 params
[0] = ctx
->Light
.Light
[l
].QuadraticAttenuation
;
288 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetLightfv" );
295 _mesa_GetLightiv( GLenum light
, GLenum pname
, GLint
*params
)
297 GET_CURRENT_CONTEXT(ctx
);
298 GLint l
= (GLint
) (light
- GL_LIGHT0
);
299 ASSERT_OUTSIDE_BEGIN_END(ctx
);
301 if (l
< 0 || l
>= (GLint
) ctx
->Const
.MaxLights
) {
302 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetLightiv" );
308 params
[0] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Ambient
[0]);
309 params
[1] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Ambient
[1]);
310 params
[2] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Ambient
[2]);
311 params
[3] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Ambient
[3]);
314 params
[0] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Diffuse
[0]);
315 params
[1] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Diffuse
[1]);
316 params
[2] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Diffuse
[2]);
317 params
[3] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Diffuse
[3]);
320 params
[0] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Specular
[0]);
321 params
[1] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Specular
[1]);
322 params
[2] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Specular
[2]);
323 params
[3] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Specular
[3]);
326 params
[0] = (GLint
) ctx
->Light
.Light
[l
].EyePosition
[0];
327 params
[1] = (GLint
) ctx
->Light
.Light
[l
].EyePosition
[1];
328 params
[2] = (GLint
) ctx
->Light
.Light
[l
].EyePosition
[2];
329 params
[3] = (GLint
) ctx
->Light
.Light
[l
].EyePosition
[3];
331 case GL_SPOT_DIRECTION
:
332 params
[0] = (GLint
) ctx
->Light
.Light
[l
].EyeDirection
[0];
333 params
[1] = (GLint
) ctx
->Light
.Light
[l
].EyeDirection
[1];
334 params
[2] = (GLint
) ctx
->Light
.Light
[l
].EyeDirection
[2];
336 case GL_SPOT_EXPONENT
:
337 params
[0] = (GLint
) ctx
->Light
.Light
[l
].SpotExponent
;
340 params
[0] = (GLint
) ctx
->Light
.Light
[l
].SpotCutoff
;
342 case GL_CONSTANT_ATTENUATION
:
343 params
[0] = (GLint
) ctx
->Light
.Light
[l
].ConstantAttenuation
;
345 case GL_LINEAR_ATTENUATION
:
346 params
[0] = (GLint
) ctx
->Light
.Light
[l
].LinearAttenuation
;
348 case GL_QUADRATIC_ATTENUATION
:
349 params
[0] = (GLint
) ctx
->Light
.Light
[l
].QuadraticAttenuation
;
352 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetLightiv" );
359 /**********************************************************************/
360 /*** Light Model ***/
361 /**********************************************************************/
365 _mesa_LightModelfv( GLenum pname
, const GLfloat
*params
)
369 GET_CURRENT_CONTEXT(ctx
);
370 ASSERT_OUTSIDE_BEGIN_END(ctx
);
373 case GL_LIGHT_MODEL_AMBIENT
:
374 if (TEST_EQ_4V( ctx
->Light
.Model
.Ambient
, params
))
376 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
377 COPY_4V( ctx
->Light
.Model
.Ambient
, params
);
379 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
380 newbool
= (params
[0]!=0.0);
381 if (ctx
->Light
.Model
.LocalViewer
== newbool
)
383 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
384 ctx
->Light
.Model
.LocalViewer
= newbool
;
386 case GL_LIGHT_MODEL_TWO_SIDE
:
387 newbool
= (params
[0]!=0.0);
388 if (ctx
->Light
.Model
.TwoSide
== newbool
)
390 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
391 ctx
->Light
.Model
.TwoSide
= newbool
;
393 if (ctx
->Light
.Enabled
&& ctx
->Light
.Model
.TwoSide
)
394 ctx
->_TriangleCaps
|= DD_TRI_LIGHT_TWOSIDE
;
396 ctx
->_TriangleCaps
&= ~DD_TRI_LIGHT_TWOSIDE
;
398 case GL_LIGHT_MODEL_COLOR_CONTROL
:
399 if (params
[0] == (GLfloat
) GL_SINGLE_COLOR
)
400 newenum
= GL_SINGLE_COLOR
;
401 else if (params
[0] == (GLfloat
) GL_SEPARATE_SPECULAR_COLOR
)
402 newenum
= GL_SEPARATE_SPECULAR_COLOR
;
404 _mesa_error( ctx
, GL_INVALID_ENUM
, "glLightModel(param=0x0%x)",
408 if (ctx
->Light
.Model
.ColorControl
== newenum
)
410 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
411 ctx
->Light
.Model
.ColorControl
= newenum
;
414 _mesa_error( ctx
, GL_INVALID_ENUM
, "glLightModel(pname=0x%x)", pname
);
418 if (ctx
->Driver
.LightModelfv
)
419 ctx
->Driver
.LightModelfv( ctx
, pname
, params
);
424 _mesa_LightModeliv( GLenum pname
, const GLint
*params
)
429 case GL_LIGHT_MODEL_AMBIENT
:
430 fparam
[0] = INT_TO_FLOAT( params
[0] );
431 fparam
[1] = INT_TO_FLOAT( params
[1] );
432 fparam
[2] = INT_TO_FLOAT( params
[2] );
433 fparam
[3] = INT_TO_FLOAT( params
[3] );
435 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
436 case GL_LIGHT_MODEL_TWO_SIDE
:
437 case GL_LIGHT_MODEL_COLOR_CONTROL
:
438 fparam
[0] = (GLfloat
) params
[0];
441 /* Error will be caught later in gl_LightModelfv */
444 _mesa_LightModelfv( pname
, fparam
);
449 _mesa_LightModeli( GLenum pname
, GLint param
)
451 _mesa_LightModeliv( pname
, ¶m
);
456 _mesa_LightModelf( GLenum pname
, GLfloat param
)
458 _mesa_LightModelfv( pname
, ¶m
);
463 /********** MATERIAL **********/
467 * Given a face and pname value (ala glColorMaterial), compute a bitmask
468 * of the targeted material values.
471 _mesa_material_bitmask( GLcontext
*ctx
, GLenum face
, GLenum pname
,
472 GLuint legal
, const char *where
)
476 /* Make a bitmask indicating what material attribute(s) we're updating */
479 bitmask
|= MAT_BIT_FRONT_EMISSION
| MAT_BIT_BACK_EMISSION
;
482 bitmask
|= MAT_BIT_FRONT_AMBIENT
| MAT_BIT_BACK_AMBIENT
;
485 bitmask
|= MAT_BIT_FRONT_DIFFUSE
| MAT_BIT_BACK_DIFFUSE
;
488 bitmask
|= MAT_BIT_FRONT_SPECULAR
| MAT_BIT_BACK_SPECULAR
;
491 bitmask
|= MAT_BIT_FRONT_SHININESS
| MAT_BIT_BACK_SHININESS
;
493 case GL_AMBIENT_AND_DIFFUSE
:
494 bitmask
|= MAT_BIT_FRONT_AMBIENT
| MAT_BIT_BACK_AMBIENT
;
495 bitmask
|= MAT_BIT_FRONT_DIFFUSE
| MAT_BIT_BACK_DIFFUSE
;
497 case GL_COLOR_INDEXES
:
498 bitmask
|= MAT_BIT_FRONT_INDEXES
| MAT_BIT_BACK_INDEXES
;
501 _mesa_error( ctx
, GL_INVALID_ENUM
, where
);
505 if (face
==GL_FRONT
) {
506 bitmask
&= FRONT_MATERIAL_BITS
;
508 else if (face
==GL_BACK
) {
509 bitmask
&= BACK_MATERIAL_BITS
;
511 else if (face
!= GL_FRONT_AND_BACK
) {
512 _mesa_error( ctx
, GL_INVALID_ENUM
, where
);
516 if (bitmask
& ~legal
) {
517 _mesa_error( ctx
, GL_INVALID_ENUM
, where
);
526 /* Perform a straight copy between materials.
529 _mesa_copy_materials( struct gl_material
*dst
,
530 const struct gl_material
*src
,
535 for (i
= 0 ; i
< MAT_ATTRIB_MAX
; i
++)
536 if (bitmask
& (1<<i
))
537 COPY_4FV( dst
->Attrib
[i
], src
->Attrib
[i
] );
542 /* Update derived values following a change in ctx->Light.Material
545 _mesa_update_material( GLcontext
*ctx
, GLuint bitmask
)
547 struct gl_light
*light
, *list
= &ctx
->Light
.EnabledList
;
548 GLfloat (*mat
)[4] = ctx
->Light
.Material
.Attrib
;
550 if (MESA_VERBOSE
&VERBOSE_IMMEDIATE
)
551 _mesa_debug(ctx
, "_mesa_update_material, mask 0x%x\n", bitmask
);
556 /* update material ambience */
557 if (bitmask
& MAT_BIT_FRONT_AMBIENT
) {
558 foreach (light
, list
) {
559 SCALE_3V( light
->_MatAmbient
[0], light
->Ambient
,
560 mat
[MAT_ATTRIB_FRONT_AMBIENT
]);
564 if (bitmask
& MAT_BIT_BACK_AMBIENT
) {
565 foreach (light
, list
) {
566 SCALE_3V( light
->_MatAmbient
[1], light
->Ambient
,
567 mat
[MAT_ATTRIB_BACK_AMBIENT
]);
571 /* update BaseColor = emission + scene's ambience * material's ambience */
572 if (bitmask
& (MAT_BIT_FRONT_EMISSION
| MAT_BIT_FRONT_AMBIENT
)) {
573 COPY_3V( ctx
->Light
._BaseColor
[0], mat
[MAT_ATTRIB_FRONT_EMISSION
] );
574 ACC_SCALE_3V( ctx
->Light
._BaseColor
[0], mat
[MAT_ATTRIB_FRONT_AMBIENT
],
575 ctx
->Light
.Model
.Ambient
);
578 if (bitmask
& (MAT_BIT_BACK_EMISSION
| MAT_BIT_BACK_AMBIENT
)) {
579 COPY_3V( ctx
->Light
._BaseColor
[1], mat
[MAT_ATTRIB_BACK_EMISSION
] );
580 ACC_SCALE_3V( ctx
->Light
._BaseColor
[1], mat
[MAT_ATTRIB_BACK_AMBIENT
],
581 ctx
->Light
.Model
.Ambient
);
584 /* update material diffuse values */
585 if (bitmask
& MAT_BIT_FRONT_DIFFUSE
) {
586 foreach (light
, list
) {
587 SCALE_3V( light
->_MatDiffuse
[0], light
->Diffuse
,
588 mat
[MAT_ATTRIB_FRONT_DIFFUSE
] );
592 if (bitmask
& MAT_BIT_BACK_DIFFUSE
) {
593 foreach (light
, list
) {
594 SCALE_3V( light
->_MatDiffuse
[1], light
->Diffuse
,
595 mat
[MAT_ATTRIB_BACK_DIFFUSE
] );
599 /* update material specular values */
600 if (bitmask
& MAT_BIT_FRONT_SPECULAR
) {
601 foreach (light
, list
) {
602 SCALE_3V( light
->_MatSpecular
[0], light
->Specular
,
603 mat
[MAT_ATTRIB_FRONT_SPECULAR
]);
607 if (bitmask
& MAT_BIT_BACK_SPECULAR
) {
608 foreach (light
, list
) {
609 SCALE_3V( light
->_MatSpecular
[1], light
->Specular
,
610 mat
[MAT_ATTRIB_BACK_SPECULAR
]);
614 if (bitmask
& MAT_BIT_FRONT_SHININESS
) {
615 _mesa_invalidate_shine_table( ctx
, 0 );
618 if (bitmask
& MAT_BIT_BACK_SHININESS
) {
619 _mesa_invalidate_shine_table( ctx
, 1 );
625 * Update the current materials from the given rgba color
626 * according to the bitmask in ColorMaterialBitmask, which is
627 * set by glColorMaterial().
630 _mesa_update_color_material( GLcontext
*ctx
, const GLfloat color
[4] )
632 GLuint bitmask
= ctx
->Light
.ColorMaterialBitmask
;
633 struct gl_material
*mat
= &ctx
->Light
.Material
;
636 for (i
= 0 ; i
< MAT_ATTRIB_MAX
; i
++)
637 if (bitmask
& (1<<i
))
638 COPY_4FV( mat
->Attrib
[i
], color
);
640 _mesa_update_material( ctx
, bitmask
);
645 _mesa_ColorMaterial( GLenum face
, GLenum mode
)
647 GET_CURRENT_CONTEXT(ctx
);
649 GLuint legal
= (MAT_BIT_FRONT_EMISSION
| MAT_BIT_BACK_EMISSION
|
650 MAT_BIT_FRONT_SPECULAR
| MAT_BIT_BACK_SPECULAR
|
651 MAT_BIT_FRONT_DIFFUSE
| MAT_BIT_BACK_DIFFUSE
|
652 MAT_BIT_FRONT_AMBIENT
| MAT_BIT_BACK_AMBIENT
);
653 ASSERT_OUTSIDE_BEGIN_END(ctx
);
655 if (MESA_VERBOSE
&VERBOSE_API
)
656 _mesa_debug(ctx
, "glColorMaterial %s %s\n",
657 _mesa_lookup_enum_by_nr(face
),
658 _mesa_lookup_enum_by_nr(mode
));
660 bitmask
= _mesa_material_bitmask(ctx
, face
, mode
, legal
, "glColorMaterial");
662 if (ctx
->Light
.ColorMaterialBitmask
== bitmask
&&
663 ctx
->Light
.ColorMaterialFace
== face
&&
664 ctx
->Light
.ColorMaterialMode
== mode
)
667 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
668 ctx
->Light
.ColorMaterialBitmask
= bitmask
;
669 ctx
->Light
.ColorMaterialFace
= face
;
670 ctx
->Light
.ColorMaterialMode
= mode
;
672 if (ctx
->Light
.ColorMaterialEnabled
) {
673 FLUSH_CURRENT( ctx
, 0 );
674 _mesa_update_color_material(ctx
,ctx
->Current
.Attrib
[VERT_ATTRIB_COLOR0
]);
677 if (ctx
->Driver
.ColorMaterial
)
678 (*ctx
->Driver
.ColorMaterial
)( ctx
, face
, mode
);
683 _mesa_GetMaterialfv( GLenum face
, GLenum pname
, GLfloat
*params
)
685 GET_CURRENT_CONTEXT(ctx
);
687 GLfloat (*mat
)[4] = ctx
->Light
.Material
.Attrib
;
688 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
); /* update materials */
690 FLUSH_CURRENT(ctx
, 0); /* update ctx->Light.Material from vertex buffer */
692 if (face
==GL_FRONT
) {
695 else if (face
==GL_BACK
) {
699 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetMaterialfv(face)" );
705 COPY_4FV( params
, mat
[MAT_ATTRIB_AMBIENT(f
)] );
708 COPY_4FV( params
, mat
[MAT_ATTRIB_DIFFUSE(f
)] );
711 COPY_4FV( params
, mat
[MAT_ATTRIB_SPECULAR(f
)] );
714 COPY_4FV( params
, mat
[MAT_ATTRIB_EMISSION(f
)] );
717 *params
= mat
[MAT_ATTRIB_SHININESS(f
)][0];
719 case GL_COLOR_INDEXES
:
720 params
[0] = mat
[MAT_ATTRIB_INDEXES(f
)][0];
721 params
[1] = mat
[MAT_ATTRIB_INDEXES(f
)][1];
722 params
[2] = mat
[MAT_ATTRIB_INDEXES(f
)][2];
725 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetMaterialfv(pname)" );
731 _mesa_GetMaterialiv( GLenum face
, GLenum pname
, GLint
*params
)
733 GET_CURRENT_CONTEXT(ctx
);
735 GLfloat (*mat
)[4] = ctx
->Light
.Material
.Attrib
;
736 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
); /* update materials */
738 FLUSH_CURRENT(ctx
, 0); /* update ctx->Light.Material from vertex buffer */
740 if (face
==GL_FRONT
) {
743 else if (face
==GL_BACK
) {
747 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetMaterialiv(face)" );
752 params
[0] = FLOAT_TO_INT( mat
[MAT_ATTRIB_AMBIENT(f
)][0] );
753 params
[1] = FLOAT_TO_INT( mat
[MAT_ATTRIB_AMBIENT(f
)][1] );
754 params
[2] = FLOAT_TO_INT( mat
[MAT_ATTRIB_AMBIENT(f
)][2] );
755 params
[3] = FLOAT_TO_INT( mat
[MAT_ATTRIB_AMBIENT(f
)][3] );
758 params
[0] = FLOAT_TO_INT( mat
[MAT_ATTRIB_DIFFUSE(f
)][0] );
759 params
[1] = FLOAT_TO_INT( mat
[MAT_ATTRIB_DIFFUSE(f
)][1] );
760 params
[2] = FLOAT_TO_INT( mat
[MAT_ATTRIB_DIFFUSE(f
)][2] );
761 params
[3] = FLOAT_TO_INT( mat
[MAT_ATTRIB_DIFFUSE(f
)][3] );
764 params
[0] = FLOAT_TO_INT( mat
[MAT_ATTRIB_SPECULAR(f
)][0] );
765 params
[1] = FLOAT_TO_INT( mat
[MAT_ATTRIB_SPECULAR(f
)][1] );
766 params
[2] = FLOAT_TO_INT( mat
[MAT_ATTRIB_SPECULAR(f
)][2] );
767 params
[3] = FLOAT_TO_INT( mat
[MAT_ATTRIB_SPECULAR(f
)][3] );
770 params
[0] = FLOAT_TO_INT( mat
[MAT_ATTRIB_EMISSION(f
)][0] );
771 params
[1] = FLOAT_TO_INT( mat
[MAT_ATTRIB_EMISSION(f
)][1] );
772 params
[2] = FLOAT_TO_INT( mat
[MAT_ATTRIB_EMISSION(f
)][2] );
773 params
[3] = FLOAT_TO_INT( mat
[MAT_ATTRIB_EMISSION(f
)][3] );
776 *params
= IROUND( mat
[MAT_ATTRIB_SHININESS(f
)][0] );
778 case GL_COLOR_INDEXES
:
779 params
[0] = IROUND( mat
[MAT_ATTRIB_INDEXES(f
)][0] );
780 params
[1] = IROUND( mat
[MAT_ATTRIB_INDEXES(f
)][1] );
781 params
[2] = IROUND( mat
[MAT_ATTRIB_INDEXES(f
)][2] );
784 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetMaterialfv(pname)" );
790 /**********************************************************************/
791 /***** Lighting computation *****/
792 /**********************************************************************/
797 * When two-sided lighting is enabled we compute the color (or index)
798 * for both the front and back side of the primitive. Then, when the
799 * orientation of the facet is later learned, we can determine which
800 * color (or index) to use for rendering.
802 * KW: We now know orientation in advance and only shade for
803 * the side or sides which are actually required.
807 * V = vertex position
808 * P = light source position
813 * // light at infinity
814 * IF local_viewer THEN
815 * _VP_inf_norm = unit vector from V to P // Precompute
818 * _h_inf_norm = Normalize( VP + <0,0,1> ) // Precompute
823 * Normalize( v ) = normalized vector v
824 * Magnitude( v ) = length of vector v
830 * Whenever the spotlight exponent for a light changes we must call
831 * this function to recompute the exponent lookup table.
834 _mesa_invalidate_spot_exp_table( struct gl_light
*l
)
836 l
->_SpotExpTable
[0][0] = -1;
841 validate_spot_exp_table( struct gl_light
*l
)
844 GLdouble exponent
= l
->SpotExponent
;
848 l
->_SpotExpTable
[0][0] = 0.0;
850 for (i
= EXP_TABLE_SIZE
- 1; i
> 0 ;i
--) {
852 tmp
= _mesa_pow(i
/ (GLdouble
) (EXP_TABLE_SIZE
- 1), exponent
);
853 if (tmp
< FLT_MIN
* 100.0) {
858 l
->_SpotExpTable
[i
][0] = (GLfloat
) tmp
;
860 for (i
= 0; i
< EXP_TABLE_SIZE
- 1; i
++) {
861 l
->_SpotExpTable
[i
][1] = (l
->_SpotExpTable
[i
+1][0] -
862 l
->_SpotExpTable
[i
][0]);
864 l
->_SpotExpTable
[EXP_TABLE_SIZE
-1][1] = 0.0;
869 /* Calculate a new shine table. Doing this here saves a branch in
870 * lighting, and the cost of doing it early may be partially offset
871 * by keeping a MRU cache of shine tables for various shine values.
874 _mesa_invalidate_shine_table( GLcontext
*ctx
, GLuint side
)
877 if (ctx
->_ShineTable
[side
])
878 ctx
->_ShineTable
[side
]->refcount
--;
879 ctx
->_ShineTable
[side
] = NULL
;
884 validate_shine_table( GLcontext
*ctx
, GLuint side
, GLfloat shininess
)
886 struct gl_shine_tab
*list
= ctx
->_ShineTabList
;
887 struct gl_shine_tab
*s
;
892 if ( s
->shininess
== shininess
)
900 if (s
->refcount
== 0)
905 if (shininess
== 0.0) {
906 for (j
= 1 ; j
<= SHINE_TABLE_SIZE
; j
++)
910 for (j
= 1 ; j
< SHINE_TABLE_SIZE
; j
++) {
911 GLdouble t
, x
= j
/ (GLfloat
) (SHINE_TABLE_SIZE
- 1);
912 if (x
< 0.005) /* underflow check */
914 t
= _mesa_pow(x
, shininess
);
920 m
[SHINE_TABLE_SIZE
] = 1.0;
923 s
->shininess
= shininess
;
926 if (ctx
->_ShineTable
[side
])
927 ctx
->_ShineTable
[side
]->refcount
--;
929 ctx
->_ShineTable
[side
] = s
;
930 move_to_tail( list
, s
);
936 _mesa_validate_all_lighting_tables( GLcontext
*ctx
)
941 shininess
= ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_SHININESS
][0];
942 if (!ctx
->_ShineTable
[0] || ctx
->_ShineTable
[0]->shininess
!= shininess
)
943 validate_shine_table( ctx
, 0, shininess
);
945 shininess
= ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_BACK_SHININESS
][0];
946 if (!ctx
->_ShineTable
[1] || ctx
->_ShineTable
[1]->shininess
!= shininess
)
947 validate_shine_table( ctx
, 1, shininess
);
949 for (i
= 0 ; i
< MAX_LIGHTS
; i
++)
950 if (ctx
->Light
.Light
[i
]._SpotExpTable
[0][0] == -1)
951 validate_spot_exp_table( &ctx
->Light
.Light
[i
] );
957 * Examine current lighting parameters to determine if the optimized lighting
958 * function can be used.
959 * Also, precompute some lighting values such as the products of light
960 * source and material ambient, diffuse and specular coefficients.
963 _mesa_update_lighting( GLcontext
*ctx
)
965 struct gl_light
*light
;
966 ctx
->Light
._NeedEyeCoords
= 0;
967 ctx
->Light
._Flags
= 0;
969 if (!ctx
->Light
.Enabled
)
972 foreach(light
, &ctx
->Light
.EnabledList
) {
973 ctx
->Light
._Flags
|= light
->_Flags
;
976 ctx
->Light
._NeedVertices
=
977 ((ctx
->Light
._Flags
& (LIGHT_POSITIONAL
|LIGHT_SPOT
)) ||
978 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
||
979 ctx
->Light
.Model
.LocalViewer
);
981 ctx
->Light
._NeedEyeCoords
= ((ctx
->Light
._Flags
& LIGHT_POSITIONAL
) ||
982 ctx
->Light
.Model
.LocalViewer
);
986 /* XXX: This test is overkill & needs to be fixed both for software and
987 * hardware t&l drivers. The above should be sufficient & should
988 * be tested to verify this.
990 if (ctx
->Light
._NeedVertices
)
991 ctx
->Light
._NeedEyeCoords
= GL_TRUE
;
994 /* Precompute some shading values. Although we reference
995 * Light.Material here, we can get away without flushing
996 * FLUSH_UPDATE_CURRENT, as when any outstanding material changes
997 * are flushed, they will update the derived state at that time.
999 if (ctx
->Visual
.rgbMode
) {
1000 if (ctx
->Light
.Model
.TwoSide
)
1001 _mesa_update_material( ctx
,
1002 MAT_BIT_FRONT_EMISSION
|
1003 MAT_BIT_FRONT_AMBIENT
|
1004 MAT_BIT_FRONT_DIFFUSE
|
1005 MAT_BIT_FRONT_SPECULAR
|
1006 MAT_BIT_BACK_EMISSION
|
1007 MAT_BIT_BACK_AMBIENT
|
1008 MAT_BIT_BACK_DIFFUSE
|
1009 MAT_BIT_BACK_SPECULAR
);
1011 _mesa_update_material( ctx
,
1012 MAT_BIT_FRONT_EMISSION
|
1013 MAT_BIT_FRONT_AMBIENT
|
1014 MAT_BIT_FRONT_DIFFUSE
|
1015 MAT_BIT_FRONT_SPECULAR
);
1018 static const GLfloat ci
[3] = { .30F
, .59F
, .11F
};
1019 foreach(light
, &ctx
->Light
.EnabledList
) {
1020 light
->_dli
= DOT3(ci
, light
->Diffuse
);
1021 light
->_sli
= DOT3(ci
, light
->Specular
);
1029 * _TNL_NEW_NEED_EYE_COORDS
1031 * Update on (_NEW_MODELVIEW | _NEW_LIGHT) when lighting is enabled.
1032 * Also update on lighting space changes.
1035 compute_light_positions( GLcontext
*ctx
)
1037 struct gl_light
*light
;
1038 static const GLfloat eye_z
[3] = { 0, 0, 1 };
1040 if (!ctx
->Light
.Enabled
)
1043 if (ctx
->_NeedEyeCoords
) {
1044 COPY_3V( ctx
->_EyeZDir
, eye_z
);
1047 TRANSFORM_NORMAL( ctx
->_EyeZDir
, eye_z
, ctx
->ModelviewMatrixStack
.Top
->m
);
1050 foreach (light
, &ctx
->Light
.EnabledList
) {
1052 if (ctx
->_NeedEyeCoords
) {
1053 COPY_4FV( light
->_Position
, light
->EyePosition
);
1056 TRANSFORM_POINT( light
->_Position
, ctx
->ModelviewMatrixStack
.Top
->inv
,
1057 light
->EyePosition
);
1060 if (!(light
->_Flags
& LIGHT_POSITIONAL
)) {
1061 /* VP (VP) = Normalize( Position ) */
1062 COPY_3V( light
->_VP_inf_norm
, light
->_Position
);
1063 NORMALIZE_3FV( light
->_VP_inf_norm
);
1065 if (!ctx
->Light
.Model
.LocalViewer
) {
1066 /* _h_inf_norm = Normalize( V_to_P + <0,0,1> ) */
1067 ADD_3V( light
->_h_inf_norm
, light
->_VP_inf_norm
, ctx
->_EyeZDir
);
1068 NORMALIZE_3FV( light
->_h_inf_norm
);
1070 light
->_VP_inf_spot_attenuation
= 1.0;
1073 if (light
->_Flags
& LIGHT_SPOT
) {
1074 if (ctx
->_NeedEyeCoords
) {
1075 COPY_3V( light
->_NormDirection
, light
->EyeDirection
);
1078 TRANSFORM_NORMAL( light
->_NormDirection
,
1079 light
->EyeDirection
,
1080 ctx
->ModelviewMatrixStack
.Top
->m
);
1083 NORMALIZE_3FV( light
->_NormDirection
);
1085 if (!(light
->_Flags
& LIGHT_POSITIONAL
)) {
1086 GLfloat PV_dot_dir
= - DOT3(light
->_VP_inf_norm
,
1087 light
->_NormDirection
);
1089 if (PV_dot_dir
> light
->_CosCutoff
) {
1090 double x
= PV_dot_dir
* (EXP_TABLE_SIZE
-1);
1092 light
->_VP_inf_spot_attenuation
=
1093 (GLfloat
) (light
->_SpotExpTable
[k
][0] +
1094 (x
-k
)*light
->_SpotExpTable
[k
][1]);
1097 light
->_VP_inf_spot_attenuation
= 0;
1107 update_modelview_scale( GLcontext
*ctx
)
1109 ctx
->_ModelViewInvScale
= 1.0F
;
1110 if (!_math_matrix_is_length_preserving(ctx
->ModelviewMatrixStack
.Top
)) {
1111 const GLfloat
*m
= ctx
->ModelviewMatrixStack
.Top
->inv
;
1112 GLfloat f
= m
[2] * m
[2] + m
[6] * m
[6] + m
[10] * m
[10];
1113 if (f
< 1e-12) f
= 1.0;
1114 if (ctx
->_NeedEyeCoords
)
1115 ctx
->_ModelViewInvScale
= (GLfloat
) INV_SQRTF(f
);
1117 ctx
->_ModelViewInvScale
= (GLfloat
) SQRTF(f
);
1122 /* Bring uptodate any state that relies on _NeedEyeCoords.
1125 _mesa_update_tnl_spaces( GLcontext
*ctx
, GLuint new_state
)
1127 const GLuint oldneedeyecoords
= ctx
->_NeedEyeCoords
;
1130 ctx
->_NeedEyeCoords
= 0;
1132 if (ctx
->_ForceEyeCoords
||
1133 (ctx
->Texture
._GenFlags
& TEXGEN_NEED_EYE_COORD
) ||
1134 ctx
->Point
._Attenuated
||
1135 ctx
->Light
._NeedEyeCoords
)
1136 ctx
->_NeedEyeCoords
= 1;
1138 if (ctx
->Light
.Enabled
&&
1139 !_math_matrix_is_length_preserving(ctx
->ModelviewMatrixStack
.Top
))
1140 ctx
->_NeedEyeCoords
= 1;
1143 /* Check if the truth-value interpretations of the bitfields have
1146 if (oldneedeyecoords
!= ctx
->_NeedEyeCoords
) {
1147 /* Recalculate all state that depends on _NeedEyeCoords.
1149 update_modelview_scale(ctx
);
1150 compute_light_positions( ctx
);
1152 if (ctx
->Driver
.LightingSpaceChange
)
1153 ctx
->Driver
.LightingSpaceChange( ctx
);
1156 GLuint new_state
= ctx
->NewState
;
1158 /* Recalculate that same state only if it has been invalidated
1159 * by other statechanges.
1161 if (new_state
& _NEW_MODELVIEW
)
1162 update_modelview_scale(ctx
);
1164 if (new_state
& (_NEW_LIGHT
|_NEW_MODELVIEW
))
1165 compute_light_positions( ctx
);
1170 /* Drivers may need this if the hardware tnl unit doesn't support the
1171 * light-in-modelspace optimization. It's also useful for debugging.
1174 _mesa_allow_light_in_model( GLcontext
*ctx
, GLboolean flag
)
1176 ctx
->_ForceEyeCoords
= !flag
;
1177 ctx
->NewState
|= _NEW_POINT
; /* one of the bits from
1178 * _MESA_NEW_NEED_EYE_COORDS.
1184 /**********************************************************************/
1185 /***** Initialization *****/
1186 /**********************************************************************/
1189 * Initialize the n-th light data structure.
1191 * \param l pointer to the gl_light structure to be initialized.
1192 * \param n number of the light.
1193 * \note The defaults for light 0 are different than the other lights.
1196 init_light( struct gl_light
*l
, GLuint n
)
1198 make_empty_list( l
);
1200 ASSIGN_4V( l
->Ambient
, 0.0, 0.0, 0.0, 1.0 );
1202 ASSIGN_4V( l
->Diffuse
, 1.0, 1.0, 1.0, 1.0 );
1203 ASSIGN_4V( l
->Specular
, 1.0, 1.0, 1.0, 1.0 );
1206 ASSIGN_4V( l
->Diffuse
, 0.0, 0.0, 0.0, 1.0 );
1207 ASSIGN_4V( l
->Specular
, 0.0, 0.0, 0.0, 1.0 );
1209 ASSIGN_4V( l
->EyePosition
, 0.0, 0.0, 1.0, 0.0 );
1210 ASSIGN_3V( l
->EyeDirection
, 0.0, 0.0, -1.0 );
1211 l
->SpotExponent
= 0.0;
1212 _mesa_invalidate_spot_exp_table( l
);
1213 l
->SpotCutoff
= 180.0;
1214 l
->_CosCutoff
= 0.0; /* KW: -ve values not admitted */
1215 l
->ConstantAttenuation
= 1.0;
1216 l
->LinearAttenuation
= 0.0;
1217 l
->QuadraticAttenuation
= 0.0;
1218 l
->Enabled
= GL_FALSE
;
1223 * Initialize the light model data structure.
1225 * \param lm pointer to the gl_lightmodel structure to be initialized.
1228 init_lightmodel( struct gl_lightmodel
*lm
)
1230 ASSIGN_4V( lm
->Ambient
, 0.2F
, 0.2F
, 0.2F
, 1.0F
);
1231 lm
->LocalViewer
= GL_FALSE
;
1232 lm
->TwoSide
= GL_FALSE
;
1233 lm
->ColorControl
= GL_SINGLE_COLOR
;
1238 * Initialize the material data structure.
1240 * \param m pointer to the gl_material structure to be initialized.
1243 init_material( struct gl_material
*m
)
1245 ASSIGN_4V( m
->Attrib
[MAT_ATTRIB_FRONT_AMBIENT
], 0.2F
, 0.2F
, 0.2F
, 1.0F
);
1246 ASSIGN_4V( m
->Attrib
[MAT_ATTRIB_FRONT_DIFFUSE
], 0.8F
, 0.8F
, 0.8F
, 1.0F
);
1247 ASSIGN_4V( m
->Attrib
[MAT_ATTRIB_FRONT_SPECULAR
], 0.0F
, 0.0F
, 0.0F
, 1.0F
);
1248 ASSIGN_4V( m
->Attrib
[MAT_ATTRIB_FRONT_EMISSION
], 0.0F
, 0.0F
, 0.0F
, 1.0F
);
1249 ASSIGN_4V( m
->Attrib
[MAT_ATTRIB_FRONT_SHININESS
], 0.0F
, 0.0F
, 0.0F
, 0.0F
);
1250 ASSIGN_4V( m
->Attrib
[MAT_ATTRIB_FRONT_INDEXES
], 0.0F
, 1.0F
, 1.0F
, 0.0F
);
1252 ASSIGN_4V( m
->Attrib
[MAT_ATTRIB_BACK_AMBIENT
], 0.2F
, 0.2F
, 0.2F
, 1.0F
);
1253 ASSIGN_4V( m
->Attrib
[MAT_ATTRIB_BACK_DIFFUSE
], 0.8F
, 0.8F
, 0.8F
, 1.0F
);
1254 ASSIGN_4V( m
->Attrib
[MAT_ATTRIB_BACK_SPECULAR
], 0.0F
, 0.0F
, 0.0F
, 1.0F
);
1255 ASSIGN_4V( m
->Attrib
[MAT_ATTRIB_BACK_EMISSION
], 0.0F
, 0.0F
, 0.0F
, 1.0F
);
1256 ASSIGN_4V( m
->Attrib
[MAT_ATTRIB_BACK_SHININESS
], 0.0F
, 0.0F
, 0.0F
, 0.0F
);
1257 ASSIGN_4V( m
->Attrib
[MAT_ATTRIB_BACK_INDEXES
], 0.0F
, 1.0F
, 1.0F
, 0.0F
);
1262 _mesa_init_lighting( GLcontext
*ctx
)
1266 /* Lighting group */
1267 for (i
= 0; i
< MAX_LIGHTS
; i
++) {
1268 init_light( &ctx
->Light
.Light
[i
], i
);
1270 make_empty_list( &ctx
->Light
.EnabledList
);
1272 init_lightmodel( &ctx
->Light
.Model
);
1273 init_material( &ctx
->Light
.Material
);
1274 ctx
->Light
.ShadeModel
= GL_SMOOTH
;
1275 ctx
->Light
.Enabled
= GL_FALSE
;
1276 ctx
->Light
.ColorMaterialFace
= GL_FRONT_AND_BACK
;
1277 ctx
->Light
.ColorMaterialMode
= GL_AMBIENT_AND_DIFFUSE
;
1278 ctx
->Light
.ColorMaterialBitmask
= _mesa_material_bitmask( ctx
,
1280 GL_AMBIENT_AND_DIFFUSE
, ~0,
1283 ctx
->Light
.ColorMaterialEnabled
= GL_FALSE
;
1285 /* Lighting miscellaneous */
1286 ctx
->_ShineTabList
= MALLOC_STRUCT( gl_shine_tab
);
1287 make_empty_list( ctx
->_ShineTabList
);
1288 /* Allocate 10 (arbitrary) shininess lookup tables */
1289 for (i
= 0 ; i
< 10 ; i
++) {
1290 struct gl_shine_tab
*s
= MALLOC_STRUCT( gl_shine_tab
);
1293 insert_at_tail( ctx
->_ShineTabList
, s
);
1297 ctx
->Light
._NeedEyeCoords
= 0;
1298 ctx
->_NeedEyeCoords
= 0;
1299 ctx
->_ModelViewInvScale
= 1.0;
1304 _mesa_free_lighting_data( GLcontext
*ctx
)
1306 struct gl_shine_tab
*s
, *tmps
;
1308 /* Free lighting shininess exponentiation table */
1309 foreach_s( s
, tmps
, ctx
->_ShineTabList
) {
1312 FREE( ctx
->_ShineTabList
);