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