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