OSDN Git Service

Merge commit 'origin/master' into gallium-0.2
[android-x86/external-mesa.git] / src / mesa / shader / prog_statevars.c
1 /*
2  * Mesa 3-D graphics library
3  * Version:  7.1
4  *
5  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11  * and/or sell copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included
15  * in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24
25 /**
26  * \file prog_statevars.c
27  * Program state variable management.
28  * \author Brian Paul
29  */
30
31
32 #include "main/glheader.h"
33 #include "main/context.h"
34 #include "main/hash.h"
35 #include "main/imports.h"
36 #include "main/macros.h"
37 #include "main/mtypes.h"
38 #include "prog_statevars.h"
39 #include "prog_parameter.h"
40
41
42 /**
43  * Use the list of tokens in the state[] array to find global GL state
44  * and return it in <value>.  Usually, four values are returned in <value>
45  * but matrix queries may return as many as 16 values.
46  * This function is used for ARB vertex/fragment programs.
47  * The program parser will produce the state[] values.
48  */
49 static void
50 _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[],
51                   GLfloat *value)
52 {
53    switch (state[0]) {
54    case STATE_MATERIAL:
55       {
56          /* state[1] is either 0=front or 1=back side */
57          const GLuint face = (GLuint) state[1];
58          const struct gl_material *mat = &ctx->Light.Material;
59          ASSERT(face == 0 || face == 1);
60          /* we rely on tokens numbered so that _BACK_ == _FRONT_+ 1 */
61          ASSERT(MAT_ATTRIB_FRONT_AMBIENT + 1 == MAT_ATTRIB_BACK_AMBIENT);
62          /* XXX we could get rid of this switch entirely with a little
63           * work in arbprogparse.c's parse_state_single_item().
64           */
65          /* state[2] is the material attribute */
66          switch (state[2]) {
67          case STATE_AMBIENT:
68             COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_AMBIENT + face]);
69             return;
70          case STATE_DIFFUSE:
71             COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_DIFFUSE + face]);
72             return;
73          case STATE_SPECULAR:
74             COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_SPECULAR + face]);
75             return;
76          case STATE_EMISSION:
77             COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_EMISSION + face]);
78             return;
79          case STATE_SHININESS:
80             value[0] = mat->Attrib[MAT_ATTRIB_FRONT_SHININESS + face][0];
81             value[1] = 0.0F;
82             value[2] = 0.0F;
83             value[3] = 1.0F;
84             return;
85          default:
86             _mesa_problem(ctx, "Invalid material state in fetch_state");
87             return;
88          }
89       }
90    case STATE_LIGHT:
91       {
92          /* state[1] is the light number */
93          const GLuint ln = (GLuint) state[1];
94          /* state[2] is the light attribute */
95          switch (state[2]) {
96          case STATE_AMBIENT:
97             COPY_4V(value, ctx->Light.Light[ln].Ambient);
98             return;
99          case STATE_DIFFUSE:
100             COPY_4V(value, ctx->Light.Light[ln].Diffuse);
101             return;
102          case STATE_SPECULAR:
103             COPY_4V(value, ctx->Light.Light[ln].Specular);
104             return;
105          case STATE_POSITION:
106             COPY_4V(value, ctx->Light.Light[ln].EyePosition);
107             return;
108          case STATE_ATTENUATION:
109             value[0] = ctx->Light.Light[ln].ConstantAttenuation;
110             value[1] = ctx->Light.Light[ln].LinearAttenuation;
111             value[2] = ctx->Light.Light[ln].QuadraticAttenuation;
112             value[3] = ctx->Light.Light[ln].SpotExponent;
113             return;
114          case STATE_SPOT_DIRECTION:
115             COPY_3V(value, ctx->Light.Light[ln].EyeDirection);
116             value[3] = ctx->Light.Light[ln]._CosCutoff;
117             return;
118          case STATE_SPOT_CUTOFF:
119             value[0] = ctx->Light.Light[ln].SpotCutoff;
120             return;
121          case STATE_HALF_VECTOR:
122             {
123                static const GLfloat eye_z[] = {0, 0, 1};
124                GLfloat p[3];
125                /* Compute infinite half angle vector:
126                 *   halfVector = normalize(normalize(lightPos) + (0, 0, 1))
127                 * light.EyePosition.w should be 0 for infinite lights.
128                 */
129                COPY_3V(p, ctx->Light.Light[ln].EyePosition);
130                NORMALIZE_3FV(p);
131                ADD_3V(value, p, eye_z);
132                NORMALIZE_3FV(value);
133                value[3] = 1.0;
134             }
135             return;
136          default:
137             _mesa_problem(ctx, "Invalid light state in fetch_state");
138             return;
139          }
140       }
141    case STATE_LIGHTMODEL_AMBIENT:
142       COPY_4V(value, ctx->Light.Model.Ambient);
143       return;
144    case STATE_LIGHTMODEL_SCENECOLOR:
145       if (state[1] == 0) {
146          /* front */
147          GLint i;
148          for (i = 0; i < 3; i++) {
149             value[i] = ctx->Light.Model.Ambient[i]
150                * ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT][i]
151                + ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION][i];
152          }
153          value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
154       }
155       else {
156          /* back */
157          GLint i;
158          for (i = 0; i < 3; i++) {
159             value[i] = ctx->Light.Model.Ambient[i]
160                * ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_AMBIENT][i]
161                + ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_EMISSION][i];
162          }
163          value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
164       }
165       return;
166    case STATE_LIGHTPROD:
167       {
168          const GLuint ln = (GLuint) state[1];
169          const GLuint face = (GLuint) state[2];
170          GLint i;
171          ASSERT(face == 0 || face == 1);
172          switch (state[3]) {
173             case STATE_AMBIENT:
174                for (i = 0; i < 3; i++) {
175                   value[i] = ctx->Light.Light[ln].Ambient[i] *
176                      ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT+face][i];
177                }
178                /* [3] = material alpha */
179                value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT+face][3];
180                return;
181             case STATE_DIFFUSE:
182                for (i = 0; i < 3; i++) {
183                   value[i] = ctx->Light.Light[ln].Diffuse[i] *
184                      ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][i];
185                }
186                /* [3] = material alpha */
187                value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][3];
188                return;
189             case STATE_SPECULAR:
190                for (i = 0; i < 3; i++) {
191                   value[i] = ctx->Light.Light[ln].Specular[i] *
192                      ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SPECULAR+face][i];
193                }
194                /* [3] = material alpha */
195                value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SPECULAR+face][3];
196                return;
197             default:
198                _mesa_problem(ctx, "Invalid lightprod state in fetch_state");
199                return;
200          }
201       }
202    case STATE_TEXGEN:
203       {
204          /* state[1] is the texture unit */
205          const GLuint unit = (GLuint) state[1];
206          /* state[2] is the texgen attribute */
207          switch (state[2]) {
208          case STATE_TEXGEN_EYE_S:
209             COPY_4V(value, ctx->Texture.Unit[unit].EyePlaneS);
210             return;
211          case STATE_TEXGEN_EYE_T:
212             COPY_4V(value, ctx->Texture.Unit[unit].EyePlaneT);
213             return;
214          case STATE_TEXGEN_EYE_R:
215             COPY_4V(value, ctx->Texture.Unit[unit].EyePlaneR);
216             return;
217          case STATE_TEXGEN_EYE_Q:
218             COPY_4V(value, ctx->Texture.Unit[unit].EyePlaneQ);
219             return;
220          case STATE_TEXGEN_OBJECT_S:
221             COPY_4V(value, ctx->Texture.Unit[unit].ObjectPlaneS);
222             return;
223          case STATE_TEXGEN_OBJECT_T:
224             COPY_4V(value, ctx->Texture.Unit[unit].ObjectPlaneT);
225             return;
226          case STATE_TEXGEN_OBJECT_R:
227             COPY_4V(value, ctx->Texture.Unit[unit].ObjectPlaneR);
228             return;
229          case STATE_TEXGEN_OBJECT_Q:
230             COPY_4V(value, ctx->Texture.Unit[unit].ObjectPlaneQ);
231             return;
232          default:
233             _mesa_problem(ctx, "Invalid texgen state in fetch_state");
234             return;
235          }
236       }
237    case STATE_TEXENV_COLOR:
238       {
239          /* state[1] is the texture unit */
240          const GLuint unit = (GLuint) state[1];
241          COPY_4V(value, ctx->Texture.Unit[unit].EnvColor);
242       }
243       return;
244    case STATE_FOG_COLOR:
245       COPY_4V(value, ctx->Fog.Color);
246       return;
247    case STATE_FOG_PARAMS:
248       value[0] = ctx->Fog.Density;
249       value[1] = ctx->Fog.Start;
250       value[2] = ctx->Fog.End;
251       value[3] = (ctx->Fog.End == ctx->Fog.Start)
252          ? 1.0f : (GLfloat)(1.0 / (ctx->Fog.End - ctx->Fog.Start));
253       return;
254    case STATE_CLIPPLANE:
255       {
256          const GLuint plane = (GLuint) state[1];
257          COPY_4V(value, ctx->Transform.EyeUserPlane[plane]);
258       }
259       return;
260    case STATE_POINT_SIZE:
261       value[0] = ctx->Point.Size;
262       value[1] = ctx->Point.MinSize;
263       value[2] = ctx->Point.MaxSize;
264       value[3] = ctx->Point.Threshold;
265       return;
266    case STATE_POINT_ATTENUATION:
267       value[0] = ctx->Point.Params[0];
268       value[1] = ctx->Point.Params[1];
269       value[2] = ctx->Point.Params[2];
270       value[3] = 1.0F;
271       return;
272    case STATE_MODELVIEW_MATRIX:
273    case STATE_PROJECTION_MATRIX:
274    case STATE_MVP_MATRIX:
275    case STATE_TEXTURE_MATRIX:
276    case STATE_PROGRAM_MATRIX:
277    case STATE_COLOR_MATRIX:
278       {
279          /* state[0] = modelview, projection, texture, etc. */
280          /* state[1] = which texture matrix or program matrix */
281          /* state[2] = first row to fetch */
282          /* state[3] = last row to fetch */
283          /* state[4] = transpose, inverse or invtrans */
284          const GLmatrix *matrix;
285          const gl_state_index mat = state[0];
286          const GLuint index = (GLuint) state[1];
287          const GLuint firstRow = (GLuint) state[2];
288          const GLuint lastRow = (GLuint) state[3];
289          const gl_state_index modifier = state[4];
290          const GLfloat *m;
291          GLuint row, i;
292          ASSERT(firstRow >= 0);
293          ASSERT(firstRow < 4);
294          ASSERT(lastRow >= 0);
295          ASSERT(lastRow < 4);
296          if (mat == STATE_MODELVIEW_MATRIX) {
297             matrix = ctx->ModelviewMatrixStack.Top;
298          }
299          else if (mat == STATE_PROJECTION_MATRIX) {
300             matrix = ctx->ProjectionMatrixStack.Top;
301          }
302          else if (mat == STATE_MVP_MATRIX) {
303             matrix = &ctx->_ModelProjectMatrix;
304          }
305          else if (mat == STATE_TEXTURE_MATRIX) {
306             matrix = ctx->TextureMatrixStack[index].Top;
307          }
308          else if (mat == STATE_PROGRAM_MATRIX) {
309             matrix = ctx->ProgramMatrixStack[index].Top;
310          }
311          else if (mat == STATE_COLOR_MATRIX) {
312             matrix = ctx->ColorMatrixStack.Top;
313          }
314          else {
315             _mesa_problem(ctx, "Bad matrix name in _mesa_fetch_state()");
316             return;
317          }
318          if (modifier == STATE_MATRIX_INVERSE ||
319              modifier == STATE_MATRIX_INVTRANS) {
320             /* Be sure inverse is up to date:
321              */
322             _math_matrix_alloc_inv( (GLmatrix *) matrix );
323             _math_matrix_analyse( (GLmatrix*) matrix );
324             m = matrix->inv;
325          }
326          else {
327             m = matrix->m;
328          }
329          if (modifier == STATE_MATRIX_TRANSPOSE ||
330              modifier == STATE_MATRIX_INVTRANS) {
331             for (i = 0, row = firstRow; row <= lastRow; row++) {
332                value[i++] = m[row * 4 + 0];
333                value[i++] = m[row * 4 + 1];
334                value[i++] = m[row * 4 + 2];
335                value[i++] = m[row * 4 + 3];
336             }
337          }
338          else {
339             for (i = 0, row = firstRow; row <= lastRow; row++) {
340                value[i++] = m[row + 0];
341                value[i++] = m[row + 4];
342                value[i++] = m[row + 8];
343                value[i++] = m[row + 12];
344             }
345          }
346       }
347       return;
348    case STATE_DEPTH_RANGE:
349       value[0] = ctx->Viewport.Near;                     /* near       */
350       value[1] = ctx->Viewport.Far;                      /* far        */
351       value[2] = ctx->Viewport.Far - ctx->Viewport.Near; /* far - near */
352       value[3] = 1.0;
353       return;
354    case STATE_FRAGMENT_PROGRAM:
355       {
356          /* state[1] = {STATE_ENV, STATE_LOCAL} */
357          /* state[2] = parameter index          */
358          const int idx = (int) state[2];
359          switch (state[1]) {
360             case STATE_ENV:
361                COPY_4V(value, ctx->FragmentProgram.Parameters[idx]);
362                break;
363             case STATE_LOCAL:
364                COPY_4V(value, ctx->FragmentProgram.Current->Base.LocalParams[idx]);
365                break;
366             default:
367                _mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()");
368                return;
369          }
370       }
371       return;
372
373    case STATE_VERTEX_PROGRAM:
374       {
375          /* state[1] = {STATE_ENV, STATE_LOCAL} */
376          /* state[2] = parameter index          */
377          const int idx = (int) state[2];
378          switch (state[1]) {
379             case STATE_ENV:
380                COPY_4V(value, ctx->VertexProgram.Parameters[idx]);
381                break;
382             case STATE_LOCAL:
383                COPY_4V(value, ctx->VertexProgram.Current->Base.LocalParams[idx]);
384                break;
385             default:
386                _mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()");
387                return;
388          }
389       }
390       return;
391
392    case STATE_NORMAL_SCALE:
393       ASSIGN_4V(value, ctx->_ModelViewInvScale, 0, 0, 1);
394       return;
395
396    case STATE_INTERNAL:
397       switch (state[1]) {
398       case STATE_CURRENT_ATTRIB: {
399          const GLuint idx = (GLuint) state[2];
400          COPY_4V(value, ctx->Current.Attrib[idx]);
401          return;
402       }                                           
403
404       case STATE_NORMAL_SCALE:
405          ASSIGN_4V(value, 
406                    ctx->_ModelViewInvScale, 
407                    ctx->_ModelViewInvScale, 
408                    ctx->_ModelViewInvScale, 
409                    1);
410          return;
411       case STATE_TEXRECT_SCALE:
412          {
413             const int unit = (int) state[2];
414             const struct gl_texture_object *texObj
415                = ctx->Texture.Unit[unit]._Current;
416             if (texObj) {
417                struct gl_texture_image *texImage = texObj->Image[0][0];
418                ASSIGN_4V(value, (GLfloat) (1.0 / texImage->Width),
419                          (GLfloat)(1.0 / texImage->Height),
420                          0.0f, 1.0f);
421             }
422          }
423          return;
424       case STATE_FOG_PARAMS_OPTIMIZED:
425          /* for simpler per-vertex/pixel fog calcs. POW (for EXP/EXP2 fog)
426           * might be more expensive than EX2 on some hw, plus it needs
427           * another constant (e) anyway. Linear fog can now be done with a
428           * single MAD.
429           * linear: fogcoord * -1/(end-start) + end/(end-start)
430           * exp: 2^-(density/ln(2) * fogcoord)
431           * exp2: 2^-((density/(ln(2)^2) * fogcoord)^2)
432           */
433          value[0] = (ctx->Fog.End == ctx->Fog.Start)
434             ? 1.0f : (GLfloat)(-1.0F / (ctx->Fog.End - ctx->Fog.Start));
435          value[1] = ctx->Fog.End * -value[0];
436          value[2] = (GLfloat)(ctx->Fog.Density * ONE_DIV_LN2);
437          value[3] = (GLfloat)(ctx->Fog.Density * ONE_DIV_SQRT_LN2);
438          return;
439
440       case STATE_LIGHT_SPOT_DIR_NORMALIZED: {
441          /* here, state[2] is the light number */
442          /* pre-normalize spot dir */
443          const GLuint ln = (GLuint) state[2];
444          COPY_3V(value, ctx->Light.Light[ln]._NormDirection);
445          value[3] = ctx->Light.Light[ln]._CosCutoff;
446          return;
447       }
448
449       case STATE_LIGHT_POSITION: {
450          const GLuint ln = (GLuint) state[2];
451          COPY_4V(value, ctx->Light.Light[ln]._Position);
452          return;
453       }
454
455       case STATE_LIGHT_POSITION_NORMALIZED: {
456          const GLuint ln = (GLuint) state[2];
457          COPY_4V(value, ctx->Light.Light[ln]._Position);
458          NORMALIZE_3FV( value );
459          return;
460       }
461
462       case STATE_LIGHT_HALF_VECTOR: {
463          const GLuint ln = (GLuint) state[2];
464          GLfloat p[3];
465          /* Compute infinite half angle vector:
466           *   halfVector = normalize(normalize(lightPos) + (0, 0, 1))
467           * light.EyePosition.w should be 0 for infinite lights.
468           */
469          COPY_3V(p, ctx->Light.Light[ln]._Position);
470          NORMALIZE_3FV(p);
471          ADD_3V(value, p, ctx->_EyeZDir);
472          NORMALIZE_3FV(value);
473          value[3] = 1.0;
474          return;
475       }                                           
476
477
478       case STATE_PT_SCALE:
479          value[0] = ctx->Pixel.RedScale;
480          value[1] = ctx->Pixel.GreenScale;
481          value[2] = ctx->Pixel.BlueScale;
482          value[3] = ctx->Pixel.AlphaScale;
483          break;
484       case STATE_PT_BIAS:
485          value[0] = ctx->Pixel.RedBias;
486          value[1] = ctx->Pixel.GreenBias;
487          value[2] = ctx->Pixel.BlueBias;
488          value[3] = ctx->Pixel.AlphaBias;
489          break;
490       case STATE_PCM_SCALE:
491          COPY_4V(value, ctx->Pixel.PostColorMatrixScale);
492          break;
493       case STATE_PCM_BIAS:
494          COPY_4V(value, ctx->Pixel.PostColorMatrixBias);
495          break;
496       case STATE_SHADOW_AMBIENT:
497          {
498             const int unit = (int) state[2];
499             const struct gl_texture_object *texObj
500                = ctx->Texture.Unit[unit]._Current;
501             if (texObj) {
502                value[0] = texObj->ShadowAmbient;
503                value[1] = texObj->ShadowAmbient;
504                value[2] = texObj->ShadowAmbient;
505                value[3] = texObj->ShadowAmbient;
506             }
507          }
508          return;
509
510          /* XXX: make sure new tokens added here are also handled in the 
511           * _mesa_program_state_flags() switch, below.
512           */
513       default:
514          /* unknown state indexes are silently ignored
515           *  should be handled by the driver.
516           */
517          return;
518       }
519       return;
520
521    default:
522       _mesa_problem(ctx, "Invalid state in _mesa_fetch_state");
523       return;
524    }
525 }
526
527
528 /**
529  * Return a bitmask of the Mesa state flags (_NEW_* values) which would
530  * indicate that the given context state may have changed.
531  * The bitmask is used during validation to determine if we need to update
532  * vertex/fragment program parameters (like "state.material.color") when
533  * some GL state has changed.
534  */
535 GLbitfield
536 _mesa_program_state_flags(const gl_state_index state[STATE_LENGTH])
537 {
538    switch (state[0]) {
539    case STATE_MATERIAL:
540    case STATE_LIGHT:
541    case STATE_LIGHTMODEL_AMBIENT:
542    case STATE_LIGHTMODEL_SCENECOLOR:
543    case STATE_LIGHTPROD:
544       return _NEW_LIGHT;
545
546    case STATE_TEXGEN:
547    case STATE_TEXENV_COLOR:
548       return _NEW_TEXTURE;
549
550    case STATE_FOG_COLOR:
551    case STATE_FOG_PARAMS:
552       return _NEW_FOG;
553
554    case STATE_CLIPPLANE:
555       return _NEW_TRANSFORM;
556
557    case STATE_POINT_SIZE:
558    case STATE_POINT_ATTENUATION:
559       return _NEW_POINT;
560
561    case STATE_MODELVIEW_MATRIX:
562       return _NEW_MODELVIEW;
563    case STATE_PROJECTION_MATRIX:
564       return _NEW_PROJECTION;
565    case STATE_MVP_MATRIX:
566       return _NEW_MODELVIEW | _NEW_PROJECTION;
567    case STATE_TEXTURE_MATRIX:
568       return _NEW_TEXTURE_MATRIX;
569    case STATE_PROGRAM_MATRIX:
570       return _NEW_TRACK_MATRIX;
571    case STATE_COLOR_MATRIX:
572       return _NEW_COLOR_MATRIX;
573
574    case STATE_DEPTH_RANGE:
575       return _NEW_VIEWPORT;
576
577    case STATE_FRAGMENT_PROGRAM:
578    case STATE_VERTEX_PROGRAM:
579       return _NEW_PROGRAM;
580
581    case STATE_NORMAL_SCALE:
582       return _NEW_MODELVIEW;
583
584    case STATE_INTERNAL:
585       switch (state[1]) {
586       case STATE_CURRENT_ATTRIB:
587          return _NEW_CURRENT_ATTRIB;
588
589       case STATE_NORMAL_SCALE:
590          return _NEW_MODELVIEW;
591
592       case STATE_TEXRECT_SCALE:
593       case STATE_SHADOW_AMBIENT:
594          return _NEW_TEXTURE;
595       case STATE_FOG_PARAMS_OPTIMIZED:
596          return _NEW_FOG;
597       case STATE_LIGHT_SPOT_DIR_NORMALIZED:
598       case STATE_LIGHT_POSITION:
599       case STATE_LIGHT_POSITION_NORMALIZED:
600       case STATE_LIGHT_HALF_VECTOR:
601          return _NEW_LIGHT;
602
603       case STATE_PT_SCALE:
604       case STATE_PT_BIAS:
605       case STATE_PCM_SCALE:
606       case STATE_PCM_BIAS:
607          return _NEW_PIXEL;
608
609       default:
610          /* unknown state indexes are silently ignored and
611          *  no flag set, since it is handled by the driver.
612          */
613          return 0;
614       }
615
616    default:
617       _mesa_problem(NULL, "unexpected state[0] in make_state_flags()");
618       return 0;
619    }
620 }
621
622
623 static void
624 append(char *dst, const char *src)
625 {
626    while (*dst)
627       dst++;
628    while (*src)
629      *dst++ = *src++;
630    *dst = 0;
631 }
632
633
634 /**
635  * Convert token 'k' to a string, append it onto 'dst' string.
636  */
637 static void
638 append_token(char *dst, gl_state_index k)
639 {
640    switch (k) {
641    case STATE_MATERIAL:
642       append(dst, "material");
643       break;
644    case STATE_LIGHT:
645       append(dst, "light");
646       break;
647    case STATE_LIGHTMODEL_AMBIENT:
648       append(dst, "lightmodel.ambient");
649       break;
650    case STATE_LIGHTMODEL_SCENECOLOR:
651       break;
652    case STATE_LIGHTPROD:
653       append(dst, "lightprod");
654       break;
655    case STATE_TEXGEN:
656       append(dst, "texgen");
657       break;
658    case STATE_FOG_COLOR:
659       append(dst, "fog.color");
660       break;
661    case STATE_FOG_PARAMS:
662       append(dst, "fog.params");
663       break;
664    case STATE_CLIPPLANE:
665       append(dst, "clip");
666       break;
667    case STATE_POINT_SIZE:
668       append(dst, "point.size");
669       break;
670    case STATE_POINT_ATTENUATION:
671       append(dst, "point.attenuation");
672       break;
673    case STATE_MODELVIEW_MATRIX:
674       append(dst, "matrix.modelview");
675       break;
676    case STATE_PROJECTION_MATRIX:
677       append(dst, "matrix.projection");
678       break;
679    case STATE_MVP_MATRIX:
680       append(dst, "matrix.mvp");
681       break;
682    case STATE_TEXTURE_MATRIX:
683       append(dst, "matrix.texture");
684       break;
685    case STATE_PROGRAM_MATRIX:
686       append(dst, "matrix.program");
687       break;
688    case STATE_COLOR_MATRIX:
689       append(dst, "matrix.color");
690       break;
691    case STATE_MATRIX_INVERSE:
692       append(dst, ".inverse");
693       break;
694    case STATE_MATRIX_TRANSPOSE:
695       append(dst, ".transpose");
696       break;
697    case STATE_MATRIX_INVTRANS:
698       append(dst, ".invtrans");
699       break;
700    case STATE_AMBIENT:
701       append(dst, ".ambient");
702       break;
703    case STATE_DIFFUSE:
704       append(dst, ".diffuse");
705       break;
706    case STATE_SPECULAR:
707       append(dst, ".specular");
708       break;
709    case STATE_EMISSION:
710       append(dst, ".emission");
711       break;
712    case STATE_SHININESS:
713       append(dst, "lshininess");
714       break;
715    case STATE_HALF_VECTOR:
716       append(dst, ".half");
717       break;
718    case STATE_POSITION:
719       append(dst, ".position");
720       break;
721    case STATE_ATTENUATION:
722       append(dst, ".attenuation");
723       break;
724    case STATE_SPOT_DIRECTION:
725       append(dst, ".spot.direction");
726       break;
727    case STATE_SPOT_CUTOFF:
728       append(dst, ".spot.cutoff");
729       break;
730    case STATE_TEXGEN_EYE_S:
731       append(dst, "eye.s");
732       break;
733    case STATE_TEXGEN_EYE_T:
734       append(dst, "eye.t");
735       break;
736    case STATE_TEXGEN_EYE_R:
737       append(dst, "eye.r");
738       break;
739    case STATE_TEXGEN_EYE_Q:
740       append(dst, "eye.q");
741       break;
742    case STATE_TEXGEN_OBJECT_S:
743       append(dst, "object.s");
744       break;
745    case STATE_TEXGEN_OBJECT_T:
746       append(dst, "object.t");
747       break;
748    case STATE_TEXGEN_OBJECT_R:
749       append(dst, "object.r");
750       break;
751    case STATE_TEXGEN_OBJECT_Q:
752       append(dst, "object.q");
753       break;
754    case STATE_TEXENV_COLOR:
755       append(dst, "texenv");
756       break;
757    case STATE_DEPTH_RANGE:
758       append(dst, "depth.range");
759       break;
760    case STATE_VERTEX_PROGRAM:
761    case STATE_FRAGMENT_PROGRAM:
762       break;
763    case STATE_ENV:
764       append(dst, "env");
765       break;
766    case STATE_LOCAL:
767       append(dst, "local");
768       break;
769    /* BEGIN internal state vars */
770    case STATE_INTERNAL:
771       append(dst, "(internal)");
772       break;
773    case STATE_NORMAL_SCALE:
774       append(dst, "normalScale");
775       break;
776    case STATE_TEXRECT_SCALE:
777       append(dst, "texrectScale");
778       break;
779    case STATE_FOG_PARAMS_OPTIMIZED:
780       append(dst, "fogParamsOptimized");
781       break;
782    case STATE_LIGHT_SPOT_DIR_NORMALIZED:
783       append(dst, "lightSpotDirNormalized");
784       break;
785    case STATE_LIGHT_POSITION:
786       append(dst, "lightPosition");
787       break;
788    case STATE_LIGHT_POSITION_NORMALIZED:
789       append(dst, "light.position.normalized");
790       break;
791    case STATE_LIGHT_HALF_VECTOR:
792       append(dst, "lightHalfVector");
793       break;
794    case STATE_PT_SCALE:
795       append(dst, "PTscale");
796       break;
797    case STATE_PT_BIAS:
798       append(dst, "PTbias");
799       break;
800    case STATE_PCM_SCALE:
801       append(dst, "PCMscale");
802       break;
803    case STATE_PCM_BIAS:
804       append(dst, "PCMbias");
805       break;
806    case STATE_SHADOW_AMBIENT:
807       append(dst, "ShadowAmbient");
808       break;
809    default:
810       /* probably STATE_INTERNAL_DRIVER+i (driver private state) */
811       append(dst, "driverState");
812    }
813 }
814
815 static void
816 append_face(char *dst, GLint face)
817 {
818    if (face == 0)
819       append(dst, "front.");
820    else
821       append(dst, "back.");
822 }
823
824 static void
825 append_index(char *dst, GLint index)
826 {
827    char s[20];
828    _mesa_sprintf(s, "[%d]", index);
829    append(dst, s);
830 }
831
832 /**
833  * Make a string from the given state vector.
834  * For example, return "state.matrix.texture[2].inverse".
835  * Use _mesa_free() to deallocate the string.
836  */
837 char *
838 _mesa_program_state_string(const gl_state_index state[STATE_LENGTH])
839 {
840    char str[1000] = "";
841    char tmp[30];
842
843    append(str, "state.");
844    append_token(str, state[0]);
845
846    switch (state[0]) {
847    case STATE_MATERIAL:
848       append_face(str, state[1]);
849       append_token(str, state[2]);
850       break;
851    case STATE_LIGHT:
852       append_index(str, state[1]); /* light number [i]. */
853       append_token(str, state[2]); /* coefficients */
854       break;
855    case STATE_LIGHTMODEL_AMBIENT:
856       append(str, "lightmodel.ambient");
857       break;
858    case STATE_LIGHTMODEL_SCENECOLOR:
859       if (state[1] == 0) {
860          append(str, "lightmodel.front.scenecolor");
861       }
862       else {
863          append(str, "lightmodel.back.scenecolor");
864       }
865       break;
866    case STATE_LIGHTPROD:
867       append_index(str, state[1]); /* light number [i]. */
868       append_face(str, state[2]);
869       append_token(str, state[3]);
870       break;
871    case STATE_TEXGEN:
872       append_index(str, state[1]); /* tex unit [i] */
873       append_token(str, state[2]); /* plane coef */
874       break;
875    case STATE_TEXENV_COLOR:
876       append_index(str, state[1]); /* tex unit [i] */
877       append(str, "color");
878       break;
879    case STATE_CLIPPLANE:
880       append_index(str, state[1]); /* plane [i] */
881       append(str, ".plane");
882       break;
883    case STATE_MODELVIEW_MATRIX:
884    case STATE_PROJECTION_MATRIX:
885    case STATE_MVP_MATRIX:
886    case STATE_TEXTURE_MATRIX:
887    case STATE_PROGRAM_MATRIX:
888    case STATE_COLOR_MATRIX:
889       {
890          /* state[0] = modelview, projection, texture, etc. */
891          /* state[1] = which texture matrix or program matrix */
892          /* state[2] = first row to fetch */
893          /* state[3] = last row to fetch */
894          /* state[4] = transpose, inverse or invtrans */
895          const gl_state_index mat = state[0];
896          const GLuint index = (GLuint) state[1];
897          const GLuint firstRow = (GLuint) state[2];
898          const GLuint lastRow = (GLuint) state[3];
899          const gl_state_index modifier = state[4];
900          if (index ||
901              mat == STATE_TEXTURE_MATRIX ||
902              mat == STATE_PROGRAM_MATRIX)
903             append_index(str, index);
904          if (modifier)
905             append_token(str, modifier);
906          if (firstRow == lastRow)
907             _mesa_sprintf(tmp, ".row[%d]", firstRow);
908          else
909             _mesa_sprintf(tmp, ".row[%d..%d]", firstRow, lastRow);
910          append(str, tmp);
911       }
912       break;
913    case STATE_POINT_SIZE:
914       break;
915    case STATE_POINT_ATTENUATION:
916       break;
917    case STATE_FOG_PARAMS:
918       break;
919    case STATE_FOG_COLOR:
920       break;
921    case STATE_DEPTH_RANGE:
922       break;
923    case STATE_FRAGMENT_PROGRAM:
924    case STATE_VERTEX_PROGRAM:
925       /* state[1] = {STATE_ENV, STATE_LOCAL} */
926       /* state[2] = parameter index          */
927       append_token(str, state[1]);
928       append_index(str, state[2]);
929       break;
930    case STATE_INTERNAL:
931       append_token(str, state[1]);
932       break;
933    default:
934       _mesa_problem(NULL, "Invalid state in _mesa_program_state_string");
935       break;
936    }
937
938    return _mesa_strdup(str);
939 }
940
941
942 /**
943  * Loop over all the parameters in a parameter list.  If the parameter
944  * is a GL state reference, look up the current value of that state
945  * variable and put it into the parameter's Value[4] array.
946  * This would be called at glBegin time when using a fragment program.
947  */
948 void
949 _mesa_load_state_parameters(GLcontext *ctx,
950                             struct gl_program_parameter_list *paramList)
951 {
952    GLuint i;
953
954    if (!paramList)
955       return;
956
957    /*assert(ctx->Driver.NeedFlush == 0);*/
958
959    for (i = 0; i < paramList->NumParameters; i++) {
960       if (paramList->Parameters[i].Type == PROGRAM_STATE_VAR) {
961          _mesa_fetch_state(ctx,
962                            (gl_state_index *) paramList->Parameters[i].StateIndexes,
963                            paramList->ParameterValues[i]);
964       }
965    }
966 }
967
968
969 /**
970  * Copy the 16 elements of a matrix into four consecutive program
971  * registers starting at 'pos'.
972  */
973 static void
974 load_matrix(GLfloat registers[][4], GLuint pos, const GLfloat mat[16])
975 {
976    GLuint i;
977    for (i = 0; i < 4; i++) {
978       registers[pos + i][0] = mat[0 + i];
979       registers[pos + i][1] = mat[4 + i];
980       registers[pos + i][2] = mat[8 + i];
981       registers[pos + i][3] = mat[12 + i];
982    }
983 }
984
985
986 /**
987  * As above, but transpose the matrix.
988  */
989 static void
990 load_transpose_matrix(GLfloat registers[][4], GLuint pos,
991                       const GLfloat mat[16])
992 {
993    MEMCPY(registers[pos], mat, 16 * sizeof(GLfloat));
994 }
995
996
997 /**
998  * Load current vertex program's parameter registers with tracked
999  * matrices (if NV program).  This only needs to be done per
1000  * glBegin/glEnd, not per-vertex.
1001  */
1002 void
1003 _mesa_load_tracked_matrices(GLcontext *ctx)
1004 {
1005    GLuint i;
1006
1007    for (i = 0; i < MAX_NV_VERTEX_PROGRAM_PARAMS / 4; i++) {
1008       /* point 'mat' at source matrix */
1009       GLmatrix *mat;
1010       if (ctx->VertexProgram.TrackMatrix[i] == GL_MODELVIEW) {
1011          mat = ctx->ModelviewMatrixStack.Top;
1012       }
1013       else if (ctx->VertexProgram.TrackMatrix[i] == GL_PROJECTION) {
1014          mat = ctx->ProjectionMatrixStack.Top;
1015       }
1016       else if (ctx->VertexProgram.TrackMatrix[i] == GL_TEXTURE) {
1017          mat = ctx->TextureMatrixStack[ctx->Texture.CurrentUnit].Top;
1018       }
1019       else if (ctx->VertexProgram.TrackMatrix[i] == GL_COLOR) {
1020          mat = ctx->ColorMatrixStack.Top;
1021       }
1022       else if (ctx->VertexProgram.TrackMatrix[i]==GL_MODELVIEW_PROJECTION_NV) {
1023          /* XXX verify the combined matrix is up to date */
1024          mat = &ctx->_ModelProjectMatrix;
1025       }
1026       else if (ctx->VertexProgram.TrackMatrix[i] >= GL_MATRIX0_NV &&
1027                ctx->VertexProgram.TrackMatrix[i] <= GL_MATRIX7_NV) {
1028          GLuint n = ctx->VertexProgram.TrackMatrix[i] - GL_MATRIX0_NV;
1029          ASSERT(n < MAX_PROGRAM_MATRICES);
1030          mat = ctx->ProgramMatrixStack[n].Top;
1031       }
1032       else {
1033          /* no matrix is tracked, but we leave the register values as-is */
1034          assert(ctx->VertexProgram.TrackMatrix[i] == GL_NONE);
1035          continue;
1036       }
1037
1038       /* load the matrix values into sequential registers */
1039       if (ctx->VertexProgram.TrackMatrixTransform[i] == GL_IDENTITY_NV) {
1040          load_matrix(ctx->VertexProgram.Parameters, i*4, mat->m);
1041       }
1042       else if (ctx->VertexProgram.TrackMatrixTransform[i] == GL_INVERSE_NV) {
1043          _math_matrix_analyse(mat); /* update the inverse */
1044          ASSERT(!_math_matrix_is_dirty(mat));
1045          load_matrix(ctx->VertexProgram.Parameters, i*4, mat->inv);
1046       }
1047       else if (ctx->VertexProgram.TrackMatrixTransform[i] == GL_TRANSPOSE_NV) {
1048          load_transpose_matrix(ctx->VertexProgram.Parameters, i*4, mat->m);
1049       }
1050       else {
1051          assert(ctx->VertexProgram.TrackMatrixTransform[i]
1052                 == GL_INVERSE_TRANSPOSE_NV);
1053          _math_matrix_analyse(mat); /* update the inverse */
1054          ASSERT(!_math_matrix_is_dirty(mat));
1055          load_transpose_matrix(ctx->VertexProgram.Parameters, i*4, mat->inv);
1056       }
1057    }
1058 }