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