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