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