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
49 static ALWAYS_INLINE void
copy_matrix(float * value,const float * m,unsigned firstRow,unsigned lastRow)50 copy_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
65 static ALWAYS_INLINE void
copy_matrix_transposed(float * value,const float * m,unsigned firstRow,unsigned lastRow)66 copy_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 */
82 static void
fetch_state(struct gl_context * ctx,const gl_state_index16 state[],gl_constant_value * val)83 fetch_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
786 unsigned
_mesa_program_state_value_size(const gl_state_index16 state[STATE_LENGTH])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 */
803 GLbitfield
_mesa_program_state_flags(const gl_state_index16 state[STATE_LENGTH])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
931 static void
append(char * dst,const char * src)932 append(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 */
945 static void
append_token(char * dst,gl_state_index k)946 append_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
1202 static void
append_index(char * dst,GLint index,bool structure)1203 append_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 */
1215 char *
_mesa_program_state_string(const gl_state_index16 state[STATE_LENGTH])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 */
1362 void
_mesa_load_state_parameters(struct gl_context * ctx,struct gl_program_parameter_list * paramList)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
1378 void
_mesa_upload_state_parameters(struct gl_context * ctx,struct gl_program_parameter_list * paramList,uint32_t * dst)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 */
1399 void
_mesa_optimize_state_parameters(struct gl_constants * consts,struct gl_program_parameter_list * list)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