Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

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