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