• 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/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 
48 static ALWAYS_INLINE void
copy_matrix(float * value,const float * m,unsigned firstRow,unsigned lastRow)49 copy_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 
64 static ALWAYS_INLINE void
copy_matrix_transposed(float * value,const float * m,unsigned firstRow,unsigned lastRow)65 copy_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  */
81 static void
fetch_state(struct gl_context * ctx,const gl_state_index16 state[],gl_constant_value * val)82 fetch_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 
793 unsigned
_mesa_program_state_value_size(const gl_state_index16 state[STATE_LENGTH])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  */
810 GLbitfield
_mesa_program_state_flags(const gl_state_index16 state[STATE_LENGTH])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 
942 static void
append(char * dst,const char * src)943 append(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  */
956 static void
append_token(char * dst,gl_state_index k)957 append_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 
1216 static void
append_index(char * dst,GLint index,bool structure)1217 append_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  */
1229 char *
_mesa_program_state_string(const gl_state_index16 state[STATE_LENGTH])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  */
1378 void
_mesa_load_state_parameters(struct gl_context * ctx,struct gl_program_parameter_list * paramList)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 
1394 void
_mesa_upload_state_parameters(struct gl_context * ctx,struct gl_program_parameter_list * paramList,uint32_t * dst)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  */
1415 void
_mesa_optimize_state_parameters(struct gl_constants * consts,struct gl_program_parameter_list * list)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