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