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