1 /* 2 * Mesa 3-D graphics library 3 * Version: 7.1 4 * 5 * Copyright (C) 1999-2007 Brian Paul 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 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25 /** 26 * \file prog_statevars.c 27 * Program state variable management. 28 * \author Brian Paul 29 */ 30 31 32 #include "main/glheader.h" 33 #include "main/context.h" 34 #include "main/imports.h" 35 #include "main/macros.h" 36 #include "main/mtypes.h" 37 #include "main/fbobject.h" 38 #include "prog_statevars.h" 39 #include "prog_parameter.h" 40 #include "main/samplerobj.h" 41 42 43 /** 44 * Use the list of tokens in the state[] array to find global GL state 45 * and return it in <value>. Usually, four values are returned in <value> 46 * but matrix queries may return as many as 16 values. 47 * This function is used for ARB vertex/fragment programs. 48 * The program parser will produce the state[] values. 49 */ 50 static void 51 _mesa_fetch_state(struct gl_context *ctx, const gl_state_index state[], 52 GLfloat *value) 53 { 54 switch (state[0]) { 55 case STATE_MATERIAL: 56 { 57 /* state[1] is either 0=front or 1=back side */ 58 const GLuint face = (GLuint) state[1]; 59 const struct gl_material *mat = &ctx->Light.Material; 60 ASSERT(face == 0 || face == 1); 61 /* we rely on tokens numbered so that _BACK_ == _FRONT_+ 1 */ 62 ASSERT(MAT_ATTRIB_FRONT_AMBIENT + 1 == MAT_ATTRIB_BACK_AMBIENT); 63 /* XXX we could get rid of this switch entirely with a little 64 * work in arbprogparse.c's parse_state_single_item(). 65 */ 66 /* state[2] is the material attribute */ 67 switch (state[2]) { 68 case STATE_AMBIENT: 69 COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_AMBIENT + face]); 70 return; 71 case STATE_DIFFUSE: 72 COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_DIFFUSE + face]); 73 return; 74 case STATE_SPECULAR: 75 COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_SPECULAR + face]); 76 return; 77 case STATE_EMISSION: 78 COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_EMISSION + face]); 79 return; 80 case STATE_SHININESS: 81 value[0] = mat->Attrib[MAT_ATTRIB_FRONT_SHININESS + face][0]; 82 value[1] = 0.0F; 83 value[2] = 0.0F; 84 value[3] = 1.0F; 85 return; 86 default: 87 _mesa_problem(ctx, "Invalid material state in fetch_state"); 88 return; 89 } 90 } 91 case STATE_LIGHT: 92 { 93 /* state[1] is the light number */ 94 const GLuint ln = (GLuint) state[1]; 95 /* state[2] is the light attribute */ 96 switch (state[2]) { 97 case STATE_AMBIENT: 98 COPY_4V(value, ctx->Light.Light[ln].Ambient); 99 return; 100 case STATE_DIFFUSE: 101 COPY_4V(value, ctx->Light.Light[ln].Diffuse); 102 return; 103 case STATE_SPECULAR: 104 COPY_4V(value, ctx->Light.Light[ln].Specular); 105 return; 106 case STATE_POSITION: 107 COPY_4V(value, ctx->Light.Light[ln].EyePosition); 108 return; 109 case STATE_ATTENUATION: 110 value[0] = ctx->Light.Light[ln].ConstantAttenuation; 111 value[1] = ctx->Light.Light[ln].LinearAttenuation; 112 value[2] = ctx->Light.Light[ln].QuadraticAttenuation; 113 value[3] = ctx->Light.Light[ln].SpotExponent; 114 return; 115 case STATE_SPOT_DIRECTION: 116 COPY_3V(value, ctx->Light.Light[ln].SpotDirection); 117 value[3] = ctx->Light.Light[ln]._CosCutoff; 118 return; 119 case STATE_SPOT_CUTOFF: 120 value[0] = ctx->Light.Light[ln].SpotCutoff; 121 return; 122 case STATE_HALF_VECTOR: 123 { 124 static const GLfloat eye_z[] = {0, 0, 1}; 125 GLfloat p[3]; 126 /* Compute infinite half angle vector: 127 * halfVector = normalize(normalize(lightPos) + (0, 0, 1)) 128 * light.EyePosition.w should be 0 for infinite lights. 129 */ 130 COPY_3V(p, ctx->Light.Light[ln].EyePosition); 131 NORMALIZE_3FV(p); 132 ADD_3V(value, p, eye_z); 133 NORMALIZE_3FV(value); 134 value[3] = 1.0; 135 } 136 return; 137 default: 138 _mesa_problem(ctx, "Invalid light state in fetch_state"); 139 return; 140 } 141 } 142 case STATE_LIGHTMODEL_AMBIENT: 143 COPY_4V(value, ctx->Light.Model.Ambient); 144 return; 145 case STATE_LIGHTMODEL_SCENECOLOR: 146 if (state[1] == 0) { 147 /* front */ 148 GLint i; 149 for (i = 0; i < 3; i++) { 150 value[i] = ctx->Light.Model.Ambient[i] 151 * ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT][i] 152 + ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION][i]; 153 } 154 value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]; 155 } 156 else { 157 /* back */ 158 GLint i; 159 for (i = 0; i < 3; i++) { 160 value[i] = ctx->Light.Model.Ambient[i] 161 * ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_AMBIENT][i] 162 + ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_EMISSION][i]; 163 } 164 value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]; 165 } 166 return; 167 case STATE_LIGHTPROD: 168 { 169 const GLuint ln = (GLuint) state[1]; 170 const GLuint face = (GLuint) state[2]; 171 GLint i; 172 ASSERT(face == 0 || face == 1); 173 switch (state[3]) { 174 case STATE_AMBIENT: 175 for (i = 0; i < 3; i++) { 176 value[i] = ctx->Light.Light[ln].Ambient[i] * 177 ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT+face][i]; 178 } 179 /* [3] = material alpha */ 180 value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT+face][3]; 181 return; 182 case STATE_DIFFUSE: 183 for (i = 0; i < 3; i++) { 184 value[i] = ctx->Light.Light[ln].Diffuse[i] * 185 ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][i]; 186 } 187 /* [3] = material alpha */ 188 value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][3]; 189 return; 190 case STATE_SPECULAR: 191 for (i = 0; i < 3; i++) { 192 value[i] = ctx->Light.Light[ln].Specular[i] * 193 ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SPECULAR+face][i]; 194 } 195 /* [3] = material alpha */ 196 value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SPECULAR+face][3]; 197 return; 198 default: 199 _mesa_problem(ctx, "Invalid lightprod state in fetch_state"); 200 return; 201 } 202 } 203 case STATE_TEXGEN: 204 { 205 /* state[1] is the texture unit */ 206 const GLuint unit = (GLuint) state[1]; 207 /* state[2] is the texgen attribute */ 208 switch (state[2]) { 209 case STATE_TEXGEN_EYE_S: 210 COPY_4V(value, ctx->Texture.Unit[unit].GenS.EyePlane); 211 return; 212 case STATE_TEXGEN_EYE_T: 213 COPY_4V(value, ctx->Texture.Unit[unit].GenT.EyePlane); 214 return; 215 case STATE_TEXGEN_EYE_R: 216 COPY_4V(value, ctx->Texture.Unit[unit].GenR.EyePlane); 217 return; 218 case STATE_TEXGEN_EYE_Q: 219 COPY_4V(value, ctx->Texture.Unit[unit].GenQ.EyePlane); 220 return; 221 case STATE_TEXGEN_OBJECT_S: 222 COPY_4V(value, ctx->Texture.Unit[unit].GenS.ObjectPlane); 223 return; 224 case STATE_TEXGEN_OBJECT_T: 225 COPY_4V(value, ctx->Texture.Unit[unit].GenT.ObjectPlane); 226 return; 227 case STATE_TEXGEN_OBJECT_R: 228 COPY_4V(value, ctx->Texture.Unit[unit].GenR.ObjectPlane); 229 return; 230 case STATE_TEXGEN_OBJECT_Q: 231 COPY_4V(value, ctx->Texture.Unit[unit].GenQ.ObjectPlane); 232 return; 233 default: 234 _mesa_problem(ctx, "Invalid texgen state in fetch_state"); 235 return; 236 } 237 } 238 case STATE_TEXENV_COLOR: 239 { 240 /* state[1] is the texture unit */ 241 const GLuint unit = (GLuint) state[1]; 242 if(ctx->Color._ClampFragmentColor) 243 COPY_4V(value, ctx->Texture.Unit[unit].EnvColor); 244 else 245 COPY_4V(value, ctx->Texture.Unit[unit].EnvColorUnclamped); 246 } 247 return; 248 case STATE_FOG_COLOR: 249 if(ctx->Color._ClampFragmentColor) 250 COPY_4V(value, ctx->Fog.Color); 251 else 252 COPY_4V(value, ctx->Fog.ColorUnclamped); 253 return; 254 case STATE_FOG_PARAMS: 255 value[0] = ctx->Fog.Density; 256 value[1] = ctx->Fog.Start; 257 value[2] = ctx->Fog.End; 258 value[3] = (ctx->Fog.End == ctx->Fog.Start) 259 ? 1.0f : (GLfloat)(1.0 / (ctx->Fog.End - ctx->Fog.Start)); 260 return; 261 case STATE_CLIPPLANE: 262 { 263 const GLuint plane = (GLuint) state[1]; 264 COPY_4V(value, ctx->Transform.EyeUserPlane[plane]); 265 } 266 return; 267 case STATE_POINT_SIZE: 268 value[0] = ctx->Point.Size; 269 value[1] = ctx->Point.MinSize; 270 value[2] = ctx->Point.MaxSize; 271 value[3] = ctx->Point.Threshold; 272 return; 273 case STATE_POINT_ATTENUATION: 274 value[0] = ctx->Point.Params[0]; 275 value[1] = ctx->Point.Params[1]; 276 value[2] = ctx->Point.Params[2]; 277 value[3] = 1.0F; 278 return; 279 case STATE_MODELVIEW_MATRIX: 280 case STATE_PROJECTION_MATRIX: 281 case STATE_MVP_MATRIX: 282 case STATE_TEXTURE_MATRIX: 283 case STATE_PROGRAM_MATRIX: 284 { 285 /* state[0] = modelview, projection, texture, etc. */ 286 /* state[1] = which texture matrix or program matrix */ 287 /* state[2] = first row to fetch */ 288 /* state[3] = last row to fetch */ 289 /* state[4] = transpose, inverse or invtrans */ 290 const GLmatrix *matrix; 291 const gl_state_index mat = state[0]; 292 const GLuint index = (GLuint) state[1]; 293 const GLuint firstRow = (GLuint) state[2]; 294 const GLuint lastRow = (GLuint) state[3]; 295 const gl_state_index modifier = state[4]; 296 const GLfloat *m; 297 GLuint row, i; 298 ASSERT(firstRow >= 0); 299 ASSERT(firstRow < 4); 300 ASSERT(lastRow >= 0); 301 ASSERT(lastRow < 4); 302 if (mat == STATE_MODELVIEW_MATRIX) { 303 matrix = ctx->ModelviewMatrixStack.Top; 304 } 305 else if (mat == STATE_PROJECTION_MATRIX) { 306 matrix = ctx->ProjectionMatrixStack.Top; 307 } 308 else if (mat == STATE_MVP_MATRIX) { 309 matrix = &ctx->_ModelProjectMatrix; 310 } 311 else if (mat == STATE_TEXTURE_MATRIX) { 312 ASSERT(index < Elements(ctx->TextureMatrixStack)); 313 matrix = ctx->TextureMatrixStack[index].Top; 314 } 315 else if (mat == STATE_PROGRAM_MATRIX) { 316 ASSERT(index < Elements(ctx->ProgramMatrixStack)); 317 matrix = ctx->ProgramMatrixStack[index].Top; 318 } 319 else { 320 _mesa_problem(ctx, "Bad matrix name in _mesa_fetch_state()"); 321 return; 322 } 323 if (modifier == STATE_MATRIX_INVERSE || 324 modifier == STATE_MATRIX_INVTRANS) { 325 /* Be sure inverse is up to date: 326 */ 327 _math_matrix_analyse( (GLmatrix*) matrix ); 328 m = matrix->inv; 329 } 330 else { 331 m = matrix->m; 332 } 333 if (modifier == STATE_MATRIX_TRANSPOSE || 334 modifier == STATE_MATRIX_INVTRANS) { 335 for (i = 0, row = firstRow; row <= lastRow; row++) { 336 value[i++] = m[row * 4 + 0]; 337 value[i++] = m[row * 4 + 1]; 338 value[i++] = m[row * 4 + 2]; 339 value[i++] = m[row * 4 + 3]; 340 } 341 } 342 else { 343 for (i = 0, row = firstRow; row <= lastRow; row++) { 344 value[i++] = m[row + 0]; 345 value[i++] = m[row + 4]; 346 value[i++] = m[row + 8]; 347 value[i++] = m[row + 12]; 348 } 349 } 350 } 351 return; 352 case STATE_DEPTH_RANGE: 353 value[0] = ctx->Viewport.Near; /* near */ 354 value[1] = ctx->Viewport.Far; /* far */ 355 value[2] = ctx->Viewport.Far - ctx->Viewport.Near; /* far - near */ 356 value[3] = 1.0; 357 return; 358 case STATE_FRAGMENT_PROGRAM: 359 { 360 /* state[1] = {STATE_ENV, STATE_LOCAL} */ 361 /* state[2] = parameter index */ 362 const int idx = (int) state[2]; 363 switch (state[1]) { 364 case STATE_ENV: 365 COPY_4V(value, ctx->FragmentProgram.Parameters[idx]); 366 return; 367 case STATE_LOCAL: 368 COPY_4V(value, ctx->FragmentProgram.Current->Base.LocalParams[idx]); 369 return; 370 default: 371 _mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()"); 372 return; 373 } 374 } 375 return; 376 377 case STATE_VERTEX_PROGRAM: 378 { 379 /* state[1] = {STATE_ENV, STATE_LOCAL} */ 380 /* state[2] = parameter index */ 381 const int idx = (int) state[2]; 382 switch (state[1]) { 383 case STATE_ENV: 384 COPY_4V(value, ctx->VertexProgram.Parameters[idx]); 385 return; 386 case STATE_LOCAL: 387 COPY_4V(value, ctx->VertexProgram.Current->Base.LocalParams[idx]); 388 return; 389 default: 390 _mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()"); 391 return; 392 } 393 } 394 return; 395 396 case STATE_NORMAL_SCALE: 397 ASSIGN_4V(value, ctx->_ModelViewInvScale, 0, 0, 1); 398 return; 399 400 case STATE_INTERNAL: 401 switch (state[1]) { 402 case STATE_CURRENT_ATTRIB: 403 { 404 const GLuint idx = (GLuint) state[2]; 405 COPY_4V(value, ctx->Current.Attrib[idx]); 406 } 407 return; 408 409 case STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED: 410 { 411 const GLuint idx = (GLuint) state[2]; 412 if(ctx->Light._ClampVertexColor && 413 (idx == VERT_ATTRIB_COLOR0 || 414 idx == VERT_ATTRIB_COLOR1)) { 415 value[0] = CLAMP(ctx->Current.Attrib[idx][0], 0.0f, 1.0f); 416 value[1] = CLAMP(ctx->Current.Attrib[idx][1], 0.0f, 1.0f); 417 value[2] = CLAMP(ctx->Current.Attrib[idx][2], 0.0f, 1.0f); 418 value[3] = CLAMP(ctx->Current.Attrib[idx][3], 0.0f, 1.0f); 419 } 420 else 421 COPY_4V(value, ctx->Current.Attrib[idx]); 422 } 423 return; 424 425 case STATE_NORMAL_SCALE: 426 ASSIGN_4V(value, 427 ctx->_ModelViewInvScale, 428 ctx->_ModelViewInvScale, 429 ctx->_ModelViewInvScale, 430 1); 431 return; 432 433 case STATE_TEXRECT_SCALE: 434 /* Value = { 1/texWidth, 1/texHeight, 0, 1 }. 435 * Used to convert unnormalized texcoords to normalized texcoords. 436 */ 437 { 438 const int unit = (int) state[2]; 439 const struct gl_texture_object *texObj 440 = ctx->Texture.Unit[unit]._Current; 441 if (texObj) { 442 struct gl_texture_image *texImage = texObj->Image[0][0]; 443 ASSIGN_4V(value, 444 (GLfloat) (1.0 / texImage->Width), 445 (GLfloat) (1.0 / texImage->Height), 446 0.0f, 1.0f); 447 } 448 } 449 return; 450 451 case STATE_FOG_PARAMS_OPTIMIZED: 452 /* for simpler per-vertex/pixel fog calcs. POW (for EXP/EXP2 fog) 453 * might be more expensive than EX2 on some hw, plus it needs 454 * another constant (e) anyway. Linear fog can now be done with a 455 * single MAD. 456 * linear: fogcoord * -1/(end-start) + end/(end-start) 457 * exp: 2^-(density/ln(2) * fogcoord) 458 * exp2: 2^-((density/(ln(2)^2) * fogcoord)^2) 459 */ 460 value[0] = (ctx->Fog.End == ctx->Fog.Start) 461 ? 1.0f : (GLfloat)(-1.0F / (ctx->Fog.End - ctx->Fog.Start)); 462 value[1] = ctx->Fog.End * -value[0]; 463 value[2] = (GLfloat)(ctx->Fog.Density * M_LOG2E); /* M_LOG2E == 1/ln(2) */ 464 value[3] = (GLfloat)(ctx->Fog.Density * ONE_DIV_SQRT_LN2); 465 return; 466 467 case STATE_POINT_SIZE_CLAMPED: 468 { 469 /* this includes implementation dependent limits, to avoid 470 * another potentially necessary clamp. 471 * Note: for sprites, point smooth (point AA) is ignored 472 * and we'll clamp to MinPointSizeAA and MaxPointSize, because we 473 * expect drivers will want to say their minimum for AA size is 0.0 474 * but for non-AA it's 1.0 (because normal points with size below 1.0 475 * need to get rounded up to 1.0, hence never disappear). GL does 476 * not specify max clamp size for sprites, other than it needs to be 477 * at least as large as max AA size, hence use non-AA size there. 478 */ 479 GLfloat minImplSize; 480 GLfloat maxImplSize; 481 if (ctx->Point.PointSprite) { 482 minImplSize = ctx->Const.MinPointSizeAA; 483 maxImplSize = ctx->Const.MaxPointSize; 484 } 485 else if (ctx->Point.SmoothFlag || ctx->Multisample._Enabled) { 486 minImplSize = ctx->Const.MinPointSizeAA; 487 maxImplSize = ctx->Const.MaxPointSizeAA; 488 } 489 else { 490 minImplSize = ctx->Const.MinPointSize; 491 maxImplSize = ctx->Const.MaxPointSize; 492 } 493 value[0] = ctx->Point.Size; 494 value[1] = ctx->Point.MinSize >= minImplSize ? ctx->Point.MinSize : minImplSize; 495 value[2] = ctx->Point.MaxSize <= maxImplSize ? ctx->Point.MaxSize : maxImplSize; 496 value[3] = ctx->Point.Threshold; 497 } 498 return; 499 case STATE_LIGHT_SPOT_DIR_NORMALIZED: 500 { 501 /* here, state[2] is the light number */ 502 /* pre-normalize spot dir */ 503 const GLuint ln = (GLuint) state[2]; 504 COPY_3V(value, ctx->Light.Light[ln]._NormSpotDirection); 505 value[3] = ctx->Light.Light[ln]._CosCutoff; 506 } 507 return; 508 509 case STATE_LIGHT_POSITION: 510 { 511 const GLuint ln = (GLuint) state[2]; 512 COPY_4V(value, ctx->Light.Light[ln]._Position); 513 } 514 return; 515 516 case STATE_LIGHT_POSITION_NORMALIZED: 517 { 518 const GLuint ln = (GLuint) state[2]; 519 COPY_4V(value, ctx->Light.Light[ln]._Position); 520 NORMALIZE_3FV( value ); 521 } 522 return; 523 524 case STATE_LIGHT_HALF_VECTOR: 525 { 526 const GLuint ln = (GLuint) state[2]; 527 GLfloat p[3]; 528 /* Compute infinite half angle vector: 529 * halfVector = normalize(normalize(lightPos) + (0, 0, 1)) 530 * light.EyePosition.w should be 0 for infinite lights. 531 */ 532 COPY_3V(p, ctx->Light.Light[ln]._Position); 533 NORMALIZE_3FV(p); 534 ADD_3V(value, p, ctx->_EyeZDir); 535 NORMALIZE_3FV(value); 536 value[3] = 1.0; 537 } 538 return; 539 540 case STATE_PT_SCALE: 541 value[0] = ctx->Pixel.RedScale; 542 value[1] = ctx->Pixel.GreenScale; 543 value[2] = ctx->Pixel.BlueScale; 544 value[3] = ctx->Pixel.AlphaScale; 545 return; 546 547 case STATE_PT_BIAS: 548 value[0] = ctx->Pixel.RedBias; 549 value[1] = ctx->Pixel.GreenBias; 550 value[2] = ctx->Pixel.BlueBias; 551 value[3] = ctx->Pixel.AlphaBias; 552 return; 553 554 case STATE_FB_SIZE: 555 value[0] = (GLfloat) (ctx->DrawBuffer->Width - 1); 556 value[1] = (GLfloat) (ctx->DrawBuffer->Height - 1); 557 value[2] = 0.0F; 558 value[3] = 0.0F; 559 return; 560 561 case STATE_FB_WPOS_Y_TRANSFORM: 562 /* A driver may negate this conditional by using ZW swizzle 563 * instead of XY (based on e.g. some other state). */ 564 if (_mesa_is_user_fbo(ctx->DrawBuffer)) { 565 /* Identity (XY) followed by flipping Y upside down (ZW). */ 566 value[0] = 1.0F; 567 value[1] = 0.0F; 568 value[2] = -1.0F; 569 value[3] = (GLfloat) ctx->DrawBuffer->Height; 570 } else { 571 /* Flipping Y upside down (XY) followed by identity (ZW). */ 572 value[0] = -1.0F; 573 value[1] = (GLfloat) ctx->DrawBuffer->Height; 574 value[2] = 1.0F; 575 value[3] = 0.0F; 576 } 577 return; 578 579 case STATE_ROT_MATRIX_0: 580 { 581 const int unit = (int) state[2]; 582 GLfloat *rotMat22 = ctx->Texture.Unit[unit].RotMatrix; 583 value[0] = rotMat22[0]; 584 value[1] = rotMat22[2]; 585 value[2] = 0.0; 586 value[3] = 0.0; 587 } 588 return; 589 590 case STATE_ROT_MATRIX_1: 591 { 592 const int unit = (int) state[2]; 593 GLfloat *rotMat22 = ctx->Texture.Unit[unit].RotMatrix; 594 value[0] = rotMat22[1]; 595 value[1] = rotMat22[3]; 596 value[2] = 0.0; 597 value[3] = 0.0; 598 } 599 return; 600 601 /* XXX: make sure new tokens added here are also handled in the 602 * _mesa_program_state_flags() switch, below. 603 */ 604 default: 605 /* Unknown state indexes are silently ignored here. 606 * Drivers may do something special. 607 */ 608 return; 609 } 610 return; 611 612 default: 613 _mesa_problem(ctx, "Invalid state in _mesa_fetch_state"); 614 return; 615 } 616 } 617 618 619 /** 620 * Return a bitmask of the Mesa state flags (_NEW_* values) which would 621 * indicate that the given context state may have changed. 622 * The bitmask is used during validation to determine if we need to update 623 * vertex/fragment program parameters (like "state.material.color") when 624 * some GL state has changed. 625 */ 626 GLbitfield 627 _mesa_program_state_flags(const gl_state_index state[STATE_LENGTH]) 628 { 629 switch (state[0]) { 630 case STATE_MATERIAL: 631 case STATE_LIGHTPROD: 632 case STATE_LIGHTMODEL_SCENECOLOR: 633 /* these can be effected by glColor when colormaterial mode is used */ 634 return _NEW_LIGHT | _NEW_CURRENT_ATTRIB; 635 636 case STATE_LIGHT: 637 case STATE_LIGHTMODEL_AMBIENT: 638 return _NEW_LIGHT; 639 640 case STATE_TEXGEN: 641 return _NEW_TEXTURE; 642 case STATE_TEXENV_COLOR: 643 return _NEW_TEXTURE | _NEW_BUFFERS | _NEW_FRAG_CLAMP; 644 645 case STATE_FOG_COLOR: 646 return _NEW_FOG | _NEW_BUFFERS | _NEW_FRAG_CLAMP; 647 case STATE_FOG_PARAMS: 648 return _NEW_FOG; 649 650 case STATE_CLIPPLANE: 651 return _NEW_TRANSFORM; 652 653 case STATE_POINT_SIZE: 654 case STATE_POINT_ATTENUATION: 655 return _NEW_POINT; 656 657 case STATE_MODELVIEW_MATRIX: 658 return _NEW_MODELVIEW; 659 case STATE_PROJECTION_MATRIX: 660 return _NEW_PROJECTION; 661 case STATE_MVP_MATRIX: 662 return _NEW_MODELVIEW | _NEW_PROJECTION; 663 case STATE_TEXTURE_MATRIX: 664 return _NEW_TEXTURE_MATRIX; 665 case STATE_PROGRAM_MATRIX: 666 return _NEW_TRACK_MATRIX; 667 668 case STATE_DEPTH_RANGE: 669 return _NEW_VIEWPORT; 670 671 case STATE_FRAGMENT_PROGRAM: 672 case STATE_VERTEX_PROGRAM: 673 return _NEW_PROGRAM; 674 675 case STATE_NORMAL_SCALE: 676 return _NEW_MODELVIEW; 677 678 case STATE_INTERNAL: 679 switch (state[1]) { 680 case STATE_CURRENT_ATTRIB: 681 return _NEW_CURRENT_ATTRIB; 682 case STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED: 683 return _NEW_CURRENT_ATTRIB | _NEW_LIGHT | _NEW_BUFFERS; 684 685 case STATE_NORMAL_SCALE: 686 return _NEW_MODELVIEW; 687 688 case STATE_TEXRECT_SCALE: 689 case STATE_ROT_MATRIX_0: 690 case STATE_ROT_MATRIX_1: 691 return _NEW_TEXTURE; 692 case STATE_FOG_PARAMS_OPTIMIZED: 693 return _NEW_FOG; 694 case STATE_POINT_SIZE_CLAMPED: 695 return _NEW_POINT | _NEW_MULTISAMPLE; 696 case STATE_LIGHT_SPOT_DIR_NORMALIZED: 697 case STATE_LIGHT_POSITION: 698 case STATE_LIGHT_POSITION_NORMALIZED: 699 case STATE_LIGHT_HALF_VECTOR: 700 return _NEW_LIGHT; 701 702 case STATE_PT_SCALE: 703 case STATE_PT_BIAS: 704 return _NEW_PIXEL; 705 706 case STATE_FB_SIZE: 707 case STATE_FB_WPOS_Y_TRANSFORM: 708 return _NEW_BUFFERS; 709 710 default: 711 /* unknown state indexes are silently ignored and 712 * no flag set, since it is handled by the driver. 713 */ 714 return 0; 715 } 716 717 default: 718 _mesa_problem(NULL, "unexpected state[0] in make_state_flags()"); 719 return 0; 720 } 721 } 722 723 724 static void 725 append(char *dst, const char *src) 726 { 727 while (*dst) 728 dst++; 729 while (*src) 730 *dst++ = *src++; 731 *dst = 0; 732 } 733 734 735 /** 736 * Convert token 'k' to a string, append it onto 'dst' string. 737 */ 738 static void 739 append_token(char *dst, gl_state_index k) 740 { 741 switch (k) { 742 case STATE_MATERIAL: 743 append(dst, "material"); 744 break; 745 case STATE_LIGHT: 746 append(dst, "light"); 747 break; 748 case STATE_LIGHTMODEL_AMBIENT: 749 append(dst, "lightmodel.ambient"); 750 break; 751 case STATE_LIGHTMODEL_SCENECOLOR: 752 break; 753 case STATE_LIGHTPROD: 754 append(dst, "lightprod"); 755 break; 756 case STATE_TEXGEN: 757 append(dst, "texgen"); 758 break; 759 case STATE_FOG_COLOR: 760 append(dst, "fog.color"); 761 break; 762 case STATE_FOG_PARAMS: 763 append(dst, "fog.params"); 764 break; 765 case STATE_CLIPPLANE: 766 append(dst, "clip"); 767 break; 768 case STATE_POINT_SIZE: 769 append(dst, "point.size"); 770 break; 771 case STATE_POINT_ATTENUATION: 772 append(dst, "point.attenuation"); 773 break; 774 case STATE_MODELVIEW_MATRIX: 775 append(dst, "matrix.modelview"); 776 break; 777 case STATE_PROJECTION_MATRIX: 778 append(dst, "matrix.projection"); 779 break; 780 case STATE_MVP_MATRIX: 781 append(dst, "matrix.mvp"); 782 break; 783 case STATE_TEXTURE_MATRIX: 784 append(dst, "matrix.texture"); 785 break; 786 case STATE_PROGRAM_MATRIX: 787 append(dst, "matrix.program"); 788 break; 789 case STATE_MATRIX_INVERSE: 790 append(dst, ".inverse"); 791 break; 792 case STATE_MATRIX_TRANSPOSE: 793 append(dst, ".transpose"); 794 break; 795 case STATE_MATRIX_INVTRANS: 796 append(dst, ".invtrans"); 797 break; 798 case STATE_AMBIENT: 799 append(dst, ".ambient"); 800 break; 801 case STATE_DIFFUSE: 802 append(dst, ".diffuse"); 803 break; 804 case STATE_SPECULAR: 805 append(dst, ".specular"); 806 break; 807 case STATE_EMISSION: 808 append(dst, ".emission"); 809 break; 810 case STATE_SHININESS: 811 append(dst, "lshininess"); 812 break; 813 case STATE_HALF_VECTOR: 814 append(dst, ".half"); 815 break; 816 case STATE_POSITION: 817 append(dst, ".position"); 818 break; 819 case STATE_ATTENUATION: 820 append(dst, ".attenuation"); 821 break; 822 case STATE_SPOT_DIRECTION: 823 append(dst, ".spot.direction"); 824 break; 825 case STATE_SPOT_CUTOFF: 826 append(dst, ".spot.cutoff"); 827 break; 828 case STATE_TEXGEN_EYE_S: 829 append(dst, ".eye.s"); 830 break; 831 case STATE_TEXGEN_EYE_T: 832 append(dst, ".eye.t"); 833 break; 834 case STATE_TEXGEN_EYE_R: 835 append(dst, ".eye.r"); 836 break; 837 case STATE_TEXGEN_EYE_Q: 838 append(dst, ".eye.q"); 839 break; 840 case STATE_TEXGEN_OBJECT_S: 841 append(dst, ".object.s"); 842 break; 843 case STATE_TEXGEN_OBJECT_T: 844 append(dst, ".object.t"); 845 break; 846 case STATE_TEXGEN_OBJECT_R: 847 append(dst, ".object.r"); 848 break; 849 case STATE_TEXGEN_OBJECT_Q: 850 append(dst, ".object.q"); 851 break; 852 case STATE_TEXENV_COLOR: 853 append(dst, "texenv"); 854 break; 855 case STATE_DEPTH_RANGE: 856 append(dst, "depth.range"); 857 break; 858 case STATE_VERTEX_PROGRAM: 859 case STATE_FRAGMENT_PROGRAM: 860 break; 861 case STATE_ENV: 862 append(dst, "env"); 863 break; 864 case STATE_LOCAL: 865 append(dst, "local"); 866 break; 867 /* BEGIN internal state vars */ 868 case STATE_INTERNAL: 869 append(dst, ".internal."); 870 break; 871 case STATE_CURRENT_ATTRIB: 872 append(dst, "current"); 873 break; 874 case STATE_NORMAL_SCALE: 875 append(dst, "normalScale"); 876 break; 877 case STATE_TEXRECT_SCALE: 878 append(dst, "texrectScale"); 879 break; 880 case STATE_FOG_PARAMS_OPTIMIZED: 881 append(dst, "fogParamsOptimized"); 882 break; 883 case STATE_POINT_SIZE_CLAMPED: 884 append(dst, "pointSizeClamped"); 885 break; 886 case STATE_LIGHT_SPOT_DIR_NORMALIZED: 887 append(dst, "lightSpotDirNormalized"); 888 break; 889 case STATE_LIGHT_POSITION: 890 append(dst, "lightPosition"); 891 break; 892 case STATE_LIGHT_POSITION_NORMALIZED: 893 append(dst, "light.position.normalized"); 894 break; 895 case STATE_LIGHT_HALF_VECTOR: 896 append(dst, "lightHalfVector"); 897 break; 898 case STATE_PT_SCALE: 899 append(dst, "PTscale"); 900 break; 901 case STATE_PT_BIAS: 902 append(dst, "PTbias"); 903 break; 904 case STATE_FB_SIZE: 905 append(dst, "FbSize"); 906 break; 907 case STATE_FB_WPOS_Y_TRANSFORM: 908 append(dst, "FbWposYTransform"); 909 break; 910 case STATE_ROT_MATRIX_0: 911 append(dst, "rotMatrixRow0"); 912 break; 913 case STATE_ROT_MATRIX_1: 914 append(dst, "rotMatrixRow1"); 915 break; 916 default: 917 /* probably STATE_INTERNAL_DRIVER+i (driver private state) */ 918 append(dst, "driverState"); 919 } 920 } 921 922 static void 923 append_face(char *dst, GLint face) 924 { 925 if (face == 0) 926 append(dst, "front."); 927 else 928 append(dst, "back."); 929 } 930 931 static void 932 append_index(char *dst, GLint index) 933 { 934 char s[20]; 935 sprintf(s, "[%d]", index); 936 append(dst, s); 937 } 938 939 /** 940 * Make a string from the given state vector. 941 * For example, return "state.matrix.texture[2].inverse". 942 * Use free() to deallocate the string. 943 */ 944 char * 945 _mesa_program_state_string(const gl_state_index state[STATE_LENGTH]) 946 { 947 char str[1000] = ""; 948 char tmp[30]; 949 950 append(str, "state."); 951 append_token(str, state[0]); 952 953 switch (state[0]) { 954 case STATE_MATERIAL: 955 append_face(str, state[1]); 956 append_token(str, state[2]); 957 break; 958 case STATE_LIGHT: 959 append_index(str, state[1]); /* light number [i]. */ 960 append_token(str, state[2]); /* coefficients */ 961 break; 962 case STATE_LIGHTMODEL_AMBIENT: 963 append(str, "lightmodel.ambient"); 964 break; 965 case STATE_LIGHTMODEL_SCENECOLOR: 966 if (state[1] == 0) { 967 append(str, "lightmodel.front.scenecolor"); 968 } 969 else { 970 append(str, "lightmodel.back.scenecolor"); 971 } 972 break; 973 case STATE_LIGHTPROD: 974 append_index(str, state[1]); /* light number [i]. */ 975 append_face(str, state[2]); 976 append_token(str, state[3]); 977 break; 978 case STATE_TEXGEN: 979 append_index(str, state[1]); /* tex unit [i] */ 980 append_token(str, state[2]); /* plane coef */ 981 break; 982 case STATE_TEXENV_COLOR: 983 append_index(str, state[1]); /* tex unit [i] */ 984 append(str, "color"); 985 break; 986 case STATE_CLIPPLANE: 987 append_index(str, state[1]); /* plane [i] */ 988 append(str, ".plane"); 989 break; 990 case STATE_MODELVIEW_MATRIX: 991 case STATE_PROJECTION_MATRIX: 992 case STATE_MVP_MATRIX: 993 case STATE_TEXTURE_MATRIX: 994 case STATE_PROGRAM_MATRIX: 995 { 996 /* state[0] = modelview, projection, texture, etc. */ 997 /* state[1] = which texture matrix or program matrix */ 998 /* state[2] = first row to fetch */ 999 /* state[3] = last row to fetch */ 1000 /* state[4] = transpose, inverse or invtrans */ 1001 const gl_state_index mat = state[0]; 1002 const GLuint index = (GLuint) state[1]; 1003 const GLuint firstRow = (GLuint) state[2]; 1004 const GLuint lastRow = (GLuint) state[3]; 1005 const gl_state_index modifier = state[4]; 1006 if (index || 1007 mat == STATE_TEXTURE_MATRIX || 1008 mat == STATE_PROGRAM_MATRIX) 1009 append_index(str, index); 1010 if (modifier) 1011 append_token(str, modifier); 1012 if (firstRow == lastRow) 1013 sprintf(tmp, ".row[%d]", firstRow); 1014 else 1015 sprintf(tmp, ".row[%d..%d]", firstRow, lastRow); 1016 append(str, tmp); 1017 } 1018 break; 1019 case STATE_POINT_SIZE: 1020 break; 1021 case STATE_POINT_ATTENUATION: 1022 break; 1023 case STATE_FOG_PARAMS: 1024 break; 1025 case STATE_FOG_COLOR: 1026 break; 1027 case STATE_DEPTH_RANGE: 1028 break; 1029 case STATE_FRAGMENT_PROGRAM: 1030 case STATE_VERTEX_PROGRAM: 1031 /* state[1] = {STATE_ENV, STATE_LOCAL} */ 1032 /* state[2] = parameter index */ 1033 append_token(str, state[1]); 1034 append_index(str, state[2]); 1035 break; 1036 case STATE_NORMAL_SCALE: 1037 break; 1038 case STATE_INTERNAL: 1039 append_token(str, state[1]); 1040 if (state[1] == STATE_CURRENT_ATTRIB) 1041 append_index(str, state[2]); 1042 break; 1043 default: 1044 _mesa_problem(NULL, "Invalid state in _mesa_program_state_string"); 1045 break; 1046 } 1047 1048 return _mesa_strdup(str); 1049 } 1050 1051 1052 /** 1053 * Loop over all the parameters in a parameter list. If the parameter 1054 * is a GL state reference, look up the current value of that state 1055 * variable and put it into the parameter's Value[4] array. 1056 * Other parameter types never change or are explicitly set by the user 1057 * with glUniform() or glProgramParameter(), etc. 1058 * This would be called at glBegin time. 1059 */ 1060 void 1061 _mesa_load_state_parameters(struct gl_context *ctx, 1062 struct gl_program_parameter_list *paramList) 1063 { 1064 GLuint i; 1065 1066 if (!paramList) 1067 return; 1068 1069 for (i = 0; i < paramList->NumParameters; i++) { 1070 if (paramList->Parameters[i].Type == PROGRAM_STATE_VAR) { 1071 _mesa_fetch_state(ctx, 1072 paramList->Parameters[i].StateIndexes, 1073 ¶mList->ParameterValues[i][0].f); 1074 } 1075 } 1076 } 1077 1078 1079 /** 1080 * Copy the 16 elements of a matrix into four consecutive program 1081 * registers starting at 'pos'. 1082 */ 1083 static void 1084 load_matrix(GLfloat registers[][4], GLuint pos, const GLfloat mat[16]) 1085 { 1086 GLuint i; 1087 for (i = 0; i < 4; i++) { 1088 registers[pos + i][0] = mat[0 + i]; 1089 registers[pos + i][1] = mat[4 + i]; 1090 registers[pos + i][2] = mat[8 + i]; 1091 registers[pos + i][3] = mat[12 + i]; 1092 } 1093 } 1094 1095 1096 /** 1097 * As above, but transpose the matrix. 1098 */ 1099 static void 1100 load_transpose_matrix(GLfloat registers[][4], GLuint pos, 1101 const GLfloat mat[16]) 1102 { 1103 memcpy(registers[pos], mat, 16 * sizeof(GLfloat)); 1104 } 1105 1106 1107 /** 1108 * Load current vertex program's parameter registers with tracked 1109 * matrices (if NV program). This only needs to be done per 1110 * glBegin/glEnd, not per-vertex. 1111 */ 1112 void 1113 _mesa_load_tracked_matrices(struct gl_context *ctx) 1114 { 1115 GLuint i; 1116 1117 for (i = 0; i < MAX_NV_VERTEX_PROGRAM_PARAMS / 4; i++) { 1118 /* point 'mat' at source matrix */ 1119 GLmatrix *mat; 1120 if (ctx->VertexProgram.TrackMatrix[i] == GL_MODELVIEW) { 1121 mat = ctx->ModelviewMatrixStack.Top; 1122 } 1123 else if (ctx->VertexProgram.TrackMatrix[i] == GL_PROJECTION) { 1124 mat = ctx->ProjectionMatrixStack.Top; 1125 } 1126 else if (ctx->VertexProgram.TrackMatrix[i] == GL_TEXTURE) { 1127 GLuint unit = MIN2(ctx->Texture.CurrentUnit, 1128 Elements(ctx->TextureMatrixStack) - 1); 1129 mat = ctx->TextureMatrixStack[unit].Top; 1130 } 1131 else if (ctx->VertexProgram.TrackMatrix[i]==GL_MODELVIEW_PROJECTION_NV) { 1132 /* XXX verify the combined matrix is up to date */ 1133 mat = &ctx->_ModelProjectMatrix; 1134 } 1135 else if (ctx->VertexProgram.TrackMatrix[i] >= GL_MATRIX0_NV && 1136 ctx->VertexProgram.TrackMatrix[i] <= GL_MATRIX7_NV) { 1137 GLuint n = ctx->VertexProgram.TrackMatrix[i] - GL_MATRIX0_NV; 1138 ASSERT(n < Elements(ctx->ProgramMatrixStack)); 1139 mat = ctx->ProgramMatrixStack[n].Top; 1140 } 1141 else { 1142 /* no matrix is tracked, but we leave the register values as-is */ 1143 assert(ctx->VertexProgram.TrackMatrix[i] == GL_NONE); 1144 continue; 1145 } 1146 1147 /* load the matrix values into sequential registers */ 1148 if (ctx->VertexProgram.TrackMatrixTransform[i] == GL_IDENTITY_NV) { 1149 load_matrix(ctx->VertexProgram.Parameters, i*4, mat->m); 1150 } 1151 else if (ctx->VertexProgram.TrackMatrixTransform[i] == GL_INVERSE_NV) { 1152 _math_matrix_analyse(mat); /* update the inverse */ 1153 ASSERT(!_math_matrix_is_dirty(mat)); 1154 load_matrix(ctx->VertexProgram.Parameters, i*4, mat->inv); 1155 } 1156 else if (ctx->VertexProgram.TrackMatrixTransform[i] == GL_TRANSPOSE_NV) { 1157 load_transpose_matrix(ctx->VertexProgram.Parameters, i*4, mat->m); 1158 } 1159 else { 1160 assert(ctx->VertexProgram.TrackMatrixTransform[i] 1161 == GL_INVERSE_TRANSPOSE_NV); 1162 _math_matrix_analyse(mat); /* update the inverse */ 1163 ASSERT(!_math_matrix_is_dirty(mat)); 1164 load_transpose_matrix(ctx->VertexProgram.Parameters, i*4, mat->inv); 1165 } 1166 } 1167 } 1168