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