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