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