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 */ 56 static void 57 _mesa_fetch_state(struct gl_context *ctx, const gl_state_index 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.Unit[unit].GenS.EyePlane); 219 return; 220 case STATE_TEXGEN_EYE_T: 221 COPY_4V(value, ctx->Texture.Unit[unit].GenT.EyePlane); 222 return; 223 case STATE_TEXGEN_EYE_R: 224 COPY_4V(value, ctx->Texture.Unit[unit].GenR.EyePlane); 225 return; 226 case STATE_TEXGEN_EYE_Q: 227 COPY_4V(value, ctx->Texture.Unit[unit].GenQ.EyePlane); 228 return; 229 case STATE_TEXGEN_OBJECT_S: 230 COPY_4V(value, ctx->Texture.Unit[unit].GenS.ObjectPlane); 231 return; 232 case STATE_TEXGEN_OBJECT_T: 233 COPY_4V(value, ctx->Texture.Unit[unit].GenT.ObjectPlane); 234 return; 235 case STATE_TEXGEN_OBJECT_R: 236 COPY_4V(value, ctx->Texture.Unit[unit].GenR.ObjectPlane); 237 return; 238 case STATE_TEXGEN_OBJECT_Q: 239 COPY_4V(value, ctx->Texture.Unit[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.Unit[unit].EnvColor); 252 else 253 COPY_4V(value, ctx->Texture.Unit[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->_ModelViewInvScale, 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_TEXRECT_SCALE: 462 /* Value = { 1/texWidth, 1/texHeight, 0, 1 }. 463 * Used to convert unnormalized texcoords to normalized texcoords. 464 */ 465 { 466 const int unit = (int) state[2]; 467 const struct gl_texture_object *texObj 468 = ctx->Texture.Unit[unit]._Current; 469 if (texObj) { 470 struct gl_texture_image *texImage = texObj->Image[0][0]; 471 ASSIGN_4V(value, 472 (GLfloat) (1.0 / texImage->Width), 473 (GLfloat) (1.0 / texImage->Height), 474 0.0f, 1.0f); 475 } 476 } 477 return; 478 479 case STATE_FOG_PARAMS_OPTIMIZED: 480 /* for simpler per-vertex/pixel fog calcs. POW (for EXP/EXP2 fog) 481 * might be more expensive than EX2 on some hw, plus it needs 482 * another constant (e) anyway. Linear fog can now be done with a 483 * single MAD. 484 * linear: fogcoord * -1/(end-start) + end/(end-start) 485 * exp: 2^-(density/ln(2) * fogcoord) 486 * exp2: 2^-((density/(sqrt(ln(2))) * fogcoord)^2) 487 */ 488 value[0] = (ctx->Fog.End == ctx->Fog.Start) 489 ? 1.0f : (GLfloat)(-1.0F / (ctx->Fog.End - ctx->Fog.Start)); 490 value[1] = ctx->Fog.End * -value[0]; 491 value[2] = (GLfloat)(ctx->Fog.Density * M_LOG2E); /* M_LOG2E == 1/ln(2) */ 492 value[3] = (GLfloat)(ctx->Fog.Density * ONE_DIV_SQRT_LN2); 493 return; 494 495 case STATE_POINT_SIZE_CLAMPED: 496 { 497 /* this includes implementation dependent limits, to avoid 498 * another potentially necessary clamp. 499 * Note: for sprites, point smooth (point AA) is ignored 500 * and we'll clamp to MinPointSizeAA and MaxPointSize, because we 501 * expect drivers will want to say their minimum for AA size is 0.0 502 * but for non-AA it's 1.0 (because normal points with size below 1.0 503 * need to get rounded up to 1.0, hence never disappear). GL does 504 * not specify max clamp size for sprites, other than it needs to be 505 * at least as large as max AA size, hence use non-AA size there. 506 */ 507 GLfloat minImplSize; 508 GLfloat maxImplSize; 509 if (ctx->Point.PointSprite) { 510 minImplSize = ctx->Const.MinPointSizeAA; 511 maxImplSize = ctx->Const.MaxPointSize; 512 } 513 else if (ctx->Point.SmoothFlag || _mesa_is_multisample_enabled(ctx)) { 514 minImplSize = ctx->Const.MinPointSizeAA; 515 maxImplSize = ctx->Const.MaxPointSizeAA; 516 } 517 else { 518 minImplSize = ctx->Const.MinPointSize; 519 maxImplSize = ctx->Const.MaxPointSize; 520 } 521 value[0] = ctx->Point.Size; 522 value[1] = ctx->Point.MinSize >= minImplSize ? ctx->Point.MinSize : minImplSize; 523 value[2] = ctx->Point.MaxSize <= maxImplSize ? ctx->Point.MaxSize : maxImplSize; 524 value[3] = ctx->Point.Threshold; 525 } 526 return; 527 case STATE_LIGHT_SPOT_DIR_NORMALIZED: 528 { 529 /* here, state[2] is the light number */ 530 /* pre-normalize spot dir */ 531 const GLuint ln = (GLuint) state[2]; 532 COPY_3V(value, ctx->Light.Light[ln]._NormSpotDirection); 533 value[3] = ctx->Light.Light[ln]._CosCutoff; 534 } 535 return; 536 537 case STATE_LIGHT_POSITION: 538 { 539 const GLuint ln = (GLuint) state[2]; 540 COPY_4V(value, ctx->Light.Light[ln]._Position); 541 } 542 return; 543 544 case STATE_LIGHT_POSITION_NORMALIZED: 545 { 546 const GLuint ln = (GLuint) state[2]; 547 COPY_4V(value, ctx->Light.Light[ln]._Position); 548 NORMALIZE_3FV( value ); 549 } 550 return; 551 552 case STATE_LIGHT_HALF_VECTOR: 553 { 554 const GLuint ln = (GLuint) state[2]; 555 GLfloat p[3]; 556 /* Compute infinite half angle vector: 557 * halfVector = normalize(normalize(lightPos) + (0, 0, 1)) 558 * light.EyePosition.w should be 0 for infinite lights. 559 */ 560 COPY_3V(p, ctx->Light.Light[ln]._Position); 561 NORMALIZE_3FV(p); 562 ADD_3V(value, p, ctx->_EyeZDir); 563 NORMALIZE_3FV(value); 564 value[3] = 1.0; 565 } 566 return; 567 568 case STATE_PT_SCALE: 569 value[0] = ctx->Pixel.RedScale; 570 value[1] = ctx->Pixel.GreenScale; 571 value[2] = ctx->Pixel.BlueScale; 572 value[3] = ctx->Pixel.AlphaScale; 573 return; 574 575 case STATE_PT_BIAS: 576 value[0] = ctx->Pixel.RedBias; 577 value[1] = ctx->Pixel.GreenBias; 578 value[2] = ctx->Pixel.BlueBias; 579 value[3] = ctx->Pixel.AlphaBias; 580 return; 581 582 case STATE_FB_SIZE: 583 value[0] = (GLfloat) (ctx->DrawBuffer->Width - 1); 584 value[1] = (GLfloat) (ctx->DrawBuffer->Height - 1); 585 value[2] = 0.0F; 586 value[3] = 0.0F; 587 return; 588 589 case STATE_FB_WPOS_Y_TRANSFORM: 590 /* A driver may negate this conditional by using ZW swizzle 591 * instead of XY (based on e.g. some other state). */ 592 if (_mesa_is_user_fbo(ctx->DrawBuffer)) { 593 /* Identity (XY) followed by flipping Y upside down (ZW). */ 594 value[0] = 1.0F; 595 value[1] = 0.0F; 596 value[2] = -1.0F; 597 value[3] = (GLfloat) ctx->DrawBuffer->Height; 598 } else { 599 /* Flipping Y upside down (XY) followed by identity (ZW). */ 600 value[0] = -1.0F; 601 value[1] = (GLfloat) ctx->DrawBuffer->Height; 602 value[2] = 1.0F; 603 value[3] = 0.0F; 604 } 605 return; 606 607 case STATE_TCS_PATCH_VERTICES_IN: 608 val[0].i = ctx->TessCtrlProgram.patch_vertices; 609 return; 610 611 case STATE_TES_PATCH_VERTICES_IN: 612 if (ctx->TessCtrlProgram._Current) 613 val[0].i = ctx->TessCtrlProgram._Current->info.tess.tcs_vertices_out; 614 else 615 val[0].i = ctx->TessCtrlProgram.patch_vertices; 616 return; 617 618 case STATE_ADVANCED_BLENDING_MODE: 619 val[0].i = ctx->Color.BlendEnabled ? ctx->Color._AdvancedBlendMode : 0; 620 return; 621 622 /* XXX: make sure new tokens added here are also handled in the 623 * _mesa_program_state_flags() switch, below. 624 */ 625 default: 626 /* Unknown state indexes are silently ignored here. 627 * Drivers may do something special. 628 */ 629 return; 630 } 631 return; 632 633 default: 634 _mesa_problem(ctx, "Invalid state in _mesa_fetch_state"); 635 return; 636 } 637 } 638 639 640 /** 641 * Return a bitmask of the Mesa state flags (_NEW_* values) which would 642 * indicate that the given context state may have changed. 643 * The bitmask is used during validation to determine if we need to update 644 * vertex/fragment program parameters (like "state.material.color") when 645 * some GL state has changed. 646 */ 647 GLbitfield 648 _mesa_program_state_flags(const gl_state_index state[STATE_LENGTH]) 649 { 650 switch (state[0]) { 651 case STATE_MATERIAL: 652 case STATE_LIGHTPROD: 653 case STATE_LIGHTMODEL_SCENECOLOR: 654 /* these can be effected by glColor when colormaterial mode is used */ 655 return _NEW_LIGHT | _NEW_CURRENT_ATTRIB; 656 657 case STATE_LIGHT: 658 case STATE_LIGHTMODEL_AMBIENT: 659 return _NEW_LIGHT; 660 661 case STATE_TEXGEN: 662 return _NEW_TEXTURE; 663 case STATE_TEXENV_COLOR: 664 return _NEW_TEXTURE | _NEW_BUFFERS | _NEW_FRAG_CLAMP; 665 666 case STATE_FOG_COLOR: 667 return _NEW_FOG | _NEW_BUFFERS | _NEW_FRAG_CLAMP; 668 case STATE_FOG_PARAMS: 669 return _NEW_FOG; 670 671 case STATE_CLIPPLANE: 672 return _NEW_TRANSFORM; 673 674 case STATE_POINT_SIZE: 675 case STATE_POINT_ATTENUATION: 676 return _NEW_POINT; 677 678 case STATE_MODELVIEW_MATRIX: 679 return _NEW_MODELVIEW; 680 case STATE_PROJECTION_MATRIX: 681 return _NEW_PROJECTION; 682 case STATE_MVP_MATRIX: 683 return _NEW_MODELVIEW | _NEW_PROJECTION; 684 case STATE_TEXTURE_MATRIX: 685 return _NEW_TEXTURE_MATRIX; 686 case STATE_PROGRAM_MATRIX: 687 return _NEW_TRACK_MATRIX; 688 689 case STATE_NUM_SAMPLES: 690 return _NEW_BUFFERS; 691 692 case STATE_DEPTH_RANGE: 693 return _NEW_VIEWPORT; 694 695 case STATE_FRAGMENT_PROGRAM: 696 case STATE_VERTEX_PROGRAM: 697 return _NEW_PROGRAM; 698 699 case STATE_NORMAL_SCALE: 700 return _NEW_MODELVIEW; 701 702 case STATE_INTERNAL: 703 switch (state[1]) { 704 case STATE_CURRENT_ATTRIB: 705 return _NEW_CURRENT_ATTRIB; 706 case STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED: 707 return _NEW_CURRENT_ATTRIB | _NEW_LIGHT | _NEW_BUFFERS; 708 709 case STATE_NORMAL_SCALE: 710 return _NEW_MODELVIEW; 711 712 case STATE_TEXRECT_SCALE: 713 return _NEW_TEXTURE; 714 case STATE_FOG_PARAMS_OPTIMIZED: 715 return _NEW_FOG; 716 case STATE_POINT_SIZE_CLAMPED: 717 return _NEW_POINT | _NEW_MULTISAMPLE; 718 case STATE_LIGHT_SPOT_DIR_NORMALIZED: 719 case STATE_LIGHT_POSITION: 720 case STATE_LIGHT_POSITION_NORMALIZED: 721 case STATE_LIGHT_HALF_VECTOR: 722 return _NEW_LIGHT; 723 724 case STATE_PT_SCALE: 725 case STATE_PT_BIAS: 726 return _NEW_PIXEL; 727 728 case STATE_FB_SIZE: 729 case STATE_FB_WPOS_Y_TRANSFORM: 730 return _NEW_BUFFERS; 731 732 case STATE_ADVANCED_BLENDING_MODE: 733 return _NEW_COLOR; 734 735 default: 736 /* unknown state indexes are silently ignored and 737 * no flag set, since it is handled by the driver. 738 */ 739 return 0; 740 } 741 742 default: 743 _mesa_problem(NULL, "unexpected state[0] in make_state_flags()"); 744 return 0; 745 } 746 } 747 748 749 static void 750 append(char *dst, const char *src) 751 { 752 while (*dst) 753 dst++; 754 while (*src) 755 *dst++ = *src++; 756 *dst = 0; 757 } 758 759 760 /** 761 * Convert token 'k' to a string, append it onto 'dst' string. 762 */ 763 static void 764 append_token(char *dst, gl_state_index k) 765 { 766 switch (k) { 767 case STATE_MATERIAL: 768 append(dst, "material"); 769 break; 770 case STATE_LIGHT: 771 append(dst, "light"); 772 break; 773 case STATE_LIGHTMODEL_AMBIENT: 774 append(dst, "lightmodel.ambient"); 775 break; 776 case STATE_LIGHTMODEL_SCENECOLOR: 777 break; 778 case STATE_LIGHTPROD: 779 append(dst, "lightprod"); 780 break; 781 case STATE_TEXGEN: 782 append(dst, "texgen"); 783 break; 784 case STATE_FOG_COLOR: 785 append(dst, "fog.color"); 786 break; 787 case STATE_FOG_PARAMS: 788 append(dst, "fog.params"); 789 break; 790 case STATE_CLIPPLANE: 791 append(dst, "clip"); 792 break; 793 case STATE_POINT_SIZE: 794 append(dst, "point.size"); 795 break; 796 case STATE_POINT_ATTENUATION: 797 append(dst, "point.attenuation"); 798 break; 799 case STATE_MODELVIEW_MATRIX: 800 append(dst, "matrix.modelview"); 801 break; 802 case STATE_PROJECTION_MATRIX: 803 append(dst, "matrix.projection"); 804 break; 805 case STATE_MVP_MATRIX: 806 append(dst, "matrix.mvp"); 807 break; 808 case STATE_TEXTURE_MATRIX: 809 append(dst, "matrix.texture"); 810 break; 811 case STATE_PROGRAM_MATRIX: 812 append(dst, "matrix.program"); 813 break; 814 case STATE_MATRIX_INVERSE: 815 append(dst, ".inverse"); 816 break; 817 case STATE_MATRIX_TRANSPOSE: 818 append(dst, ".transpose"); 819 break; 820 case STATE_MATRIX_INVTRANS: 821 append(dst, ".invtrans"); 822 break; 823 case STATE_AMBIENT: 824 append(dst, ".ambient"); 825 break; 826 case STATE_DIFFUSE: 827 append(dst, ".diffuse"); 828 break; 829 case STATE_SPECULAR: 830 append(dst, ".specular"); 831 break; 832 case STATE_EMISSION: 833 append(dst, ".emission"); 834 break; 835 case STATE_SHININESS: 836 append(dst, "lshininess"); 837 break; 838 case STATE_HALF_VECTOR: 839 append(dst, ".half"); 840 break; 841 case STATE_POSITION: 842 append(dst, ".position"); 843 break; 844 case STATE_ATTENUATION: 845 append(dst, ".attenuation"); 846 break; 847 case STATE_SPOT_DIRECTION: 848 append(dst, ".spot.direction"); 849 break; 850 case STATE_SPOT_CUTOFF: 851 append(dst, ".spot.cutoff"); 852 break; 853 case STATE_TEXGEN_EYE_S: 854 append(dst, ".eye.s"); 855 break; 856 case STATE_TEXGEN_EYE_T: 857 append(dst, ".eye.t"); 858 break; 859 case STATE_TEXGEN_EYE_R: 860 append(dst, ".eye.r"); 861 break; 862 case STATE_TEXGEN_EYE_Q: 863 append(dst, ".eye.q"); 864 break; 865 case STATE_TEXGEN_OBJECT_S: 866 append(dst, ".object.s"); 867 break; 868 case STATE_TEXGEN_OBJECT_T: 869 append(dst, ".object.t"); 870 break; 871 case STATE_TEXGEN_OBJECT_R: 872 append(dst, ".object.r"); 873 break; 874 case STATE_TEXGEN_OBJECT_Q: 875 append(dst, ".object.q"); 876 break; 877 case STATE_TEXENV_COLOR: 878 append(dst, "texenv"); 879 break; 880 case STATE_NUM_SAMPLES: 881 append(dst, "numsamples"); 882 break; 883 case STATE_DEPTH_RANGE: 884 append(dst, "depth.range"); 885 break; 886 case STATE_VERTEX_PROGRAM: 887 case STATE_FRAGMENT_PROGRAM: 888 break; 889 case STATE_ENV: 890 append(dst, "env"); 891 break; 892 case STATE_LOCAL: 893 append(dst, "local"); 894 break; 895 /* BEGIN internal state vars */ 896 case STATE_INTERNAL: 897 append(dst, ".internal."); 898 break; 899 case STATE_CURRENT_ATTRIB: 900 append(dst, "current"); 901 break; 902 case STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED: 903 append(dst, "currentAttribMaybeVPClamped"); 904 break; 905 case STATE_NORMAL_SCALE: 906 append(dst, "normalScale"); 907 break; 908 case STATE_TEXRECT_SCALE: 909 append(dst, "texrectScale"); 910 break; 911 case STATE_FOG_PARAMS_OPTIMIZED: 912 append(dst, "fogParamsOptimized"); 913 break; 914 case STATE_POINT_SIZE_CLAMPED: 915 append(dst, "pointSizeClamped"); 916 break; 917 case STATE_LIGHT_SPOT_DIR_NORMALIZED: 918 append(dst, "lightSpotDirNormalized"); 919 break; 920 case STATE_LIGHT_POSITION: 921 append(dst, "lightPosition"); 922 break; 923 case STATE_LIGHT_POSITION_NORMALIZED: 924 append(dst, "light.position.normalized"); 925 break; 926 case STATE_LIGHT_HALF_VECTOR: 927 append(dst, "lightHalfVector"); 928 break; 929 case STATE_PT_SCALE: 930 append(dst, "PTscale"); 931 break; 932 case STATE_PT_BIAS: 933 append(dst, "PTbias"); 934 break; 935 case STATE_FB_SIZE: 936 append(dst, "FbSize"); 937 break; 938 case STATE_FB_WPOS_Y_TRANSFORM: 939 append(dst, "FbWposYTransform"); 940 break; 941 case STATE_ADVANCED_BLENDING_MODE: 942 append(dst, "AdvancedBlendingMode"); 943 break; 944 default: 945 /* probably STATE_INTERNAL_DRIVER+i (driver private state) */ 946 append(dst, "driverState"); 947 } 948 } 949 950 static void 951 append_face(char *dst, GLint face) 952 { 953 if (face == 0) 954 append(dst, "front."); 955 else 956 append(dst, "back."); 957 } 958 959 static void 960 append_index(char *dst, GLint index) 961 { 962 char s[20]; 963 sprintf(s, "[%d]", index); 964 append(dst, s); 965 } 966 967 /** 968 * Make a string from the given state vector. 969 * For example, return "state.matrix.texture[2].inverse". 970 * Use free() to deallocate the string. 971 */ 972 char * 973 _mesa_program_state_string(const gl_state_index state[STATE_LENGTH]) 974 { 975 char str[1000] = ""; 976 char tmp[30]; 977 978 append(str, "state."); 979 append_token(str, state[0]); 980 981 switch (state[0]) { 982 case STATE_MATERIAL: 983 append_face(str, state[1]); 984 append_token(str, state[2]); 985 break; 986 case STATE_LIGHT: 987 append_index(str, state[1]); /* light number [i]. */ 988 append_token(str, state[2]); /* coefficients */ 989 break; 990 case STATE_LIGHTMODEL_AMBIENT: 991 append(str, "lightmodel.ambient"); 992 break; 993 case STATE_LIGHTMODEL_SCENECOLOR: 994 if (state[1] == 0) { 995 append(str, "lightmodel.front.scenecolor"); 996 } 997 else { 998 append(str, "lightmodel.back.scenecolor"); 999 } 1000 break; 1001 case STATE_LIGHTPROD: 1002 append_index(str, state[1]); /* light number [i]. */ 1003 append_face(str, state[2]); 1004 append_token(str, state[3]); 1005 break; 1006 case STATE_TEXGEN: 1007 append_index(str, state[1]); /* tex unit [i] */ 1008 append_token(str, state[2]); /* plane coef */ 1009 break; 1010 case STATE_TEXENV_COLOR: 1011 append_index(str, state[1]); /* tex unit [i] */ 1012 append(str, "color"); 1013 break; 1014 case STATE_CLIPPLANE: 1015 append_index(str, state[1]); /* plane [i] */ 1016 append(str, ".plane"); 1017 break; 1018 case STATE_MODELVIEW_MATRIX: 1019 case STATE_PROJECTION_MATRIX: 1020 case STATE_MVP_MATRIX: 1021 case STATE_TEXTURE_MATRIX: 1022 case STATE_PROGRAM_MATRIX: 1023 { 1024 /* state[0] = modelview, projection, texture, etc. */ 1025 /* state[1] = which texture matrix or program matrix */ 1026 /* state[2] = first row to fetch */ 1027 /* state[3] = last row to fetch */ 1028 /* state[4] = transpose, inverse or invtrans */ 1029 const gl_state_index mat = state[0]; 1030 const GLuint index = (GLuint) state[1]; 1031 const GLuint firstRow = (GLuint) state[2]; 1032 const GLuint lastRow = (GLuint) state[3]; 1033 const gl_state_index modifier = state[4]; 1034 if (index || 1035 mat == STATE_TEXTURE_MATRIX || 1036 mat == STATE_PROGRAM_MATRIX) 1037 append_index(str, index); 1038 if (modifier) 1039 append_token(str, modifier); 1040 if (firstRow == lastRow) 1041 sprintf(tmp, ".row[%d]", firstRow); 1042 else 1043 sprintf(tmp, ".row[%d..%d]", firstRow, lastRow); 1044 append(str, tmp); 1045 } 1046 break; 1047 case STATE_POINT_SIZE: 1048 break; 1049 case STATE_POINT_ATTENUATION: 1050 break; 1051 case STATE_FOG_PARAMS: 1052 break; 1053 case STATE_FOG_COLOR: 1054 break; 1055 case STATE_NUM_SAMPLES: 1056 break; 1057 case STATE_DEPTH_RANGE: 1058 break; 1059 case STATE_FRAGMENT_PROGRAM: 1060 case STATE_VERTEX_PROGRAM: 1061 /* state[1] = {STATE_ENV, STATE_LOCAL} */ 1062 /* state[2] = parameter index */ 1063 append_token(str, state[1]); 1064 append_index(str, state[2]); 1065 break; 1066 case STATE_NORMAL_SCALE: 1067 break; 1068 case STATE_INTERNAL: 1069 append_token(str, state[1]); 1070 if (state[1] == STATE_CURRENT_ATTRIB) 1071 append_index(str, state[2]); 1072 break; 1073 default: 1074 _mesa_problem(NULL, "Invalid state in _mesa_program_state_string"); 1075 break; 1076 } 1077 1078 return strdup(str); 1079 } 1080 1081 1082 /** 1083 * Loop over all the parameters in a parameter list. If the parameter 1084 * is a GL state reference, look up the current value of that state 1085 * variable and put it into the parameter's Value[4] array. 1086 * Other parameter types never change or are explicitly set by the user 1087 * with glUniform() or glProgramParameter(), etc. 1088 * This would be called at glBegin time. 1089 */ 1090 void 1091 _mesa_load_state_parameters(struct gl_context *ctx, 1092 struct gl_program_parameter_list *paramList) 1093 { 1094 GLuint i; 1095 1096 if (!paramList) 1097 return; 1098 1099 for (i = 0; i < paramList->NumParameters; i++) { 1100 if (paramList->Parameters[i].Type == PROGRAM_STATE_VAR) { 1101 _mesa_fetch_state(ctx, 1102 paramList->Parameters[i].StateIndexes, 1103 ¶mList->ParameterValues[i][0]); 1104 } 1105 } 1106 } 1107