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