• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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