OSDN Git Service

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