1848b8605Smrg/*
2848b8605Smrg * Mesa 3-D graphics library
3848b8605Smrg *
4848b8605Smrg * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
5848b8605Smrg *
6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
7848b8605Smrg * copy of this software and associated documentation files (the "Software"),
8848b8605Smrg * to deal in the Software without restriction, including without limitation
9848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the
11848b8605Smrg * Software is furnished to do so, subject to the following conditions:
12848b8605Smrg *
13848b8605Smrg * The above copyright notice and this permission notice shall be included
14848b8605Smrg * in all copies or substantial portions of the Software.
15848b8605Smrg *
16848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE.
23848b8605Smrg */
24848b8605Smrg
25848b8605Smrg/**
26848b8605Smrg * \file prog_statevars.c
27848b8605Smrg * Program state variable management.
28848b8605Smrg * \author Brian Paul
29848b8605Smrg */
30848b8605Smrg
31848b8605Smrg
32b8e80941Smrg#include <stdio.h>
33848b8605Smrg#include "main/glheader.h"
34848b8605Smrg#include "main/context.h"
35848b8605Smrg#include "main/blend.h"
36848b8605Smrg#include "main/imports.h"
37848b8605Smrg#include "main/macros.h"
38848b8605Smrg#include "main/mtypes.h"
39848b8605Smrg#include "main/fbobject.h"
40848b8605Smrg#include "prog_statevars.h"
41848b8605Smrg#include "prog_parameter.h"
42848b8605Smrg#include "main/samplerobj.h"
43b8e80941Smrg#include "main/framebuffer.h"
44b8e80941Smrg
45b8e80941Smrg
46b8e80941Smrg#define ONE_DIV_SQRT_LN2 (1.201122408786449815)
47848b8605Smrg
48848b8605Smrg
49848b8605Smrg/**
50848b8605Smrg * Use the list of tokens in the state[] array to find global GL state
51848b8605Smrg * and return it in <value>.  Usually, four values are returned in <value>
52848b8605Smrg * but matrix queries may return as many as 16 values.
53848b8605Smrg * This function is used for ARB vertex/fragment programs.
54848b8605Smrg * The program parser will produce the state[] values.
55848b8605Smrg */
56848b8605Smrgstatic void
57b8e80941Smrg_mesa_fetch_state(struct gl_context *ctx, const gl_state_index16 state[],
58b8e80941Smrg                  gl_constant_value *val)
59848b8605Smrg{
60b8e80941Smrg   GLfloat *value = &val->f;
61b8e80941Smrg
62848b8605Smrg   switch (state[0]) {
63848b8605Smrg   case STATE_MATERIAL:
64848b8605Smrg      {
65848b8605Smrg         /* state[1] is either 0=front or 1=back side */
66848b8605Smrg         const GLuint face = (GLuint) state[1];
67848b8605Smrg         const struct gl_material *mat = &ctx->Light.Material;
68b8e80941Smrg         assert(face == 0 || face == 1);
69848b8605Smrg         /* we rely on tokens numbered so that _BACK_ == _FRONT_+ 1 */
70b8e80941Smrg         assert(MAT_ATTRIB_FRONT_AMBIENT + 1 == MAT_ATTRIB_BACK_AMBIENT);
71848b8605Smrg         /* XXX we could get rid of this switch entirely with a little
72848b8605Smrg          * work in arbprogparse.c's parse_state_single_item().
73848b8605Smrg          */
74848b8605Smrg         /* state[2] is the material attribute */
75848b8605Smrg         switch (state[2]) {
76848b8605Smrg         case STATE_AMBIENT:
77848b8605Smrg            COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_AMBIENT + face]);
78848b8605Smrg            return;
79848b8605Smrg         case STATE_DIFFUSE:
80848b8605Smrg            COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_DIFFUSE + face]);
81848b8605Smrg            return;
82848b8605Smrg         case STATE_SPECULAR:
83848b8605Smrg            COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_SPECULAR + face]);
84848b8605Smrg            return;
85848b8605Smrg         case STATE_EMISSION:
86848b8605Smrg            COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_EMISSION + face]);
87848b8605Smrg            return;
88848b8605Smrg         case STATE_SHININESS:
89848b8605Smrg            value[0] = mat->Attrib[MAT_ATTRIB_FRONT_SHININESS + face][0];
90848b8605Smrg            value[1] = 0.0F;
91848b8605Smrg            value[2] = 0.0F;
92848b8605Smrg            value[3] = 1.0F;
93848b8605Smrg            return;
94848b8605Smrg         default:
95848b8605Smrg            _mesa_problem(ctx, "Invalid material state in fetch_state");
96848b8605Smrg            return;
97848b8605Smrg         }
98848b8605Smrg      }
99848b8605Smrg   case STATE_LIGHT:
100848b8605Smrg      {
101848b8605Smrg         /* state[1] is the light number */
102848b8605Smrg         const GLuint ln = (GLuint) state[1];
103848b8605Smrg         /* state[2] is the light attribute */
104848b8605Smrg         switch (state[2]) {
105848b8605Smrg         case STATE_AMBIENT:
106848b8605Smrg            COPY_4V(value, ctx->Light.Light[ln].Ambient);
107848b8605Smrg            return;
108848b8605Smrg         case STATE_DIFFUSE:
109848b8605Smrg            COPY_4V(value, ctx->Light.Light[ln].Diffuse);
110848b8605Smrg            return;
111848b8605Smrg         case STATE_SPECULAR:
112848b8605Smrg            COPY_4V(value, ctx->Light.Light[ln].Specular);
113848b8605Smrg            return;
114848b8605Smrg         case STATE_POSITION:
115848b8605Smrg            COPY_4V(value, ctx->Light.Light[ln].EyePosition);
116848b8605Smrg            return;
117848b8605Smrg         case STATE_ATTENUATION:
118848b8605Smrg            value[0] = ctx->Light.Light[ln].ConstantAttenuation;
119848b8605Smrg            value[1] = ctx->Light.Light[ln].LinearAttenuation;
120848b8605Smrg            value[2] = ctx->Light.Light[ln].QuadraticAttenuation;
121848b8605Smrg            value[3] = ctx->Light.Light[ln].SpotExponent;
122848b8605Smrg            return;
123848b8605Smrg         case STATE_SPOT_DIRECTION:
124848b8605Smrg            COPY_3V(value, ctx->Light.Light[ln].SpotDirection);
125848b8605Smrg            value[3] = ctx->Light.Light[ln]._CosCutoff;
126848b8605Smrg            return;
127848b8605Smrg         case STATE_SPOT_CUTOFF:
128848b8605Smrg            value[0] = ctx->Light.Light[ln].SpotCutoff;
129848b8605Smrg            return;
130848b8605Smrg         case STATE_HALF_VECTOR:
131848b8605Smrg            {
132848b8605Smrg               static const GLfloat eye_z[] = {0, 0, 1};
133848b8605Smrg               GLfloat p[3];
134848b8605Smrg               /* Compute infinite half angle vector:
135848b8605Smrg                *   halfVector = normalize(normalize(lightPos) + (0, 0, 1))
136848b8605Smrg		* light.EyePosition.w should be 0 for infinite lights.
137848b8605Smrg                */
138848b8605Smrg               COPY_3V(p, ctx->Light.Light[ln].EyePosition);
139848b8605Smrg               NORMALIZE_3FV(p);
140848b8605Smrg	       ADD_3V(value, p, eye_z);
141848b8605Smrg	       NORMALIZE_3FV(value);
142848b8605Smrg	       value[3] = 1.0;
143848b8605Smrg            }
144848b8605Smrg            return;
145848b8605Smrg         default:
146848b8605Smrg            _mesa_problem(ctx, "Invalid light state in fetch_state");
147848b8605Smrg            return;
148848b8605Smrg         }
149848b8605Smrg      }
150848b8605Smrg   case STATE_LIGHTMODEL_AMBIENT:
151848b8605Smrg      COPY_4V(value, ctx->Light.Model.Ambient);
152848b8605Smrg      return;
153848b8605Smrg   case STATE_LIGHTMODEL_SCENECOLOR:
154848b8605Smrg      if (state[1] == 0) {
155848b8605Smrg         /* front */
156848b8605Smrg         GLint i;
157848b8605Smrg         for (i = 0; i < 3; i++) {
158848b8605Smrg            value[i] = ctx->Light.Model.Ambient[i]
159848b8605Smrg               * ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT][i]
160848b8605Smrg               + ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION][i];
161848b8605Smrg         }
162848b8605Smrg	 value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
163848b8605Smrg      }
164848b8605Smrg      else {
165848b8605Smrg         /* back */
166848b8605Smrg         GLint i;
167848b8605Smrg         for (i = 0; i < 3; i++) {
168848b8605Smrg            value[i] = ctx->Light.Model.Ambient[i]
169848b8605Smrg               * ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_AMBIENT][i]
170848b8605Smrg               + ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_EMISSION][i];
171848b8605Smrg         }
172848b8605Smrg	 value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
173848b8605Smrg      }
174848b8605Smrg      return;
175848b8605Smrg   case STATE_LIGHTPROD:
176848b8605Smrg      {
177848b8605Smrg         const GLuint ln = (GLuint) state[1];
178848b8605Smrg         const GLuint face = (GLuint) state[2];
179848b8605Smrg         GLint i;
180b8e80941Smrg         assert(face == 0 || face == 1);
181848b8605Smrg         switch (state[3]) {
182848b8605Smrg            case STATE_AMBIENT:
183848b8605Smrg               for (i = 0; i < 3; i++) {
184848b8605Smrg                  value[i] = ctx->Light.Light[ln].Ambient[i] *
185848b8605Smrg                     ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT+face][i];
186848b8605Smrg               }
187848b8605Smrg               /* [3] = material alpha */
188848b8605Smrg               value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT+face][3];
189848b8605Smrg               return;
190848b8605Smrg            case STATE_DIFFUSE:
191848b8605Smrg               for (i = 0; i < 3; i++) {
192848b8605Smrg                  value[i] = ctx->Light.Light[ln].Diffuse[i] *
193848b8605Smrg                     ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][i];
194848b8605Smrg               }
195848b8605Smrg               /* [3] = material alpha */
196848b8605Smrg               value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][3];
197848b8605Smrg               return;
198848b8605Smrg            case STATE_SPECULAR:
199848b8605Smrg               for (i = 0; i < 3; i++) {
200848b8605Smrg                  value[i] = ctx->Light.Light[ln].Specular[i] *
201848b8605Smrg                     ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SPECULAR+face][i];
202848b8605Smrg               }
203848b8605Smrg               /* [3] = material alpha */
204848b8605Smrg               value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SPECULAR+face][3];
205848b8605Smrg               return;
206848b8605Smrg            default:
207848b8605Smrg               _mesa_problem(ctx, "Invalid lightprod state in fetch_state");
208848b8605Smrg               return;
209848b8605Smrg         }
210848b8605Smrg      }
211848b8605Smrg   case STATE_TEXGEN:
212848b8605Smrg      {
213848b8605Smrg         /* state[1] is the texture unit */
214848b8605Smrg         const GLuint unit = (GLuint) state[1];
215848b8605Smrg         /* state[2] is the texgen attribute */
216848b8605Smrg         switch (state[2]) {
217848b8605Smrg         case STATE_TEXGEN_EYE_S:
218b8e80941Smrg            COPY_4V(value, ctx->Texture.FixedFuncUnit[unit].GenS.EyePlane);
219848b8605Smrg            return;
220848b8605Smrg         case STATE_TEXGEN_EYE_T:
221b8e80941Smrg            COPY_4V(value, ctx->Texture.FixedFuncUnit[unit].GenT.EyePlane);
222848b8605Smrg            return;
223848b8605Smrg         case STATE_TEXGEN_EYE_R:
224b8e80941Smrg            COPY_4V(value, ctx->Texture.FixedFuncUnit[unit].GenR.EyePlane);
225848b8605Smrg            return;
226848b8605Smrg         case STATE_TEXGEN_EYE_Q:
227b8e80941Smrg            COPY_4V(value, ctx->Texture.FixedFuncUnit[unit].GenQ.EyePlane);
228848b8605Smrg            return;
229848b8605Smrg         case STATE_TEXGEN_OBJECT_S:
230b8e80941Smrg            COPY_4V(value, ctx->Texture.FixedFuncUnit[unit].GenS.ObjectPlane);
231848b8605Smrg            return;
232848b8605Smrg         case STATE_TEXGEN_OBJECT_T:
233b8e80941Smrg            COPY_4V(value, ctx->Texture.FixedFuncUnit[unit].GenT.ObjectPlane);
234848b8605Smrg            return;
235848b8605Smrg         case STATE_TEXGEN_OBJECT_R:
236b8e80941Smrg            COPY_4V(value, ctx->Texture.FixedFuncUnit[unit].GenR.ObjectPlane);
237848b8605Smrg            return;
238848b8605Smrg         case STATE_TEXGEN_OBJECT_Q:
239b8e80941Smrg            COPY_4V(value, ctx->Texture.FixedFuncUnit[unit].GenQ.ObjectPlane);
240848b8605Smrg            return;
241848b8605Smrg         default:
242848b8605Smrg            _mesa_problem(ctx, "Invalid texgen state in fetch_state");
243848b8605Smrg            return;
244848b8605Smrg         }
245848b8605Smrg      }
246848b8605Smrg   case STATE_TEXENV_COLOR:
247848b8605Smrg      {
248848b8605Smrg         /* state[1] is the texture unit */
249848b8605Smrg         const GLuint unit = (GLuint) state[1];
250b8e80941Smrg         if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer))
251b8e80941Smrg            COPY_4V(value, ctx->Texture.FixedFuncUnit[unit].EnvColor);
252848b8605Smrg         else
253b8e80941Smrg            COPY_4V(value, ctx->Texture.FixedFuncUnit[unit].EnvColorUnclamped);
254848b8605Smrg      }
255848b8605Smrg      return;
256848b8605Smrg   case STATE_FOG_COLOR:
257b8e80941Smrg      if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer))
258848b8605Smrg         COPY_4V(value, ctx->Fog.Color);
259848b8605Smrg      else
260848b8605Smrg         COPY_4V(value, ctx->Fog.ColorUnclamped);
261848b8605Smrg      return;
262848b8605Smrg   case STATE_FOG_PARAMS:
263848b8605Smrg      value[0] = ctx->Fog.Density;
264848b8605Smrg      value[1] = ctx->Fog.Start;
265848b8605Smrg      value[2] = ctx->Fog.End;
266848b8605Smrg      value[3] = 1.0f / (ctx->Fog.End - ctx->Fog.Start);
267848b8605Smrg      return;
268848b8605Smrg   case STATE_CLIPPLANE:
269848b8605Smrg      {
270848b8605Smrg         const GLuint plane = (GLuint) state[1];
271848b8605Smrg         COPY_4V(value, ctx->Transform.EyeUserPlane[plane]);
272848b8605Smrg      }
273848b8605Smrg      return;
274848b8605Smrg   case STATE_POINT_SIZE:
275848b8605Smrg      value[0] = ctx->Point.Size;
276848b8605Smrg      value[1] = ctx->Point.MinSize;
277848b8605Smrg      value[2] = ctx->Point.MaxSize;
278848b8605Smrg      value[3] = ctx->Point.Threshold;
279848b8605Smrg      return;
280848b8605Smrg   case STATE_POINT_ATTENUATION:
281848b8605Smrg      value[0] = ctx->Point.Params[0];
282848b8605Smrg      value[1] = ctx->Point.Params[1];
283848b8605Smrg      value[2] = ctx->Point.Params[2];
284848b8605Smrg      value[3] = 1.0F;
285848b8605Smrg      return;
286848b8605Smrg   case STATE_MODELVIEW_MATRIX:
287848b8605Smrg   case STATE_PROJECTION_MATRIX:
288848b8605Smrg   case STATE_MVP_MATRIX:
289848b8605Smrg   case STATE_TEXTURE_MATRIX:
290848b8605Smrg   case STATE_PROGRAM_MATRIX:
291848b8605Smrg      {
292848b8605Smrg         /* state[0] = modelview, projection, texture, etc. */
293848b8605Smrg         /* state[1] = which texture matrix or program matrix */
294848b8605Smrg         /* state[2] = first row to fetch */
295848b8605Smrg         /* state[3] = last row to fetch */
296848b8605Smrg         /* state[4] = transpose, inverse or invtrans */
297848b8605Smrg         const GLmatrix *matrix;
298848b8605Smrg         const gl_state_index mat = state[0];
299848b8605Smrg         const GLuint index = (GLuint) state[1];
300848b8605Smrg         const GLuint firstRow = (GLuint) state[2];
301848b8605Smrg         const GLuint lastRow = (GLuint) state[3];
302848b8605Smrg         const gl_state_index modifier = state[4];
303848b8605Smrg         const GLfloat *m;
304848b8605Smrg         GLuint row, i;
305b8e80941Smrg         assert(firstRow < 4);
306b8e80941Smrg         assert(lastRow < 4);
307848b8605Smrg         if (mat == STATE_MODELVIEW_MATRIX) {
308848b8605Smrg            matrix = ctx->ModelviewMatrixStack.Top;
309848b8605Smrg         }
310848b8605Smrg         else if (mat == STATE_PROJECTION_MATRIX) {
311848b8605Smrg            matrix = ctx->ProjectionMatrixStack.Top;
312848b8605Smrg         }
313848b8605Smrg         else if (mat == STATE_MVP_MATRIX) {
314848b8605Smrg            matrix = &ctx->_ModelProjectMatrix;
315848b8605Smrg         }
316848b8605Smrg         else if (mat == STATE_TEXTURE_MATRIX) {
317b8e80941Smrg            assert(index < ARRAY_SIZE(ctx->TextureMatrixStack));
318848b8605Smrg            matrix = ctx->TextureMatrixStack[index].Top;
319848b8605Smrg         }
320848b8605Smrg         else if (mat == STATE_PROGRAM_MATRIX) {
321b8e80941Smrg            assert(index < ARRAY_SIZE(ctx->ProgramMatrixStack));
322848b8605Smrg            matrix = ctx->ProgramMatrixStack[index].Top;
323848b8605Smrg         }
324848b8605Smrg         else {
325848b8605Smrg            _mesa_problem(ctx, "Bad matrix name in _mesa_fetch_state()");
326848b8605Smrg            return;
327848b8605Smrg         }
328848b8605Smrg         if (modifier == STATE_MATRIX_INVERSE ||
329848b8605Smrg             modifier == STATE_MATRIX_INVTRANS) {
330848b8605Smrg            /* Be sure inverse is up to date:
331848b8605Smrg	     */
332848b8605Smrg	    _math_matrix_analyse( (GLmatrix*) matrix );
333848b8605Smrg            m = matrix->inv;
334848b8605Smrg         }
335848b8605Smrg         else {
336848b8605Smrg            m = matrix->m;
337848b8605Smrg         }
338848b8605Smrg         if (modifier == STATE_MATRIX_TRANSPOSE ||
339848b8605Smrg             modifier == STATE_MATRIX_INVTRANS) {
340848b8605Smrg            for (i = 0, row = firstRow; row <= lastRow; row++) {
341848b8605Smrg               value[i++] = m[row * 4 + 0];
342848b8605Smrg               value[i++] = m[row * 4 + 1];
343848b8605Smrg               value[i++] = m[row * 4 + 2];
344848b8605Smrg               value[i++] = m[row * 4 + 3];
345848b8605Smrg            }
346848b8605Smrg         }
347848b8605Smrg         else {
348848b8605Smrg            for (i = 0, row = firstRow; row <= lastRow; row++) {
349848b8605Smrg               value[i++] = m[row + 0];
350848b8605Smrg               value[i++] = m[row + 4];
351848b8605Smrg               value[i++] = m[row + 8];
352848b8605Smrg               value[i++] = m[row + 12];
353848b8605Smrg            }
354848b8605Smrg         }
355848b8605Smrg      }
356848b8605Smrg      return;
357848b8605Smrg   case STATE_NUM_SAMPLES:
358b8e80941Smrg      val[0].i = MAX2(1, _mesa_geometric_samples(ctx->DrawBuffer));
359848b8605Smrg      return;
360848b8605Smrg   case STATE_DEPTH_RANGE:
361848b8605Smrg      value[0] = ctx->ViewportArray[0].Near;                /* near       */
362848b8605Smrg      value[1] = ctx->ViewportArray[0].Far;                 /* far        */
363848b8605Smrg      value[2] = ctx->ViewportArray[0].Far - ctx->ViewportArray[0].Near; /* far - near */
364848b8605Smrg      value[3] = 1.0;
365848b8605Smrg      return;
366848b8605Smrg   case STATE_FRAGMENT_PROGRAM:
367848b8605Smrg      {
368848b8605Smrg         /* state[1] = {STATE_ENV, STATE_LOCAL} */
369848b8605Smrg         /* state[2] = parameter index          */
370848b8605Smrg         const int idx = (int) state[2];
371848b8605Smrg         switch (state[1]) {
372848b8605Smrg            case STATE_ENV:
373848b8605Smrg               COPY_4V(value, ctx->FragmentProgram.Parameters[idx]);
374848b8605Smrg               return;
375848b8605Smrg            case STATE_LOCAL:
376b8e80941Smrg               if (!ctx->FragmentProgram.Current->arb.LocalParams) {
377b8e80941Smrg                  ctx->FragmentProgram.Current->arb.LocalParams =
378b8e80941Smrg                     rzalloc_array_size(ctx->FragmentProgram.Current,
379b8e80941Smrg                                        sizeof(float[4]),
380b8e80941Smrg                                        MAX_PROGRAM_LOCAL_PARAMS);
381b8e80941Smrg                  if (!ctx->FragmentProgram.Current->arb.LocalParams)
382848b8605Smrg                     return;
383848b8605Smrg               }
384848b8605Smrg
385b8e80941Smrg               COPY_4V(value,
386b8e80941Smrg                       ctx->FragmentProgram.Current->arb.LocalParams[idx]);
387848b8605Smrg               return;
388848b8605Smrg            default:
389848b8605Smrg               _mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()");
390848b8605Smrg               return;
391848b8605Smrg         }
392848b8605Smrg      }
393848b8605Smrg      return;
394848b8605Smrg
395848b8605Smrg   case STATE_VERTEX_PROGRAM:
396848b8605Smrg      {
397848b8605Smrg         /* state[1] = {STATE_ENV, STATE_LOCAL} */
398848b8605Smrg         /* state[2] = parameter index          */
399848b8605Smrg         const int idx = (int) state[2];
400848b8605Smrg         switch (state[1]) {
401848b8605Smrg            case STATE_ENV:
402848b8605Smrg               COPY_4V(value, ctx->VertexProgram.Parameters[idx]);
403848b8605Smrg               return;
404848b8605Smrg            case STATE_LOCAL:
405b8e80941Smrg               if (!ctx->VertexProgram.Current->arb.LocalParams) {
406b8e80941Smrg                  ctx->VertexProgram.Current->arb.LocalParams =
407b8e80941Smrg                     rzalloc_array_size(ctx->VertexProgram.Current,
408b8e80941Smrg                                        sizeof(float[4]),
409b8e80941Smrg                                        MAX_PROGRAM_LOCAL_PARAMS);
410b8e80941Smrg                  if (!ctx->VertexProgram.Current->arb.LocalParams)
411848b8605Smrg                     return;
412848b8605Smrg               }
413848b8605Smrg
414b8e80941Smrg               COPY_4V(value,
415b8e80941Smrg                       ctx->VertexProgram.Current->arb.LocalParams[idx]);
416848b8605Smrg               return;
417848b8605Smrg            default:
418848b8605Smrg               _mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()");
419848b8605Smrg               return;
420848b8605Smrg         }
421848b8605Smrg      }
422848b8605Smrg      return;
423848b8605Smrg
424848b8605Smrg   case STATE_NORMAL_SCALE:
425b8e80941Smrg      ASSIGN_4V(value, ctx->_ModelViewInvScaleEyespace, 0, 0, 1);
426848b8605Smrg      return;
427848b8605Smrg
428848b8605Smrg   case STATE_INTERNAL:
429848b8605Smrg      switch (state[1]) {
430848b8605Smrg      case STATE_CURRENT_ATTRIB:
431848b8605Smrg         {
432848b8605Smrg            const GLuint idx = (GLuint) state[2];
433848b8605Smrg            COPY_4V(value, ctx->Current.Attrib[idx]);
434848b8605Smrg         }
435848b8605Smrg         return;
436848b8605Smrg
437848b8605Smrg      case STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED:
438848b8605Smrg         {
439848b8605Smrg            const GLuint idx = (GLuint) state[2];
440848b8605Smrg            if(ctx->Light._ClampVertexColor &&
441848b8605Smrg               (idx == VERT_ATTRIB_COLOR0 ||
442848b8605Smrg                idx == VERT_ATTRIB_COLOR1)) {
443848b8605Smrg               value[0] = CLAMP(ctx->Current.Attrib[idx][0], 0.0f, 1.0f);
444848b8605Smrg               value[1] = CLAMP(ctx->Current.Attrib[idx][1], 0.0f, 1.0f);
445848b8605Smrg               value[2] = CLAMP(ctx->Current.Attrib[idx][2], 0.0f, 1.0f);
446848b8605Smrg               value[3] = CLAMP(ctx->Current.Attrib[idx][3], 0.0f, 1.0f);
447848b8605Smrg            }
448848b8605Smrg            else
449848b8605Smrg               COPY_4V(value, ctx->Current.Attrib[idx]);
450848b8605Smrg         }
451848b8605Smrg         return;
452848b8605Smrg
453848b8605Smrg      case STATE_NORMAL_SCALE:
454848b8605Smrg         ASSIGN_4V(value,
455848b8605Smrg                   ctx->_ModelViewInvScale,
456848b8605Smrg                   ctx->_ModelViewInvScale,
457848b8605Smrg                   ctx->_ModelViewInvScale,
458848b8605Smrg                   1);
459848b8605Smrg         return;
460848b8605Smrg
461848b8605Smrg      case STATE_FOG_PARAMS_OPTIMIZED:
462848b8605Smrg         /* for simpler per-vertex/pixel fog calcs. POW (for EXP/EXP2 fog)
463848b8605Smrg          * might be more expensive than EX2 on some hw, plus it needs
464848b8605Smrg          * another constant (e) anyway. Linear fog can now be done with a
465848b8605Smrg          * single MAD.
466848b8605Smrg          * linear: fogcoord * -1/(end-start) + end/(end-start)
467848b8605Smrg          * exp: 2^-(density/ln(2) * fogcoord)
468b8e80941Smrg          * exp2: 2^-((density/(sqrt(ln(2))) * fogcoord)^2)
469848b8605Smrg          */
470848b8605Smrg         value[0] = (ctx->Fog.End == ctx->Fog.Start)
471848b8605Smrg            ? 1.0f : (GLfloat)(-1.0F / (ctx->Fog.End - ctx->Fog.Start));
472848b8605Smrg         value[1] = ctx->Fog.End * -value[0];
473848b8605Smrg         value[2] = (GLfloat)(ctx->Fog.Density * M_LOG2E); /* M_LOG2E == 1/ln(2) */
474848b8605Smrg         value[3] = (GLfloat)(ctx->Fog.Density * ONE_DIV_SQRT_LN2);
475848b8605Smrg         return;
476848b8605Smrg
477848b8605Smrg      case STATE_POINT_SIZE_CLAMPED:
478848b8605Smrg         {
479848b8605Smrg           /* this includes implementation dependent limits, to avoid
480848b8605Smrg            * another potentially necessary clamp.
481848b8605Smrg            * Note: for sprites, point smooth (point AA) is ignored
482848b8605Smrg            * and we'll clamp to MinPointSizeAA and MaxPointSize, because we
483848b8605Smrg            * expect drivers will want to say their minimum for AA size is 0.0
484848b8605Smrg            * but for non-AA it's 1.0 (because normal points with size below 1.0
485848b8605Smrg            * need to get rounded up to 1.0, hence never disappear). GL does
486848b8605Smrg            * not specify max clamp size for sprites, other than it needs to be
487848b8605Smrg            * at least as large as max AA size, hence use non-AA size there.
488848b8605Smrg            */
489848b8605Smrg            GLfloat minImplSize;
490848b8605Smrg            GLfloat maxImplSize;
491848b8605Smrg            if (ctx->Point.PointSprite) {
492848b8605Smrg               minImplSize = ctx->Const.MinPointSizeAA;
493848b8605Smrg               maxImplSize = ctx->Const.MaxPointSize;
494848b8605Smrg            }
495b8e80941Smrg            else if (ctx->Point.SmoothFlag || _mesa_is_multisample_enabled(ctx)) {
496848b8605Smrg               minImplSize = ctx->Const.MinPointSizeAA;
497848b8605Smrg               maxImplSize = ctx->Const.MaxPointSizeAA;
498848b8605Smrg            }
499848b8605Smrg            else {
500848b8605Smrg               minImplSize = ctx->Const.MinPointSize;
501848b8605Smrg               maxImplSize = ctx->Const.MaxPointSize;
502848b8605Smrg            }
503848b8605Smrg            value[0] = ctx->Point.Size;
504848b8605Smrg            value[1] = ctx->Point.MinSize >= minImplSize ? ctx->Point.MinSize : minImplSize;
505848b8605Smrg            value[2] = ctx->Point.MaxSize <= maxImplSize ? ctx->Point.MaxSize : maxImplSize;
506848b8605Smrg            value[3] = ctx->Point.Threshold;
507848b8605Smrg         }
508848b8605Smrg         return;
509848b8605Smrg      case STATE_LIGHT_SPOT_DIR_NORMALIZED:
510848b8605Smrg         {
511848b8605Smrg            /* here, state[2] is the light number */
512848b8605Smrg            /* pre-normalize spot dir */
513848b8605Smrg            const GLuint ln = (GLuint) state[2];
514848b8605Smrg            COPY_3V(value, ctx->Light.Light[ln]._NormSpotDirection);
515848b8605Smrg            value[3] = ctx->Light.Light[ln]._CosCutoff;
516848b8605Smrg         }
517848b8605Smrg         return;
518848b8605Smrg
519848b8605Smrg      case STATE_LIGHT_POSITION:
520848b8605Smrg         {
521848b8605Smrg            const GLuint ln = (GLuint) state[2];
522848b8605Smrg            COPY_4V(value, ctx->Light.Light[ln]._Position);
523848b8605Smrg         }
524848b8605Smrg         return;
525848b8605Smrg
526848b8605Smrg      case STATE_LIGHT_POSITION_NORMALIZED:
527848b8605Smrg         {
528848b8605Smrg            const GLuint ln = (GLuint) state[2];
529848b8605Smrg            COPY_4V(value, ctx->Light.Light[ln]._Position);
530848b8605Smrg            NORMALIZE_3FV( value );
531848b8605Smrg         }
532848b8605Smrg         return;
533848b8605Smrg
534848b8605Smrg      case STATE_LIGHT_HALF_VECTOR:
535848b8605Smrg         {
536848b8605Smrg            const GLuint ln = (GLuint) state[2];
537848b8605Smrg            GLfloat p[3];
538848b8605Smrg            /* Compute infinite half angle vector:
539848b8605Smrg             *   halfVector = normalize(normalize(lightPos) + (0, 0, 1))
540848b8605Smrg             * light.EyePosition.w should be 0 for infinite lights.
541848b8605Smrg             */
542848b8605Smrg            COPY_3V(p, ctx->Light.Light[ln]._Position);
543848b8605Smrg            NORMALIZE_3FV(p);
544848b8605Smrg            ADD_3V(value, p, ctx->_EyeZDir);
545848b8605Smrg            NORMALIZE_3FV(value);
546848b8605Smrg            value[3] = 1.0;
547848b8605Smrg         }
548848b8605Smrg         return;
549848b8605Smrg
550848b8605Smrg      case STATE_PT_SCALE:
551848b8605Smrg         value[0] = ctx->Pixel.RedScale;
552848b8605Smrg         value[1] = ctx->Pixel.GreenScale;
553848b8605Smrg         value[2] = ctx->Pixel.BlueScale;
554848b8605Smrg         value[3] = ctx->Pixel.AlphaScale;
555848b8605Smrg         return;
556848b8605Smrg
557848b8605Smrg      case STATE_PT_BIAS:
558848b8605Smrg         value[0] = ctx->Pixel.RedBias;
559848b8605Smrg         value[1] = ctx->Pixel.GreenBias;
560848b8605Smrg         value[2] = ctx->Pixel.BlueBias;
561848b8605Smrg         value[3] = ctx->Pixel.AlphaBias;
562848b8605Smrg         return;
563848b8605Smrg
564848b8605Smrg      case STATE_FB_SIZE:
565848b8605Smrg         value[0] = (GLfloat) (ctx->DrawBuffer->Width - 1);
566848b8605Smrg         value[1] = (GLfloat) (ctx->DrawBuffer->Height - 1);
567848b8605Smrg         value[2] = 0.0F;
568848b8605Smrg         value[3] = 0.0F;
569848b8605Smrg         return;
570848b8605Smrg
571848b8605Smrg      case STATE_FB_WPOS_Y_TRANSFORM:
572848b8605Smrg         /* A driver may negate this conditional by using ZW swizzle
573848b8605Smrg          * instead of XY (based on e.g. some other state). */
574b8e80941Smrg         if (!ctx->DrawBuffer->FlipY) {
575848b8605Smrg            /* Identity (XY) followed by flipping Y upside down (ZW). */
576848b8605Smrg            value[0] = 1.0F;
577848b8605Smrg            value[1] = 0.0F;
578848b8605Smrg            value[2] = -1.0F;
579848b8605Smrg            value[3] = (GLfloat) ctx->DrawBuffer->Height;
580848b8605Smrg         } else {
581848b8605Smrg            /* Flipping Y upside down (XY) followed by identity (ZW). */
582848b8605Smrg            value[0] = -1.0F;
583848b8605Smrg            value[1] = (GLfloat) ctx->DrawBuffer->Height;
584848b8605Smrg            value[2] = 1.0F;
585848b8605Smrg            value[3] = 0.0F;
586848b8605Smrg         }
587848b8605Smrg         return;
588848b8605Smrg
589b8e80941Smrg      case STATE_TCS_PATCH_VERTICES_IN:
590b8e80941Smrg         val[0].i = ctx->TessCtrlProgram.patch_vertices;
591b8e80941Smrg         return;
592b8e80941Smrg
593b8e80941Smrg      case STATE_TES_PATCH_VERTICES_IN:
594b8e80941Smrg         if (ctx->TessCtrlProgram._Current)
595b8e80941Smrg            val[0].i = ctx->TessCtrlProgram._Current->info.tess.tcs_vertices_out;
596b8e80941Smrg         else
597b8e80941Smrg            val[0].i = ctx->TessCtrlProgram.patch_vertices;
598b8e80941Smrg         return;
599b8e80941Smrg
600b8e80941Smrg      case STATE_ADVANCED_BLENDING_MODE:
601b8e80941Smrg         val[0].i = _mesa_get_advanced_blend_sh_constant(
602b8e80941Smrg                      ctx->Color.BlendEnabled, ctx->Color._AdvancedBlendMode);
603b8e80941Smrg         return;
604b8e80941Smrg
605848b8605Smrg      /* XXX: make sure new tokens added here are also handled in the
606848b8605Smrg       * _mesa_program_state_flags() switch, below.
607848b8605Smrg       */
608848b8605Smrg      default:
609848b8605Smrg         /* Unknown state indexes are silently ignored here.
610848b8605Smrg          * Drivers may do something special.
611848b8605Smrg          */
612848b8605Smrg         return;
613848b8605Smrg      }
614848b8605Smrg      return;
615848b8605Smrg
616848b8605Smrg   default:
617848b8605Smrg      _mesa_problem(ctx, "Invalid state in _mesa_fetch_state");
618848b8605Smrg      return;
619848b8605Smrg   }
620848b8605Smrg}
621848b8605Smrg
622848b8605Smrg
623848b8605Smrg/**
624848b8605Smrg * Return a bitmask of the Mesa state flags (_NEW_* values) which would
625848b8605Smrg * indicate that the given context state may have changed.
626848b8605Smrg * The bitmask is used during validation to determine if we need to update
627848b8605Smrg * vertex/fragment program parameters (like "state.material.color") when
628848b8605Smrg * some GL state has changed.
629848b8605Smrg */
630848b8605SmrgGLbitfield
631b8e80941Smrg_mesa_program_state_flags(const gl_state_index16 state[STATE_LENGTH])
632848b8605Smrg{
633848b8605Smrg   switch (state[0]) {
634848b8605Smrg   case STATE_MATERIAL:
635848b8605Smrg   case STATE_LIGHTPROD:
636848b8605Smrg   case STATE_LIGHTMODEL_SCENECOLOR:
637848b8605Smrg      /* these can be effected by glColor when colormaterial mode is used */
638848b8605Smrg      return _NEW_LIGHT | _NEW_CURRENT_ATTRIB;
639848b8605Smrg
640848b8605Smrg   case STATE_LIGHT:
641848b8605Smrg   case STATE_LIGHTMODEL_AMBIENT:
642848b8605Smrg      return _NEW_LIGHT;
643848b8605Smrg
644848b8605Smrg   case STATE_TEXGEN:
645b8e80941Smrg      return _NEW_TEXTURE_STATE;
646848b8605Smrg   case STATE_TEXENV_COLOR:
647b8e80941Smrg      return _NEW_TEXTURE_STATE | _NEW_BUFFERS | _NEW_FRAG_CLAMP;
648848b8605Smrg
649848b8605Smrg   case STATE_FOG_COLOR:
650848b8605Smrg      return _NEW_FOG | _NEW_BUFFERS | _NEW_FRAG_CLAMP;
651848b8605Smrg   case STATE_FOG_PARAMS:
652848b8605Smrg      return _NEW_FOG;
653848b8605Smrg
654848b8605Smrg   case STATE_CLIPPLANE:
655848b8605Smrg      return _NEW_TRANSFORM;
656848b8605Smrg
657848b8605Smrg   case STATE_POINT_SIZE:
658848b8605Smrg   case STATE_POINT_ATTENUATION:
659848b8605Smrg      return _NEW_POINT;
660848b8605Smrg
661848b8605Smrg   case STATE_MODELVIEW_MATRIX:
662848b8605Smrg      return _NEW_MODELVIEW;
663848b8605Smrg   case STATE_PROJECTION_MATRIX:
664848b8605Smrg      return _NEW_PROJECTION;
665848b8605Smrg   case STATE_MVP_MATRIX:
666848b8605Smrg      return _NEW_MODELVIEW | _NEW_PROJECTION;
667848b8605Smrg   case STATE_TEXTURE_MATRIX:
668848b8605Smrg      return _NEW_TEXTURE_MATRIX;
669848b8605Smrg   case STATE_PROGRAM_MATRIX:
670848b8605Smrg      return _NEW_TRACK_MATRIX;
671848b8605Smrg
672848b8605Smrg   case STATE_NUM_SAMPLES:
673848b8605Smrg      return _NEW_BUFFERS;
674848b8605Smrg
675848b8605Smrg   case STATE_DEPTH_RANGE:
676848b8605Smrg      return _NEW_VIEWPORT;
677848b8605Smrg
678848b8605Smrg   case STATE_FRAGMENT_PROGRAM:
679848b8605Smrg   case STATE_VERTEX_PROGRAM:
680848b8605Smrg      return _NEW_PROGRAM;
681848b8605Smrg
682848b8605Smrg   case STATE_NORMAL_SCALE:
683848b8605Smrg      return _NEW_MODELVIEW;
684848b8605Smrg
685848b8605Smrg   case STATE_INTERNAL:
686848b8605Smrg      switch (state[1]) {
687848b8605Smrg      case STATE_CURRENT_ATTRIB:
688848b8605Smrg         return _NEW_CURRENT_ATTRIB;
689848b8605Smrg      case STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED:
690848b8605Smrg         return _NEW_CURRENT_ATTRIB | _NEW_LIGHT | _NEW_BUFFERS;
691848b8605Smrg
692848b8605Smrg      case STATE_NORMAL_SCALE:
693848b8605Smrg         return _NEW_MODELVIEW;
694848b8605Smrg
695848b8605Smrg      case STATE_FOG_PARAMS_OPTIMIZED:
696848b8605Smrg	 return _NEW_FOG;
697848b8605Smrg      case STATE_POINT_SIZE_CLAMPED:
698848b8605Smrg         return _NEW_POINT | _NEW_MULTISAMPLE;
699848b8605Smrg      case STATE_LIGHT_SPOT_DIR_NORMALIZED:
700848b8605Smrg      case STATE_LIGHT_POSITION:
701848b8605Smrg      case STATE_LIGHT_POSITION_NORMALIZED:
702848b8605Smrg      case STATE_LIGHT_HALF_VECTOR:
703848b8605Smrg         return _NEW_LIGHT;
704848b8605Smrg
705848b8605Smrg      case STATE_PT_SCALE:
706848b8605Smrg      case STATE_PT_BIAS:
707848b8605Smrg         return _NEW_PIXEL;
708848b8605Smrg
709848b8605Smrg      case STATE_FB_SIZE:
710848b8605Smrg      case STATE_FB_WPOS_Y_TRANSFORM:
711848b8605Smrg         return _NEW_BUFFERS;
712848b8605Smrg
713b8e80941Smrg      case STATE_ADVANCED_BLENDING_MODE:
714b8e80941Smrg         return _NEW_COLOR;
715b8e80941Smrg
716848b8605Smrg      default:
717848b8605Smrg         /* unknown state indexes are silently ignored and
718848b8605Smrg         *  no flag set, since it is handled by the driver.
719848b8605Smrg         */
720848b8605Smrg	 return 0;
721848b8605Smrg      }
722848b8605Smrg
723848b8605Smrg   default:
724848b8605Smrg      _mesa_problem(NULL, "unexpected state[0] in make_state_flags()");
725848b8605Smrg      return 0;
726848b8605Smrg   }
727848b8605Smrg}
728848b8605Smrg
729848b8605Smrg
730848b8605Smrgstatic void
731848b8605Smrgappend(char *dst, const char *src)
732848b8605Smrg{
733848b8605Smrg   while (*dst)
734848b8605Smrg      dst++;
735848b8605Smrg   while (*src)
736848b8605Smrg     *dst++ = *src++;
737848b8605Smrg   *dst = 0;
738848b8605Smrg}
739848b8605Smrg
740848b8605Smrg
741848b8605Smrg/**
742848b8605Smrg * Convert token 'k' to a string, append it onto 'dst' string.
743848b8605Smrg */
744848b8605Smrgstatic void
745848b8605Smrgappend_token(char *dst, gl_state_index k)
746848b8605Smrg{
747848b8605Smrg   switch (k) {
748848b8605Smrg   case STATE_MATERIAL:
749848b8605Smrg      append(dst, "material");
750848b8605Smrg      break;
751848b8605Smrg   case STATE_LIGHT:
752848b8605Smrg      append(dst, "light");
753848b8605Smrg      break;
754848b8605Smrg   case STATE_LIGHTMODEL_AMBIENT:
755848b8605Smrg      append(dst, "lightmodel.ambient");
756848b8605Smrg      break;
757848b8605Smrg   case STATE_LIGHTMODEL_SCENECOLOR:
758848b8605Smrg      break;
759848b8605Smrg   case STATE_LIGHTPROD:
760848b8605Smrg      append(dst, "lightprod");
761848b8605Smrg      break;
762848b8605Smrg   case STATE_TEXGEN:
763848b8605Smrg      append(dst, "texgen");
764848b8605Smrg      break;
765848b8605Smrg   case STATE_FOG_COLOR:
766848b8605Smrg      append(dst, "fog.color");
767848b8605Smrg      break;
768848b8605Smrg   case STATE_FOG_PARAMS:
769848b8605Smrg      append(dst, "fog.params");
770848b8605Smrg      break;
771848b8605Smrg   case STATE_CLIPPLANE:
772848b8605Smrg      append(dst, "clip");
773848b8605Smrg      break;
774848b8605Smrg   case STATE_POINT_SIZE:
775848b8605Smrg      append(dst, "point.size");
776848b8605Smrg      break;
777848b8605Smrg   case STATE_POINT_ATTENUATION:
778848b8605Smrg      append(dst, "point.attenuation");
779848b8605Smrg      break;
780848b8605Smrg   case STATE_MODELVIEW_MATRIX:
781848b8605Smrg      append(dst, "matrix.modelview");
782848b8605Smrg      break;
783848b8605Smrg   case STATE_PROJECTION_MATRIX:
784848b8605Smrg      append(dst, "matrix.projection");
785848b8605Smrg      break;
786848b8605Smrg   case STATE_MVP_MATRIX:
787848b8605Smrg      append(dst, "matrix.mvp");
788848b8605Smrg      break;
789848b8605Smrg   case STATE_TEXTURE_MATRIX:
790848b8605Smrg      append(dst, "matrix.texture");
791848b8605Smrg      break;
792848b8605Smrg   case STATE_PROGRAM_MATRIX:
793848b8605Smrg      append(dst, "matrix.program");
794848b8605Smrg      break;
795848b8605Smrg   case STATE_MATRIX_INVERSE:
796848b8605Smrg      append(dst, ".inverse");
797848b8605Smrg      break;
798848b8605Smrg   case STATE_MATRIX_TRANSPOSE:
799848b8605Smrg      append(dst, ".transpose");
800848b8605Smrg      break;
801848b8605Smrg   case STATE_MATRIX_INVTRANS:
802848b8605Smrg      append(dst, ".invtrans");
803848b8605Smrg      break;
804848b8605Smrg   case STATE_AMBIENT:
805848b8605Smrg      append(dst, ".ambient");
806848b8605Smrg      break;
807848b8605Smrg   case STATE_DIFFUSE:
808848b8605Smrg      append(dst, ".diffuse");
809848b8605Smrg      break;
810848b8605Smrg   case STATE_SPECULAR:
811848b8605Smrg      append(dst, ".specular");
812848b8605Smrg      break;
813848b8605Smrg   case STATE_EMISSION:
814848b8605Smrg      append(dst, ".emission");
815848b8605Smrg      break;
816848b8605Smrg   case STATE_SHININESS:
817848b8605Smrg      append(dst, "lshininess");
818848b8605Smrg      break;
819848b8605Smrg   case STATE_HALF_VECTOR:
820848b8605Smrg      append(dst, ".half");
821848b8605Smrg      break;
822848b8605Smrg   case STATE_POSITION:
823848b8605Smrg      append(dst, ".position");
824848b8605Smrg      break;
825848b8605Smrg   case STATE_ATTENUATION:
826848b8605Smrg      append(dst, ".attenuation");
827848b8605Smrg      break;
828848b8605Smrg   case STATE_SPOT_DIRECTION:
829848b8605Smrg      append(dst, ".spot.direction");
830848b8605Smrg      break;
831848b8605Smrg   case STATE_SPOT_CUTOFF:
832848b8605Smrg      append(dst, ".spot.cutoff");
833848b8605Smrg      break;
834848b8605Smrg   case STATE_TEXGEN_EYE_S:
835848b8605Smrg      append(dst, ".eye.s");
836848b8605Smrg      break;
837848b8605Smrg   case STATE_TEXGEN_EYE_T:
838848b8605Smrg      append(dst, ".eye.t");
839848b8605Smrg      break;
840848b8605Smrg   case STATE_TEXGEN_EYE_R:
841848b8605Smrg      append(dst, ".eye.r");
842848b8605Smrg      break;
843848b8605Smrg   case STATE_TEXGEN_EYE_Q:
844848b8605Smrg      append(dst, ".eye.q");
845848b8605Smrg      break;
846848b8605Smrg   case STATE_TEXGEN_OBJECT_S:
847848b8605Smrg      append(dst, ".object.s");
848848b8605Smrg      break;
849848b8605Smrg   case STATE_TEXGEN_OBJECT_T:
850848b8605Smrg      append(dst, ".object.t");
851848b8605Smrg      break;
852848b8605Smrg   case STATE_TEXGEN_OBJECT_R:
853848b8605Smrg      append(dst, ".object.r");
854848b8605Smrg      break;
855848b8605Smrg   case STATE_TEXGEN_OBJECT_Q:
856848b8605Smrg      append(dst, ".object.q");
857848b8605Smrg      break;
858848b8605Smrg   case STATE_TEXENV_COLOR:
859848b8605Smrg      append(dst, "texenv");
860848b8605Smrg      break;
861848b8605Smrg   case STATE_NUM_SAMPLES:
862848b8605Smrg      append(dst, "numsamples");
863848b8605Smrg      break;
864848b8605Smrg   case STATE_DEPTH_RANGE:
865848b8605Smrg      append(dst, "depth.range");
866848b8605Smrg      break;
867848b8605Smrg   case STATE_VERTEX_PROGRAM:
868848b8605Smrg   case STATE_FRAGMENT_PROGRAM:
869848b8605Smrg      break;
870848b8605Smrg   case STATE_ENV:
871848b8605Smrg      append(dst, "env");
872848b8605Smrg      break;
873848b8605Smrg   case STATE_LOCAL:
874848b8605Smrg      append(dst, "local");
875848b8605Smrg      break;
876848b8605Smrg   /* BEGIN internal state vars */
877848b8605Smrg   case STATE_INTERNAL:
878848b8605Smrg      append(dst, ".internal.");
879848b8605Smrg      break;
880848b8605Smrg   case STATE_CURRENT_ATTRIB:
881848b8605Smrg      append(dst, "current");
882848b8605Smrg      break;
883848b8605Smrg   case STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED:
884848b8605Smrg      append(dst, "currentAttribMaybeVPClamped");
885848b8605Smrg      break;
886848b8605Smrg   case STATE_NORMAL_SCALE:
887848b8605Smrg      append(dst, "normalScale");
888848b8605Smrg      break;
889848b8605Smrg   case STATE_FOG_PARAMS_OPTIMIZED:
890848b8605Smrg      append(dst, "fogParamsOptimized");
891848b8605Smrg      break;
892848b8605Smrg   case STATE_POINT_SIZE_CLAMPED:
893848b8605Smrg      append(dst, "pointSizeClamped");
894848b8605Smrg      break;
895848b8605Smrg   case STATE_LIGHT_SPOT_DIR_NORMALIZED:
896848b8605Smrg      append(dst, "lightSpotDirNormalized");
897848b8605Smrg      break;
898848b8605Smrg   case STATE_LIGHT_POSITION:
899848b8605Smrg      append(dst, "lightPosition");
900848b8605Smrg      break;
901848b8605Smrg   case STATE_LIGHT_POSITION_NORMALIZED:
902848b8605Smrg      append(dst, "light.position.normalized");
903848b8605Smrg      break;
904848b8605Smrg   case STATE_LIGHT_HALF_VECTOR:
905848b8605Smrg      append(dst, "lightHalfVector");
906848b8605Smrg      break;
907848b8605Smrg   case STATE_PT_SCALE:
908848b8605Smrg      append(dst, "PTscale");
909848b8605Smrg      break;
910848b8605Smrg   case STATE_PT_BIAS:
911848b8605Smrg      append(dst, "PTbias");
912848b8605Smrg      break;
913848b8605Smrg   case STATE_FB_SIZE:
914848b8605Smrg      append(dst, "FbSize");
915848b8605Smrg      break;
916848b8605Smrg   case STATE_FB_WPOS_Y_TRANSFORM:
917848b8605Smrg      append(dst, "FbWposYTransform");
918848b8605Smrg      break;
919b8e80941Smrg   case STATE_ADVANCED_BLENDING_MODE:
920b8e80941Smrg      append(dst, "AdvancedBlendingMode");
921b8e80941Smrg      break;
922848b8605Smrg   default:
923848b8605Smrg      /* probably STATE_INTERNAL_DRIVER+i (driver private state) */
924848b8605Smrg      append(dst, "driverState");
925848b8605Smrg   }
926848b8605Smrg}
927848b8605Smrg
928848b8605Smrgstatic void
929848b8605Smrgappend_face(char *dst, GLint face)
930848b8605Smrg{
931848b8605Smrg   if (face == 0)
932848b8605Smrg      append(dst, "front.");
933848b8605Smrg   else
934848b8605Smrg      append(dst, "back.");
935848b8605Smrg}
936848b8605Smrg
937848b8605Smrgstatic void
938848b8605Smrgappend_index(char *dst, GLint index)
939848b8605Smrg{
940848b8605Smrg   char s[20];
941848b8605Smrg   sprintf(s, "[%d]", index);
942848b8605Smrg   append(dst, s);
943848b8605Smrg}
944848b8605Smrg
945848b8605Smrg/**
946848b8605Smrg * Make a string from the given state vector.
947848b8605Smrg * For example, return "state.matrix.texture[2].inverse".
948848b8605Smrg * Use free() to deallocate the string.
949848b8605Smrg */
950848b8605Smrgchar *
951b8e80941Smrg_mesa_program_state_string(const gl_state_index16 state[STATE_LENGTH])
952848b8605Smrg{
953848b8605Smrg   char str[1000] = "";
954848b8605Smrg   char tmp[30];
955848b8605Smrg
956848b8605Smrg   append(str, "state.");
957848b8605Smrg   append_token(str, state[0]);
958848b8605Smrg
959848b8605Smrg   switch (state[0]) {
960848b8605Smrg   case STATE_MATERIAL:
961848b8605Smrg      append_face(str, state[1]);
962848b8605Smrg      append_token(str, state[2]);
963848b8605Smrg      break;
964848b8605Smrg   case STATE_LIGHT:
965848b8605Smrg      append_index(str, state[1]); /* light number [i]. */
966848b8605Smrg      append_token(str, state[2]); /* coefficients */
967848b8605Smrg      break;
968848b8605Smrg   case STATE_LIGHTMODEL_AMBIENT:
969848b8605Smrg      append(str, "lightmodel.ambient");
970848b8605Smrg      break;
971848b8605Smrg   case STATE_LIGHTMODEL_SCENECOLOR:
972848b8605Smrg      if (state[1] == 0) {
973848b8605Smrg         append(str, "lightmodel.front.scenecolor");
974848b8605Smrg      }
975848b8605Smrg      else {
976848b8605Smrg         append(str, "lightmodel.back.scenecolor");
977848b8605Smrg      }
978848b8605Smrg      break;
979848b8605Smrg   case STATE_LIGHTPROD:
980848b8605Smrg      append_index(str, state[1]); /* light number [i]. */
981848b8605Smrg      append_face(str, state[2]);
982848b8605Smrg      append_token(str, state[3]);
983848b8605Smrg      break;
984848b8605Smrg   case STATE_TEXGEN:
985848b8605Smrg      append_index(str, state[1]); /* tex unit [i] */
986848b8605Smrg      append_token(str, state[2]); /* plane coef */
987848b8605Smrg      break;
988848b8605Smrg   case STATE_TEXENV_COLOR:
989848b8605Smrg      append_index(str, state[1]); /* tex unit [i] */
990848b8605Smrg      append(str, "color");
991848b8605Smrg      break;
992848b8605Smrg   case STATE_CLIPPLANE:
993848b8605Smrg      append_index(str, state[1]); /* plane [i] */
994848b8605Smrg      append(str, ".plane");
995848b8605Smrg      break;
996848b8605Smrg   case STATE_MODELVIEW_MATRIX:
997848b8605Smrg   case STATE_PROJECTION_MATRIX:
998848b8605Smrg   case STATE_MVP_MATRIX:
999848b8605Smrg   case STATE_TEXTURE_MATRIX:
1000848b8605Smrg   case STATE_PROGRAM_MATRIX:
1001848b8605Smrg      {
1002848b8605Smrg         /* state[0] = modelview, projection, texture, etc. */
1003848b8605Smrg         /* state[1] = which texture matrix or program matrix */
1004848b8605Smrg         /* state[2] = first row to fetch */
1005848b8605Smrg         /* state[3] = last row to fetch */
1006848b8605Smrg         /* state[4] = transpose, inverse or invtrans */
1007848b8605Smrg         const gl_state_index mat = state[0];
1008848b8605Smrg         const GLuint index = (GLuint) state[1];
1009848b8605Smrg         const GLuint firstRow = (GLuint) state[2];
1010848b8605Smrg         const GLuint lastRow = (GLuint) state[3];
1011848b8605Smrg         const gl_state_index modifier = state[4];
1012848b8605Smrg         if (index ||
1013848b8605Smrg             mat == STATE_TEXTURE_MATRIX ||
1014848b8605Smrg             mat == STATE_PROGRAM_MATRIX)
1015848b8605Smrg            append_index(str, index);
1016848b8605Smrg         if (modifier)
1017848b8605Smrg            append_token(str, modifier);
1018848b8605Smrg         if (firstRow == lastRow)
1019848b8605Smrg            sprintf(tmp, ".row[%d]", firstRow);
1020848b8605Smrg         else
1021848b8605Smrg            sprintf(tmp, ".row[%d..%d]", firstRow, lastRow);
1022848b8605Smrg         append(str, tmp);
1023848b8605Smrg      }
1024848b8605Smrg      break;
1025848b8605Smrg   case STATE_POINT_SIZE:
1026848b8605Smrg      break;
1027848b8605Smrg   case STATE_POINT_ATTENUATION:
1028848b8605Smrg      break;
1029848b8605Smrg   case STATE_FOG_PARAMS:
1030848b8605Smrg      break;
1031848b8605Smrg   case STATE_FOG_COLOR:
1032848b8605Smrg      break;
1033848b8605Smrg   case STATE_NUM_SAMPLES:
1034848b8605Smrg      break;
1035848b8605Smrg   case STATE_DEPTH_RANGE:
1036848b8605Smrg      break;
1037848b8605Smrg   case STATE_FRAGMENT_PROGRAM:
1038848b8605Smrg   case STATE_VERTEX_PROGRAM:
1039848b8605Smrg      /* state[1] = {STATE_ENV, STATE_LOCAL} */
1040848b8605Smrg      /* state[2] = parameter index          */
1041848b8605Smrg      append_token(str, state[1]);
1042848b8605Smrg      append_index(str, state[2]);
1043848b8605Smrg      break;
1044848b8605Smrg   case STATE_NORMAL_SCALE:
1045848b8605Smrg      break;
1046848b8605Smrg   case STATE_INTERNAL:
1047848b8605Smrg      append_token(str, state[1]);
1048848b8605Smrg      if (state[1] == STATE_CURRENT_ATTRIB)
1049848b8605Smrg         append_index(str, state[2]);
1050848b8605Smrg       break;
1051848b8605Smrg   default:
1052848b8605Smrg      _mesa_problem(NULL, "Invalid state in _mesa_program_state_string");
1053848b8605Smrg      break;
1054848b8605Smrg   }
1055848b8605Smrg
1056b8e80941Smrg   return strdup(str);
1057848b8605Smrg}
1058848b8605Smrg
1059848b8605Smrg
1060848b8605Smrg/**
1061848b8605Smrg * Loop over all the parameters in a parameter list.  If the parameter
1062848b8605Smrg * is a GL state reference, look up the current value of that state
1063848b8605Smrg * variable and put it into the parameter's Value[4] array.
1064848b8605Smrg * Other parameter types never change or are explicitly set by the user
1065848b8605Smrg * with glUniform() or glProgramParameter(), etc.
1066848b8605Smrg * This would be called at glBegin time.
1067848b8605Smrg */
1068848b8605Smrgvoid
1069848b8605Smrg_mesa_load_state_parameters(struct gl_context *ctx,
1070848b8605Smrg                            struct gl_program_parameter_list *paramList)
1071848b8605Smrg{
1072848b8605Smrg   GLuint i;
1073848b8605Smrg
1074848b8605Smrg   if (!paramList)
1075848b8605Smrg      return;
1076848b8605Smrg
1077848b8605Smrg   for (i = 0; i < paramList->NumParameters; i++) {
1078848b8605Smrg      if (paramList->Parameters[i].Type == PROGRAM_STATE_VAR) {
1079b8e80941Smrg         unsigned pvo = paramList->ParameterValueOffset[i];
1080848b8605Smrg         _mesa_fetch_state(ctx,
1081848b8605Smrg			   paramList->Parameters[i].StateIndexes,
1082b8e80941Smrg                           paramList->ParameterValues + pvo);
1083848b8605Smrg      }
1084848b8605Smrg   }
1085848b8605Smrg}
1086