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 <stddef.h> 34#include "main/glheader.h" 35#include "main/context.h" 36#include "main/blend.h" 37 38#include "main/macros.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 48static ALWAYS_INLINE void 49copy_matrix(float *value, const float *m, unsigned firstRow, unsigned lastRow) 50{ 51 unsigned i, row; 52 53 assert(firstRow < 4); 54 assert(lastRow < 4); 55 56 for (i = 0, row = firstRow; row <= lastRow; row++) { 57 value[i++] = m[row + 0]; 58 value[i++] = m[row + 4]; 59 value[i++] = m[row + 8]; 60 value[i++] = m[row + 12]; 61 } 62} 63 64static ALWAYS_INLINE void 65copy_matrix_transposed(float *value, const float *m, unsigned firstRow, unsigned lastRow) 66{ 67 assert(firstRow < 4); 68 assert(lastRow < 4); 69 70 memcpy(value, &m[firstRow * 4], 71 (lastRow - firstRow + 1) * 4 * sizeof(GLfloat)); 72} 73 74/** 75 * Use the list of tokens in the state[] array to find global GL state 76 * and return it in <value>. Usually, four values are returned in <value> 77 * but matrix queries may return as many as 16 values. 78 * This function is used for ARB vertex/fragment programs. 79 * The program parser will produce the state[] values. 80 */ 81static void 82fetch_state(struct gl_context *ctx, const gl_state_index16 state[], 83 gl_constant_value *val) 84{ 85 GLfloat *value = &val->f; 86 87 switch (state[0]) { 88 case STATE_MATERIAL: 89 { 90 /* state[1] is MAT_ATTRIB_FRONT_* */ 91 const GLuint index = (GLuint) state[1]; 92 const struct gl_material *mat = &ctx->Light.Material; 93 assert(index >= MAT_ATTRIB_FRONT_AMBIENT && 94 index <= MAT_ATTRIB_BACK_SHININESS); 95 if (index >= MAT_ATTRIB_FRONT_SHININESS) { 96 value[0] = mat->Attrib[index][0]; 97 value[1] = 0.0F; 98 value[2] = 0.0F; 99 value[3] = 1.0F; 100 } else { 101 COPY_4V(value, mat->Attrib[index]); 102 } 103 return; 104 } 105 case STATE_LIGHT: 106 { 107 /* state[1] is the light number */ 108 const GLuint ln = (GLuint) state[1]; 109 /* state[2] is the light attribute */ 110 const unsigned index = state[2] - STATE_AMBIENT; 111 assert(index < 8); 112 if (index != STATE_SPOT_CUTOFF) 113 COPY_4V(value, (float*)&ctx->Light.LightSource[ln] + index * 4); 114 else 115 value[0] = ctx->Light.LightSource[ln].SpotCutoff; 116 return; 117 } 118 case STATE_LIGHT_ARRAY: { 119 /* This must be exact because it must match the gl_LightSource layout 120 * in GLSL. 121 */ 122 STATIC_ASSERT(sizeof(struct gl_light_uniforms) == 29 * 4); 123 STATIC_ASSERT(ARRAY_SIZE(ctx->Light.LightSourceData) == 29 * MAX_LIGHTS); 124 /* state[1] is the index of the first value */ 125 /* state[2] is the number of values */ 126 assert(state[1] + state[2] <= ARRAY_SIZE(ctx->Light.LightSourceData)); 127 memcpy(value, &ctx->Light.LightSourceData[state[1]], 128 state[2] * sizeof(float)); 129 return; 130 } 131 case STATE_LIGHT_ATTENUATION_ARRAY: { 132 const unsigned first = state[1]; 133 const unsigned num_lights = state[2]; 134 for (unsigned i = 0; i < num_lights; i++) { 135 COPY_4V(value, 136 &ctx->Light.LightSource[first + i].ConstantAttenuation); 137 value += 4; 138 } 139 return; 140 } 141 case STATE_LIGHTMODEL_AMBIENT: 142 COPY_4V(value, ctx->Light.Model.Ambient); 143 return; 144 case STATE_LIGHTMODEL_SCENECOLOR: 145 if (state[1] == 0) { 146 /* front */ 147 GLint i; 148 for (i = 0; i < 3; i++) { 149 value[i] = ctx->Light.Model.Ambient[i] 150 * ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT][i] 151 + ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION][i]; 152 } 153 value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]; 154 } 155 else { 156 /* back */ 157 GLint i; 158 for (i = 0; i < 3; i++) { 159 value[i] = ctx->Light.Model.Ambient[i] 160 * ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_AMBIENT][i] 161 + ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_EMISSION][i]; 162 } 163 value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]; 164 } 165 return; 166 case STATE_LIGHTPROD: 167 { 168 const GLuint ln = (GLuint) state[1]; 169 const GLuint index = (GLuint) state[2]; 170 const GLuint attr = (index / 2) * 4; 171 assert(index >= MAT_ATTRIB_FRONT_AMBIENT && 172 index <= MAT_ATTRIB_BACK_SPECULAR); 173 for (int i = 0; i < 3; i++) { 174 /* We want attr to access out of bounds into the following Diffuse 175 * and Specular fields. This is guaranteed to work because 176 * STATE_LIGHT and STATE_LIGHT_ARRAY also rely on this memory 177 * layout. 178 */ 179 STATIC_ASSERT(offsetof(struct gl_light_uniforms, Ambient) + 16 == 180 offsetof(struct gl_light_uniforms, Diffuse)); 181 STATIC_ASSERT(offsetof(struct gl_light_uniforms, Diffuse) + 16 == 182 offsetof(struct gl_light_uniforms, Specular)); 183 value[i] = ctx->Light.LightSource[ln].Ambient[attr + i] * 184 ctx->Light.Material.Attrib[index][i]; 185 } 186 /* [3] = material alpha */ 187 value[3] = ctx->Light.Material.Attrib[index][3]; 188 return; 189 } 190 case STATE_LIGHTPROD_ARRAY_FRONT: { 191 const unsigned first_light = state[1]; 192 const unsigned num_lights = state[2]; 193 194 for (unsigned i = 0; i < num_lights; i++) { 195 unsigned light = first_light + i; 196 197 for (unsigned attrib = MAT_ATTRIB_FRONT_AMBIENT; 198 attrib <= MAT_ATTRIB_FRONT_SPECULAR; attrib += 2) { 199 for (int chan = 0; chan < 3; chan++) { 200 /* We want offset to access out of bounds into the following 201 * Diffuse and Specular fields. This is guaranteed to work 202 * because STATE_LIGHT and STATE_LIGHT_ATTRIBS also rely 203 * on this memory layout. 204 */ 205 unsigned offset = (attrib / 2) * 4 + chan; 206 *value++ = 207 (&ctx->Light.LightSource[light].Ambient[0])[offset] * 208 ctx->Light.Material.Attrib[attrib][chan]; 209 } 210 /* [3] = material alpha */ 211 *value++ = ctx->Light.Material.Attrib[attrib][3]; 212 } 213 } 214 return; 215 } 216 case STATE_LIGHTPROD_ARRAY_BACK: { 217 const unsigned first_light = state[1]; 218 const unsigned num_lights = state[2]; 219 220 for (unsigned i = 0; i < num_lights; i++) { 221 unsigned light = first_light + i; 222 223 for (unsigned attrib = MAT_ATTRIB_BACK_AMBIENT; 224 attrib <= MAT_ATTRIB_BACK_SPECULAR; attrib += 2) { 225 for (int chan = 0; chan < 3; chan++) { 226 /* We want offset to access out of bounds into the following 227 * Diffuse and Specular fields. This is guaranteed to work 228 * because STATE_LIGHT and STATE_LIGHT_ATTRIBS also rely 229 * on this memory layout. 230 */ 231 unsigned offset = (attrib / 2) * 4 + chan; 232 *value++ = 233 (&ctx->Light.LightSource[light].Ambient[0])[offset] * 234 ctx->Light.Material.Attrib[attrib][chan]; 235 } 236 /* [3] = material alpha */ 237 *value++ = ctx->Light.Material.Attrib[attrib][3]; 238 } 239 } 240 return; 241 } 242 case STATE_LIGHTPROD_ARRAY_TWOSIDE: { 243 const unsigned first_light = state[1]; 244 const unsigned num_lights = state[2]; 245 246 for (unsigned i = 0; i < num_lights; i++) { 247 unsigned light = first_light + i; 248 249 for (unsigned attrib = MAT_ATTRIB_FRONT_AMBIENT; 250 attrib <= MAT_ATTRIB_BACK_SPECULAR; attrib++) { 251 for (int chan = 0; chan < 3; chan++) { 252 /* We want offset to access out of bounds into the following 253 * Diffuse and Specular fields. This is guaranteed to work 254 * because STATE_LIGHT and STATE_LIGHT_ATTRIBS also rely 255 * on this memory layout. 256 */ 257 unsigned offset = (attrib / 2) * 4 + chan; 258 *value++ = 259 (&ctx->Light.LightSource[light].Ambient[0])[offset] * 260 ctx->Light.Material.Attrib[attrib][chan]; 261 } 262 /* [3] = material alpha */ 263 *value++ = ctx->Light.Material.Attrib[attrib][3]; 264 } 265 } 266 return; 267 } 268 case STATE_TEXGEN: 269 { 270 /* state[1] is the texture unit */ 271 const GLuint unit = (GLuint) state[1]; 272 /* state[2] is the texgen attribute */ 273 /* Assertions for the expected memory layout. */ 274#define MEMBER_SIZEOF(type, member) sizeof(((type *)0)->member) 275 STATIC_ASSERT(MEMBER_SIZEOF(struct gl_fixedfunc_texture_unit, 276 EyePlane[0]) == 4 * sizeof(float)); 277 STATIC_ASSERT(MEMBER_SIZEOF(struct gl_fixedfunc_texture_unit, 278 ObjectPlane[0]) == 4 * sizeof(float)); 279#undef MEMBER_SIZEOF 280 STATIC_ASSERT(STATE_TEXGEN_EYE_T - STATE_TEXGEN_EYE_S == GEN_T - GEN_S); 281 STATIC_ASSERT(STATE_TEXGEN_EYE_R - STATE_TEXGEN_EYE_S == GEN_R - GEN_S); 282 STATIC_ASSERT(STATE_TEXGEN_EYE_Q - STATE_TEXGEN_EYE_S == GEN_Q - GEN_S); 283 STATIC_ASSERT(offsetof(struct gl_fixedfunc_texture_unit, ObjectPlane) - 284 offsetof(struct gl_fixedfunc_texture_unit, EyePlane) == 285 (STATE_TEXGEN_OBJECT_S - STATE_TEXGEN_EYE_S) * 4 * sizeof(float)); 286 STATIC_ASSERT(STATE_TEXGEN_OBJECT_T - STATE_TEXGEN_OBJECT_S == GEN_T - GEN_S); 287 STATIC_ASSERT(STATE_TEXGEN_OBJECT_R - STATE_TEXGEN_OBJECT_S == GEN_R - GEN_S); 288 STATIC_ASSERT(STATE_TEXGEN_OBJECT_Q - STATE_TEXGEN_OBJECT_S == GEN_Q - GEN_S); 289 290 const float *attr = (float*)ctx->Texture.FixedFuncUnit[unit].EyePlane + 291 (state[2] - STATE_TEXGEN_EYE_S) * 4; 292 COPY_4V(value, attr); 293 return; 294 } 295 case STATE_TEXENV_COLOR: 296 { 297 /* state[1] is the texture unit */ 298 const GLuint unit = (GLuint) state[1]; 299 if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer)) 300 COPY_4V(value, ctx->Texture.FixedFuncUnit[unit].EnvColor); 301 else 302 COPY_4V(value, ctx->Texture.FixedFuncUnit[unit].EnvColorUnclamped); 303 } 304 return; 305 case STATE_FOG_COLOR: 306 if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer)) 307 COPY_4V(value, ctx->Fog.Color); 308 else 309 COPY_4V(value, ctx->Fog.ColorUnclamped); 310 return; 311 case STATE_FOG_PARAMS: 312 value[0] = ctx->Fog.Density; 313 value[1] = ctx->Fog.Start; 314 value[2] = ctx->Fog.End; 315 value[3] = 1.0f / (ctx->Fog.End - ctx->Fog.Start); 316 return; 317 case STATE_CLIPPLANE: 318 { 319 const GLuint plane = (GLuint) state[1]; 320 COPY_4V(value, ctx->Transform.EyeUserPlane[plane]); 321 } 322 return; 323 case STATE_POINT_SIZE: 324 value[0] = ctx->Point.Size; 325 value[1] = ctx->Point.MinSize; 326 value[2] = ctx->Point.MaxSize; 327 value[3] = ctx->Point.Threshold; 328 return; 329 case STATE_POINT_ATTENUATION: 330 value[0] = ctx->Point.Params[0]; 331 value[1] = ctx->Point.Params[1]; 332 value[2] = ctx->Point.Params[2]; 333 value[3] = 1.0F; 334 return; 335 /* state[0] = modelview, projection, texture, etc. */ 336 /* state[1] = which texture matrix or program matrix */ 337 /* state[2] = first row to fetch */ 338 /* state[3] = last row to fetch */ 339 case STATE_MODELVIEW_MATRIX: { 340 const GLmatrix *matrix = ctx->ModelviewMatrixStack.Top; 341 copy_matrix(value, matrix->m, state[2], state[3]); 342 return; 343 } 344 case STATE_MODELVIEW_MATRIX_INVERSE: { 345 const GLmatrix *matrix = ctx->ModelviewMatrixStack.Top; 346 copy_matrix(value, matrix->inv, state[2], state[3]); 347 return; 348 } 349 case STATE_MODELVIEW_MATRIX_TRANSPOSE: { 350 const GLmatrix *matrix = ctx->ModelviewMatrixStack.Top; 351 copy_matrix_transposed(value, matrix->m, state[2], state[3]); 352 return; 353 } 354 case STATE_MODELVIEW_MATRIX_INVTRANS: { 355 const GLmatrix *matrix = ctx->ModelviewMatrixStack.Top; 356 copy_matrix_transposed(value, matrix->inv, state[2], state[3]); 357 return; 358 } 359 case STATE_PROJECTION_MATRIX: { 360 const GLmatrix *matrix = ctx->ProjectionMatrixStack.Top; 361 copy_matrix(value, matrix->m, state[2], state[3]); 362 return; 363 } 364 case STATE_PROJECTION_MATRIX_INVERSE: { 365 GLmatrix *matrix = ctx->ProjectionMatrixStack.Top; 366 _math_matrix_analyse(matrix); /* make sure the inverse is up to date */ 367 copy_matrix(value, matrix->inv, state[2], state[3]); 368 return; 369 } 370 case STATE_PROJECTION_MATRIX_TRANSPOSE: { 371 const GLmatrix *matrix = ctx->ProjectionMatrixStack.Top; 372 copy_matrix_transposed(value, matrix->m, state[2], state[3]); 373 return; 374 } 375 case STATE_PROJECTION_MATRIX_INVTRANS: { 376 GLmatrix *matrix = ctx->ProjectionMatrixStack.Top; 377 _math_matrix_analyse(matrix); /* make sure the inverse is up to date */ 378 copy_matrix_transposed(value, matrix->inv, state[2], state[3]); 379 return; 380 } 381 case STATE_MVP_MATRIX: { 382 const GLmatrix *matrix = &ctx->_ModelProjectMatrix; 383 copy_matrix(value, matrix->m, state[2], state[3]); 384 return; 385 } 386 case STATE_MVP_MATRIX_INVERSE: { 387 GLmatrix *matrix = &ctx->_ModelProjectMatrix; 388 _math_matrix_analyse(matrix); /* make sure the inverse is up to date */ 389 copy_matrix(value, matrix->inv, state[2], state[3]); 390 return; 391 } 392 case STATE_MVP_MATRIX_TRANSPOSE: { 393 const GLmatrix *matrix = &ctx->_ModelProjectMatrix; 394 copy_matrix_transposed(value, matrix->m, state[2], state[3]); 395 return; 396 } 397 case STATE_MVP_MATRIX_INVTRANS: { 398 GLmatrix *matrix = &ctx->_ModelProjectMatrix; 399 _math_matrix_analyse(matrix); /* make sure the inverse is up to date */ 400 copy_matrix_transposed(value, matrix->inv, state[2], state[3]); 401 return; 402 } 403 case STATE_TEXTURE_MATRIX: { 404 const GLuint index = (GLuint) state[1]; 405 assert(index < ARRAY_SIZE(ctx->TextureMatrixStack)); 406 const GLmatrix *matrix = ctx->TextureMatrixStack[index].Top; 407 copy_matrix(value, matrix->m, state[2], state[3]); 408 return; 409 } 410 case STATE_TEXTURE_MATRIX_INVERSE: { 411 const GLuint index = (GLuint) state[1]; 412 assert(index < ARRAY_SIZE(ctx->TextureMatrixStack)); 413 const GLmatrix *matrix = ctx->TextureMatrixStack[index].Top; 414 copy_matrix(value, matrix->inv, state[2], state[3]); 415 return; 416 } 417 case STATE_TEXTURE_MATRIX_TRANSPOSE: { 418 const GLuint index = (GLuint) state[1]; 419 assert(index < ARRAY_SIZE(ctx->TextureMatrixStack)); 420 const GLmatrix *matrix = ctx->TextureMatrixStack[index].Top; 421 copy_matrix_transposed(value, matrix->m, state[2], state[3]); 422 return; 423 } 424 case STATE_TEXTURE_MATRIX_INVTRANS: { 425 const GLuint index = (GLuint) state[1]; 426 assert(index < ARRAY_SIZE(ctx->TextureMatrixStack)); 427 const GLmatrix *matrix = ctx->TextureMatrixStack[index].Top; 428 copy_matrix_transposed(value, matrix->inv, state[2], state[3]); 429 return; 430 } 431 case STATE_PROGRAM_MATRIX: { 432 const GLuint index = (GLuint) state[1]; 433 assert(index < ARRAY_SIZE(ctx->ProgramMatrixStack)); 434 const GLmatrix *matrix = ctx->ProgramMatrixStack[index].Top; 435 copy_matrix(value, matrix->m, state[2], state[3]); 436 return; 437 } 438 case STATE_PROGRAM_MATRIX_INVERSE: { 439 const GLuint index = (GLuint) state[1]; 440 assert(index < ARRAY_SIZE(ctx->ProgramMatrixStack)); 441 const GLmatrix *matrix = ctx->ProgramMatrixStack[index].Top; 442 _math_matrix_analyse((GLmatrix*)matrix); /* Be sure inverse is up to date: */ 443 copy_matrix(value, matrix->inv, state[2], state[3]); 444 return; 445 } 446 case STATE_PROGRAM_MATRIX_TRANSPOSE: { 447 const GLuint index = (GLuint) state[1]; 448 assert(index < ARRAY_SIZE(ctx->ProgramMatrixStack)); 449 const GLmatrix *matrix = ctx->ProgramMatrixStack[index].Top; 450 copy_matrix_transposed(value, matrix->m, state[2], state[3]); 451 return; 452 } 453 case STATE_PROGRAM_MATRIX_INVTRANS: { 454 const GLuint index = (GLuint) state[1]; 455 assert(index < ARRAY_SIZE(ctx->ProgramMatrixStack)); 456 const GLmatrix *matrix = ctx->ProgramMatrixStack[index].Top; 457 _math_matrix_analyse((GLmatrix*)matrix); /* Be sure inverse is up to date: */ 458 copy_matrix_transposed(value, matrix->inv, state[2], state[3]); 459 return; 460 } 461 case STATE_NUM_SAMPLES: 462 val[0].i = MAX2(1, _mesa_geometric_samples(ctx->DrawBuffer)); 463 return; 464 case STATE_DEPTH_RANGE: 465 value[0] = ctx->ViewportArray[0].Near; /* near */ 466 value[1] = ctx->ViewportArray[0].Far; /* far */ 467 value[2] = ctx->ViewportArray[0].Far - ctx->ViewportArray[0].Near; /* far - near */ 468 value[3] = 1.0; 469 return; 470 case STATE_FRAGMENT_PROGRAM_ENV: { 471 const int idx = (int) state[1]; 472 COPY_4V(value, ctx->FragmentProgram.Parameters[idx]); 473 return; 474 } 475 case STATE_FRAGMENT_PROGRAM_ENV_ARRAY: { 476 const unsigned idx = state[1]; 477 const unsigned bytes = state[2] * 16; 478 memcpy(value, ctx->FragmentProgram.Parameters[idx], bytes); 479 return; 480 } 481 case STATE_FRAGMENT_PROGRAM_LOCAL: { 482 float (*params)[4] = ctx->FragmentProgram.Current->arb.LocalParams; 483 if (unlikely(!params)) { 484 /* Local parameters haven't been allocated yet. 485 * ARB_fragment_program says that local parameters are 486 * "initially set to (0,0,0,0)." Return that. 487 */ 488 memset(value, 0, sizeof(float) * 4); 489 return; 490 } 491 492 const int idx = (int) state[1]; 493 COPY_4V(value, params[idx]); 494 return; 495 } 496 case STATE_FRAGMENT_PROGRAM_LOCAL_ARRAY: { 497 const unsigned idx = state[1]; 498 const unsigned bytes = state[2] * 16; 499 float (*params)[4] = ctx->FragmentProgram.Current->arb.LocalParams; 500 if (!params) { 501 /* Local parameters haven't been allocated yet. 502 * ARB_fragment_program says that local parameters are 503 * "initially set to (0,0,0,0)." Return that. 504 */ 505 memset(value, 0, bytes); 506 return; 507 } 508 memcpy(value, params[idx], bytes); 509 return; 510 } 511 case STATE_VERTEX_PROGRAM_ENV: { 512 const int idx = (int) state[1]; 513 COPY_4V(value, ctx->VertexProgram.Parameters[idx]); 514 return; 515 } 516 case STATE_VERTEX_PROGRAM_ENV_ARRAY: { 517 const unsigned idx = state[1]; 518 const unsigned bytes = state[2] * 16; 519 memcpy(value, ctx->VertexProgram.Parameters[idx], bytes); 520 return; 521 } 522 case STATE_VERTEX_PROGRAM_LOCAL: { 523 float (*params)[4] = ctx->VertexProgram.Current->arb.LocalParams; 524 if (unlikely(!params)) { 525 /* Local parameters haven't been allocated yet. 526 * ARB_vertex_program says that local parameters are 527 * "initially set to (0,0,0,0)." Return that. 528 */ 529 memset(value, 0, sizeof(float) * 4); 530 return; 531 } 532 533 const int idx = (int) state[1]; 534 COPY_4V(value, params[idx]); 535 return; 536 } 537 case STATE_VERTEX_PROGRAM_LOCAL_ARRAY: { 538 const unsigned idx = state[1]; 539 const unsigned bytes = state[2] * 16; 540 float (*params)[4] = ctx->VertexProgram.Current->arb.LocalParams; 541 if (!params) { 542 /* Local parameters haven't been allocated yet. 543 * ARB_vertex_program says that local parameters are 544 * "initially set to (0,0,0,0)." Return that. 545 */ 546 memset(value, 0, bytes); 547 return; 548 } 549 memcpy(value, params[idx], bytes); 550 return; 551 } 552 553 case STATE_NORMAL_SCALE_EYESPACE: 554 ASSIGN_4V(value, ctx->_ModelViewInvScaleEyespace, 0, 0, 1); 555 return; 556 557 case STATE_CURRENT_ATTRIB: 558 { 559 const GLuint idx = (GLuint) state[1]; 560 COPY_4V(value, ctx->Current.Attrib[idx]); 561 } 562 return; 563 564 case STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED: 565 { 566 const GLuint idx = (GLuint) state[1]; 567 if(ctx->Light._ClampVertexColor && 568 (idx == VERT_ATTRIB_COLOR0 || 569 idx == VERT_ATTRIB_COLOR1)) { 570 value[0] = SATURATE(ctx->Current.Attrib[idx][0]); 571 value[1] = SATURATE(ctx->Current.Attrib[idx][1]); 572 value[2] = SATURATE(ctx->Current.Attrib[idx][2]); 573 value[3] = SATURATE(ctx->Current.Attrib[idx][3]); 574 } 575 else 576 COPY_4V(value, ctx->Current.Attrib[idx]); 577 } 578 return; 579 580 case STATE_NORMAL_SCALE: 581 ASSIGN_4V(value, 582 ctx->_ModelViewInvScale, 583 ctx->_ModelViewInvScale, 584 ctx->_ModelViewInvScale, 585 1); 586 return; 587 588 case STATE_FOG_PARAMS_OPTIMIZED: { 589 /* for simpler per-vertex/pixel fog calcs. POW (for EXP/EXP2 fog) 590 * might be more expensive than EX2 on some hw, plus it needs 591 * another constant (e) anyway. Linear fog can now be done with a 592 * single MAD. 593 * linear: fogcoord * -1/(end-start) + end/(end-start) 594 * exp: 2^-(density/ln(2) * fogcoord) 595 * exp2: 2^-((density/(sqrt(ln(2))) * fogcoord)^2) 596 */ 597 float val = (ctx->Fog.End == ctx->Fog.Start) 598 ? 1.0f : (GLfloat)(-1.0F / (ctx->Fog.End - ctx->Fog.Start)); 599 value[0] = val; 600 value[1] = ctx->Fog.End * -val; 601 value[2] = (GLfloat)(ctx->Fog.Density * M_LOG2E); /* M_LOG2E == 1/ln(2) */ 602 value[3] = (GLfloat)(ctx->Fog.Density * ONE_DIV_SQRT_LN2); 603 return; 604 } 605 606 case STATE_POINT_SIZE_CLAMPED: 607 { 608 /* this includes implementation dependent limits, to avoid 609 * another potentially necessary clamp. 610 * Note: for sprites, point smooth (point AA) is ignored 611 * and we'll clamp to MinPointSizeAA and MaxPointSize, because we 612 * expect drivers will want to say their minimum for AA size is 0.0 613 * but for non-AA it's 1.0 (because normal points with size below 1.0 614 * need to get rounded up to 1.0, hence never disappear). GL does 615 * not specify max clamp size for sprites, other than it needs to be 616 * at least as large as max AA size, hence use non-AA size there. 617 */ 618 GLfloat minImplSize; 619 GLfloat maxImplSize; 620 if (ctx->Point.PointSprite) { 621 minImplSize = ctx->Const.MinPointSizeAA; 622 maxImplSize = ctx->Const.MaxPointSize; 623 } 624 else if (ctx->Point.SmoothFlag || _mesa_is_multisample_enabled(ctx)) { 625 minImplSize = ctx->Const.MinPointSizeAA; 626 maxImplSize = ctx->Const.MaxPointSizeAA; 627 } 628 else { 629 minImplSize = ctx->Const.MinPointSize; 630 maxImplSize = ctx->Const.MaxPointSize; 631 } 632 value[0] = ctx->Point.Size; 633 value[1] = ctx->Point.MinSize >= minImplSize ? ctx->Point.MinSize : minImplSize; 634 value[2] = ctx->Point.MaxSize <= maxImplSize ? ctx->Point.MaxSize : maxImplSize; 635 value[3] = ctx->Point.Threshold; 636 } 637 return; 638 case STATE_LIGHT_SPOT_DIR_NORMALIZED: 639 { 640 /* here, state[1] is the light number */ 641 /* pre-normalize spot dir */ 642 const GLuint ln = (GLuint) state[1]; 643 COPY_3V(value, ctx->Light.Light[ln]._NormSpotDirection); 644 value[3] = ctx->Light.LightSource[ln]._CosCutoff; 645 } 646 return; 647 648 case STATE_LIGHT_POSITION: 649 { 650 const GLuint ln = (GLuint) state[1]; 651 COPY_4V(value, ctx->Light.Light[ln]._Position); 652 } 653 return; 654 655 case STATE_LIGHT_POSITION_ARRAY: { 656 const unsigned first = state[1]; 657 const unsigned num_lights = state[2]; 658 for (unsigned i = 0; i < num_lights; i++) { 659 COPY_4V(value, ctx->Light.Light[first + i]._Position); 660 value += 4; 661 } 662 return; 663 } 664 665 case STATE_LIGHT_POSITION_NORMALIZED: 666 { 667 const GLuint ln = (GLuint) state[1]; 668 float p[4]; 669 COPY_4V(p, ctx->Light.Light[ln]._Position); 670 NORMALIZE_3FV(p); 671 COPY_4V(value, p); 672 } 673 return; 674 675 case STATE_LIGHT_POSITION_NORMALIZED_ARRAY: { 676 const unsigned first = state[1]; 677 const unsigned num_lights = state[2]; 678 for (unsigned i = 0; i < num_lights; i++) { 679 float p[4]; 680 COPY_4V(p, ctx->Light.Light[first + i]._Position); 681 NORMALIZE_3FV(p); 682 COPY_4V(value, p); 683 value += 4; 684 } 685 return; 686 } 687 688 case STATE_LIGHT_HALF_VECTOR: 689 { 690 const GLuint ln = (GLuint) state[1]; 691 GLfloat p[3]; 692 /* Compute infinite half angle vector: 693 * halfVector = normalize(normalize(lightPos) + (0, 0, 1)) 694 * light.EyePosition.w should be 0 for infinite lights. 695 */ 696 COPY_3V(p, ctx->Light.Light[ln]._Position); 697 NORMALIZE_3FV(p); 698 ADD_3V(p, p, ctx->_EyeZDir); 699 NORMALIZE_3FV(p); 700 COPY_3V(value, p); 701 value[3] = 1.0; 702 } 703 return; 704 705 case STATE_PT_SCALE: 706 value[0] = ctx->Pixel.RedScale; 707 value[1] = ctx->Pixel.GreenScale; 708 value[2] = ctx->Pixel.BlueScale; 709 value[3] = ctx->Pixel.AlphaScale; 710 return; 711 712 case STATE_PT_BIAS: 713 value[0] = ctx->Pixel.RedBias; 714 value[1] = ctx->Pixel.GreenBias; 715 value[2] = ctx->Pixel.BlueBias; 716 value[3] = ctx->Pixel.AlphaBias; 717 return; 718 719 case STATE_FB_SIZE: 720 value[0] = (GLfloat) (ctx->DrawBuffer->Width - 1); 721 value[1] = (GLfloat) (ctx->DrawBuffer->Height - 1); 722 value[2] = 0.0F; 723 value[3] = 0.0F; 724 return; 725 726 case STATE_FB_WPOS_Y_TRANSFORM: 727 /* A driver may negate this conditional by using ZW swizzle 728 * instead of XY (based on e.g. some other state). */ 729 if (!ctx->DrawBuffer->FlipY) { 730 /* Identity (XY) followed by flipping Y upside down (ZW). */ 731 value[0] = 1.0F; 732 value[1] = 0.0F; 733 value[2] = -1.0F; 734 value[3] = _mesa_geometric_height(ctx->DrawBuffer); 735 } else { 736 /* Flipping Y upside down (XY) followed by identity (ZW). */ 737 value[0] = -1.0F; 738 value[1] = _mesa_geometric_height(ctx->DrawBuffer); 739 value[2] = 1.0F; 740 value[3] = 0.0F; 741 } 742 return; 743 744 case STATE_FB_PNTC_Y_TRANSFORM: 745 { 746 bool flip_y = (ctx->Point.SpriteOrigin == GL_UPPER_LEFT) ^ 747 (ctx->Const.PointCoordOriginUpperLeft) ^ 748 (ctx->DrawBuffer->FlipY); 749 750 value[0] = flip_y ? -1.0F : 1.0F; 751 value[1] = flip_y ? 1.0F : 0.0F; 752 value[2] = 0.0F; 753 value[3] = 0.0F; 754 } 755 return; 756 757 case STATE_TCS_PATCH_VERTICES_IN: 758 val[0].i = ctx->TessCtrlProgram.patch_vertices; 759 return; 760 761 case STATE_TES_PATCH_VERTICES_IN: 762 if (ctx->TessCtrlProgram._Current) 763 val[0].i = ctx->TessCtrlProgram._Current->info.tess.tcs_vertices_out; 764 else 765 val[0].i = ctx->TessCtrlProgram.patch_vertices; 766 return; 767 768 case STATE_ADVANCED_BLENDING_MODE: 769 val[0].i = _mesa_get_advanced_blend_sh_constant( 770 ctx->Color.BlendEnabled, ctx->Color._AdvancedBlendMode); 771 return; 772 773 case STATE_ALPHA_REF: 774 value[0] = ctx->Color.AlphaRefUnclamped; 775 return; 776 777 case STATE_CLIP_INTERNAL: 778 { 779 const GLuint plane = (GLuint) state[1]; 780 COPY_4V(value, ctx->Transform._ClipUserPlane[plane]); 781 } 782 return; 783 784 case STATE_ATOMIC_COUNTER_OFFSET: 785 { 786 const GLuint counter = (GLuint) state[1]; 787 val[0].i = ctx->AtomicBufferBindings[counter].Offset % ctx->Const.ShaderStorageBufferOffsetAlignment; 788 } 789 return; 790 } 791} 792 793unsigned 794_mesa_program_state_value_size(const gl_state_index16 state[STATE_LENGTH]) 795{ 796 if (state[0] == STATE_LIGHT && state[2] == STATE_SPOT_CUTOFF) 797 return 1; 798 799 /* Everything else is packed into vec4s */ 800 return 4; 801} 802 803/** 804 * Return a bitmask of the Mesa state flags (_NEW_* values) which would 805 * indicate that the given context state may have changed. 806 * The bitmask is used during validation to determine if we need to update 807 * vertex/fragment program parameters (like "state.material.color") when 808 * some GL state has changed. 809 */ 810GLbitfield 811_mesa_program_state_flags(const gl_state_index16 state[STATE_LENGTH]) 812{ 813 switch (state[0]) { 814 case STATE_MATERIAL: 815 return _NEW_MATERIAL; 816 817 case STATE_LIGHTPROD: 818 case STATE_LIGHTPROD_ARRAY_FRONT: 819 case STATE_LIGHTPROD_ARRAY_BACK: 820 case STATE_LIGHTPROD_ARRAY_TWOSIDE: 821 case STATE_LIGHTMODEL_SCENECOLOR: 822 return _NEW_LIGHT_CONSTANTS | _NEW_MATERIAL; 823 824 case STATE_LIGHT: 825 case STATE_LIGHT_ARRAY: 826 case STATE_LIGHT_ATTENUATION_ARRAY: 827 case STATE_LIGHTMODEL_AMBIENT: 828 case STATE_LIGHT_SPOT_DIR_NORMALIZED: 829 case STATE_LIGHT_POSITION: 830 case STATE_LIGHT_POSITION_ARRAY: 831 case STATE_LIGHT_POSITION_NORMALIZED: 832 case STATE_LIGHT_POSITION_NORMALIZED_ARRAY: 833 case STATE_LIGHT_HALF_VECTOR: 834 return _NEW_LIGHT_CONSTANTS; 835 836 case STATE_TEXGEN: 837 return _NEW_TEXTURE_STATE; 838 case STATE_TEXENV_COLOR: 839 return _NEW_TEXTURE_STATE | _NEW_BUFFERS | _NEW_FRAG_CLAMP; 840 841 case STATE_FOG_COLOR: 842 return _NEW_FOG | _NEW_BUFFERS | _NEW_FRAG_CLAMP; 843 case STATE_FOG_PARAMS: 844 case STATE_FOG_PARAMS_OPTIMIZED: 845 return _NEW_FOG; 846 847 case STATE_CLIPPLANE: 848 return _NEW_TRANSFORM; 849 850 case STATE_POINT_SIZE: 851 case STATE_POINT_ATTENUATION: 852 return _NEW_POINT; 853 854 case STATE_MODELVIEW_MATRIX: 855 case STATE_MODELVIEW_MATRIX_INVERSE: 856 case STATE_MODELVIEW_MATRIX_TRANSPOSE: 857 case STATE_MODELVIEW_MATRIX_INVTRANS: 858 case STATE_NORMAL_SCALE_EYESPACE: 859 case STATE_NORMAL_SCALE: 860 return _NEW_MODELVIEW; 861 862 case STATE_PROJECTION_MATRIX: 863 case STATE_PROJECTION_MATRIX_INVERSE: 864 case STATE_PROJECTION_MATRIX_TRANSPOSE: 865 case STATE_PROJECTION_MATRIX_INVTRANS: 866 return _NEW_PROJECTION; 867 case STATE_MVP_MATRIX: 868 case STATE_MVP_MATRIX_INVERSE: 869 case STATE_MVP_MATRIX_TRANSPOSE: 870 case STATE_MVP_MATRIX_INVTRANS: 871 return _NEW_MODELVIEW | _NEW_PROJECTION; 872 case STATE_TEXTURE_MATRIX: 873 case STATE_TEXTURE_MATRIX_INVERSE: 874 case STATE_TEXTURE_MATRIX_TRANSPOSE: 875 case STATE_TEXTURE_MATRIX_INVTRANS: 876 return _NEW_TEXTURE_MATRIX; 877 case STATE_PROGRAM_MATRIX: 878 case STATE_PROGRAM_MATRIX_INVERSE: 879 case STATE_PROGRAM_MATRIX_TRANSPOSE: 880 case STATE_PROGRAM_MATRIX_INVTRANS: 881 return _NEW_TRACK_MATRIX; 882 883 case STATE_NUM_SAMPLES: 884 case STATE_FB_SIZE: 885 case STATE_FB_WPOS_Y_TRANSFORM: 886 return _NEW_BUFFERS; 887 888 case STATE_FB_PNTC_Y_TRANSFORM: 889 return _NEW_BUFFERS | _NEW_POINT; 890 891 case STATE_DEPTH_RANGE: 892 return _NEW_VIEWPORT; 893 894 case STATE_FRAGMENT_PROGRAM_ENV: 895 case STATE_FRAGMENT_PROGRAM_ENV_ARRAY: 896 case STATE_FRAGMENT_PROGRAM_LOCAL: 897 case STATE_FRAGMENT_PROGRAM_LOCAL_ARRAY: 898 case STATE_VERTEX_PROGRAM_ENV: 899 case STATE_VERTEX_PROGRAM_ENV_ARRAY: 900 case STATE_VERTEX_PROGRAM_LOCAL: 901 case STATE_VERTEX_PROGRAM_LOCAL_ARRAY: 902 return _NEW_PROGRAM; 903 904 case STATE_CURRENT_ATTRIB: 905 return _NEW_CURRENT_ATTRIB; 906 case STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED: 907 return _NEW_CURRENT_ATTRIB | _NEW_LIGHT_STATE | _NEW_BUFFERS; 908 909 case STATE_POINT_SIZE_CLAMPED: 910 return _NEW_POINT | _NEW_MULTISAMPLE; 911 912 case STATE_PT_SCALE: 913 case STATE_PT_BIAS: 914 return _NEW_PIXEL; 915 916 case STATE_ADVANCED_BLENDING_MODE: 917 case STATE_ALPHA_REF: 918 return _NEW_COLOR; 919 920 case STATE_CLIP_INTERNAL: 921 return _NEW_TRANSFORM | _NEW_PROJECTION; 922 923 /* Needs to return any nonzero value to trigger constant updating */ 924 case STATE_ATOMIC_COUNTER_OFFSET: 925 return _NEW_PROGRAM_CONSTANTS; 926 927 case STATE_TCS_PATCH_VERTICES_IN: 928 case STATE_TES_PATCH_VERTICES_IN: 929 case STATE_INTERNAL_DRIVER: 930 return 0; /* internal driver state */ 931 932 case STATE_NOT_STATE_VAR: 933 return 0; 934 935 default: 936 _mesa_problem(NULL, "unexpected state[0] in make_state_flags()"); 937 return 0; 938 } 939} 940 941 942static void 943append(char *dst, const char *src) 944{ 945 while (*dst) 946 dst++; 947 while (*src) 948 *dst++ = *src++; 949 *dst = 0; 950} 951 952 953/** 954 * Convert token 'k' to a string, append it onto 'dst' string. 955 */ 956static void 957append_token(char *dst, gl_state_index k) 958{ 959 switch (k) { 960 case STATE_MATERIAL: 961 append(dst, "material"); 962 break; 963 case STATE_LIGHT: 964 append(dst, "light"); 965 break; 966 case STATE_LIGHT_ARRAY: 967 append(dst, "light.array"); 968 break; 969 case STATE_LIGHT_ATTENUATION_ARRAY: 970 append(dst, "light.attenuation"); 971 break; 972 case STATE_LIGHTMODEL_AMBIENT: 973 append(dst, "lightmodel.ambient"); 974 break; 975 case STATE_LIGHTMODEL_SCENECOLOR: 976 break; 977 case STATE_LIGHTPROD: 978 append(dst, "lightprod"); 979 break; 980 case STATE_LIGHTPROD_ARRAY_FRONT: 981 append(dst, "lightprod.array.front"); 982 break; 983 case STATE_LIGHTPROD_ARRAY_BACK: 984 append(dst, "lightprod.array.back"); 985 break; 986 case STATE_LIGHTPROD_ARRAY_TWOSIDE: 987 append(dst, "lightprod.array.twoside"); 988 break; 989 case STATE_TEXGEN: 990 append(dst, "texgen"); 991 break; 992 case STATE_FOG_COLOR: 993 append(dst, "fog.color"); 994 break; 995 case STATE_FOG_PARAMS: 996 append(dst, "fog.params"); 997 break; 998 case STATE_CLIPPLANE: 999 append(dst, "clip"); 1000 break; 1001 case STATE_POINT_SIZE: 1002 append(dst, "point.size"); 1003 break; 1004 case STATE_POINT_ATTENUATION: 1005 append(dst, "point.attenuation"); 1006 break; 1007 case STATE_MODELVIEW_MATRIX: 1008 append(dst, "matrix.modelview."); 1009 break; 1010 case STATE_MODELVIEW_MATRIX_INVERSE: 1011 append(dst, "matrix.modelview.inverse."); 1012 break; 1013 case STATE_MODELVIEW_MATRIX_TRANSPOSE: 1014 append(dst, "matrix.modelview.transpose."); 1015 break; 1016 case STATE_MODELVIEW_MATRIX_INVTRANS: 1017 append(dst, "matrix.modelview.invtrans."); 1018 break; 1019 case STATE_PROJECTION_MATRIX: 1020 append(dst, "matrix.projection."); 1021 break; 1022 case STATE_PROJECTION_MATRIX_INVERSE: 1023 append(dst, "matrix.projection.inverse."); 1024 break; 1025 case STATE_PROJECTION_MATRIX_TRANSPOSE: 1026 append(dst, "matrix.projection.transpose."); 1027 break; 1028 case STATE_PROJECTION_MATRIX_INVTRANS: 1029 append(dst, "matrix.projection.invtrans."); 1030 break; 1031 case STATE_MVP_MATRIX: 1032 append(dst, "matrix.mvp."); 1033 break; 1034 case STATE_MVP_MATRIX_INVERSE: 1035 append(dst, "matrix.mvp.inverse."); 1036 break; 1037 case STATE_MVP_MATRIX_TRANSPOSE: 1038 append(dst, "matrix.mvp.transpose."); 1039 break; 1040 case STATE_MVP_MATRIX_INVTRANS: 1041 append(dst, "matrix.mvp.invtrans."); 1042 break; 1043 case STATE_TEXTURE_MATRIX: 1044 append(dst, "matrix.texture"); 1045 break; 1046 case STATE_TEXTURE_MATRIX_INVERSE: 1047 append(dst, "matrix.texture.inverse"); 1048 break; 1049 case STATE_TEXTURE_MATRIX_TRANSPOSE: 1050 append(dst, "matrix.texture.transpose"); 1051 break; 1052 case STATE_TEXTURE_MATRIX_INVTRANS: 1053 append(dst, "matrix.texture.invtrans"); 1054 break; 1055 case STATE_PROGRAM_MATRIX: 1056 append(dst, "matrix.program"); 1057 break; 1058 case STATE_PROGRAM_MATRIX_INVERSE: 1059 append(dst, "matrix.program.inverse"); 1060 break; 1061 case STATE_PROGRAM_MATRIX_TRANSPOSE: 1062 append(dst, "matrix.program.transpose"); 1063 break; 1064 case STATE_PROGRAM_MATRIX_INVTRANS: 1065 append(dst, "matrix.program.invtrans"); 1066 break; 1067 break; 1068 case STATE_AMBIENT: 1069 append(dst, "ambient"); 1070 break; 1071 case STATE_DIFFUSE: 1072 append(dst, "diffuse"); 1073 break; 1074 case STATE_SPECULAR: 1075 append(dst, "specular"); 1076 break; 1077 case STATE_EMISSION: 1078 append(dst, "emission"); 1079 break; 1080 case STATE_SHININESS: 1081 append(dst, "shininess"); 1082 break; 1083 case STATE_HALF_VECTOR: 1084 append(dst, "half"); 1085 break; 1086 case STATE_POSITION: 1087 append(dst, "position"); 1088 break; 1089 case STATE_ATTENUATION: 1090 append(dst, "attenuation"); 1091 break; 1092 case STATE_SPOT_DIRECTION: 1093 append(dst, "spot.direction"); 1094 break; 1095 case STATE_SPOT_CUTOFF: 1096 append(dst, "spot.cutoff"); 1097 break; 1098 case STATE_TEXGEN_EYE_S: 1099 append(dst, "eye.s"); 1100 break; 1101 case STATE_TEXGEN_EYE_T: 1102 append(dst, "eye.t"); 1103 break; 1104 case STATE_TEXGEN_EYE_R: 1105 append(dst, "eye.r"); 1106 break; 1107 case STATE_TEXGEN_EYE_Q: 1108 append(dst, "eye.q"); 1109 break; 1110 case STATE_TEXGEN_OBJECT_S: 1111 append(dst, "object.s"); 1112 break; 1113 case STATE_TEXGEN_OBJECT_T: 1114 append(dst, "object.t"); 1115 break; 1116 case STATE_TEXGEN_OBJECT_R: 1117 append(dst, "object.r"); 1118 break; 1119 case STATE_TEXGEN_OBJECT_Q: 1120 append(dst, "object.q"); 1121 break; 1122 case STATE_TEXENV_COLOR: 1123 append(dst, "texenv"); 1124 break; 1125 case STATE_NUM_SAMPLES: 1126 append(dst, "numsamples"); 1127 break; 1128 case STATE_DEPTH_RANGE: 1129 append(dst, "depth.range"); 1130 break; 1131 case STATE_VERTEX_PROGRAM_ENV: 1132 case STATE_FRAGMENT_PROGRAM_ENV: 1133 append(dst, "env"); 1134 break; 1135 case STATE_VERTEX_PROGRAM_ENV_ARRAY: 1136 case STATE_FRAGMENT_PROGRAM_ENV_ARRAY: 1137 append(dst, "env.range"); 1138 break; 1139 case STATE_VERTEX_PROGRAM_LOCAL: 1140 case STATE_FRAGMENT_PROGRAM_LOCAL: 1141 append(dst, "local"); 1142 break; 1143 case STATE_VERTEX_PROGRAM_LOCAL_ARRAY: 1144 case STATE_FRAGMENT_PROGRAM_LOCAL_ARRAY: 1145 append(dst, "local.range"); 1146 break; 1147 case STATE_CURRENT_ATTRIB: 1148 append(dst, "current"); 1149 break; 1150 case STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED: 1151 append(dst, "currentAttribMaybeVPClamped"); 1152 break; 1153 case STATE_NORMAL_SCALE_EYESPACE: 1154 append(dst, "normalScaleEyeSpace"); 1155 break; 1156 case STATE_NORMAL_SCALE: 1157 append(dst, "normalScale"); 1158 break; 1159 case STATE_FOG_PARAMS_OPTIMIZED: 1160 append(dst, "fogParamsOptimized"); 1161 break; 1162 case STATE_POINT_SIZE_CLAMPED: 1163 append(dst, "pointSizeClamped"); 1164 break; 1165 case STATE_LIGHT_SPOT_DIR_NORMALIZED: 1166 append(dst, "lightSpotDirNormalized"); 1167 break; 1168 case STATE_LIGHT_POSITION: 1169 append(dst, "light.position"); 1170 break; 1171 case STATE_LIGHT_POSITION_ARRAY: 1172 append(dst, "light.position.array"); 1173 break; 1174 case STATE_LIGHT_POSITION_NORMALIZED: 1175 append(dst, "light.position.normalized"); 1176 break; 1177 case STATE_LIGHT_POSITION_NORMALIZED_ARRAY: 1178 append(dst, "light.position.normalized.array"); 1179 break; 1180 case STATE_LIGHT_HALF_VECTOR: 1181 append(dst, "lightHalfVector"); 1182 break; 1183 case STATE_PT_SCALE: 1184 append(dst, "PTscale"); 1185 break; 1186 case STATE_PT_BIAS: 1187 append(dst, "PTbias"); 1188 break; 1189 case STATE_FB_SIZE: 1190 append(dst, "FbSize"); 1191 break; 1192 case STATE_FB_WPOS_Y_TRANSFORM: 1193 append(dst, "FbWposYTransform"); 1194 break; 1195 case STATE_FB_PNTC_Y_TRANSFORM: 1196 append(dst, "PntcYTransform"); 1197 break; 1198 case STATE_ADVANCED_BLENDING_MODE: 1199 append(dst, "AdvancedBlendingMode"); 1200 break; 1201 case STATE_ALPHA_REF: 1202 append(dst, "alphaRef"); 1203 break; 1204 case STATE_CLIP_INTERNAL: 1205 append(dst, "clipInternal"); 1206 break; 1207 case STATE_ATOMIC_COUNTER_OFFSET: 1208 append(dst, "counterOffset"); 1209 break; 1210 default: 1211 /* probably STATE_INTERNAL_DRIVER+i (driver private state) */ 1212 append(dst, "driverState"); 1213 } 1214} 1215 1216static void 1217append_index(char *dst, GLint index, bool structure) 1218{ 1219 char s[20]; 1220 sprintf(s, "[%d]%s", index, structure ? "." : ""); 1221 append(dst, s); 1222} 1223 1224/** 1225 * Make a string from the given state vector. 1226 * For example, return "state.matrix.texture[2].inverse". 1227 * Use free() to deallocate the string. 1228 */ 1229char * 1230_mesa_program_state_string(const gl_state_index16 state[STATE_LENGTH]) 1231{ 1232 char str[1000] = ""; 1233 char tmp[30]; 1234 1235 append(str, "state."); 1236 append_token(str, state[0]); 1237 1238 switch (state[0]) { 1239 case STATE_LIGHT: 1240 append_index(str, state[1], true); /* light number [i]. */ 1241 append_token(str, state[2]); /* coefficients */ 1242 break; 1243 case STATE_LIGHTMODEL_AMBIENT: 1244 break; 1245 case STATE_LIGHTMODEL_SCENECOLOR: 1246 if (state[1] == 0) { 1247 append(str, "lightmodel.front.scenecolor"); 1248 } 1249 else { 1250 append(str, "lightmodel.back.scenecolor"); 1251 } 1252 break; 1253 case STATE_LIGHTPROD: 1254 append_index(str, state[1], false); /* light number [i] */ 1255 append_index(str, state[2], false); 1256 break; 1257 case STATE_TEXGEN: 1258 append_index(str, state[1], true); /* tex unit [i] */ 1259 append_token(str, state[2]); /* plane coef */ 1260 break; 1261 case STATE_TEXENV_COLOR: 1262 append_index(str, state[1], true); /* tex unit [i] */ 1263 append(str, "color"); 1264 break; 1265 case STATE_CLIPPLANE: 1266 append_index(str, state[1], true); /* plane [i] */ 1267 append(str, "plane"); 1268 break; 1269 case STATE_MODELVIEW_MATRIX: 1270 case STATE_MODELVIEW_MATRIX_INVERSE: 1271 case STATE_MODELVIEW_MATRIX_TRANSPOSE: 1272 case STATE_MODELVIEW_MATRIX_INVTRANS: 1273 case STATE_PROJECTION_MATRIX: 1274 case STATE_PROJECTION_MATRIX_INVERSE: 1275 case STATE_PROJECTION_MATRIX_TRANSPOSE: 1276 case STATE_PROJECTION_MATRIX_INVTRANS: 1277 case STATE_MVP_MATRIX: 1278 case STATE_MVP_MATRIX_INVERSE: 1279 case STATE_MVP_MATRIX_TRANSPOSE: 1280 case STATE_MVP_MATRIX_INVTRANS: 1281 case STATE_TEXTURE_MATRIX: 1282 case STATE_TEXTURE_MATRIX_INVERSE: 1283 case STATE_TEXTURE_MATRIX_TRANSPOSE: 1284 case STATE_TEXTURE_MATRIX_INVTRANS: 1285 case STATE_PROGRAM_MATRIX: 1286 case STATE_PROGRAM_MATRIX_INVERSE: 1287 case STATE_PROGRAM_MATRIX_TRANSPOSE: 1288 case STATE_PROGRAM_MATRIX_INVTRANS: 1289 { 1290 /* state[0] = modelview, projection, texture, etc. */ 1291 /* state[1] = which texture matrix or program matrix */ 1292 /* state[2] = first row to fetch */ 1293 /* state[3] = last row to fetch */ 1294 const gl_state_index mat = state[0]; 1295 const GLuint index = (GLuint) state[1]; 1296 const GLuint firstRow = (GLuint) state[2]; 1297 const GLuint lastRow = (GLuint) state[3]; 1298 if (index || 1299 (mat >= STATE_TEXTURE_MATRIX && 1300 mat <= STATE_PROGRAM_MATRIX_INVTRANS)) 1301 append_index(str, index, true); 1302 if (firstRow == lastRow) 1303 sprintf(tmp, "row[%d]", firstRow); 1304 else 1305 sprintf(tmp, "row[%d..%d]", firstRow, lastRow); 1306 append(str, tmp); 1307 } 1308 break; 1309 case STATE_LIGHT_ARRAY: 1310 case STATE_LIGHT_ATTENUATION_ARRAY: 1311 case STATE_FRAGMENT_PROGRAM_ENV_ARRAY: 1312 case STATE_FRAGMENT_PROGRAM_LOCAL_ARRAY: 1313 case STATE_VERTEX_PROGRAM_ENV_ARRAY: 1314 case STATE_VERTEX_PROGRAM_LOCAL_ARRAY: 1315 case STATE_LIGHTPROD_ARRAY_FRONT: 1316 case STATE_LIGHTPROD_ARRAY_BACK: 1317 case STATE_LIGHTPROD_ARRAY_TWOSIDE: 1318 case STATE_LIGHT_POSITION_ARRAY: 1319 case STATE_LIGHT_POSITION_NORMALIZED_ARRAY: 1320 sprintf(tmp, "[%d..%d]", state[1], state[1] + state[2] - 1); 1321 append(str, tmp); 1322 break; 1323 case STATE_MATERIAL: 1324 case STATE_FRAGMENT_PROGRAM_ENV: 1325 case STATE_FRAGMENT_PROGRAM_LOCAL: 1326 case STATE_VERTEX_PROGRAM_ENV: 1327 case STATE_VERTEX_PROGRAM_LOCAL: 1328 case STATE_CURRENT_ATTRIB: 1329 case STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED: 1330 case STATE_LIGHT_SPOT_DIR_NORMALIZED: 1331 case STATE_LIGHT_POSITION: 1332 case STATE_LIGHT_POSITION_NORMALIZED: 1333 case STATE_LIGHT_HALF_VECTOR: 1334 case STATE_CLIP_INTERNAL: 1335 case STATE_ATOMIC_COUNTER_OFFSET: 1336 append_index(str, state[1], false); 1337 break; 1338 case STATE_POINT_SIZE: 1339 case STATE_POINT_ATTENUATION: 1340 case STATE_FOG_PARAMS: 1341 case STATE_FOG_COLOR: 1342 case STATE_NUM_SAMPLES: 1343 case STATE_DEPTH_RANGE: 1344 case STATE_NORMAL_SCALE_EYESPACE: 1345 case STATE_NORMAL_SCALE: 1346 case STATE_FOG_PARAMS_OPTIMIZED: 1347 case STATE_POINT_SIZE_CLAMPED: 1348 case STATE_PT_SCALE: 1349 case STATE_PT_BIAS: 1350 case STATE_FB_SIZE: 1351 case STATE_FB_WPOS_Y_TRANSFORM: 1352 case STATE_FB_PNTC_Y_TRANSFORM: 1353 case STATE_TCS_PATCH_VERTICES_IN: 1354 case STATE_TES_PATCH_VERTICES_IN: 1355 case STATE_ADVANCED_BLENDING_MODE: 1356 case STATE_ALPHA_REF: 1357 break; 1358 case STATE_NOT_STATE_VAR: 1359 append(str, "not_state"); 1360 break; 1361 default: 1362 _mesa_problem(NULL, "Invalid state in _mesa_program_state_string: %d", state[0]); 1363 break; 1364 } 1365 1366 return strdup(str); 1367} 1368 1369 1370/** 1371 * Loop over all the parameters in a parameter list. If the parameter 1372 * is a GL state reference, look up the current value of that state 1373 * variable and put it into the parameter's Value[4] array. 1374 * Other parameter types never change or are explicitly set by the user 1375 * with glUniform() or glProgramParameter(), etc. 1376 * This would be called at glBegin time. 1377 */ 1378void 1379_mesa_load_state_parameters(struct gl_context *ctx, 1380 struct gl_program_parameter_list *paramList) 1381{ 1382 if (!paramList) 1383 return; 1384 1385 int last = paramList->LastStateVarIndex; 1386 1387 for (int i = paramList->FirstStateVarIndex; i <= last; i++) { 1388 unsigned pvo = paramList->Parameters[i].ValueOffset; 1389 fetch_state(ctx, paramList->Parameters[i].StateIndexes, 1390 paramList->ParameterValues + pvo); 1391 } 1392} 1393 1394void 1395_mesa_upload_state_parameters(struct gl_context *ctx, 1396 struct gl_program_parameter_list *paramList, 1397 uint32_t *dst) 1398{ 1399 int last = paramList->LastStateVarIndex; 1400 1401 for (int i = paramList->FirstStateVarIndex; i <= last; i++) { 1402 unsigned pvo = paramList->Parameters[i].ValueOffset; 1403 fetch_state(ctx, paramList->Parameters[i].StateIndexes, 1404 (gl_constant_value*)(dst + pvo)); 1405 } 1406} 1407 1408/* Merge consecutive state vars into one for the state vars that allow 1409 * multiple vec4s. 1410 * 1411 * This should be done after shader compilation, so that drivers don't 1412 * have to deal with multi-slot state parameters in their backends. 1413 * It's only meant to optimize _mesa_load/upload_state_parameters. 1414 */ 1415void 1416_mesa_optimize_state_parameters(struct gl_constants *consts, 1417 struct gl_program_parameter_list *list) 1418{ 1419 for (int first_param = list->FirstStateVarIndex; 1420 first_param < (int)list->NumParameters; first_param++) { 1421 int last_param = first_param; 1422 int param_diff = 0; 1423 1424 switch (list->Parameters[first_param].StateIndexes[0]) { 1425 case STATE_MODELVIEW_MATRIX: 1426 case STATE_MODELVIEW_MATRIX_INVERSE: 1427 case STATE_MODELVIEW_MATRIX_TRANSPOSE: 1428 case STATE_MODELVIEW_MATRIX_INVTRANS: 1429 case STATE_PROJECTION_MATRIX: 1430 case STATE_PROJECTION_MATRIX_INVERSE: 1431 case STATE_PROJECTION_MATRIX_TRANSPOSE: 1432 case STATE_PROJECTION_MATRIX_INVTRANS: 1433 case STATE_MVP_MATRIX: 1434 case STATE_MVP_MATRIX_INVERSE: 1435 case STATE_MVP_MATRIX_TRANSPOSE: 1436 case STATE_MVP_MATRIX_INVTRANS: 1437 case STATE_TEXTURE_MATRIX: 1438 case STATE_TEXTURE_MATRIX_INVERSE: 1439 case STATE_TEXTURE_MATRIX_TRANSPOSE: 1440 case STATE_TEXTURE_MATRIX_INVTRANS: 1441 case STATE_PROGRAM_MATRIX: 1442 case STATE_PROGRAM_MATRIX_INVERSE: 1443 case STATE_PROGRAM_MATRIX_TRANSPOSE: 1444 case STATE_PROGRAM_MATRIX_INVTRANS: 1445 /* Skip unaligned state vars. */ 1446 if (list->Parameters[first_param].Size % 4) 1447 break; 1448 1449 /* Search for adjacent state vars that refer to adjacent rows. */ 1450 for (int i = first_param + 1; i < (int)list->NumParameters; i++) { 1451 if (list->Parameters[i].StateIndexes[0] == 1452 list->Parameters[i - 1].StateIndexes[0] && 1453 list->Parameters[i].StateIndexes[1] == 1454 list->Parameters[i - 1].StateIndexes[1] && 1455 list->Parameters[i].StateIndexes[2] == /* FirstRow */ 1456 list->Parameters[i - 1].StateIndexes[3] + 1 && /* LastRow + 1 */ 1457 list->Parameters[i].Size == 4) { 1458 last_param = i; 1459 continue; 1460 } 1461 break; /* The adjacent state var is incompatible. */ 1462 } 1463 if (last_param > first_param) { 1464 int first_vec = list->Parameters[first_param].StateIndexes[2]; 1465 int last_vec = list->Parameters[last_param].StateIndexes[3]; 1466 1467 assert(first_vec < last_vec); 1468 assert(last_vec - first_vec == last_param - first_param); 1469 1470 /* Update LastRow. */ 1471 list->Parameters[first_param].StateIndexes[3] = last_vec; 1472 list->Parameters[first_param].Size = (last_vec - first_vec + 1) * 4; 1473 1474 param_diff = last_param - first_param; 1475 } 1476 break; 1477 1478 case STATE_LIGHT: 1479 /* Skip trimmed state vars. (this shouldn't occur though) */ 1480 if (list->Parameters[first_param].Size != 1481 _mesa_program_state_value_size(list->Parameters[first_param].StateIndexes)) 1482 break; 1483 1484 /* Search for light attributes that are adjacent in memory. */ 1485 for (int i = first_param + 1; i < (int)list->NumParameters; i++) { 1486 if (list->Parameters[i].StateIndexes[0] == STATE_LIGHT && 1487 /* Consecutive attributes of the same light: */ 1488 ((list->Parameters[i].StateIndexes[1] == 1489 list->Parameters[i - 1].StateIndexes[1] && 1490 list->Parameters[i].StateIndexes[2] == 1491 list->Parameters[i - 1].StateIndexes[2] + 1) || 1492 /* Consecutive attributes between 2 lights: */ 1493 /* SPOT_CUTOFF should have only 1 component, which isn't true 1494 * with unpacked uniform storage. */ 1495 (consts->PackedDriverUniformStorage && 1496 list->Parameters[i].StateIndexes[1] == 1497 list->Parameters[i - 1].StateIndexes[1] + 1 && 1498 list->Parameters[i].StateIndexes[2] == STATE_AMBIENT && 1499 list->Parameters[i - 1].StateIndexes[2] == STATE_SPOT_CUTOFF))) { 1500 last_param = i; 1501 continue; 1502 } 1503 break; /* The adjacent state var is incompatible. */ 1504 } 1505 if (last_param > first_param) { 1506 /* Convert the state var to STATE_LIGHT_ARRAY. */ 1507 list->Parameters[first_param].StateIndexes[0] = STATE_LIGHT_ARRAY; 1508 /* Set the offset in floats. */ 1509 list->Parameters[first_param].StateIndexes[1] = 1510 list->Parameters[first_param].StateIndexes[1] * /* light index */ 1511 sizeof(struct gl_light_uniforms) / 4 + 1512 (list->Parameters[first_param].StateIndexes[2] - STATE_AMBIENT) * 4; 1513 1514 /* Set the real size in floats that we will upload (memcpy). */ 1515 list->Parameters[first_param].StateIndexes[2] = 1516 _mesa_program_state_value_size(list->Parameters[last_param].StateIndexes) + 1517 list->Parameters[last_param].ValueOffset - 1518 list->Parameters[first_param].ValueOffset; 1519 1520 /* Set the allocated size, which can be aligned to 4 components. */ 1521 list->Parameters[first_param].Size = 1522 list->Parameters[last_param].Size + 1523 list->Parameters[last_param].ValueOffset - 1524 list->Parameters[first_param].ValueOffset; 1525 1526 param_diff = last_param - first_param; 1527 break; /* all done */ 1528 } 1529 1530 /* We were not able to convert light attributes to STATE_LIGHT_ARRAY. 1531 * Another occuring pattern is light attentuation vectors placed back 1532 * to back. Find them. 1533 */ 1534 if (list->Parameters[first_param].StateIndexes[2] == STATE_ATTENUATION) { 1535 for (int i = first_param + 1; i < (int)list->NumParameters; i++) { 1536 if (list->Parameters[i].StateIndexes[0] == STATE_LIGHT && 1537 /* Consecutive light: */ 1538 list->Parameters[i].StateIndexes[1] == 1539 list->Parameters[i - 1].StateIndexes[1] + 1 && 1540 /* Same attribute: */ 1541 list->Parameters[i].StateIndexes[2] == 1542 list->Parameters[i - 1].StateIndexes[2]) { 1543 last_param = i; 1544 continue; 1545 } 1546 break; /* The adjacent state var is incompatible. */ 1547 } 1548 if (last_param > first_param) { 1549 param_diff = last_param - first_param; 1550 1551 /* Convert the state var to STATE_LIGHT_ATTENUATION_ARRAY. */ 1552 list->Parameters[first_param].StateIndexes[0] = 1553 STATE_LIGHT_ATTENUATION_ARRAY; 1554 /* Keep the light index the same. */ 1555 /* Set the number of lights. */ 1556 unsigned size = param_diff + 1; 1557 list->Parameters[first_param].StateIndexes[2] = size; 1558 list->Parameters[first_param].Size = size * 4; 1559 break; /* all done */ 1560 } 1561 } 1562 break; 1563 1564 case STATE_VERTEX_PROGRAM_ENV: 1565 case STATE_VERTEX_PROGRAM_LOCAL: 1566 case STATE_FRAGMENT_PROGRAM_ENV: 1567 case STATE_FRAGMENT_PROGRAM_LOCAL: 1568 if (list->Parameters[first_param].Size != 4) 1569 break; 1570 1571 /* Search for adjacent mergeable state vars. */ 1572 for (int i = first_param + 1; i < (int)list->NumParameters; i++) { 1573 if (list->Parameters[i].StateIndexes[0] == 1574 list->Parameters[i - 1].StateIndexes[0] && 1575 list->Parameters[i].StateIndexes[1] == 1576 list->Parameters[i - 1].StateIndexes[1] + 1 && 1577 list->Parameters[i].Size == 4) { 1578 last_param = i; 1579 continue; 1580 } 1581 break; /* The adjacent state var is incompatible. */ 1582 } 1583 if (last_param > first_param) { 1584 /* Set STATE_xxx_RANGE. */ 1585 STATIC_ASSERT(STATE_VERTEX_PROGRAM_ENV + 1 == 1586 STATE_VERTEX_PROGRAM_ENV_ARRAY); 1587 STATIC_ASSERT(STATE_VERTEX_PROGRAM_LOCAL + 1 == 1588 STATE_VERTEX_PROGRAM_LOCAL_ARRAY); 1589 STATIC_ASSERT(STATE_FRAGMENT_PROGRAM_ENV + 1 == 1590 STATE_FRAGMENT_PROGRAM_ENV_ARRAY); 1591 STATIC_ASSERT(STATE_FRAGMENT_PROGRAM_LOCAL + 1 == 1592 STATE_FRAGMENT_PROGRAM_LOCAL_ARRAY); 1593 list->Parameters[first_param].StateIndexes[0]++; 1594 1595 param_diff = last_param - first_param; 1596 1597 /* Set the size. */ 1598 unsigned size = param_diff + 1; 1599 list->Parameters[first_param].StateIndexes[2] = size; 1600 list->Parameters[first_param].Size = size * 4; 1601 } 1602 break; 1603 1604 case STATE_LIGHTPROD: { 1605 if (list->Parameters[first_param].Size != 4) 1606 break; 1607 1608 gl_state_index16 state = STATE_NOT_STATE_VAR; 1609 unsigned num_lights = 0; 1610 1611 for (unsigned state_iter = STATE_LIGHTPROD_ARRAY_FRONT; 1612 state_iter <= STATE_LIGHTPROD_ARRAY_TWOSIDE; state_iter++) { 1613 unsigned num_attribs, base_attrib, attrib_incr; 1614 1615 if (state_iter == STATE_LIGHTPROD_ARRAY_FRONT) { 1616 num_attribs = 3; 1617 base_attrib = MAT_ATTRIB_FRONT_AMBIENT; 1618 attrib_incr = 2; 1619 } else if (state_iter == STATE_LIGHTPROD_ARRAY_BACK) { 1620 num_attribs = 3; 1621 base_attrib = MAT_ATTRIB_BACK_AMBIENT; 1622 attrib_incr = 2; 1623 } else if (state_iter == STATE_LIGHTPROD_ARRAY_TWOSIDE) { 1624 num_attribs = 6; 1625 base_attrib = MAT_ATTRIB_FRONT_AMBIENT; 1626 attrib_incr = 1; 1627 } 1628 1629 /* Find all attributes for one light. */ 1630 while (first_param + (num_lights + 1) * num_attribs <= 1631 list->NumParameters && 1632 (state == STATE_NOT_STATE_VAR || state == state_iter)) { 1633 unsigned i = 0, base = first_param + num_lights * num_attribs; 1634 1635 /* Consecutive light indices: */ 1636 if (list->Parameters[first_param].StateIndexes[1] + num_lights == 1637 list->Parameters[base].StateIndexes[1]) { 1638 for (i = 0; i < num_attribs; i++) { 1639 if (list->Parameters[base + i].StateIndexes[0] == 1640 STATE_LIGHTPROD && 1641 list->Parameters[base + i].Size == 4 && 1642 /* Equal light indices: */ 1643 list->Parameters[base + i].StateIndexes[1] == 1644 list->Parameters[base + 0].StateIndexes[1] && 1645 /* Consecutive attributes: */ 1646 list->Parameters[base + i].StateIndexes[2] == 1647 base_attrib + i * attrib_incr) 1648 continue; 1649 break; 1650 } 1651 } 1652 if (i == num_attribs) { 1653 /* Accept all parameters for merging. */ 1654 state = state_iter; 1655 last_param = base + num_attribs - 1; 1656 num_lights++; 1657 } else { 1658 break; 1659 } 1660 } 1661 } 1662 1663 if (last_param > first_param) { 1664 param_diff = last_param - first_param; 1665 1666 list->Parameters[first_param].StateIndexes[0] = state; 1667 list->Parameters[first_param].StateIndexes[2] = num_lights; 1668 list->Parameters[first_param].Size = (param_diff + 1) * 4; 1669 } 1670 break; 1671 } 1672 1673 case STATE_LIGHT_POSITION: 1674 case STATE_LIGHT_POSITION_NORMALIZED: 1675 if (list->Parameters[first_param].Size != 4) 1676 break; 1677 1678 for (int i = first_param + 1; i < (int)list->NumParameters; i++) { 1679 if (list->Parameters[i].StateIndexes[0] == 1680 list->Parameters[i - 1].StateIndexes[0] && 1681 /* Consecutive light: */ 1682 list->Parameters[i].StateIndexes[1] == 1683 list->Parameters[i - 1].StateIndexes[1] + 1) { 1684 last_param = i; 1685 continue; 1686 } 1687 break; /* The adjacent state var is incompatible. */ 1688 } 1689 if (last_param > first_param) { 1690 param_diff = last_param - first_param; 1691 1692 /* Convert the state var to STATE_LIGHT_POSITION_*ARRAY. */ 1693 STATIC_ASSERT(STATE_LIGHT_POSITION + 1 == 1694 STATE_LIGHT_POSITION_ARRAY); 1695 STATIC_ASSERT(STATE_LIGHT_POSITION_NORMALIZED + 1 == 1696 STATE_LIGHT_POSITION_NORMALIZED_ARRAY); 1697 list->Parameters[first_param].StateIndexes[0]++; 1698 /* Keep the light index the same. */ 1699 unsigned size = param_diff + 1; 1700 /* Set the number of lights. */ 1701 list->Parameters[first_param].StateIndexes[2] = size; 1702 list->Parameters[first_param].Size = size * 4; 1703 } 1704 } 1705 1706 if (param_diff) { 1707 /* Update the name. */ 1708 free((void*)list->Parameters[first_param].Name); 1709 list->Parameters[first_param].Name = 1710 _mesa_program_state_string(list->Parameters[first_param].StateIndexes); 1711 1712 /* Free names that we are going to overwrite. */ 1713 for (int i = first_param + 1; i <= last_param; i++) 1714 free((char*)list->Parameters[i].Name); 1715 1716 /* Remove the merged state vars. */ 1717 if (last_param + 1 < list->NumParameters) { 1718 memmove(&list->Parameters[first_param + 1], 1719 &list->Parameters[last_param + 1], 1720 sizeof(list->Parameters[0]) * 1721 (list->NumParameters - last_param - 1)); 1722 } 1723 list->NumParameters -= param_diff; 1724 } 1725 } 1726 1727 _mesa_recompute_parameter_bounds(list); 1728} 1729