merge from master
authorBrian <brian@yutani.localnet.net>
Wed, 21 Mar 2007 17:57:30 +0000 (11:57 -0600)
committerBrian <brian@yutani.localnet.net>
Wed, 21 Mar 2007 17:57:30 +0000 (11:57 -0600)
25 files changed:
1  2 
docs/relnotes-6.5.3.html
src/mesa/drivers/dri/i915/i915_state.c
src/mesa/drivers/dri/i915/i915_vtbl.c
src/mesa/drivers/dri/i915tex/i915_state.c
src/mesa/drivers/dri/i965/brw_vs_tnl.c
src/mesa/drivers/dri/nouveau/nouveau_context.c
src/mesa/drivers/dri/nouveau/nouveau_shader.c
src/mesa/drivers/dri/nouveau/nouveau_shader_0.c
src/mesa/drivers/dri/nouveau/nouveau_shader_2.c
src/mesa/drivers/dri/r300/r300_fragprog.c
src/mesa/drivers/dri/r300/r300_state.c
src/mesa/drivers/dri/r300/r300_vertprog.c
src/mesa/main/colortab.c
src/mesa/main/get.c
src/mesa/main/get_gen.py
src/mesa/main/mtypes.h
src/mesa/main/pixel.c
src/mesa/shader/nvvertparse.c
src/mesa/shader/prog_instruction.c
src/mesa/shader/prog_instruction.h
src/mesa/shader/programopt.c
src/mesa/swrast/s_copypix.c
src/mesa/swrast/s_drawpix.c
src/mesa/swrast/s_readpix.c
src/mesa/tnl/t_vp_build.c

diff --combined docs/relnotes-6.5.3.html
index 5bde4e00c0214e158512f4046924d34ba7c786e7,b3d2fe64556b5365ff5a8bc7e6d96910f2711aee..27053c071b825e20d2eaa62f113ed09a964e8fa2
@@@ -11,7 -11,8 +11,7 @@@
  <H1>Mesa 6.5.3 Release Notes / (in progress)</H1>
  
  <p>
 -Mesa 6.5.3 is a 6.5 follow-on development release mostly consisting of
 -bug fixes</a>.
 +Mesa 6.5.3 is a 6.5 follow-on development release with many internal changes.
  </p>
  
  
@@@ -23,12 -24,8 +23,14 @@@ TB
  
  <h2>New features</h2>
  <ul>
 +<li>OpenGL 2.0 support.
 +<li>Entirely new Shading Language code generator.
 +<li>Much faster software execution of vertex, fragment shaders.
 +<li>New vertex buffer object infrastructure (replaces old array_cache code).
  <li>Updated glext.h file (version 39)
  <li>Updated glxext.h file (version 18)
++<li>GL_MAX_DRAWBUFFERS is now 4 (software rendering) so
++    "multiple render targets" are really supported.
  </ul>
  
  <h2>Bug fixes</h2>
  <li>Fog was errantly applied when a fragment shader was enabled (bug 9346)
  <li>glPush/PopClientAttrib didn't handle VBO bindings correctly (bug 9445)
  <li>With 32-bit Z buffer, the fragment Z of lines and points was sometimes wrong.
- <li>GL_MAX_DRAWBUFFERS is now 4 (software rendering) so
-     "multiple render targets" are really supported.
 +<li>GL_POST_CONVOLUTION_ALPHA_BIAS/SCALE was broken.
+ <li>1D convolution state could effect 2D image transfers
  </ul>
  
  
  <h2>Internal code changes</h2>
  
  <ul>
 +<li>Massive changes to the Shading Language compiler.
  <li>The _MaintainTnlProgram, _MaintainTexEnvProgram, _TexEnvProgram and
  _TnlProgram fields have been moved.
  <li>The ctx->FragmentProgram._Active field has been removed.
@@@ -59,6 -53,7 +60,6 @@@ fixed-function program
  <h2>To Do (someday) items</h2>
  <ul>
  <li>Switch to freeglut
 -<li>Increase MAX_DRAWBUFFERS
  <li>Fix linux-glide target/driver.
  <li>Improved lambda and derivative calculation for frag progs.
  </ul>
@@@ -70,8 -65,8 +71,8 @@@
  Driver                        Status
  ----------------------        ----------------------
  DRI drivers           varies with the driver
 -XMesa/GLX (on Xlib)   implements OpenGL 1.5
 -OSMesa (off-screen)   implements OpenGL 1.5
 +XMesa/GLX (on Xlib)   implements OpenGL 2.0
 +OSMesa (off-screen)   implements OpenGL 2.0
  Glide (3dfx Voodoo1/2)        implements OpenGL 1.3
  SVGA                  implements OpenGL 1.3
  Wind River UGL                implements OpenGL 1.3
index 56922893366fbd0d3cca8f830479819729146556,5e00e6597b055189b59a25c40d0ab8bd05a25b12..d126208ce05fc3d6698dea998f429d02640412e3
@@@ -531,7 -531,7 +531,7 @@@ void i915_update_fog( GLcontext *ctx 
     GLboolean enabled;
     GLboolean try_pixel_fog;
     
 -   if (ctx->FragmentProgram._Active) {
 +   if (ctx->FragmentProgram._Enabled) {
        /* Pull in static fog state from program */
        
        mode = ctx->FragmentProgram._Current->FogOption;
@@@ -813,7 -813,7 +813,7 @@@ static void i915_init_packets( i915Cont
                                       I1_LOAD_S(4) |
                                       I1_LOAD_S(5) |
                                       I1_LOAD_S(6) | 
-                                      (4));
+                                      (3));
        i915->state.Ctx[I915_CTXREG_LIS2] = 0;
        i915->state.Ctx[I915_CTXREG_LIS4] = 0;
        i915->state.Ctx[I915_CTXREG_LIS5] = 0;
index 82a421b961c65ed6c9b63996a1c5ef908342976d,b533e153beb03f7eb0283f9603a54df63eec23a3..c920fc47ea0dd90b6c73fb12d821d4310f2245cf
@@@ -46,10 -46,10 +46,10 @@@ static void i915_render_start( intelCon
     GLcontext *ctx = &intel->ctx;
     i915ContextPtr i915 = I915_CONTEXT(intel);
  
 -   if (ctx->FragmentProgram._Active
 +   if (ctx->FragmentProgram._Current
        i915ValidateFragmentProgram( i915 );
     else {
 -      assert(!ctx->_MaintainTexEnvProgram);
 +      assert(!ctx->FragmentProgram._MaintainTexEnvProgram);
        i915ValidateTextureProgram( i915 );
     }
  }
@@@ -180,7 -180,7 +180,7 @@@ static void i915_emit_invarient_state( 
      */
     OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | 
             I1_LOAD_S(3) |
-            (1));
+            (0));
     OUT_BATCH(0);
   
     /* XXX: Use this */
index 4816afc9343bbb54c1cb4ae7cd36f2c84f165f44,1fafadced020ea36be40e4273e860aafed11c2b6..c2c2ff366f107cbe01f8a848d2410ad302243223
@@@ -561,7 -561,7 +561,7 @@@ i915_update_fog(GLcontext * ctx
     GLboolean enabled;
     GLboolean try_pixel_fog;
  
 -   if (ctx->FragmentProgram._Active) {
 +   if (ctx->FragmentProgram._Enabled) {
        /* Pull in static fog state from program */
  
        mode = ctx->FragmentProgram._Current->FogOption;
@@@ -859,7 -859,7 +859,7 @@@ i915_init_packets(struct i915_context *
        i915->state.Ctx[I915_CTXREG_LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
                                           I1_LOAD_S(2) |
                                           I1_LOAD_S(4) |
-                                          I1_LOAD_S(5) | I1_LOAD_S(6) | (4));
+                                          I1_LOAD_S(5) | I1_LOAD_S(6) | (3));
        i915->state.Ctx[I915_CTXREG_LIS2] = 0;
        i915->state.Ctx[I915_CTXREG_LIS4] = 0;
        i915->state.Ctx[I915_CTXREG_LIS5] = 0;
index 21e961ce9cdcdd4d5a1c914fa74aa7d813b7a79b,dd1664bf33ab2965d318d6d64b6aa926e206b8f4..35adc4846a0744aa7d899f7a338daf65f0c7aa82
  #include "glheader.h"
  #include "macros.h"
  #include "enums.h"
 +#include "shader/prog_parameter.h"
 +#include "shader/prog_print.h"
  #include "brw_vs.h"
  #include "brw_state.h"
  
 -#include "shader/program.h"
 -#include "shader/program_instruction.h"
 -#include "shader/arbprogparse.h"
  
  struct state_key {
     unsigned light_global_enabled:1;
@@@ -397,14 -398,11 +397,14 @@@ static struct ureg register_const4f( st
  {
     GLfloat values[4];
     GLint idx;
 +   GLuint swizzle;
     values[0] = s0;
     values[1] = s1;
     values[2] = s2;
     values[3] = s3;
 -   idx = _mesa_add_unnamed_constant( p->program->Base.Parameters, values, 4 );
 +   idx = _mesa_add_unnamed_constant( p->program->Base.Parameters, values, 4,
 +                                     &swizzle);
 +   /* XXX what about swizzle? */
     return make_ureg(PROGRAM_STATE_VAR, idx);
  }
  
@@@ -426,37 -424,40 +426,37 @@@ static struct ureg get_identity_param( 
     return p->identity;
  }
  
 -static struct ureg register_param6( struct tnl_program *p, 
 -                                 GLint s0,
 -                                 GLint s1,
 -                                 GLint s2,
 -                                 GLint s3,
 -                                 GLint s4,
 -                                 GLint s5)
 +static struct ureg register_param5( struct tnl_program *p, 
 +                                    GLint s0,
 +                                    GLint s1,
 +                                    GLint s2,
 +                                    GLint s3,
 +                                    GLint s4)
  {
 -   GLint tokens[6];
 +   gl_state_index tokens[STATE_LENGTH];
     GLint idx;
     tokens[0] = s0;
     tokens[1] = s1;
     tokens[2] = s2;
     tokens[3] = s3;
     tokens[4] = s4;
 -   tokens[5] = s5;
     idx = _mesa_add_state_reference( p->program->Base.Parameters, tokens );
     return make_ureg(PROGRAM_STATE_VAR, idx);
  }
  
  
 -#define register_param1(p,s0)          register_param6(p,s0,0,0,0,0,0)
 -#define register_param2(p,s0,s1)       register_param6(p,s0,s1,0,0,0,0)
 -#define register_param3(p,s0,s1,s2)    register_param6(p,s0,s1,s2,0,0,0)
 -#define register_param4(p,s0,s1,s2,s3) register_param6(p,s0,s1,s2,s3,0,0)
 +#define register_param1(p,s0)          register_param5(p,s0,0,0,0,0)
 +#define register_param2(p,s0,s1)       register_param5(p,s0,s1,0,0,0)
 +#define register_param3(p,s0,s1,s2)    register_param5(p,s0,s1,s2,0,0)
 +#define register_param4(p,s0,s1,s2,s3) register_param5(p,s0,s1,s2,s3,0)
  
  
 -static void register_matrix_param6( struct tnl_program *p,
 -                                  GLint s0,
 -                                  GLint s1,
 -                                  GLint s2,
 -                                  GLint s3,
 -                                  GLint s4,
 -                                  GLint s5,
 +static void register_matrix_param5( struct tnl_program *p,
 +                                  GLint s0, /* matrix name */
 +                                  GLint s1, /* texture matrix number */
 +                                  GLint s2, /* first row */
 +                                  GLint s3, /* last row */
 +                                  GLint s4, /* modifier */
                                    struct ureg *matrix )
  {
     GLint i;
     /* This is a bit sad as the support is there to pull the whole
      * matrix out in one go:
      */
 -   for (i = 0; i <= s4 - s3; i++) 
 -      matrix[i] = register_param6( p, s0, s1, s2, i, i, s5 );
 +   for (i = 0; i <= s3 - s2; i++) 
 +      matrix[i] = register_param5( p, s0, s1, i, i, s4 );
  }
  
  
@@@ -649,13 -650,13 +649,13 @@@ static struct ureg get_eye_position( st
        p->eye_position = reserve_temp(p);
  
        if (PREFER_DP4) {
 -       register_matrix_param6( p, STATE_MATRIX, STATE_MODELVIEW, 0, 0, 3, 
 -                               STATE_MATRIX, modelview );
 +       register_matrix_param5( p, STATE_MODELVIEW_MATRIX, 0, 0, 3, 
 +                               0, modelview );
  
         emit_matrix_transform_vec4(p, p->eye_position, modelview, pos);
        }
        else {
 -       register_matrix_param6( p, STATE_MATRIX, STATE_MODELVIEW, 0, 0, 3, 
 +       register_matrix_param5( p, STATE_MODELVIEW_MATRIX, 0, 0, 3, 
                                 STATE_MATRIX_TRANSPOSE, modelview );
  
         emit_transpose_matrix_transform_vec4(p, p->eye_position, modelview, pos);
@@@ -709,7 -710,7 +709,7 @@@ static struct ureg get_eye_normal( stru
        struct ureg normal = register_input(p, VERT_ATTRIB_NORMAL );
        struct ureg mvinv[3];
  
 -      register_matrix_param6( p, STATE_MATRIX, STATE_MODELVIEW, 0, 0, 2,
 +      register_matrix_param5( p, STATE_MODELVIEW_MATRIX, 0, 0, 2,
                              STATE_MATRIX_INVTRANS, mvinv );
  
        p->eye_normal = reserve_temp(p);
@@@ -744,12 -745,12 +744,12 @@@ static void build_hpos( struct tnl_prog
     struct ureg mvp[4];
  
     if (PREFER_DP4) {
 -      register_matrix_param6( p, STATE_MATRIX, STATE_MVP, 0, 0, 3, 
 -                            STATE_MATRIX, mvp );
 +      register_matrix_param5( p, STATE_MVP_MATRIX, 0, 0, 3, 
 +                            0, mvp );
        emit_matrix_transform_vec4( p, hpos, mvp, pos );
     }
     else {
 -      register_matrix_param6( p, STATE_MATRIX, STATE_MVP, 0, 0, 3, 
 +      register_matrix_param5( p, STATE_MVP_MATRIX, 0, 0, 3, 
                              STATE_MATRIX_TRANSPOSE, mvp );
        emit_transpose_matrix_transform_vec4( p, hpos, mvp, pos );
     }
@@@ -849,14 -850,13 +849,13 @@@ static struct ureg calculate_light_atte
     /* Calculate spot attenuation:
      */
     if (!p->state->unit[i].light_spotcutoff_is_180) {
-       struct ureg spot_dir = register_param3(p, STATE_LIGHT, i,
-                                            STATE_SPOT_DIRECTION);
+       struct ureg spot_dir_norm = register_param3(p, STATE_INTERNAL,
+                                                 STATE_SPOT_DIR_NORMALIZED, i);
        struct ureg spot = get_temp(p);
        struct ureg slt = get_temp(p);
-              
-       emit_normalize_vec3( p, spot, spot_dir ); /* XXX: precompute! */
-       emit_op2(p, OPCODE_DP3, spot, 0, ureg_negate(VPpli), spot);
-       emit_op2(p, OPCODE_SLT, slt, 0, swizzle1(spot_dir,W), spot);
+       emit_op2(p, OPCODE_DP3, spot, 0, ureg_negate(VPpli), spot_dir_norm);
+       emit_op2(p, OPCODE_SLT, slt, 0, swizzle1(spot_dir_norm,W), spot);
        emit_op2(p, OPCODE_POW, spot, 0, spot, swizzle1(attenuation, W));
        emit_op2(p, OPCODE_MUL, att, 0, slt, spot);
  
  
  
  /* Need to add some addtional parameters to allow lighting in object
-- * space - STATE_SPOT_DIRECTION and STATE_HALF implicitly assume eye
++ * space - STATE_SPOT_DIRECTION and STATE_HALF_VECTOR implicitly assume eye
   * space lighting.
   */
  static void build_lighting( struct tnl_program *p )
             */
            VPpli = register_param3(p, STATE_LIGHT, i, 
                                    STATE_POSITION_NORMALIZED); 
-           half = register_param3(p, STATE_LIGHT, i, STATE_HALF_VECTOR);
+             if (p->state->light_local_viewer) {
+                 struct ureg eye_hat = get_eye_position_normalized(p);
+                 half = get_temp(p);
+                 emit_op2(p, OPCODE_SUB, half, 0, VPpli, eye_hat);
+                 emit_normalize_vec3(p, half, half);
+             } else {
 -                half = register_param3(p, STATE_LIGHT, i, STATE_HALF);
++                half = register_param3(p, STATE_LIGHT, i, STATE_HALF_VECTOR);
+             }
         } 
         else {
            struct ureg Ppli = register_param3(p, STATE_LIGHT, i, 
@@@ -1158,7 -1165,8 +1164,8 @@@ static void build_fog( struct tnl_progr
  
     if (p->state->fog_option &&
         p->state->tnl_do_vertex_fog) {
-       struct ureg params = register_param1(p, STATE_FOG_PARAMS);
+       struct ureg params = register_param2(p, STATE_INTERNAL,
+                                          STATE_FOG_PARAMS_OPTIMIZED);
        struct ureg tmp = get_temp(p);
        struct ureg id = get_identity_param(p);
  
  
        switch (p->state->fog_option) {
        case FOG_LINEAR: {
-        emit_op1(p, OPCODE_ABS, tmp, 0, input); 
-        emit_op2(p, OPCODE_SUB, tmp, 0, swizzle1(params,Z), tmp); 
-        emit_op2(p, OPCODE_MUL, tmp, 0, tmp, swizzle1(params,W)); 
+        emit_op1(p, OPCODE_ABS, tmp, 0, input);
+        emit_op3(p, OPCODE_MAD, tmp, 0, tmp, swizzle1(params,X), swizzle1(params,Y));
         emit_op2(p, OPCODE_MAX, tmp, 0, tmp, swizzle1(id,X)); /* saturate */
         emit_op2(p, OPCODE_MIN, fog, WRITEMASK_X, tmp, swizzle1(id,W));
         break;
        }
        case FOG_EXP:
         emit_op1(p, OPCODE_ABS, tmp, 0, input); 
-        emit_op2(p, OPCODE_MUL, tmp, 0, tmp, swizzle1(params,X)); 
-        emit_op2(p, OPCODE_POW, fog, WRITEMASK_X, 
-                 register_const1f(p, M_E), ureg_negate(tmp)); 
+        emit_op2(p, OPCODE_MUL, tmp, 0, tmp, swizzle1(params,Z));
+        emit_op1(p, OPCODE_EX2, fog, WRITEMASK_X, ureg_negate(tmp));
         break;
        case FOG_EXP2:
-        emit_op2(p, OPCODE_MUL, tmp, 0, input, swizzle1(params,X)); 
+        emit_op2(p, OPCODE_MUL, tmp, 0, input, swizzle1(params,W));
         emit_op2(p, OPCODE_MUL, tmp, 0, tmp, tmp); 
-        emit_op2(p, OPCODE_POW, fog, WRITEMASK_X, 
-                 register_const1f(p, M_E), ureg_negate(tmp)); 
+        emit_op1(p, OPCODE_EX2, fog, WRITEMASK_X, ureg_negate(tmp));
         break;
        }
        
@@@ -1355,13 -1360,13 +1359,13 @@@ static void build_texture_transform( st
                              out_texgen : 
                              register_input(p, VERT_ATTRIB_TEX0+i));
            if (PREFER_DP4) {
 -             register_matrix_param6( p, STATE_MATRIX, STATE_TEXTURE, i, 
 -                                     0, 3, STATE_MATRIX, texmat );
 +             register_matrix_param5( p, STATE_TEXTURE_MATRIX, i, 0, 3,
 +                                     0, texmat );
               emit_matrix_transform_vec4( p, out, texmat, in );
            }
            else {
 -             register_matrix_param6( p, STATE_MATRIX, STATE_TEXTURE, i, 
 -                                     0, 3, STATE_MATRIX_TRANSPOSE, texmat );
 +             register_matrix_param5( p, STATE_TEXTURE_MATRIX, i, 0, 3,
 +                                     STATE_MATRIX_TRANSPOSE, texmat );
               emit_transpose_matrix_transform_vec4( p, out, texmat, in );
            }
         }
index 627679a14797ec01ef5df1d03a8402a8e4bbe3d8,f217c4404e9254356fd585d124f5e91f0213e301..8e11eb61342843a389090038de528ddae9eb31f7
@@@ -201,7 -201,7 +201,7 @@@ GLboolean nouveauCreateContext( const _
        nouveauShaderInitFuncs(ctx);
        /* Install Mesa's fixed-function texenv shader support */
        if (nmesa->screen->card->type >= NV_40)
 -              ctx->_MaintainTexEnvProgram = GL_TRUE;
 +              ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE;
  
        /* Initialize the swrast */
        _swrast_CreateContext( ctx );
@@@ -352,6 -352,7 +352,7 @@@ static void nouveauDoSwapBuffers(nouvea
                OUT_RING       (((box->y2 - box->y1) << 16) |
                                (box->x2 - box->x1));
        }
+       FIRE_RING();
  
        UNLOCK_HARDWARE(nmesa);
  #endif
index bee8d5a935440cefed58d2263322c78f7cc5bb51,3d5b6843a15db3efb100bdc5a6a1df3e05c45d3f..b6837c5de1412c1206f497692735102b0377cef9
  #include "enums.h"
  #include "extensions.h"
  
 -#include "program.h"
 +#include "shader/program.h"
 +#include "shader/prog_instruction.h"
 +/*#include "shader/arbprogparse.h"*/
  #include "tnl/tnl.h"
 -#include "shader/arbprogparse.h"
  
  #include "nouveau_context.h"
  #include "nouveau_shader.h"
@@@ -49,6 -48,7 +49,7 @@@
  static void
  nouveauBindProgram(GLcontext *ctx, GLenum target, struct gl_program *prog)
  {
+    NVSDBG("target=%s, prog=%p\n", _mesa_lookup_enum_by_nr(target), prog);
  }
  
  static struct gl_program *
@@@ -56,7 -56,10 +57,10 @@@ nouveauNewProgram(GLcontext *ctx, GLenu
  {
     nouveauShader *nvs;
  
+    NVSDBG("target=%s, id=%d\n", _mesa_lookup_enum_by_nr(target), id);
     nvs = CALLOC_STRUCT(_nouveauShader);
+    NVSDBG("prog=%p\n", nvs);
     switch (target) {
     case GL_VERTEX_PROGRAM_ARB:
        return _mesa_init_vertex_program(ctx, &nvs->mesa.vp, target, id);
@@@ -76,6 -79,8 +80,8 @@@ nouveauDeleteProgram(GLcontext *ctx, st
  {
     nouveauShader *nvs = (nouveauShader *)prog;
  
+    NVSDBG("prog=%p\n", prog);
     if (nvs->translated)
        FREE(nvs->program);
     _mesa_delete_program(ctx, prog);
@@@ -87,9 -92,13 +93,13 @@@ nouveauProgramStringNotify(GLcontext *c
  {
     nouveauShader *nvs = (nouveauShader *)prog;
  
+    NVSDBG("target=%s, prog=%p\n", _mesa_lookup_enum_by_nr(target), prog);
     if (nvs->translated)
        FREE(nvs->program);
-    nvs->translated = 0;
+    nvs->error      = GL_FALSE;
+    nvs->translated = GL_FALSE;
  
     _tnl_program_string(ctx, target, prog);
  }
@@@ -99,6 -108,8 +109,8 @@@ nouveauIsProgramNative(GLcontext * ctx
  {
     nouveauShader *nvs = (nouveauShader *)prog;
  
+    NVSDBG("target=%s, prog=%p\n", _mesa_lookup_enum_by_nr(target), prog);
     return nvs->translated;
  }
  
@@@ -109,6 -120,8 +121,8 @@@ nvsUpdateShader(GLcontext *ctx, nouveau
     struct gl_program_parameter_list *plist;
     int i;
  
+    NVSDBG("prog=%p\n", nvs);
     /* Translate to HW format now if necessary */
     if (!nvs->translated) {
        /* Mesa ASM shader -> nouveauShader */
index abba59dc0c26984229f26f73ba47bafea4ff0506,7c2e2b9443bff7415037be25ea33269f72a6fb65..8c203cc664baa6603e29c59723ca916ac7bc1718
  #include "macros.h"
  #include "enums.h"
  
 -#include "program.h"
 -#include "programopt.h"
 -#include "program_instruction.h"
 +#include "shader/prog_instruction.h"
 +#include "shader/prog_parameter.h"
 +#include "shader/prog_statevars.h"
 +#include "shader/programopt.h"
  
  #include "nouveau_context.h"
  #include "nouveau_shader.h"
@@@ -264,6 -263,23 +264,23 @@@ pass0_make_mask(GLuint mesa_mask
        return mask;
  }
  
+ static GLboolean
+ pass0_opcode_is_tex(enum prog_opcode op)
+ {
+       switch (op) {
+       case OPCODE_TEX:
+       case OPCODE_TXB:
+       case OPCODE_TXD:
+       case OPCODE_TXL:
+       case OPCODE_TXP:
+               return GL_TRUE;
+       default:
+               break;
+       }
+       return GL_FALSE;
+ }
  static nvsTexTarget
  pass0_make_tex_target(GLuint mesa)
  {
@@@ -412,10 -428,8 +429,10 @@@ pass0_fixup_swizzle(nvsPtr nvs, nvsFrag
  
        if (!rec->swzconst_done) {
                struct gl_program *prog = &nvs->mesa.vp.Base;
 +                GLuint swizzle;
                rec->swzconst_id = _mesa_add_unnamed_constant(prog->Parameters,
 -                                                            sc, 4);
 +                                                            sc, 4, &swizzle);
 +                /* XXX what about swizzle? */
                rec->swzconst_done = 1;
                COPY_4V(nvs->params[rec->swzconst_id].val, sc);
        }
@@@ -724,7 -738,11 +741,11 @@@ pass0_translate_arith(nouveauShader *nv
                                (inst->SaturateMode != SATURATE_OFF),
                                src[0], src[1], src[2]);
                nvsinst->tex_unit   = inst->TexSrcUnit;
-               nvsinst->tex_target = pass0_make_tex_target(inst->TexSrcTarget);
+               if (pass0_opcode_is_tex(inst->Opcode))
+                       nvsinst->tex_target =
+                               pass0_make_tex_target(inst->TexSrcTarget);
+               else
+                       nvsinst->tex_target = NVS_TEX_TARGET_UNKNOWN;
  
                ret = GL_TRUE;
        } else
@@@ -821,8 -839,7 +842,8 @@@ pass0_vp_insert_ff_clip_planes(GLcontex
        nvsInstruction *nvsinst;
        GLuint fpos = 0;
        nvsRegister opos, epos, eqn, mv[4];
 -      GLint tokens[6] = { STATE_MATRIX, STATE_MODELVIEW, 0, 0, 0, 0 };
 +      gl_state_index tokens[STATE_LENGTH]
 +           = { STATE_MODELVIEW_MATRIX, 0, 0, 0, 0 };
        GLint id;
        int i;
  
        pass0_make_reg(nvs, &opos, NVS_FILE_ATTRIB, NVS_FR_POSITION);
        pass0_make_reg(nvs, &epos, NVS_FILE_TEMP  , -1);
        for (i=0; i<4; i++) {
 -              tokens[3] = tokens[4] = i;
 +              tokens[2] = tokens[3] = i;
                id = _mesa_add_state_reference(prog->Parameters, tokens);
                pass0_make_reg(nvs, &mv[i], NVS_FILE_CONST, id);
        }
@@@ -907,7 -924,7 +928,7 @@@ pass0_rebase_mesa_consts(nouveauShader 
        }
  }
  
- static void
+ static GLboolean
  pass0_resolve_mesa_consts(nouveauShader *nvs)
  {
        struct pass0_rec *rec = nvs->pass_rec;
        for (i=0; i<plist->NumParameters; i++) {
                int hw = rec->mesa_const_base + i;
  
+               if (hw > NVS_MAX_CONSTS) {
+                       nvsProgramError(nvs, "hw = %d > NVS_MAX_CONSTS!\n", hw);
+                       return GL_FALSE;
+               }
                switch (plist->Parameters[i].Type) {
                case PROGRAM_NAMED_PARAM:
                case PROGRAM_STATE_VAR:
                        COPY_4V(nvs->params[hw].val, plist->ParameterValues[i]);
                        break;
                default:
-                       assert(0);
-                       break;
+                       nvsProgramError(nvs, "hit bad type=%d on param %d\n",
+                                       plist->Parameters[i].Type, i);
+                       return GL_FALSE;
                }
        }
+       return GL_TRUE;
  }
  
  GLboolean
@@@ -957,6 -982,16 +986,16 @@@ nouveau_shader_pass0(GLcontext *ctx, no
        struct pass0_rec *rec;
        int ret = GL_FALSE;
  
+       NVSDBG("start: nvs=%p\n", nvs);
+       /* Previously detected an error, and haven't recieved new program
+        * string, so fail immediately.
+        */
+       if (nvs->error) {
+               NVSDBG("failed previous compile attempt, not retrying\n");
+               return GL_FALSE;
+       }
        rec = CALLOC_STRUCT(pass0_rec);
        if (!rec)
                return GL_FALSE;
  
        ret = pass0_translate_instructions(nvs, 0, 0, nvs->program_tree);
        if (ret)
-               pass0_resolve_mesa_consts(nvs);
+               ret = pass0_resolve_mesa_consts(nvs);   
+       
        /*XXX: if (!ret) DESTROY TREE!!! */
  
        FREE(rec);
index 6eb9de477699b5561fb0d6e393e96645dd2f98a1,130ef35e57b84b5f48881664ca3e772eaa9b28e3..cd27daca88b088a9c8c03a8a98114fbaddcedec8
@@@ -34,8 -34,7 +34,8 @@@
  #include "macros.h"
  #include "enums.h"
  
 -#include "program.h"
 +#include "shader/prog_parameter.h"
 +#include "shader/prog_print.h"
  
  #include "nouveau_context.h"
  #include "nouveau_shader.h"
@@@ -210,6 -209,8 +210,8 @@@ nouveau_shader_pass2(nvsPtr nvs
        struct pass2_rec *rec;
        int i;
  
+       NVSDBG("start: nvs=%p\n", nvs);
        rec = calloc(1, sizeof(struct pass2_rec));
        for (i=0; i<NVS_MAX_TEMPS; i++)
                rec->temps[i] = -1;
index f18a982debef24ca7a32a9a130d379c3ec229352,0d7d1f1af296571e04058d3e6049a9176b3b13e4..c407dfb5b0bc1a98fccfb36cbe22a0a802f7c360
  #include "glheader.h"
  #include "macros.h"
  #include "enums.h"
 +#include "shader/prog_instruction.h"
 +#include "shader/prog_parameter.h"
 +#include "shader/prog_print.h"
  
 -#include "program.h"
 -#include "program_instruction.h"
  #include "r300_context.h"
  #include "r300_fragprog.h"
  #include "r300_reg.h"
+ #include "r300_state.h"
  
  /*
   * Usefull macros and values
@@@ -94,8 -94,9 +95,9 @@@
  #define REG_NEGV_SHIFT                18
  #define REG_NEGS_SHIFT                19
  #define REG_ABS_SHIFT         20
- #define REG_NO_USE_SHIFT      21
- #define REG_VALID_SHIFT               22
+ #define REG_NO_USE_SHIFT      21 // Hack for refcounting
+ #define REG_VALID_SHIFT               22 // Does the register contain a defined value?
+ #define REG_BUILTIN_SHIFT   23 // Is it a builtin (like all zero/all one)?
  
  #define REG_TYPE_MASK         (0x03 << REG_TYPE_SHIFT)
  #define REG_INDEX_MASK                (0x3F << REG_INDEX_SHIFT)
  #define REG_ABS_MASK          (0x01 << REG_ABS_SHIFT)
  #define REG_NO_USE_MASK               (0x01 << REG_NO_USE_SHIFT)
  #define REG_VALID_MASK                (0x01 << REG_VALID_SHIFT)
+ #define REG_BUILTIN_MASK      (0x01 << REG_BUILTIN_SHIFT)
  
- #define REG(type, index, vswz, sswz, nouse, valid)                    \
+ #define REG(type, index, vswz, sswz, nouse, valid, builtin)   \
        (((type << REG_TYPE_SHIFT) & REG_TYPE_MASK) |                   \
         ((index << REG_INDEX_SHIFT) & REG_INDEX_MASK) |                \
         ((nouse << REG_NO_USE_SHIFT) & REG_NO_USE_MASK) |              \
         ((valid << REG_VALID_SHIFT) & REG_VALID_MASK) |                \
+        ((builtin << REG_BUILTIN_SHIFT) & REG_BUILTIN_MASK) |  \
         ((vswz << REG_VSWZ_SHIFT) & REG_VSWZ_MASK) |                   \
         ((sswz << REG_SSWZ_SHIFT) & REG_SSWZ_MASK))
  #define REG_GET_TYPE(reg)                                             \
        ((reg & REG_NO_USE_MASK) >> REG_NO_USE_SHIFT)
  #define REG_GET_VALID(reg)                                            \
        ((reg & REG_VALID_MASK) >> REG_VALID_SHIFT)
+ #define REG_GET_BUILTIN(reg)                                          \
+       ((reg & REG_BUILTIN_MASK) >> REG_BUILTIN_SHIFT)
  #define REG_SET_TYPE(reg, type)                                               \
        reg = ((reg & ~REG_TYPE_MASK) |                                 \
               ((type << REG_TYPE_SHIFT) & REG_TYPE_MASK))
  #define REG_SET_VALID(reg, valid)                                     \
        reg = ((reg & ~REG_VALID_MASK) |                                \
               ((valid << REG_VALID_SHIFT) & REG_VALID_MASK))
+ #define REG_SET_BUILTIN(reg, builtin)                                 \
+       reg = ((reg & ~REG_BUILTIN_MASK) |                              \
+              ((builtin << REG_BUILTIN_SHIFT) & REG_BUILTIN_MASK))
  #define REG_ABS(reg)                                                  \
        reg = (reg | REG_ABS_MASK)
  #define REG_NEGV(reg)                                                 \
@@@ -184,9 -192,6 +193,6 @@@ static const struct 
   *
   * REG_VSWZ/REG_SSWZ is an index into this table
   */
- #define SLOT_VECTOR   (1<<0)
- #define SLOT_SCALAR   (1<<3)
- #define SLOT_BOTH     (SLOT_VECTOR | SLOT_SCALAR)
  
  /* mapping from SWIZZLE_* to r300 native values for scalar insns */
  #define SWIZZLE_HALF 6
@@@ -202,14 -207,14 +208,14 @@@ static const struct r300_pfs_swizzle 
        GLuint flags;
  } v_swiz[] = {
  /* native swizzles */
-       { MAKE_SWZ3(X, Y, Z), R300_FPI0_ARGC_SRC0C_XYZ, 4, SLOT_VECTOR },
-       { MAKE_SWZ3(X, X, X), R300_FPI0_ARGC_SRC0C_XXX, 4, SLOT_VECTOR },
-       { MAKE_SWZ3(Y, Y, Y), R300_FPI0_ARGC_SRC0C_YYY, 4, SLOT_VECTOR },
-       { MAKE_SWZ3(Z, Z, Z), R300_FPI0_ARGC_SRC0C_ZZZ, 4, SLOT_VECTOR },
-       { MAKE_SWZ3(W, W, W), R300_FPI0_ARGC_SRC0A,     1, SLOT_SCALAR },
-       { MAKE_SWZ3(Y, Z, X), R300_FPI0_ARGC_SRC0C_YZX, 1, SLOT_VECTOR },
-       { MAKE_SWZ3(Z, X, Y), R300_FPI0_ARGC_SRC0C_ZXY, 1, SLOT_VECTOR },
-       { MAKE_SWZ3(W, Z, Y), R300_FPI0_ARGC_SRC0CA_WZY, 1, SLOT_BOTH },
+       { MAKE_SWZ3(X, Y, Z), R300_FPI0_ARGC_SRC0C_XYZ, 4, SLOT_SRC_VECTOR },
+       { MAKE_SWZ3(X, X, X), R300_FPI0_ARGC_SRC0C_XXX, 4, SLOT_SRC_VECTOR },
+       { MAKE_SWZ3(Y, Y, Y), R300_FPI0_ARGC_SRC0C_YYY, 4, SLOT_SRC_VECTOR },
+       { MAKE_SWZ3(Z, Z, Z), R300_FPI0_ARGC_SRC0C_ZZZ, 4, SLOT_SRC_VECTOR },
+       { MAKE_SWZ3(W, W, W), R300_FPI0_ARGC_SRC0A,     1, SLOT_SRC_SCALAR },
+       { MAKE_SWZ3(Y, Z, X), R300_FPI0_ARGC_SRC0C_YZX, 1, SLOT_SRC_VECTOR },
+       { MAKE_SWZ3(Z, X, Y), R300_FPI0_ARGC_SRC0C_ZXY, 1, SLOT_SRC_VECTOR },
+       { MAKE_SWZ3(W, Z, Y), R300_FPI0_ARGC_SRC0CA_WZY, 1, SLOT_SRC_BOTH },
        { MAKE_SWZ3(ONE, ONE, ONE), R300_FPI0_ARGC_ONE, 0, 0},
        { MAKE_SWZ3(ZERO, ZERO, ZERO), R300_FPI0_ARGC_ZERO, 0, 0},
        { MAKE_SWZ3(HALF, HALF, HALF), R300_FPI0_ARGC_HALF, 0, 0},
@@@ -241,10 -246,10 +247,10 @@@ static const struct 
        int stride;     /* difference between SRC0/1/2 */
        GLuint flags;
  } s_swiz[] = {
-       { R300_FPI2_ARGA_SRC0C_X, 3, SLOT_VECTOR },
-       { R300_FPI2_ARGA_SRC0C_Y, 3, SLOT_VECTOR },
-       { R300_FPI2_ARGA_SRC0C_Z, 3, SLOT_VECTOR },
-       { R300_FPI2_ARGA_SRC0A  , 1, SLOT_SCALAR },
+       { R300_FPI2_ARGA_SRC0C_X, 3, SLOT_SRC_VECTOR },
+       { R300_FPI2_ARGA_SRC0C_Y, 3, SLOT_SRC_VECTOR },
+       { R300_FPI2_ARGA_SRC0C_Z, 3, SLOT_SRC_VECTOR },
+       { R300_FPI2_ARGA_SRC0A  , 1, SLOT_SRC_SCALAR },
        { R300_FPI2_ARGA_ZERO   , 0, 0 },
        { R300_FPI2_ARGA_ONE    , 0, 0 },
        { R300_FPI2_ARGA_HALF   , 0, 0 }
@@@ -256,6 -261,7 +262,7 @@@ static const GLuint undef = REG(REG_TYP
                                SWIZZLE_XYZ,
                                SWIZZLE_W,
                                GL_FALSE,
+                               GL_FALSE,
                                GL_FALSE);
  
  /* constant one source */
@@@ -264,6 -270,7 +271,7 @@@ static const GLuint pfs_one = REG(REG_T
                                  SWIZZLE_111,
                                  SWIZZLE_ONE,
                                  GL_FALSE,
+                                 GL_TRUE,
                                  GL_TRUE);
  
  /* constant half source */
@@@ -272,6 -279,7 +280,7 @@@ static const GLuint pfs_half = REG(REG_
                                   SWIZZLE_HHH,
                                   SWIZZLE_HALF,
                                   GL_FALSE,
+                                  GL_TRUE,
                                   GL_TRUE);
  
  /* constant zero source */
@@@ -280,6 -288,7 +289,7 @@@ static const GLuint pfs_zero = REG(REG_
                                   SWIZZLE_000,
                                   SWIZZLE_ZERO,
                                   GL_FALSE,
+                                  GL_TRUE,
                                   GL_TRUE);
  
  /*
@@@ -291,47 -300,105 +301,105 @@@ static void emit_arith(struct r300_frag
                                GLuint src0, GLuint src1, GLuint src2,
                                int flags);
  
- /*
-  * Helper functions prototypes
+ /**
+  * Get an R300 temporary that can be written to in the given slot.
   */
- static int get_hw_temp(struct r300_fragment_program *rp)
+ static int get_hw_temp(struct r300_fragment_program *rp, int slot)
  {
        COMPILE_STATE;
-       int r = ffs(~cs->hwreg_in_use);
-       if (!r) {
+       int r;
+       for(r = 0; r < PFS_NUM_TEMP_REGS; ++r) {
+               if (cs->hwtemps[r].free >= 0 && cs->hwtemps[r].free <= slot)
+                       break;
+       }
+       if (r >= PFS_NUM_TEMP_REGS) {
                ERROR("Out of hardware temps\n");
                return 0;
        }
  
-       cs->hwreg_in_use |= (1 << --r);
+       // Reserved is used to avoid the following scenario:
+       //  R300 temporary X is first assigned to Mesa temporary Y during vector ops
+       //  R300 temporary X is then assigned to Mesa temporary Z for further vector ops
+       //  Then scalar ops on Mesa temporary Z are emitted and move back in time
+       //  to overwrite the value of temporary Y.
+       // End scenario.
+       cs->hwtemps[r].reserved = cs->hwtemps[r].free;
+       cs->hwtemps[r].free = -1;
+       // Reset to some value that won't mess things up when the user
+       // tries to read from a temporary that hasn't been assigned a value yet.
+       // In the normal case, vector_valid and scalar_valid should be set to
+       // a sane value by the first emit that writes to this temporary.
+       cs->hwtemps[r].vector_valid = 0;
+       cs->hwtemps[r].scalar_valid = 0;
        if (r > rp->max_temp_idx)
                rp->max_temp_idx = r;
  
        return r;
  }
  
+ /**
+  * Get an R300 temporary that will act as a TEX destination register.
+  */
  static int get_hw_temp_tex(struct r300_fragment_program *rp)
  {
        COMPILE_STATE;
        int r;
  
-       r = ffs(~(cs->hwreg_in_use | cs->used_in_node));
-       if (!r)
-               return get_hw_temp(rp); /* Will cause an indirection */
+       for(r = 0; r < PFS_NUM_TEMP_REGS; ++r) {
+               if (cs->used_in_node & (1 << r))
+                       continue;
+               // Note: Be very careful here
+               if (cs->hwtemps[r].free >= 0 && cs->hwtemps[r].free <= 0)
+                       break;
+       }
+       if (r >= PFS_NUM_TEMP_REGS)
+               return get_hw_temp(rp, 0); /* Will cause an indirection */
+       cs->hwtemps[r].reserved = cs->hwtemps[r].free;
+       cs->hwtemps[r].free = -1;
+       // Reset to some value that won't mess things up when the user
+       // tries to read from a temporary that hasn't been assigned a value yet.
+       // In the normal case, vector_valid and scalar_valid should be set to
+       // a sane value by the first emit that writes to this temporary.
+       cs->hwtemps[r].vector_valid = cs->nrslots;
+       cs->hwtemps[r].scalar_valid = cs->nrslots;
  
-       cs->hwreg_in_use |= (1 << --r);
        if (r > rp->max_temp_idx)
                rp->max_temp_idx = r;
  
        return r;
  }
  
+ /**
+  * Mark the given hardware register as free.
+  */
  static void free_hw_temp(struct r300_fragment_program *rp, int idx)
  {
        COMPILE_STATE;
-       cs->hwreg_in_use &= ~(1<<idx);
+       // Be very careful here. Consider sequences like
+       //  MAD r0, r1,r2,r3
+       //  TEX r4, ...
+       // The TEX instruction may be moved in front of the MAD instruction
+       // due to the way nodes work. We don't want to alias r1 and r4 in
+       // this case.
+       // I'm certain the register allocation could be further sanitized,
+       // but it's tricky because of stuff that can happen inside emit_tex
+       // and emit_arith.
+       cs->hwtemps[idx].free = cs->nrslots+1;
  }
  
+ /**
+  * Create a new Mesa temporary register.
+  */
  static GLuint get_temp_reg(struct r300_fragment_program *rp)
  {
        COMPILE_STATE;
        return r;
  }
  
+ /**
+  * Create a new Mesa temporary register that will act as the destination
+  * register for a texture read.
+  */
  static GLuint get_temp_reg_tex(struct r300_fragment_program *rp)
  {
        COMPILE_STATE;
        return r;
  }
  
+ /**
+  * Free a Mesa temporary and the associated R300 temporary.
+  */
  static void free_temp(struct r300_fragment_program *rp, GLuint r)
  {
        COMPILE_STATE;
  
        if (!(cs->temp_in_use & (1 << index)))
                return;
-       
        if (REG_GET_TYPE(r) == REG_TYPE_TEMP) {
                free_hw_temp(rp, cs->temps[index].reg);
                cs->temps[index].reg = -1;
        }
  }
  
- static GLuint emit_param4fv(struct r300_fragment_program *rp,
-                           GLfloat *values)
+ /**
+  * Emit a hardware constant/parameter.
+  *
+  * \p cp Stable pointer to an array of 4 floats.
+  *  The pointer must be stable in the sense that it remains to be valid
+  *  and hold the contents of the constant/parameter throughout the lifetime
+  *  of the fragment program (actually, up until the next time the fragment
+  *  program is translated).
+  */
+ static GLuint emit_const4fv(struct r300_fragment_program *rp, const GLfloat* cp)
  {
-       GLuint r = undef;
-       GLuint index;
-       int pidx;
+       GLuint reg = undef;
+       int index;
  
-       pidx = rp->param_nr++;
-       index = rp->const_nr++;
-       if (pidx >= PFS_NUM_CONST_REGS || index >= PFS_NUM_CONST_REGS) {
-               ERROR("Out of const/param slots!\n");
-               return r;
+       for(index = 0; index < rp->const_nr; ++index) {
+               if (rp->constant[index] == cp)
+                       break;
        }
  
-       rp->param[pidx].idx = index;
-       rp->param[pidx].values = values;
-       rp->params_uptodate = GL_FALSE;
-       REG_SET_TYPE(r, REG_TYPE_CONST);
-       REG_SET_INDEX(r, index);
-       REG_SET_VALID(r, GL_TRUE);
-       return r;
- }
- static GLuint emit_const4fv(struct r300_fragment_program *rp, GLfloat *cp)
- { 
-       GLuint r = undef;
-       GLuint index;
+       if (index >= rp->const_nr) {
+               if (index >= PFS_NUM_CONST_REGS) {
+                       ERROR("Out of hw constants!\n");
+                       return reg;
+               }
  
-       index = rp->const_nr++;
-       if (index >= PFS_NUM_CONST_REGS) {
-               ERROR("Out of hw constants!\n");
-               return r;
+               rp->const_nr++;
+               rp->constant[index] = cp;
        }
  
-       COPY_4V(rp->constant[index], cp);
-       REG_SET_TYPE(r, REG_TYPE_CONST);
-       REG_SET_INDEX(r, index);
-       REG_SET_VALID(r, GL_TRUE);
-       return r;
+       REG_SET_TYPE(reg, REG_TYPE_CONST);
+       REG_SET_INDEX(reg, index);
+       REG_SET_VALID(reg, GL_TRUE);
+       return reg;
  }
  
  static inline GLuint negate(GLuint r)
@@@ -617,7 -683,7 +684,7 @@@ static GLuint do_swizzle(struct r300_fr
            GLuint offset;
            for(i=0; i < 4; ++i){
                offset = GET_SWZ(arbswz, i);
-               
                newswz |= (offset <= 3)?GET_SWZ(vsrcswz, offset) << i*3:offset << i*3;
            }
  
@@@ -688,16 -754,16 +755,16 @@@ static GLuint t_src(struct r300_fragmen
                REG_SET_TYPE(r, REG_TYPE_INPUT);
                break;
        case PROGRAM_LOCAL_PARAM:
-               r = emit_param4fv(rp,
+               r = emit_const4fv(rp,
                                  rp->mesa_program.Base.LocalParams[fpsrc.Index]);
                break;
        case PROGRAM_ENV_PARAM:
-               r = emit_param4fv(rp,
+               r = emit_const4fv(rp,
                                  rp->ctx->FragmentProgram.Parameters[fpsrc.Index]);
                break;
        case PROGRAM_STATE_VAR:
        case PROGRAM_NAMED_PARAM:
-               r = emit_param4fv(rp,
+               r = emit_const4fv(rp,
                                  rp->mesa_program.Base.Parameters->ParameterValues[fpsrc.Index]);
                break;
        default:
@@@ -726,7 -792,7 +793,7 @@@ static GLuint t_dst(struct r300_fragmen
                       struct prog_dst_register dest)
  {
        GLuint r = undef;
-       
        switch (dest.File) {
        case PROGRAM_TEMPORARY:
                REG_SET_INDEX(r, dest.Index);
@@@ -762,10 -828,10 +829,10 @@@ static int t_hw_src(struct r300_fragmen
        switch(REG_GET_TYPE(src)) {
        case REG_TYPE_TEMP:
                /* NOTE: if reg==-1 here, a source is being read that
-                *       hasn't been written to. Undefined results
+                *       hasn't been written to. Undefined results.
                 */
                if (cs->temps[index].reg == -1)
-                       cs->temps[index].reg = get_hw_temp(rp);
+                       cs->temps[index].reg = get_hw_temp(rp, cs->nrslots);
  
                idx = cs->temps[index].reg;
  
  
  static int t_hw_dst(struct r300_fragment_program *rp,
                    GLuint dest,
-                   GLboolean tex)
+                   GLboolean tex,
+                   int slot)
  {
        COMPILE_STATE;
        int idx;
        case REG_TYPE_TEMP:
                if (cs->temps[REG_GET_INDEX(dest)].reg == -1) {
                        if (!tex) {
-                               cs->temps[index].reg = get_hw_temp(rp);
+                               cs->temps[index].reg = get_hw_temp(rp, slot);
                        } else {
                                cs->temps[index].reg = get_hw_temp_tex(rp);
                        }
                ERROR("invalid dest reg type %d\n", REG_GET_TYPE(dest));
                return 0;
        }
-       
        return idx;
  }
  
- static void emit_nop(struct r300_fragment_program *rp,
-                    GLuint mask,
-                    GLboolean sync)
+ static void emit_nop(struct r300_fragment_program *rp)
  {
        COMPILE_STATE;
-       
-       if (sync)
-               cs->v_pos = cs->s_pos = MAX2(cs->v_pos, cs->s_pos);
  
-       if (mask & WRITEMASK_XYZ) {
-               rp->alu.inst[cs->v_pos].inst0 = NOP_INST0;
-               rp->alu.inst[cs->v_pos].inst1 = NOP_INST1;
-               cs->v_pos++;
+       if (cs->nrslots >= PFS_MAX_ALU_INST) {
+               ERROR("Out of ALU instruction slots\n");
+               return;
        }
  
-       if (mask & WRITEMASK_W) {
-               rp->alu.inst[cs->s_pos].inst2 = NOP_INST2;
-               rp->alu.inst[cs->s_pos].inst3 = NOP_INST3;
-               cs->s_pos++;
-       }
+       rp->alu.inst[cs->nrslots].inst0 = NOP_INST0;
+       rp->alu.inst[cs->nrslots].inst1 = NOP_INST1;
+       rp->alu.inst[cs->nrslots].inst2 = NOP_INST2;
+       rp->alu.inst[cs->nrslots].inst3 = NOP_INST3;
+       cs->nrslots++;
  }
  
  static void emit_tex(struct r300_fragment_program *rp,
        GLuint din = cs->dest_in_node, uin = cs->used_in_node;
        int unit = fpi->TexSrcUnit;
        int hwsrc, hwdest;
-       
        /* Resolve source/dest to hardware registers */
        hwsrc = t_hw_src(rp, coord, GL_TRUE);
        if (opcode != R300_FPITX_OP_KIL) {
                        rdest = dest;
                        dest = get_temp_reg_tex(rp);
                }
-               hwdest = t_hw_dst(rp, dest, GL_TRUE);
-               
+               hwdest = t_hw_dst(rp, dest, GL_TRUE, rp->node[rp->cur_node].alu_offset);
                /* Use a temp that hasn't been used in this node, rather
                 * than causing an indirection
                 */
                hwdest = 0;
                unit = 0;
        }
-       
        /* Indirection if source has been written in this node, or if the
         * dest has been read/written in this node
         */
        if ((REG_GET_TYPE(coord) != REG_TYPE_CONST &&
             (din & (1<<hwsrc))) || (uin & (1<<hwdest))) {
-                       
                /* Finish off current node */
-               cs->v_pos = cs->s_pos = MAX2(cs->v_pos, cs->s_pos);
-               if (rp->node[rp->cur_node].alu_offset == cs->v_pos) {
-                       /* No alu instructions in the node? Emit a NOP. */
-                       emit_nop(rp, WRITEMASK_XYZW, GL_TRUE);
-                       cs->v_pos = cs->s_pos = MAX2(cs->v_pos, cs->s_pos);
-               }
-                               
+               if (rp->node[rp->cur_node].alu_offset == cs->nrslots)
+                       emit_nop(rp);
                rp->node[rp->cur_node].alu_end =
-                               cs->v_pos - rp->node[rp->cur_node].alu_offset - 1;
+                               cs->nrslots - rp->node[rp->cur_node].alu_offset - 1;
                assert(rp->node[rp->cur_node].alu_end >= 0);
  
                if (++rp->cur_node >= PFS_MAX_TEX_INDIRECT) {
  
                /* Start new node */
                rp->node[rp->cur_node].tex_offset = rp->tex.length;
-               rp->node[rp->cur_node].alu_offset = cs->v_pos;
+               rp->node[rp->cur_node].alu_offset = cs->nrslots;
                rp->node[rp->cur_node].tex_end = -1;
-               rp->node[rp->cur_node].alu_end = -1;    
+               rp->node[rp->cur_node].alu_end = -1;
                rp->node[rp->cur_node].flags = 0;
                cs->used_in_node = 0;
                cs->dest_in_node = 0;
        }
-       
        if (rp->cur_node == 0)
                rp->first_node_has_tex = 1;
  
                /* not entirely sure about this */
                | (opcode << R300_FPITX_OPCODE_SHIFT);
  
-       cs->dest_in_node |= (1 << hwdest); 
+       cs->dest_in_node |= (1 << hwdest);
        if (REG_GET_TYPE(coord) != REG_TYPE_CONST)
                cs->used_in_node |= (1 << hwsrc);
  
        }
  }
  
- /* Add sources to FPI1/FPI3 lists.  If source is already on list,
-  * reuse the index instead of wasting a source.
+ /**
+  * Returns the first slot where we could possibly allow writing to dest,
+  * according to register allocation.
   */
- static int add_src(struct r300_fragment_program *rp,
-                  int reg,
-                  int pos,
-                  int srcmask)
+ static int get_earliest_allowed_write(
+               struct r300_fragment_program* rp,
+               GLuint dest, int mask)
  {
        COMPILE_STATE;
-       int csm, i;
-       
-       /* Look for matches */
-       for (i=0,csm=srcmask; i<3; i++,csm=csm<<1) {    
-               /* If sources have been allocated in this position(s)... */
-               if ((cs->slot[pos].umask & csm) == csm) {
-                       /* ... and the register number(s) match, re-use the
-                          source */
-                       if (srcmask == SLOT_VECTOR &&
-                           cs->slot[pos].vsrc[i] == reg)
-                               return i;
-                       if (srcmask == SLOT_SCALAR &&
-                           cs->slot[pos].ssrc[i] == reg)
-                               return i;
-                       if (srcmask == SLOT_BOTH &&
-                           cs->slot[pos].vsrc[i] == reg &&
-                           cs->slot[pos].ssrc[i] == reg)
-                               return i;
-               }
+       int idx;
+       int pos;
+       GLuint index = REG_GET_INDEX(dest);
+       assert(REG_GET_VALID(dest));
+       switch(REG_GET_TYPE(dest)) {
+               case REG_TYPE_TEMP:
+                       if (cs->temps[index].reg == -1)
+                               return 0;
+                       idx = cs->temps[index].reg;
+                       break;
+               case REG_TYPE_OUTPUT:
+                       return 0;
+               default:
+                       ERROR("invalid dest reg type %d\n", REG_GET_TYPE(dest));
+                       return 0;
        }
  
-       /* Look for free spaces */
-       for (i=0,csm=srcmask; i<3; i++,csm=csm<<1) {
-               /* If the position(s) haven't been allocated */
-               if ((cs->slot[pos].umask & csm) == 0) {
-                       cs->slot[pos].umask |= csm;
-                       if (srcmask & SLOT_VECTOR)
-                               cs->slot[pos].vsrc[i] = reg;
-                       if (srcmask & SLOT_SCALAR)
-                               cs->slot[pos].ssrc[i] = reg;
-                       return i;
-               }       
+       pos = cs->hwtemps[idx].reserved;
+       if (mask & WRITEMASK_XYZ) {
+               if (pos < cs->hwtemps[idx].vector_lastread)
+                       pos = cs->hwtemps[idx].vector_lastread;
        }
-       
-       //ERROR("Failed to allocate sources in FPI1/FPI3!\n");
-       return 0;
+       if (mask & WRITEMASK_W) {
+               if (pos < cs->hwtemps[idx].scalar_lastread)
+                       pos = cs->hwtemps[idx].scalar_lastread;
+       }
+       return pos;
  }
  
- /* Determine whether or not to position opcode in the same ALU slot for both
-  * vector and scalar portions of an instruction.
+ /**
+  * Allocates a slot for an ALU instruction that can consist of
+  * a vertex part or a scalar part or both.
+  *
+  * Sources from src (src[0] to src[argc-1]) are added to the slot in the
+  * appropriate position (vector and/or scalar), and their positions are
+  * recorded in the srcpos array.
   *
-  * It's not necessary to force the first case, but it makes disassembled
-  * shaders easier to read.
+  * This function emits instruction code for the source fetch and the
+  * argument selection. It does not emit instruction code for the
+  * opcode or the destination selection.
+  *
+  * @return the index of the slot
   */
- static GLboolean force_same_slot(int vop,
-                                int sop,
-                                GLboolean emit_vop,
-                                GLboolean emit_sop,
-                                int argc,
-                                GLuint *src)
+ static int find_and_prepare_slot(struct r300_fragment_program* rp,
+               GLboolean emit_vop,
+               GLboolean emit_sop,
+               int argc,
+               GLuint* src,
+               GLuint dest,
+               int mask)
  {
-       int i;
+       COMPILE_STATE;
+       int hwsrc[3];
+       int srcpos[3];
+       unsigned int used;
+       int tempused;
+       int tempvsrc[3];
+       int tempssrc[3];
+       int pos;
+       int regnr;
+       int i,j;
+       // Determine instruction slots, whether sources are required on
+       // vector or scalar side, and the smallest slot number where
+       // all source registers are available
+       used = 0;
+       if (emit_vop)
+               used |= SLOT_OP_VECTOR;
+       if (emit_sop)
+               used |= SLOT_OP_SCALAR;
+       pos = get_earliest_allowed_write(rp, dest, mask);
+       if (rp->node[rp->cur_node].alu_offset > pos)
+               pos = rp->node[rp->cur_node].alu_offset;
+       for(i = 0; i < argc; ++i) {
+               if (!REG_GET_BUILTIN(src[i])) {
+                       if (emit_vop)
+                               used |= v_swiz[REG_GET_VSWZ(src[i])].flags << i;
+                       if (emit_sop)
+                               used |= s_swiz[REG_GET_SSWZ(src[i])].flags << i;
+               }
+               hwsrc[i] = t_hw_src(rp, src[i], GL_FALSE); /* Note: sideeffects wrt refcounting! */
+               regnr = hwsrc[i] & 31;
+               if (REG_GET_TYPE(src[i]) == REG_TYPE_TEMP) {
+                       if (used & (SLOT_SRC_VECTOR << i)) {
+                               if (cs->hwtemps[regnr].vector_valid > pos)
+                                       pos = cs->hwtemps[regnr].vector_valid;
+                       }
+                       if (used & (SLOT_SRC_SCALAR << i)) {
+                               if (cs->hwtemps[regnr].scalar_valid > pos)
+                                       pos = cs->hwtemps[regnr].scalar_valid;
+                       }
+               }
+       }
+       // Find a slot that fits
+       for(; ; ++pos) {
+               if (cs->slot[pos].used & used & SLOT_OP_BOTH)
+                       continue;
+               if (pos >= cs->nrslots) {
+                       if (cs->nrslots >= PFS_MAX_ALU_INST) {
+                               ERROR("Out of ALU instruction slots\n");
+                               return -1;
+                       }
  
-       if (emit_vop && emit_sop)
-               return GL_TRUE;
+                       rp->alu.inst[pos].inst0 = NOP_INST0;
+                       rp->alu.inst[pos].inst1 = NOP_INST1;
+                       rp->alu.inst[pos].inst2 = NOP_INST2;
+                       rp->alu.inst[pos].inst3 = NOP_INST3;
+                       cs->nrslots++;
+               }
+               // Note: When we need both parts (vector and scalar) of a source,
+               // we always try to put them into the same position. This makes the
+               // code easier to read, and it is optimal (i.e. one doesn't gain
+               // anything by splitting the parts).
+               // It also avoids headaches with swizzles that access both parts (i.e WXY)
+               tempused = cs->slot[pos].used;
+               for(i = 0; i < 3; ++i) {
+                       tempvsrc[i] = cs->slot[pos].vsrc[i];
+                       tempssrc[i] = cs->slot[pos].ssrc[i];
+               }
  
-       if (emit_vop && vop == R300_FPI0_OUTC_REPL_ALPHA)
-               return GL_TRUE;
+               for(i = 0; i < argc; ++i) {
+                       int flags = (used >> i) & SLOT_SRC_BOTH;
  
+                       if (!flags) {
+                               srcpos[i] = 0;
+                               continue;
+                       }
+                       for(j = 0; j < 3; ++j) {
+                               if ((tempused >> j) & flags & SLOT_SRC_VECTOR) {
+                                       if (tempvsrc[j] != hwsrc[i])
+                                               continue;
+                               }
+                               if ((tempused >> j) & flags & SLOT_SRC_SCALAR) {
+                                       if (tempssrc[j] != hwsrc[i])
+                                               continue;
+                               }
+                               break;
+                       }
+                       if (j == 3)
+                               break;
+                       srcpos[i] = j;
+                       tempused |= flags << j;
+                       if (flags & SLOT_SRC_VECTOR)
+                               tempvsrc[j] = hwsrc[i];
+                       if (flags & SLOT_SRC_SCALAR)
+                               tempssrc[j] = hwsrc[i];
+               }
+               if (i == argc)
+                       break;
+       }
+       // Found a slot, reserve it
+       cs->slot[pos].used = tempused | (used & SLOT_OP_BOTH);
+       for(i = 0; i < 3; ++i) {
+               cs->slot[pos].vsrc[i] = tempvsrc[i];
+               cs->slot[pos].ssrc[i] = tempssrc[i];
+       }
+       for(i = 0; i < argc; ++i) {
+               if (REG_GET_TYPE(src[i]) == REG_TYPE_TEMP) {
+                       int regnr = hwsrc[i] & 31;
+                       if (used & (SLOT_SRC_VECTOR << i)) {
+                               if (cs->hwtemps[regnr].vector_lastread < pos)
+                                       cs->hwtemps[regnr].vector_lastread = pos;
+                       }
+                       if (used & (SLOT_SRC_SCALAR << i)) {
+                               if (cs->hwtemps[regnr].scalar_lastread < pos)
+                                       cs->hwtemps[regnr].scalar_lastread = pos;
+                       }
+               }
+       }
+       // Emit the source fetch code
+       rp->alu.inst[pos].inst1 &= ~R300_FPI1_SRC_MASK;
+       rp->alu.inst[pos].inst1 |=
+                       ((cs->slot[pos].vsrc[0] << R300_FPI1_SRC0C_SHIFT) |
+                        (cs->slot[pos].vsrc[1] << R300_FPI1_SRC1C_SHIFT) |
+                        (cs->slot[pos].vsrc[2] << R300_FPI1_SRC2C_SHIFT));
+       rp->alu.inst[pos].inst3 &= ~R300_FPI3_SRC_MASK;
+       rp->alu.inst[pos].inst3 |=
+                       ((cs->slot[pos].ssrc[0] << R300_FPI3_SRC0A_SHIFT) |
+                        (cs->slot[pos].ssrc[1] << R300_FPI3_SRC1A_SHIFT) |
+                        (cs->slot[pos].ssrc[2] << R300_FPI3_SRC2A_SHIFT));
+       // Emit the argument selection code
        if (emit_vop) {
-               for (i=0;i<argc;i++)
-                       if (REG_GET_VSWZ(src[i]) == SWIZZLE_WZY)
-                               return GL_TRUE;
+               int swz[3];
+               for(i = 0; i < 3; ++i) {
+                       if (i < argc) {
+                               swz[i] = (v_swiz[REG_GET_VSWZ(src[i])].base +
+                                           (srcpos[i] * v_swiz[REG_GET_VSWZ(src[i])].stride)) |
+                                       ((src[i] & REG_NEGV_MASK) ? ARG_NEG : 0) |
+                                       ((src[i] & REG_ABS_MASK) ? ARG_ABS : 0);
+                       } else {
+                               swz[i] = R300_FPI0_ARGC_ZERO;
+                       }
+               }
+               rp->alu.inst[pos].inst0 &=
+                               ~(R300_FPI0_ARG0C_MASK|R300_FPI0_ARG1C_MASK|R300_FPI0_ARG2C_MASK);
+               rp->alu.inst[pos].inst0 |=
+                               (swz[0] << R300_FPI0_ARG0C_SHIFT) |
+                               (swz[1] << R300_FPI0_ARG1C_SHIFT) |
+                               (swz[2] << R300_FPI0_ARG2C_SHIFT);
+       }
+       if (emit_sop) {
+               int swz[3];
+               for(i = 0; i < 3; ++i) {
+                       if (i < argc) {
+                               swz[i] = (s_swiz[REG_GET_SSWZ(src[i])].base +
+                                               (srcpos[i] * s_swiz[REG_GET_SSWZ(src[i])].stride)) |
+                                               ((src[i] & REG_NEGV_MASK) ? ARG_NEG : 0) |
+                                               ((src[i] & REG_ABS_MASK) ? ARG_ABS : 0);
+                       } else {
+                               swz[i] = R300_FPI2_ARGA_ZERO;
+                       }
+               }
+               rp->alu.inst[pos].inst2 &=
+                               ~(R300_FPI2_ARG0A_MASK|R300_FPI2_ARG1A_MASK|R300_FPI2_ARG2A_MASK);
+               rp->alu.inst[pos].inst2 |=
+                               (swz[0] << R300_FPI2_ARG0A_SHIFT) |
+                               (swz[1] << R300_FPI2_ARG1A_SHIFT) |
+                               (swz[2] << R300_FPI2_ARG2A_SHIFT);
        }
  
-       return GL_FALSE;
+       return pos;
  }
  
+ /**
+  * Append an ALU instruction to the instruction list.
+  */
  static void emit_arith(struct r300_fragment_program *rp,
                       int op,
                       GLuint dest,
  {
        COMPILE_STATE;
        GLuint src[3] = { src0, src1, src2 };
-       int hwsrc[3], sswz[3], vswz[3];
        int hwdest;
-       GLboolean emit_vop = GL_FALSE, emit_sop = GL_FALSE;
+       GLboolean emit_vop, emit_sop;
        int vop, sop, argc;
-       int vpos, spos;
-       int i;
+       int pos;
  
        vop = r300_fpop[op].v_op;
        sop = r300_fpop[op].s_op;
        argc = r300_fpop[op].argc;
  
+       if (REG_GET_TYPE(dest) == REG_TYPE_OUTPUT &&
+           REG_GET_INDEX(dest) == FRAG_RESULT_DEPR) {
+               if (mask & WRITEMASK_Z) {
+                       mask = WRITEMASK_W;
+               } else {
+                       return;
+               }
+       }
+       emit_vop = GL_FALSE;
+       emit_sop = GL_FALSE;
        if ((mask & WRITEMASK_XYZ) || vop == R300_FPI0_OUTC_DP3)
                emit_vop = GL_TRUE;
        if ((mask & WRITEMASK_W) || vop == R300_FPI0_OUTC_REPL_ALPHA)
                emit_sop = GL_TRUE;
  
-       if (REG_GET_TYPE(dest) == REG_TYPE_OUTPUT &&
-           REG_GET_INDEX(dest) == FRAG_RESULT_DEPR)
-               emit_vop = GL_FALSE;
-                                       
-       if (force_same_slot(vop, sop, emit_vop, emit_sop, argc, src)) {
-               vpos = spos = MAX2(cs->v_pos, cs->s_pos);
-       } else {
-               vpos = cs->v_pos;
-               spos = cs->s_pos;
-               /* Here is where we'd decide on where a safe place is to
-                * combine this instruction with a previous one.
-                *
-                * This is extremely simple for now.. if a source depends
-                * on the opposite stream, force the same instruction.
-                */
-               for (i=0;i<3;i++) {
-                       if (emit_vop &&
-                           (v_swiz[REG_GET_VSWZ(src[i])].flags & SLOT_SCALAR)) {
-                               vpos = spos = MAX2(vpos, spos);
-                               break;
-                       }
-                       if (emit_sop &&
-                           (s_swiz[REG_GET_SSWZ(src[i])].flags & SLOT_VECTOR)) {
-                               vpos = spos = MAX2(vpos, spos);
-                               break;
-                       }
-               }
-       }
-       
-       /* - Convert src->hwsrc, record for FPI1/FPI3
-        * - Determine ARG parts of FPI0/FPI2, unused args are filled
-        *   with ARG_ZERO.
-        */     
-       for (i=0;i<3;i++) {
-               int srcpos;
-               
-               if (i >= argc) {
-                       vswz[i] = R300_FPI0_ARGC_ZERO;
-                       sswz[i] = R300_FPI2_ARGA_ZERO;
-                       continue;
-               }
-               
-               hwsrc[i] = t_hw_src(rp, src[i], GL_FALSE);      
-               if (emit_vop && vop != R300_FPI0_OUTC_REPL_ALPHA) {
-                       srcpos = add_src(rp, hwsrc[i], vpos,
-                                        v_swiz[REG_GET_VSWZ(src[i])].flags);
-                       vswz[i] = (v_swiz[REG_GET_VSWZ(src[i])].base +
-                                  (srcpos *
-                                   v_swiz[REG_GET_VSWZ(src[i])].stride)) |
-                               ((src[i] & REG_NEGV_MASK) ? ARG_NEG : 0) |
-                               ((src[i] & REG_ABS_MASK) ? ARG_ABS : 0);
-               } else vswz[i] = R300_FPI0_ARGC_ZERO;
-               
-               if (emit_sop) {
-                       srcpos = add_src(rp, hwsrc[i], spos,
-                                        s_swiz[REG_GET_SSWZ(src[i])].flags);
-                       sswz[i] = (s_swiz[REG_GET_SSWZ(src[i])].base +
-                                  (srcpos *
-                                   s_swiz[REG_GET_SSWZ(src[i])].stride)) |
-                               ((src[i] & REG_NEGS_MASK) ? ARG_NEG : 0) |
-                               ((src[i] & REG_ABS_MASK) ? ARG_ABS : 0);
-               } else sswz[i] = R300_FPI2_ARGA_ZERO;
-       }
-       hwdest = t_hw_dst(rp, dest, GL_FALSE);
-       
+       pos = find_and_prepare_slot(rp, emit_vop, emit_sop, argc, src, dest, mask);
+       if (pos < 0)
+               return;
+       hwdest = t_hw_dst(rp, dest, GL_FALSE, pos); /* Note: Side effects wrt register allocation */
        if (flags & PFS_FLAG_SAT) {
                vop |= R300_FPI0_OUTC_SAT;
                sop |= R300_FPI2_OUTA_SAT;
        }
  
        /* Throw the pieces together and get FPI0/1 */
-       rp->alu.inst[vpos].inst1 =
-                       ((cs->slot[vpos].vsrc[0] << R300_FPI1_SRC0C_SHIFT) |
-                        (cs->slot[vpos].vsrc[1] << R300_FPI1_SRC1C_SHIFT) |
-                        (cs->slot[vpos].vsrc[2] << R300_FPI1_SRC2C_SHIFT));
        if (emit_vop) {
-               rp->alu.inst[vpos].inst0 = vop |
-                               (vswz[0] << R300_FPI0_ARG0C_SHIFT) |
-                               (vswz[1] << R300_FPI0_ARG1C_SHIFT) |
-                               (vswz[2] << R300_FPI0_ARG2C_SHIFT);
+               rp->alu.inst[pos].inst0 |= vop;
+               rp->alu.inst[pos].inst1 |= hwdest << R300_FPI1_DSTC_SHIFT;
  
-               rp->alu.inst[vpos].inst1 |= hwdest << R300_FPI1_DSTC_SHIFT;
                if (REG_GET_TYPE(dest) == REG_TYPE_OUTPUT) {
                        if (REG_GET_INDEX(dest) == FRAG_RESULT_COLR) {
-                               rp->alu.inst[vpos].inst1 |=
+                               rp->alu.inst[pos].inst1 |=
                                        (mask & WRITEMASK_XYZ) << R300_FPI1_DSTC_OUTPUT_MASK_SHIFT;
                        } else assert(0);
                } else {
-                       rp->alu.inst[vpos].inst1 |=
+                       rp->alu.inst[pos].inst1 |=
                                        (mask & WRITEMASK_XYZ) << R300_FPI1_DSTC_REG_MASK_SHIFT;
+                       cs->hwtemps[hwdest].vector_valid = pos+1;
                }
-               cs->v_pos = vpos+1;
-       } else if (spos >= vpos)
-               rp->alu.inst[spos].inst0 = NOP_INST0;
+       }
  
        /* And now FPI2/3 */
-       rp->alu.inst[spos].inst3 =
-                       ((cs->slot[spos].ssrc[0] << R300_FPI3_SRC0A_SHIFT) |
-                        (cs->slot[spos].ssrc[1] << R300_FPI3_SRC1A_SHIFT) |
-                        (cs->slot[spos].ssrc[2] << R300_FPI3_SRC2A_SHIFT));
        if (emit_sop) {
-               rp->alu.inst[spos].inst2 = sop |
-                               sswz[0] << R300_FPI2_ARG0A_SHIFT |
-                               sswz[1] << R300_FPI2_ARG1A_SHIFT |
-                               sswz[2] << R300_FPI2_ARG2A_SHIFT;
+               rp->alu.inst[pos].inst2 |= sop;
  
                if (mask & WRITEMASK_W) {
                        if (REG_GET_TYPE(dest) == REG_TYPE_OUTPUT) {
                                if (REG_GET_INDEX(dest) == FRAG_RESULT_COLR) {
-                                       rp->alu.inst[spos].inst3 |= 
+                                       rp->alu.inst[pos].inst3 |=
                                                        (hwdest << R300_FPI3_DSTA_SHIFT) | R300_FPI3_DSTA_OUTPUT;
                                } else if (REG_GET_INDEX(dest) == FRAG_RESULT_DEPR) {
-                                       rp->alu.inst[spos].inst3 |= R300_FPI3_DSTA_DEPTH;
+                                       rp->alu.inst[pos].inst3 |= R300_FPI3_DSTA_DEPTH;
                                } else assert(0);
                        } else {
-                               rp->alu.inst[spos].inst3 |=
+                               rp->alu.inst[pos].inst3 |=
                                                (hwdest << R300_FPI3_DSTA_SHIFT) | R300_FPI3_DSTA_REG;
+                               cs->hwtemps[hwdest].scalar_valid = pos+1;
                        }
                }
-               cs->s_pos = spos+1;
-       } else if (vpos >= spos)
-               rp->alu.inst[vpos].inst2 = NOP_INST2;
+       }
  
        return;
  }
@@@ -1204,34 -1385,130 +1386,130 @@@ static GLuint get_attrib(struct r300_fr
  }
  #endif
  
- static void make_sin_const(struct r300_fragment_program *rp)
+ static GLfloat SinCosConsts[2][4] = {
+       {
+               1.273239545,  // 4/PI
+               -0.405284735, // -4/(PI*PI)
+               3.141592654,  // PI
+               0.2225        // weight
+       },
+       {
+               0.75,
+               0.0,
+               0.159154943,  // 1/(2*PI)
+               6.283185307   // 2*PI
+       }
+ };
+ /**
+  * Emit a LIT instruction.
+  * \p flags may be PFS_FLAG_SAT
+  *
+  * Definition of LIT (from ARB_fragment_program):
+  * tmp = VectorLoad(op0);
+  * if (tmp.x < 0) tmp.x = 0;
+  * if (tmp.y < 0) tmp.y = 0;
+  * if (tmp.w < -(128.0-epsilon)) tmp.w = -(128.0-epsilon);
+  * else if (tmp.w > 128-epsilon) tmp.w = 128-epsilon;
+  * result.x = 1.0;
+  * result.y = tmp.x;
+  * result.z = (tmp.x > 0) ? RoughApproxPower(tmp.y, tmp.w) : 0.0;
+  * result.w = 1.0;
+  *
+  * The longest path of computation is the one leading to result.z,
+  * consisting of 5 operations. This implementation of LIT takes
+  * 5 slots. So unless there's some special undocumented opcode,
+  * this implementation is potentially optimal. Unfortunately,
+  * emit_arith is a bit too conservative because it doesn't understand
+  * partial writes to the vector component.
+  */
+ static const GLfloat LitConst[4] = { 127.999999, 127.999999, 127.999999, -127.999999 };
+ static void emit_lit(struct r300_fragment_program *rp,
+               GLuint dest,
+               int mask,
+               GLuint src,
+               int flags)
  {
-       if(rp->const_sin[0] == -1){
-           GLfloat cnstv[4];
-           cnstv[0] = 1.273239545; // 4/PI
-           cnstv[1] =-0.405284735; // -4/(PI*PI)
-           cnstv[2] = 3.141592654; // PI
-           cnstv[3] = 0.2225;      // weight
-           rp->const_sin[0] = emit_const4fv(rp, cnstv);
-           cnstv[0] = 0.75;
-           cnstv[1] = 0.0;
-           cnstv[2] = 0.159154943; // 1/(2*PI)
-           cnstv[3] = 6.283185307; // 2*PI
-           rp->const_sin[1] = emit_const4fv(rp, cnstv);
+       COMPILE_STATE;
+       GLuint cnst;
+       int needTemporary;
+       GLuint temp;
+       cnst = emit_const4fv(rp, LitConst);
+       needTemporary = 0;
+       if ((mask & WRITEMASK_XYZW) != WRITEMASK_XYZW) {
+               needTemporary = 1;
+       } else if (REG_GET_TYPE(dest) == REG_TYPE_OUTPUT) {
+               // LIT is typically followed by DP3/DP4, so there's no point
+               // in creating special code for this case
+               needTemporary = 1;
+       }
+       if (needTemporary) {
+               temp = keep(get_temp_reg(rp));
+       } else {
+               temp = keep(dest);
+       }
+       // Note: The order of emit_arith inside the slots is relevant,
+       // because emit_arith only looks at scalar vs. vector when resolving
+       // dependencies, and it does not consider individual vector components,
+       // so swizzling between the two parts can create fake dependencies.
+       // First slot
+       emit_arith(rp, PFS_OP_MAX, temp, WRITEMASK_XY,
+                  keep(src), pfs_zero, undef, 0);
+       emit_arith(rp, PFS_OP_MAX, temp, WRITEMASK_W,
+                  src, cnst, undef, 0);
+       // Second slot
+       emit_arith(rp, PFS_OP_MIN, temp, WRITEMASK_Z,
+                  swizzle(temp, W, W, W, W), cnst, undef, 0);
+       emit_arith(rp, PFS_OP_LG2, temp, WRITEMASK_W,
+                  swizzle(temp, Y, Y, Y, Y), undef, undef, 0);
+       // Third slot
+       // If desired, we saturate the y result here.
+       // This does not affect the use as a condition variable in the CMP later
+       emit_arith(rp, PFS_OP_MAD, temp, WRITEMASK_W,
+                  temp, swizzle(temp, Z, Z, Z, Z), pfs_zero, 0);
+       emit_arith(rp, PFS_OP_MAD, temp, WRITEMASK_Y,
+                  swizzle(temp, X, X, X, X), pfs_one, pfs_zero, flags);
+       // Fourth slot
+       emit_arith(rp, PFS_OP_MAD, temp, WRITEMASK_X,
+                  pfs_one, pfs_one, pfs_zero, 0);
+       emit_arith(rp, PFS_OP_EX2, temp, WRITEMASK_W,
+                  temp, undef, undef, 0);
+       // Fifth slot
+       emit_arith(rp, PFS_OP_CMP, temp, WRITEMASK_Z,
+                  pfs_zero, swizzle(temp, W, W, W, W), negate(swizzle(temp, Y, Y, Y, Y)), flags);
+       emit_arith(rp, PFS_OP_MAD, temp, WRITEMASK_W,
+                  pfs_one, pfs_one, pfs_zero, 0);
+       if (needTemporary) {
+               emit_arith(rp, PFS_OP_MAD, dest, mask,
+                                  temp, pfs_one, pfs_zero, flags);
+               free_temp(rp, temp);
+       } else {
+               // Decrease refcount of the destination
+               t_hw_dst(rp, dest, GL_FALSE, cs->nrslots);
        }
  }
  
  static GLboolean parse_program(struct r300_fragment_program *rp)
- {     
+ {
        struct gl_fragment_program *mp = &rp->mesa_program;
        const struct prog_instruction *inst = mp->Base.Instructions;
        struct prog_instruction *fpi;
        GLuint src[3], dest, temp[2];
-       GLuint cnst;
        int flags, mask = 0;
-       GLfloat cnstv[4] = {0.0, 0.0, 0.0, 0.0};
+       int const_sin[2];
  
        if (!inst || inst[0].Opcode == OPCODE_END) {
                ERROR("empty program?\n");
                         *   result = sin(x)
                         */
                        temp[0] = get_temp_reg(rp);
-                       make_sin_const(rp);
+                       const_sin[0] = emit_const4fv(rp, SinCosConsts[0]);
+                       const_sin[1] = emit_const4fv(rp, SinCosConsts[1]);
                        src[0] = t_scalar_src(rp, fpi->SrcReg[0]);
  
                        /* add 0.5*PI and do range reduction */
  
                        emit_arith(rp, PFS_OP_MAD, temp[0], WRITEMASK_X,
                                   swizzle(src[0], X, X, X, X),
-                                  swizzle(rp->const_sin[1], Z, Z, Z, Z),
-                                  swizzle(rp->const_sin[1], X, X, X, X),
+                                  swizzle(const_sin[1], Z, Z, Z, Z),
+                                  swizzle(const_sin[1], X, X, X, X),
                                   0);
  
                        emit_arith(rp, PFS_OP_FRC, temp[0], WRITEMASK_X,
  
                        emit_arith(rp, PFS_OP_MAD, temp[0], WRITEMASK_Z,
                                   swizzle(temp[0], X, X, X, X),
-                                  swizzle(rp->const_sin[1], W, W, W, W), //2*PI
-                                  negate(swizzle(rp->const_sin[0], Z, Z, Z, Z)), //-PI
+                                  swizzle(const_sin[1], W, W, W, W), //2*PI
+                                  negate(swizzle(const_sin[0], Z, Z, Z, Z)), //-PI
                                   0);
  
                        /* SIN */
  
                        emit_arith(rp, PFS_OP_MAD, temp[0], WRITEMASK_X | WRITEMASK_Y,
                                   swizzle(temp[0], Z, Z, Z, Z),
-                                  rp->const_sin[0],
+                                  const_sin[0],
                                   pfs_zero,
                                   0);
  
                                   absolute(swizzle(temp[0], Z, Z, Z, Z)),
                                   swizzle(temp[0], X, X, X, X),
                                   0);
-                       
                        emit_arith(rp, PFS_OP_MAD, temp[0], WRITEMASK_Y,
                                   swizzle(temp[0], X, X, X, X),
                                   absolute(swizzle(temp[0], X, X, X, X)),
  
                        emit_arith(rp, PFS_OP_MAD, dest, mask,
                                   swizzle(temp[0], Y, Y, Y, Y),
-                                  swizzle(rp->const_sin[0], W, W, W, W),
+                                  swizzle(const_sin[0], W, W, W, W),
                                   swizzle(temp[0], X, X, X, X),
                                   flags);
  
                                   0);
                        emit_arith(rp, PFS_OP_DP4, dest, mask,
                                   temp[0], src[1], undef,
-                                  flags);      
+                                  flags);
                        free_temp(rp, temp[0]);
  #else
                        emit_arith(rp, PFS_OP_DP4, dest, mask,
                                   swizzle(src[0], X, Y, Z, ONE), src[1],
-                                  undef, flags);       
+                                  undef, flags);
  #endif
                        break;
                case OPCODE_DST:
                                   src[0], undef, undef,
                                   flags);
                        break;
-               case OPCODE_FLR:                
+               case OPCODE_FLR:
                        src[0] = t_src(rp, fpi->SrcReg[0]);
                        temp[0] = get_temp_reg(rp);
                        /* FRC temp, src0
                                   flags);
                        break;
                case OPCODE_LIT:
-                       /* LIT
-                        * if (s.x < 0) t.x = 0; else t.x = s.x;
-                        * if (s.y < 0) t.y = 0; else t.y = s.y;
-                        * if (s.w >  128.0) t.w =  128.0; else t.w = s.w;
-                        * if (s.w < -128.0) t.w = -128.0; else t.w = s.w;
-                        * r.x = 1.0
-                        * if (t.x > 0) r.y = pow(t.y, t.w); else r.y = 0;
-                        * Also r.y = 0 if t.y < 0
-                        * For the t.x > 0 FGLRX use the CMPH opcode which
-                        * change the compare to (t.x + 0.5) > 0.5 we may
-                        * save one instruction by doing CMP -t.x 
-                        */
-                       cnstv[0] = cnstv[1] = cnstv[2] = cnstv[3] = 0.50001;
                        src[0] = t_src(rp, fpi->SrcReg[0]);
-                       temp[0] = get_temp_reg(rp);
-                       cnst = emit_const4fv(rp, cnstv);
-                       emit_arith(rp, PFS_OP_CMP, temp[0],
-                                  WRITEMASK_X | WRITEMASK_Y,
-                                  src[0], pfs_zero, src[0], flags);
-                       emit_arith(rp, PFS_OP_MIN, temp[0], WRITEMASK_Z,
-                                  swizzle(keep(src[0]), W, W, W, W),
-                                  cnst, undef, flags);
-                       emit_arith(rp, PFS_OP_LG2, temp[0], WRITEMASK_W,
-                                  swizzle(temp[0], Y, Y, Y, Y),
-                                  undef, undef, flags);
-                       emit_arith(rp, PFS_OP_MAX, temp[0], WRITEMASK_Z,
-                                  temp[0], negate(cnst), undef, flags);
-                       emit_arith(rp, PFS_OP_MAD, temp[0], WRITEMASK_W,
-                                  temp[0], swizzle(temp[0], Z, Z, Z, Z),
-                                  pfs_zero, flags);
-                       emit_arith(rp, PFS_OP_EX2, temp[0], WRITEMASK_W,
-                                  temp[0], undef, undef, flags);
-                       emit_arith(rp, PFS_OP_MAD, dest, WRITEMASK_Y,
-                                  swizzle(keep(temp[0]), X, X, X, X),
-                                  pfs_one, pfs_zero, flags);
- #if 0
-                       emit_arith(rp, PFS_OP_MAD, temp[0], WRITEMASK_X,
-                                  temp[0], pfs_one, pfs_half, flags);
-                       emit_arith(rp, PFS_OP_CMPH, temp[0], WRITEMASK_Z,
-                                  swizzle(keep(temp[0]), W, W, W, W),
-                                  pfs_zero, swizzle(keep(temp[0]), X, X, X, X),
-                                  flags);
- #else
-                       emit_arith(rp, PFS_OP_CMP, temp[0], WRITEMASK_Z,
-                                  pfs_zero,
-                                  swizzle(keep(temp[0]), W, W, W, W),
-                                  negate(swizzle(keep(temp[0]), X, X, X, X)),
-                                  flags);
- #endif
-                       emit_arith(rp, PFS_OP_CMP, dest, WRITEMASK_Z,
-                                  pfs_zero, temp[0],
-                                  negate(swizzle(keep(temp[0]), Y, Y, Y, Y)),
-                                  flags);
-                       emit_arith(rp, PFS_OP_MAD, dest,
-                                  WRITEMASK_X | WRITEMASK_W,
-                                  pfs_one,
-                                  pfs_one,
-                                  pfs_zero,
-                                  flags);
-                       free_temp(rp, temp[0]);
+                       emit_lit(rp, dest, mask, src[0], flags);
                        break;
                case OPCODE_LRP:
                        src[0] = t_src(rp, fpi->SrcReg[0]);
                                   src[0], src[1], temp[0],
                                   flags);
                        free_temp(rp, temp[0]);
-                       break;                  
+                       break;
                case OPCODE_MAD:
                        src[0] = t_src(rp, fpi->SrcReg[0]);
                        src[1] = t_src(rp, fpi->SrcReg[1]);
                case OPCODE_SWZ:
                        src[0] = t_src(rp, fpi->SrcReg[0]);
                        emit_arith(rp, PFS_OP_MAD, dest, mask,
-                                  src[0], pfs_one, pfs_zero, 
+                                  src[0], pfs_one, pfs_zero,
                                   flags);
                        break;
                case OPCODE_MUL:
                case OPCODE_POW:
                        src[0] = t_scalar_src(rp, fpi->SrcReg[0]);
                        src[1] = t_scalar_src(rp, fpi->SrcReg[1]);
-                       temp[0] = get_temp_reg(rp);     
+                       temp[0] = get_temp_reg(rp);
                        emit_arith(rp, PFS_OP_LG2, temp[0], WRITEMASK_W,
                                   src[0], undef, undef,
                                   0);
                         */
                        temp[0] = get_temp_reg(rp);
                        temp[1] = get_temp_reg(rp);
-                       make_sin_const(rp);
+                       const_sin[0] = emit_const4fv(rp, SinCosConsts[0]);
+                       const_sin[1] = emit_const4fv(rp, SinCosConsts[1]);
                        src[0] = t_scalar_src(rp, fpi->SrcReg[0]);
  
                        /* x = -abs(x)+0.5*PI */
                        emit_arith(rp, PFS_OP_MAD, temp[0], WRITEMASK_Z,
-                                  swizzle(rp->const_sin[0], Z, Z, Z, Z), //PI
+                                  swizzle(const_sin[0], Z, Z, Z, Z), //PI
                                   pfs_half,
                                   negate(abs(swizzle(keep(src[0]), X, X, X, X))),
                                   0);
  
                        /* C*x (sin) */
                        emit_arith(rp, PFS_OP_MAD, temp[0], WRITEMASK_W,
-                                  swizzle(rp->const_sin[0], Y, Y, Y, Y),
+                                  swizzle(const_sin[0], Y, Y, Y, Y),
                                   swizzle(keep(src[0]), X, X, X, X),
                                   pfs_zero,
                                   0);
                        /* B*x, C*x (cos) */
                        emit_arith(rp, PFS_OP_MAD, temp[0], WRITEMASK_X | WRITEMASK_Y,
                                   swizzle(temp[0], Z, Z, Z, Z),
-                                  rp->const_sin[0],
+                                  const_sin[0],
                                   pfs_zero,
                                   0);
  
                        /* B*x (sin) */
                        emit_arith(rp, PFS_OP_MAD, temp[1], WRITEMASK_W,
-                                  swizzle(rp->const_sin[0], X, X, X, X),
+                                  swizzle(const_sin[0], X, X, X, X),
                                   keep(src[0]),
                                   pfs_zero,
                                   0);
                        /* dest.xy = mad(temp.xy, P, temp2.wz) */
                        emit_arith(rp, PFS_OP_MAD, dest, mask & (WRITEMASK_X | WRITEMASK_Y),
                                   temp[0],
-                                  swizzle(rp->const_sin[0], W, W, W, W),
+                                  swizzle(const_sin[0], W, W, W, W),
                                   swizzle(temp[1], W, Z, Y, X),
                                   flags);
  
                         */
  
                        temp[0] = get_temp_reg(rp);
-                       make_sin_const(rp);
+                       const_sin[0] = emit_const4fv(rp, SinCosConsts[0]);
+                       const_sin[1] = emit_const4fv(rp, SinCosConsts[1]);
                        src[0] = t_scalar_src(rp, fpi->SrcReg[0]);
  
  
  
                        emit_arith(rp, PFS_OP_MAD, temp[0], WRITEMASK_X,
                                   swizzle(keep(src[0]), X, X, X, X),
-                                  swizzle(rp->const_sin[1], Z, Z, Z, Z),
+                                  swizzle(const_sin[1], Z, Z, Z, Z),
                                   pfs_half,
                                   0);
  
  
                        emit_arith(rp, PFS_OP_MAD, temp[0], WRITEMASK_Z,
                                   swizzle(temp[0], X, X, X, X),
-                                  swizzle(rp->const_sin[1], W, W, W, W), //2*PI
-                                  negate(swizzle(rp->const_sin[0], Z, Z, Z, Z)), //PI
+                                  swizzle(const_sin[1], W, W, W, W), //2*PI
+                                  negate(swizzle(const_sin[0], Z, Z, Z, Z)), //PI
                                   0);
  
                        /* SIN */
  
                        emit_arith(rp, PFS_OP_MAD, temp[0], WRITEMASK_X | WRITEMASK_Y,
                                   swizzle(temp[0], Z, Z, Z, Z),
-                                  rp->const_sin[0],
+                                  const_sin[0],
                                   pfs_zero,
                                   0);
  
                                   absolute(swizzle(temp[0], Z, Z, Z, Z)),
                                   swizzle(temp[0], X, X, X, X),
                                   0);
-                       
                        emit_arith(rp, PFS_OP_MAD, temp[0], WRITEMASK_Y,
                                   swizzle(temp[0], X, X, X, X),
                                   absolute(swizzle(temp[0], X, X, X, X)),
  
                        emit_arith(rp, PFS_OP_MAD, dest, mask,
                                   swizzle(temp[0], Y, Y, Y, Y),
-                                  swizzle(rp->const_sin[0], W, W, W, W),
+                                  swizzle(const_sin[0], W, W, W, W),
                                   swizzle(temp[0], X, X, X, X),
                                   flags);
  
                                   swizzle(keep(src[1]), Y, Z, X, W),
                                   pfs_zero,
                                   0);
-                       /* dest.xyz = src0.yzx * src1.zxy - temp 
+                       /* dest.xyz = src0.yzx * src1.zxy - temp
                         * dest.w       = undefined
                         * */
                        emit_arith(rp, PFS_OP_MAD, dest, mask & WRITEMASK_XYZ,
        return GL_TRUE;
  }
  
+ static void insert_wpos(struct gl_program *prog)
+ {
+       GLint tokens[6] = { STATE_INTERNAL, STATE_R300_WINDOW_DIMENSION, 0, 0, 0, 0 };
+       struct prog_instruction *fpi;
+       GLuint window_index;
+       int i = 0;
+       GLuint tempregi = prog->NumTemporaries;
+       /* should do something else if no temps left... */
+       prog->NumTemporaries++;
+       fpi = _mesa_alloc_instructions (prog->NumInstructions + 3);
+       _mesa_init_instructions (fpi, prog->NumInstructions + 3);
+       /* perspective divide */
+       fpi[i].Opcode = OPCODE_RCP;
+       fpi[i].DstReg.File = PROGRAM_TEMPORARY;
+       fpi[i].DstReg.Index = tempregi;
+       fpi[i].DstReg.WriteMask = WRITEMASK_W;
+       fpi[i].DstReg.CondMask = COND_TR;
+       fpi[i].SrcReg[0].File = PROGRAM_INPUT;
+       fpi[i].SrcReg[0].Index = FRAG_ATTRIB_WPOS;
+       fpi[i].SrcReg[0].Swizzle = SWIZZLE_WWWW;
+       i++;
+       fpi[i].Opcode = OPCODE_MUL;
+       fpi[i].DstReg.File = PROGRAM_TEMPORARY;
+       fpi[i].DstReg.Index = tempregi;
+       fpi[i].DstReg.WriteMask = WRITEMASK_XYZ;
+       fpi[i].DstReg.CondMask = COND_TR;
+       fpi[i].SrcReg[0].File = PROGRAM_INPUT;
+       fpi[i].SrcReg[0].Index = FRAG_ATTRIB_WPOS;
+       fpi[i].SrcReg[0].Swizzle = SWIZZLE_XYZW;
+       fpi[i].SrcReg[1].File = PROGRAM_TEMPORARY;
+       fpi[i].SrcReg[1].Index = tempregi;
+       fpi[i].SrcReg[1].Swizzle = SWIZZLE_WWWW;
+       i++;
+       /* viewport transformation */
+       window_index = _mesa_add_state_reference(prog->Parameters, tokens);
+       fpi[i].Opcode = OPCODE_MAD;
+       fpi[i].DstReg.File = PROGRAM_TEMPORARY;
+       fpi[i].DstReg.Index = tempregi;
+       fpi[i].DstReg.WriteMask = WRITEMASK_XYZ;
+       fpi[i].DstReg.CondMask = COND_TR;
+       fpi[i].SrcReg[0].File = PROGRAM_TEMPORARY;
+       fpi[i].SrcReg[0].Index = tempregi;
+       fpi[i].SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ZERO);
+       fpi[i].SrcReg[1].File = PROGRAM_STATE_VAR;
+       fpi[i].SrcReg[1].Index = window_index;
+       fpi[i].SrcReg[1].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ZERO);
+       fpi[i].SrcReg[2].File = PROGRAM_STATE_VAR;
+       fpi[i].SrcReg[2].Index = window_index;
+       fpi[i].SrcReg[2].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ZERO);
+       i++;
+       _mesa_copy_instructions (&fpi[i], prog->Instructions, prog->NumInstructions);
+       free(prog->Instructions);
+       prog->Instructions = fpi;
+       prog->NumInstructions += i;
+       fpi = &prog->Instructions[prog->NumInstructions-1];
+       assert(fpi->Opcode == OPCODE_END);
+       for(fpi = &prog->Instructions[3]; fpi->Opcode != OPCODE_END; fpi++){
+               for(i=0; i<3; i++)
+                   if( fpi->SrcReg[i].File == PROGRAM_INPUT &&
+                       fpi->SrcReg[i].Index == FRAG_ATTRIB_WPOS ){
+                           fpi->SrcReg[i].File = PROGRAM_TEMPORARY;
+                           fpi->SrcReg[i].Index = tempregi;
+                   }
+       }
+ }
  /* - Init structures
   * - Determine what hwregs each input corresponds to
   */
  static void init_program(r300ContextPtr r300, struct r300_fragment_program *rp)
  {
        struct r300_pfs_compile_state *cs = NULL;
-       struct gl_fragment_program *mp = &rp->mesa_program;     
+       struct gl_fragment_program *mp = &rp->mesa_program;
        struct prog_instruction *fpi;
        GLuint InputsRead = mp->Base.InputsRead;
        GLuint temps_used = 0; /* for rp->temps[] */
        rp->cur_node   = 0;
        rp->first_node_has_tex = 0;
        rp->const_nr   = 0;
-       rp->param_nr   = 0;
-       rp->params_uptodate = GL_FALSE;
        rp->max_temp_idx = 0;
        rp->node[0].alu_end = -1;
        rp->node[0].tex_end = -1;
-       rp->const_sin[0] = -1;
-       
        _mesa_memset(cs, 0, sizeof(*rp->cs));
        for (i=0;i<PFS_MAX_ALU_INST;i++) {
                for (j=0;j<3;j++) {
                        cs->slot[i].ssrc[j] = SRC_CONST;
                }
        }
-       
        /* Work out what temps the Mesa inputs correspond to, this must match
         * what setup_rs_unit does, which shouldn't be a problem as rs_unit
         * configures itself based on the fragprog's InputsRead
        for (i=0;i<rp->ctx->Const.MaxTextureUnits;i++) {
                if (InputsRead & (FRAG_BIT_TEX0 << i)) {
                        cs->inputs[FRAG_ATTRIB_TEX0+i].refcount = 0;
-                       cs->inputs[FRAG_ATTRIB_TEX0+i].reg = get_hw_temp(rp);
+                       cs->inputs[FRAG_ATTRIB_TEX0+i].reg = get_hw_temp(rp, 0);
                }
        }
        InputsRead &= ~FRAG_BITS_TEX_ANY;
        /* fragment position treated as a texcoord */
        if (InputsRead & FRAG_BIT_WPOS) {
                cs->inputs[FRAG_ATTRIB_WPOS].refcount = 0;
-               cs->inputs[FRAG_ATTRIB_WPOS].reg = get_hw_temp(rp);
+               cs->inputs[FRAG_ATTRIB_WPOS].reg = get_hw_temp(rp, 0);
+               insert_wpos(&mp->Base);
        }
        InputsRead &= ~FRAG_BIT_WPOS;
  
        /* Then primary colour */
        if (InputsRead & FRAG_BIT_COL0) {
                cs->inputs[FRAG_ATTRIB_COL0].refcount = 0;
-               cs->inputs[FRAG_ATTRIB_COL0].reg = get_hw_temp(rp);
+               cs->inputs[FRAG_ATTRIB_COL0].reg = get_hw_temp(rp, 0);
        }
        InputsRead &= ~FRAG_BIT_COL0;
-       
        /* Secondary color */
        if (InputsRead & FRAG_BIT_COL1) {
                cs->inputs[FRAG_ATTRIB_COL1].refcount = 0;
-               cs->inputs[FRAG_ATTRIB_COL1].reg = get_hw_temp(rp);
+               cs->inputs[FRAG_ATTRIB_COL1].reg = get_hw_temp(rp, 0);
        }
        InputsRead &= ~FRAG_BIT_COL1;
  
  
        for (fpi=mp->Base.Instructions;fpi->Opcode != OPCODE_END; fpi++) {
                int idx;
-               
                for (i=0;i<3;i++) {
                        idx = fpi->SrcReg[i].Index;
                        switch (fpi->SrcReg[i].File) {
  static void update_params(struct r300_fragment_program *rp)
  {
        struct gl_fragment_program *mp = &rp->mesa_program;
-       int i;
  
        /* Ask Mesa nicely to fill in ParameterValues for us */
-       if (rp->param_nr)
+       if (mp->Base.Parameters)
                _mesa_load_state_parameters(rp->ctx, mp->Base.Parameters);
-       for (i=0;i<rp->param_nr;i++)
-               COPY_4V(rp->constant[rp->param[i].idx], rp->param[i].values);
-       rp->params_uptodate = GL_TRUE;
  }
  
  void r300_translate_fragment_shader(r300ContextPtr r300, struct r300_fragment_program *rp)
        struct r300_pfs_compile_state *cs = NULL;
  
        if (!rp->translated) {
-               
                init_program(r300, rp);
                cs = rp->cs;
  
                        dump_program(rp);
                        return;
                }
-               
                /* Finish off */
-               cs->v_pos = cs->s_pos = MAX2(cs->v_pos, cs->s_pos);
                rp->node[rp->cur_node].alu_end =
-                               cs->v_pos - rp->node[rp->cur_node].alu_offset - 1;
+                               cs->nrslots - rp->node[rp->cur_node].alu_offset - 1;
                if (rp->node[rp->cur_node].tex_end < 0)
                        rp->node[rp->cur_node].tex_end = 0;
                rp->alu_offset = 0;
-               rp->alu_end    = cs->v_pos - 1;
+               rp->alu_end    = cs->nrslots - 1;
                rp->tex_offset = 0;
                rp->tex_end    = rp->tex.length ? rp->tex.length - 1 : 0;
                assert(rp->node[rp->cur_node].alu_end >= 0);
                assert(rp->alu_end >= 0);
-       
                rp->translated = GL_TRUE;
-               if (0) dump_program(rp);
+               if (RADEON_DEBUG & DEBUG_PIXEL) dump_program(rp);
+               r300UpdateStateParameters(rp->ctx, _NEW_PROGRAM);
        }
  
        update_params(rp);
  /* just some random things... */
  static void dump_program(struct r300_fragment_program *rp)
  {
-       int i;
+       int n, i, j;
        static int pc = 0;
  
        fprintf(stderr, "pc=%d*************************************\n", pc++);
-                       
        fprintf(stderr, "Mesa program:\n");
        fprintf(stderr, "-------------\n");
                _mesa_print_program(&rp->mesa_program.Base);
  
        fprintf(stderr, "Hardware program\n");
        fprintf(stderr, "----------------\n");
-       
-       fprintf(stderr, "tex:\n");
-       
-       for(i=0;i<rp->tex.length;i++) {
-               fprintf(stderr, "%08x\n", rp->tex.inst[i]);
-       }
-       
-       for (i=0;i<(rp->cur_node+1);i++) {
+       for (n = 0; n < (rp->cur_node+1); n++) {
                fprintf(stderr, "NODE %d: alu_offset: %d, tex_offset: %d, "\
-                       "alu_end: %d, tex_end: %d\n", i,
-                       rp->node[i].alu_offset,
-                       rp->node[i].tex_offset,
-                       rp->node[i].alu_end,
-                       rp->node[i].tex_end);
+                       "alu_end: %d, tex_end: %d\n", n,
+                       rp->node[n].alu_offset,
+                       rp->node[n].tex_offset,
+                       rp->node[n].alu_end,
+                       rp->node[n].tex_end);
+               if (rp->tex.length) {
+                       fprintf(stderr, "  TEX:\n");
+                       for(i = rp->node[n].tex_offset; i <= rp->node[n].tex_offset+rp->node[n].tex_end; ++i) {
+                               const char* instr;
+                               switch((rp->tex.inst[i] >> R300_FPITX_OPCODE_SHIFT) & 15) {
+                               case R300_FPITX_OP_TEX:
+                                       instr = "TEX";
+                                       break;
+                               case R300_FPITX_OP_KIL:
+                                       instr = "KIL";
+                                       break;
+                               case R300_FPITX_OP_TXP:
+                                       instr = "TXP";
+                                       break;
+                               case R300_FPITX_OP_TXB:
+                                       instr = "TXB";
+                                       break;
+                               default:
+                                       instr = "UNKNOWN";
+                               }
+                               fprintf(stderr, "    %s t%i, %c%i, texture[%i]   (%08x)\n",
+                                               instr,
+                                               (rp->tex.inst[i] >> R300_FPITX_DST_SHIFT) & 31,
+                                               (rp->tex.inst[i] & R300_FPITX_SRC_CONST) ? 'c': 't',
+                                               (rp->tex.inst[i] >> R300_FPITX_SRC_SHIFT) & 31,
+                                               (rp->tex.inst[i] & R300_FPITX_IMAGE_MASK) >> R300_FPITX_IMAGE_SHIFT,
+                                               rp->tex.inst[i]);
+                       }
+               }
+               for(i = rp->node[n].alu_offset; i <= rp->node[n].alu_offset+rp->node[n].alu_end; ++i) {
+                       char srcc[3][10], dstc[20];
+                       char srca[3][10], dsta[20];
+                       char argc[3][20];
+                       char arga[3][20];
+                       char flags[5], tmp[10];
+                       for(j = 0; j < 3; ++j) {
+                               int regc = rp->alu.inst[i].inst1 >> (j*6);
+                               int rega = rp->alu.inst[i].inst3 >> (j*6);
+                               sprintf(srcc[j], "%c%i", (regc & 32) ? 'c' : 't', regc & 31);
+                               sprintf(srca[j], "%c%i", (rega & 32) ? 'c' : 't', rega & 31);
+                       }
+                       dstc[0] = 0;
+                       sprintf(flags, "%s%s%s",
+                                       (rp->alu.inst[i].inst1 & R300_FPI1_DSTC_REG_X) ? "x" : "",
+                                       (rp->alu.inst[i].inst1 & R300_FPI1_DSTC_REG_Y) ? "y" : "",
+                                       (rp->alu.inst[i].inst1 & R300_FPI1_DSTC_REG_Z) ? "z" : "");
+                       if (flags[0] != 0) {
+                               sprintf(dstc, "t%i.%s ",
+                                               (rp->alu.inst[i].inst1 >> R300_FPI1_DSTC_SHIFT) & 31,
+                                               flags);
+                       }
+                       sprintf(flags, "%s%s%s",
+                                       (rp->alu.inst[i].inst1 & R300_FPI1_DSTC_OUTPUT_X) ? "x" : "",
+                                       (rp->alu.inst[i].inst1 & R300_FPI1_DSTC_OUTPUT_Y) ? "y" : "",
+                                       (rp->alu.inst[i].inst1 & R300_FPI1_DSTC_OUTPUT_Z) ? "z" : "");
+                       if (flags[0] != 0) {
+                               sprintf(tmp, "o%i.%s",
+                                               (rp->alu.inst[i].inst1 >> R300_FPI1_DSTC_SHIFT) & 31,
+                                               flags);
+                               strcat(dstc, tmp);
+                       }
+                       dsta[0] = 0;
+                       if (rp->alu.inst[i].inst3 & R300_FPI3_DSTA_REG) {
+                               sprintf(dsta, "t%i.w ", (rp->alu.inst[i].inst3 >> R300_FPI3_DSTA_SHIFT) & 31);
+                       }
+                       if (rp->alu.inst[i].inst3 & R300_FPI3_DSTA_OUTPUT) {
+                               sprintf(tmp, "o%i.w ", (rp->alu.inst[i].inst3 >> R300_FPI3_DSTA_SHIFT) & 31);
+                               strcat(dsta, tmp);
+                       }
+                       if (rp->alu.inst[i].inst3 & R300_FPI3_DSTA_DEPTH) {
+                               strcat(dsta, "Z");
+                       }
+                       fprintf(stderr, "%3i: xyz: %3s %3s %3s -> %-20s (%08x)\n"
+                                       "       w: %3s %3s %3s -> %-20s (%08x)\n",
+                                       i,
+                                       srcc[0], srcc[1], srcc[2], dstc, rp->alu.inst[i].inst1,
+                                       srca[0], srca[1], srca[2], dsta, rp->alu.inst[i].inst3);
+                       for(j = 0; j < 3; ++j) {
+                               int regc = rp->alu.inst[i].inst0 >> (j*7);
+                               int rega = rp->alu.inst[i].inst2 >> (j*7);
+                               int d;
+                               char buf[20];
+                               d = regc & 31;
+                               if (d < 12) {
+                                       switch(d % 4) {
+                                               case R300_FPI0_ARGC_SRC0C_XYZ:
+                                                       sprintf(buf, "%s.xyz", srcc[d / 4]);
+                                                       break;
+                                               case R300_FPI0_ARGC_SRC0C_XXX:
+                                                       sprintf(buf, "%s.xxx", srcc[d / 4]);
+                                                       break;
+                                               case R300_FPI0_ARGC_SRC0C_YYY:
+                                                       sprintf(buf, "%s.yyy", srcc[d / 4]);
+                                                       break;
+                                               case R300_FPI0_ARGC_SRC0C_ZZZ:
+                                                       sprintf(buf, "%s.zzz", srcc[d / 4]);
+                                                       break;
+                                       }
+                               } else if (d < 15) {
+                                       sprintf(buf, "%s.www", srca[d-12]);
+                               } else if (d == 20) {
+                                       sprintf(buf, "0.0");
+                               } else if (d == 21) {
+                                       sprintf(buf, "1.0");
+                               } else if (d == 22) {
+                                       sprintf(buf, "0.5");
+                               } else if (d >= 23 && d < 32) {
+                                       d -= 23;
+                                       switch(d/3) {
+                                               case 0:
+                                                       sprintf(buf, "%s.yzx", srcc[d % 3]);
+                                                       break;
+                                               case 1:
+                                                       sprintf(buf, "%s.zxy", srcc[d % 3]);
+                                                       break;
+                                               case 2:
+                                                       sprintf(buf, "%s.Wzy", srcc[d % 3]);
+                                                       break;
+                                       }
+                               } else {
+                                       sprintf(buf, "%i", d);
+                               }
+                               sprintf(argc[j], "%s%s%s%s",
+                                               (regc & 32) ? "-" : "",
+                                               (regc & 64) ? "|" : "",
+                                               buf,
+                                               (regc & 64) ? "|" : "");
+                               d = rega & 31;
+                               if (d < 9) {
+                                       sprintf(buf, "%s.%c", srcc[d / 3], 'x' + (char)(d%3));
+                               } else if (d < 12) {
+                                       sprintf(buf, "%s.w", srca[d-9]);
+                               } else if (d == 16) {
+                                       sprintf(buf, "0.0");
+                               } else if (d == 17) {
+                                       sprintf(buf, "1.0");
+                               } else if (d == 18) {
+                                       sprintf(buf, "0.5");
+                               } else {
+                                       sprintf(buf, "%i", d);
+                               }
+                               sprintf(arga[j], "%s%s%s%s",
+                                               (rega & 32) ? "-" : "",
+                                               (rega & 64) ? "|" : "",
+                                               buf,
+                                               (rega & 64) ? "|" : "");
+                       }
+                       fprintf(stderr, "     xyz: %8s %8s %8s    op: %08x\n"
+                                       "       w: %8s %8s %8s    op: %08x\n",
+                                       argc[0], argc[1], argc[2], rp->alu.inst[i].inst0,
+                                       arga[0], arga[1], arga[2], rp->alu.inst[i].inst2);
+               }
        }
-       
-       fprintf(stderr, "%08x\n",
-               ((rp->tex_end << 16) | (R300_PFS_TEXI_0 >> 2)));
-       for (i=0;i<=rp->tex_end;i++)
-               fprintf(stderr, "%08x\n", rp->tex.inst[i]);
-       /* dump program in pretty_print_command_stream.tcl-readable format */
-       fprintf(stderr, "%08x\n",
-               ((rp->alu_end << 16) | (R300_PFS_INSTR0_0 >> 2)));
-       for (i=0;i<=rp->alu_end;i++)
-               fprintf(stderr, "%08x\n", rp->alu.inst[i].inst0);
-       fprintf(stderr, "%08x\n",
-               ((rp->alu_end << 16) | (R300_PFS_INSTR1_0 >> 2)));
-       for (i=0;i<=rp->alu_end;i++)
-               fprintf(stderr, "%08x\n", rp->alu.inst[i].inst1);
-       fprintf(stderr, "%08x\n",
-               ((rp->alu_end << 16) | (R300_PFS_INSTR2_0 >> 2)));
-       for (i=0;i<=rp->alu_end;i++)
-               fprintf(stderr, "%08x\n", rp->alu.inst[i].inst2);
-       fprintf(stderr, "%08x\n",
-               ((rp->alu_end << 16) | (R300_PFS_INSTR3_0 >> 2)));
-       for (i=0;i<=rp->alu_end;i++)
-               fprintf(stderr, "%08x\n", rp->alu.inst[i].inst3);
-       fprintf(stderr, "00000000\n");
  }
index 50dcee4755953ef3a6462537146b768124076fbd,fcb61a2831600399719805c14fdc1ab047a67be9..fff11653de1451faa6f34961c15c17ef148a6840
@@@ -46,8 -46,6 +46,8 @@@ WITH THE SOFTWARE OR THE USE OR OTHER D
  #include "api_arrayelt.h"
  #include "swrast/swrast.h"
  #include "swrast_setup/swrast_setup.h"
 +#include "shader/prog_parameter.h"
 +#include "shader/prog_statevars.h"
  #include "vbo/vbo.h"
  #include "tnl/tnl.h"
  #include "texformat.h"
@@@ -71,14 -69,14 +71,14 @@@ static void r300BlendColor(GLcontext * 
        GLubyte color[4];
        r300ContextPtr rmesa = R300_CONTEXT(ctx);
  
-       R300_STATECHANGE(rmesa, unk4E10);
+       R300_STATECHANGE(rmesa, blend_color);
  
        CLAMPED_FLOAT_TO_UBYTE(color[0], cf[0]);
        CLAMPED_FLOAT_TO_UBYTE(color[1], cf[1]);
        CLAMPED_FLOAT_TO_UBYTE(color[2], cf[2]);
        CLAMPED_FLOAT_TO_UBYTE(color[3], cf[3]);
  
-       rmesa->hw.unk4E10.cmd[1] = r300PackColor(4, color[3], color[0],
+       rmesa->hw.blend_color.cmd[1] = r300PackColor(4, color[3], color[0],
                                                 color[1], color[2]);
  }
  
@@@ -337,17 -335,17 +337,17 @@@ static void update_early_z(GLcontext *c
        */
        r300ContextPtr r300 = R300_CONTEXT(ctx);
  
-       R300_STATECHANGE(r300, unk4F10);
+       R300_STATECHANGE(r300, zstencil_format);
        if (ctx->Color.AlphaEnabled && ctx->Color.AlphaFunc != GL_ALWAYS)
                /* disable early Z */
-               r300->hw.unk4F10.cmd[2] = R300_EARLY_Z_DISABLE;
+               r300->hw.zstencil_format.cmd[2] = R300_EARLY_Z_DISABLE;
        else {
                if (ctx->Depth.Test && ctx->Depth.Func != GL_NEVER)
                        /* enable early Z */
-                       r300->hw.unk4F10.cmd[2] = R300_EARLY_Z_ENABLE;
+                       r300->hw.zstencil_format.cmd[2] = R300_EARLY_Z_ENABLE;
                else
                        /* disable early Z */
-                       r300->hw.unk4F10.cmd[2] = R300_EARLY_Z_DISABLE;
+                       r300->hw.zstencil_format.cmd[2] = R300_EARLY_Z_DISABLE;
        }
  }
  
@@@ -533,11 -531,11 +533,11 @@@ static void r300Enable(GLcontext* ctx, 
                break;
  
        case GL_POLYGON_OFFSET_FILL:
-               R300_STATECHANGE(r300, unk42B4);
+               R300_STATECHANGE(r300, occlusion_cntl);
                if(state){
-                       r300->hw.unk42B4.cmd[1] |= (3<<0);
+                       r300->hw.occlusion_cntl.cmd[1] |= (3<<0);
                } else {
-                       r300->hw.unk42B4.cmd[1] &= ~(3<<0);
+                       r300->hw.occlusion_cntl.cmd[1] &= ~(3<<0);
                }
                break;
        default:
@@@ -591,9 -589,9 +591,9 @@@ static void r300UpdatePolygonMode(GLcon
                }
        }
  
-       if (r300->hw.unk4288.cmd[1] != hw_mode) {
-               R300_STATECHANGE(r300, unk4288);
-               r300->hw.unk4288.cmd[1] = hw_mode;
+       if (r300->hw.polygon_mode.cmd[1] != hw_mode) {
+               R300_STATECHANGE(r300, polygon_mode);
+               r300->hw.polygon_mode.cmd[1] = hw_mode;
        }
  }
  
@@@ -832,13 -830,13 +832,13 @@@ static void r300ShadeModel(GLcontext * 
  {
        r300ContextPtr rmesa = R300_CONTEXT(ctx);
        
-       R300_STATECHANGE(rmesa, unk4274);
+       R300_STATECHANGE(rmesa, shade);
        switch (mode) {
        case GL_FLAT:
-               rmesa->hw.unk4274.cmd[2] = R300_RE_SHADE_MODEL_FLAT;
+               rmesa->hw.shade.cmd[2] = R300_RE_SHADE_MODEL_FLAT;
                break;
        case GL_SMOOTH:
-               rmesa->hw.unk4274.cmd[2] = R300_RE_SHADE_MODEL_SMOOTH;
+               rmesa->hw.shade.cmd[2] = R300_RE_SHADE_MODEL_SMOOTH;
                break;
        default:
                return;
@@@ -1057,10 -1055,8 +1057,10 @@@ r300UpdateDrawBuffer(GLcontext *ctx
  #endif
  }
  
 -static void r300FetchStateParameter(GLcontext *ctx, const enum state_index state[],
 -                  GLfloat *value)
 +static void
 +r300FetchStateParameter(GLcontext *ctx,
 +                        const gl_state_index state[STATE_LENGTH],
 +                        GLfloat *value)
  {
      r300ContextPtr r300 = R300_CONTEXT(ctx);
  
        switch(state[1])
        {
        case STATE_R300_WINDOW_DIMENSION:
-           value[0] = r300->radeon.dri.drawable->w;    /* width */
-           value[1] = r300->radeon.dri.drawable->h;    /* height */
+           value[0] = r300->radeon.dri.drawable->w*0.5f;/* width*0.5 */
+           value[1] = r300->radeon.dri.drawable->h*0.5f;/* height*0.5 */
            value[2] = 0.5F;                            /* for moving range [-1 1] -> [0 1] */
            value[3] = 1.0F;                            /* not used */
            break;
   * Update R300's own internal state parameters.
   * For now just STATE_R300_WINDOW_DIMENSION
   */
static void r300UpdateStateParameters(GLcontext * ctx, GLuint new_state)
+ void r300UpdateStateParameters(GLcontext * ctx, GLuint new_state)
  {
-       struct r300_vertex_program_cont *vpc;
+       struct r300_fragment_program *fp;
        struct gl_program_parameter_list *paramList;
        GLuint i;
  
        if(!(new_state & (_NEW_BUFFERS|_NEW_PROGRAM)))
            return;
  
-       vpc = (struct r300_vertex_program_cont *)ctx->VertexProgram._Current;
-       if (!vpc)
+       fp = (struct r300_fragment_program *)ctx->FragmentProgram._Current;
+       if (!fp)
            return;
  
-       paramList = vpc->mesa_program.Base.Parameters;
+       paramList = fp->mesa_program.Base.Parameters;
  
        if (!paramList)
            return;
@@@ -1221,12 -1217,12 +1221,12 @@@ void r300_setup_textures(GLcontext *ctx
  
        R300_STATECHANGE(r300, txe);
        R300_STATECHANGE(r300, tex.filter);
-       R300_STATECHANGE(r300, tex.unknown1);
+       R300_STATECHANGE(r300, tex.filter_1);
        R300_STATECHANGE(r300, tex.size);
        R300_STATECHANGE(r300, tex.format);
        R300_STATECHANGE(r300, tex.pitch);
        R300_STATECHANGE(r300, tex.offset);
-       R300_STATECHANGE(r300, tex.unknown4);
+       R300_STATECHANGE(r300, tex.chroma_key);
        R300_STATECHANGE(r300, tex.border_color);
        
        r300->hw.txe.cmd[R300_TXE_ENABLE]=0x0;
                        
                        r300->hw.tex.filter.cmd[R300_TEX_VALUE_0 + hw_tmu] = gen_fixed_filter(t->filter) | (hw_tmu << 28);
                        /* Currently disabled! */
-                       r300->hw.tex.unknown1.cmd[R300_TEX_VALUE_0 + hw_tmu] = 0x0; //0x20501f80;
+                       r300->hw.tex.filter_1.cmd[R300_TEX_VALUE_0 + hw_tmu] = 0x0; //0x20501f80;
                        r300->hw.tex.size.cmd[R300_TEX_VALUE_0 + hw_tmu] = t->size;
                        r300->hw.tex.format.cmd[R300_TEX_VALUE_0 + hw_tmu] = t->format;
                        r300->hw.tex.pitch.cmd[R300_TEX_VALUE_0 + hw_tmu] = t->pitch_reg;
                                WARN_ONCE("micro tiling enabled!\n");
                        }
                        
-                       r300->hw.tex.unknown4.cmd[R300_TEX_VALUE_0 + hw_tmu] = 0x0;
+                       r300->hw.tex.chroma_key.cmd[R300_TEX_VALUE_0 + hw_tmu] = 0x0;
                        r300->hw.tex.border_color.cmd[R300_TEX_VALUE_0 + hw_tmu] = t->pp_border_color;
                        
                        last_hw_tmu = hw_tmu;
        }
        
        r300->hw.tex.filter.cmd[R300_TEX_CMD_0] = cmdpacket0(R300_TX_FILTER_0, last_hw_tmu + 1);
-       r300->hw.tex.unknown1.cmd[R300_TEX_CMD_0] = cmdpacket0(R300_TX_FILTER1_0, last_hw_tmu + 1);
+       r300->hw.tex.filter_1.cmd[R300_TEX_CMD_0] = cmdpacket0(R300_TX_FILTER1_0, last_hw_tmu + 1);
        r300->hw.tex.size.cmd[R300_TEX_CMD_0] = cmdpacket0(R300_TX_SIZE_0, last_hw_tmu + 1);
        r300->hw.tex.format.cmd[R300_TEX_CMD_0] = cmdpacket0(R300_TX_FORMAT_0, last_hw_tmu + 1);
        r300->hw.tex.pitch.cmd[R300_TEX_CMD_0] = cmdpacket0(R300_TX_PITCH_0, last_hw_tmu + 1);
        r300->hw.tex.offset.cmd[R300_TEX_CMD_0] = cmdpacket0(R300_TX_OFFSET_0, last_hw_tmu + 1);
-       r300->hw.tex.unknown4.cmd[R300_TEX_CMD_0] = cmdpacket0(R300_TX_CHROMA_KEY_0, last_hw_tmu + 1);
+       r300->hw.tex.chroma_key.cmd[R300_TEX_CMD_0] = cmdpacket0(R300_TX_CHROMA_KEY_0, last_hw_tmu + 1);
        r300->hw.tex.border_color.cmd[R300_TEX_CMD_0] = cmdpacket0(R300_TX_BORDER_COLOR_0, last_hw_tmu + 1);
        
        
@@@ -1977,7 -1973,7 +1977,7 @@@ void r300ResetHwState(r300ContextPtr r3
                /* Initialize magic registers
                 TODO : learn what they really do, or get rid of
                 those we don't have to touch */
-       r300->hw.unk2080.cmd[1] = 0x0030045A; //0x0030065a /* Dangerous */
+       r300->hw.vap_cntl.cmd[1] = 0x0030045A; //0x0030065a /* Dangerous */
  
        r300->hw.vte.cmd[1] = R300_VPORT_X_SCALE_ENA
                                | R300_VPORT_X_OFFSET_ENA
        r300->hw.unk2134.cmd[1] = 0x00FFFFFF;
        r300->hw.unk2134.cmd[2] = 0x00000000;
        if (_mesa_little_endian())
-               r300->hw.unk2140.cmd[1] = 0x00000000;
+               r300->hw.vap_cntl_status.cmd[1] = 0x00000000;
        else
-               r300->hw.unk2140.cmd[1] = 0x00000002;
+               r300->hw.vap_cntl_status.cmd[1] = 0x00000002;
  
  #if 0 /* Done in setup routing */
        ((drm_r300_cmd_header_t*)r300->hw.vir[0].cmd)->packet0.count = 1;
        r300->hw.unk4260.cmd[2] = r300PackFloat32(0.0);
        r300->hw.unk4260.cmd[3] = r300PackFloat32(1.0);
  
-       r300->hw.unk4274.cmd[1] = 0x00000002;
+       r300->hw.shade.cmd[1] = 0x00000002;
        r300ShadeModel(ctx, ctx->Light.ShadeModel);
-       r300->hw.unk4274.cmd[3] = 0x00000000;
-       r300->hw.unk4274.cmd[4] = 0x00000000;
+       r300->hw.shade.cmd[3] = 0x00000000;
+       r300->hw.shade.cmd[4] = 0x00000000;
  
        r300PolygonMode(ctx, GL_FRONT, ctx->Polygon.FrontMode);
        r300PolygonMode(ctx, GL_BACK, ctx->Polygon.BackMode);
-       r300->hw.unk4288.cmd[2] = 0x00000001;
-       r300->hw.unk4288.cmd[3] = 0x00000000;
-       r300->hw.unk42A0.cmd[1] = 0x00000000;
+       r300->hw.polygon_mode.cmd[2] = 0x00000001;
+       r300->hw.polygon_mode.cmd[3] = 0x00000000;
+       r300->hw.zbias_cntl.cmd[1] = 0x00000000;
  
        r300PolygonOffset(ctx, ctx->Polygon.OffsetFactor, ctx->Polygon.OffsetUnits);
        r300Enable(ctx, GL_POLYGON_OFFSET_FILL, ctx->Polygon.OffsetFill);
  #endif
  
        r300BlendColor(ctx, ctx->Color.BlendColor);
-       r300->hw.unk4E10.cmd[2] = 0;
-       r300->hw.unk4E10.cmd[3] = 0;
+       r300->hw.blend_color.cmd[2] = 0;
+       r300->hw.blend_color.cmd[3] = 0;
        
        /* Again, r300ClearBuffer uses this */
        r300->hw.cb.cmd[R300_CB_OFFSET] = r300->radeon.state.color.drawOffset +
  
        switch (ctx->Visual.depthBits) {
        case 16:
-               r300->hw.unk4F10.cmd[1] = R300_DEPTH_FORMAT_16BIT_INT_Z;
+               r300->hw.zstencil_format.cmd[1] = R300_DEPTH_FORMAT_16BIT_INT_Z;
        break;
        case 24:
-               r300->hw.unk4F10.cmd[1] = R300_DEPTH_FORMAT_24BIT_INT_Z;
+               r300->hw.zstencil_format.cmd[1] = R300_DEPTH_FORMAT_24BIT_INT_Z;
        break;
        default:
                fprintf(stderr, "Error: Unsupported depth %d... exiting\n",
                        
        }
        /* z compress? */
-       //r300->hw.unk4F10.cmd[1] |= R300_DEPTH_FORMAT_UNK32;
+       //r300->hw.zstencil_format.cmd[1] |= R300_DEPTH_FORMAT_UNK32;
        
-       r300->hw.unk4F10.cmd[3] = 0x00000003;
-       r300->hw.unk4F10.cmd[4] = 0x00000000;
+       r300->hw.zstencil_format.cmd[3] = 0x00000003;
+       r300->hw.zstencil_format.cmd[4] = 0x00000000;
  
        r300->hw.zb.cmd[R300_ZB_OFFSET] =
                r300->radeon.radeonScreen->depthOffset +
index 0000000000000000000000000000000000000000,092ebb1140e31532885e6a79a9bd35765741c6f2..aa2f20127ba81df942fcdcd41d8843b8368409d6
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,1117 +1,1119 @@@
 -#include "nvvertexec.h"
+ /**************************************************************************
+ Copyright (C) 2005 Aapo Tahkola.
+ All Rights Reserved.
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ on the rights to use, copy, modify, merge, publish, distribute, sub
+ license, and/or sell copies of the Software, and to permit persons to whom
+ the Software is furnished to do so, subject to the following conditions:
+ The above copyright notice and this permission notice (including the next
+ paragraph) shall be included in all copies or substantial portions of the
+ Software.
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ USE OR OTHER DEALINGS IN THE SOFTWARE.
+ **************************************************************************/
+ /*
+  * Authors:
+  *   Aapo Tahkola <aet@rasterburn.org>
+  */
+ #include "glheader.h"
+ #include "macros.h"
+ #include "enums.h"
+ #include "program.h"
 -#include "program_instruction.h"
++#include "shader/prog_instruction.h"
++#include "shader/prog_parameter.h"
++#include "shader/prog_statevars.h"
++#include "tnl/tnl.h"
+ #include "r300_context.h"
+ #include "r300_program.h"
 -              _mesa_init_vp_per_primitive_registers(ctx);
+ #if SWIZZLE_X != VSF_IN_COMPONENT_X || \
+     SWIZZLE_Y != VSF_IN_COMPONENT_Y || \
+     SWIZZLE_Z != VSF_IN_COMPONENT_Z || \
+     SWIZZLE_W != VSF_IN_COMPONENT_W || \
+     SWIZZLE_ZERO != VSF_IN_COMPONENT_ZERO || \
+     SWIZZLE_ONE != VSF_IN_COMPONENT_ONE || \
+     WRITEMASK_X != VSF_FLAG_X || \
+     WRITEMASK_Y != VSF_FLAG_Y || \
+     WRITEMASK_Z != VSF_FLAG_Z || \
+     WRITEMASK_W != VSF_FLAG_W
+ #error Cannot change these!
+ #endif
+     
+ #define SCALAR_FLAG (1<<31)
+ #define FLAG_MASK (1<<31)
+ #define OP_MASK       (0xf)  /* we are unlikely to have more than 15 */
+ #define OPN(operator, ip) {#operator, OPCODE_##operator, ip}
+ static struct{
+       char *name;
+       int opcode;
+       unsigned long ip; /* number of input operands and flags */
+ }op_names[]={
+       OPN(ABS, 1),
+       OPN(ADD, 2),
+       OPN(ARL, 1|SCALAR_FLAG),
+       OPN(DP3, 2),
+       OPN(DP4, 2),
+       OPN(DPH, 2),
+       OPN(DST, 2),
+       OPN(EX2, 1|SCALAR_FLAG),
+       OPN(EXP, 1|SCALAR_FLAG),
+       OPN(FLR, 1),
+       OPN(FRC, 1),
+       OPN(LG2, 1|SCALAR_FLAG),
+       OPN(LIT, 1),
+       OPN(LOG, 1|SCALAR_FLAG),
+       OPN(MAD, 3),
+       OPN(MAX, 2),
+       OPN(MIN, 2),
+       OPN(MOV, 1),
+       OPN(MUL, 2),
+       OPN(POW, 2|SCALAR_FLAG),
+       OPN(RCP, 1|SCALAR_FLAG),
+       OPN(RSQ, 1|SCALAR_FLAG),
+       OPN(SGE, 2),
+       OPN(SLT, 2),
+       OPN(SUB, 2),
+       OPN(SWZ, 1),
+       OPN(XPD, 2),
+       OPN(RCC, 0), //extra
+       OPN(PRINT, 0),
+       OPN(END, 0),
+ };
+ #undef OPN
+       
+ int r300VertexProgUpdateParams(GLcontext *ctx, struct r300_vertex_program_cont *vp, float *dst)
+ {
+       int pi;
+       struct gl_vertex_program *mesa_vp = &vp->mesa_program;
+       float *dst_o=dst;
+         struct gl_program_parameter_list *paramList;
+       
+       if (mesa_vp->IsNVProgram) {
 -      GLint tokens[6] = { STATE_MATRIX, STATE_MVP, 0, 0, 0, STATE_MATRIX };
++              _mesa_load_tracked_matrices(ctx);
+               
+               for (pi=0; pi < MAX_NV_VERTEX_PROGRAM_PARAMS; pi++) {
+                       *dst++=ctx->VertexProgram.Parameters[pi][0];
+                       *dst++=ctx->VertexProgram.Parameters[pi][1];
+                       *dst++=ctx->VertexProgram.Parameters[pi][2];
+                       *dst++=ctx->VertexProgram.Parameters[pi][3];
+               }
+               return dst - dst_o;
+       }
+       
+       assert(mesa_vp->Base.Parameters);
+       _mesa_load_state_parameters(ctx, mesa_vp->Base.Parameters);
+       
+       if(mesa_vp->Base.Parameters->NumParameters * 4 > VSF_MAX_FRAGMENT_LENGTH){
+               fprintf(stderr, "%s:Params exhausted\n", __FUNCTION__);
+               exit(-1);
+       }
+       
+         paramList = mesa_vp->Base.Parameters;
+       for(pi=0; pi < paramList->NumParameters; pi++){
+               switch(paramList->Parameters[pi].Type){
+                       
+               case PROGRAM_STATE_VAR:
+               case PROGRAM_NAMED_PARAM:
+                       //fprintf(stderr, "%s", vp->Parameters->Parameters[pi].Name);
+               case PROGRAM_CONSTANT:
+                       *dst++=paramList->ParameterValues[pi][0];
+                       *dst++=paramList->ParameterValues[pi][1];
+                       *dst++=paramList->ParameterValues[pi][2];
+                       *dst++=paramList->ParameterValues[pi][3];
+               break;
+               
+               default: _mesa_problem(NULL, "Bad param type in %s", __FUNCTION__);
+               }
+       
+       }
+       
+       return dst - dst_o;
+ }
+               
+ static unsigned long t_dst_mask(GLuint mask)
+ {
+       /* WRITEMASK_* is equivalent to VSF_FLAG_* */
+       return mask & VSF_FLAG_ALL;
+ }
+ static unsigned long t_dst_class(enum register_file file)
+ {
+       
+       switch(file){
+               case PROGRAM_TEMPORARY:
+                       return VSF_OUT_CLASS_TMP;
+               case PROGRAM_OUTPUT:
+                       return VSF_OUT_CLASS_RESULT;
+               case PROGRAM_ADDRESS:
+                       return VSF_OUT_CLASS_ADDR;
+               /*      
+               case PROGRAM_INPUT:
+               case PROGRAM_LOCAL_PARAM:
+               case PROGRAM_ENV_PARAM:
+               case PROGRAM_NAMED_PARAM:
+               case PROGRAM_STATE_VAR:
+               case PROGRAM_WRITE_ONLY:
+               case PROGRAM_ADDRESS:
+               */
+               default:
+                       fprintf(stderr, "problem in %s", __FUNCTION__);
+                       exit(0);
+       }
+ }
+ static unsigned long t_dst_index(struct r300_vertex_program *vp, struct prog_dst_register *dst)
+ {
+       if(dst->File == PROGRAM_OUTPUT)
+               return vp->outputs[dst->Index];
+       return dst->Index;
+ }
+ static unsigned long t_src_class(enum register_file file)
+ {
+       
+       switch(file){
+               case PROGRAM_TEMPORARY:
+                       return VSF_IN_CLASS_TMP;
+                       
+               case PROGRAM_INPUT:
+                       return VSF_IN_CLASS_ATTR;
+                       
+               case PROGRAM_LOCAL_PARAM:
+               case PROGRAM_ENV_PARAM:
+               case PROGRAM_NAMED_PARAM:
+               case PROGRAM_STATE_VAR:
+                       return VSF_IN_CLASS_PARAM;
+               /*      
+               case PROGRAM_OUTPUT:
+               case PROGRAM_WRITE_ONLY:
+               case PROGRAM_ADDRESS:
+               */
+               default:
+                       fprintf(stderr, "problem in %s", __FUNCTION__);
+                       exit(0);
+       }
+ }
+ static __inline unsigned long t_swizzle(GLubyte swizzle)
+ {
+ /* this is in fact a NOP as the Mesa SWIZZLE_* are all identical to VSF_IN_COMPONENT_* */
+       return swizzle;
+ }
+ #if 0
+ static void vp_dump_inputs(struct r300_vertex_program *vp, char *caller)
+ {
+       int i;
+       
+       if(vp == NULL){
+               fprintf(stderr, "vp null in call to %s from %s\n", __FUNCTION__, caller);
+               return ;
+       }
+       
+       fprintf(stderr, "%s:<", caller);
+       for(i=0; i < VERT_ATTRIB_MAX; i++)
+               fprintf(stderr, "%d ", vp->inputs[i]);
+       fprintf(stderr, ">\n");
+       
+ }
+ #endif
+ static unsigned long t_src_index(struct r300_vertex_program *vp, struct prog_src_register *src)
+ {
+       int i;
+       int max_reg=-1;
+       
+       if(src->File == PROGRAM_INPUT){
+               if(vp->inputs[src->Index] != -1)
+                       return vp->inputs[src->Index];
+               
+               for(i=0; i < VERT_ATTRIB_MAX; i++)
+                       if(vp->inputs[i] > max_reg)
+                               max_reg=vp->inputs[i];
+               
+               vp->inputs[src->Index]=max_reg+1;
+               
+               //vp_dump_inputs(vp, __FUNCTION__);     
+               
+               return vp->inputs[src->Index];
+       }else{
+               if (src->Index < 0) {
+                       fprintf(stderr, "WARNING negative offsets for indirect addressing do not work\n");
+                       return 0;
+               }
+               return src->Index;
+       }
+ }
+ static unsigned long t_src(struct r300_vertex_program *vp, struct prog_src_register *src)
+ {
+       /* src->NegateBase uses the NEGATE_ flags from program_instruction.h,
+        * which equal our VSF_FLAGS_ values, so it's safe to just pass it here.
+        */
+       return MAKE_VSF_SOURCE(t_src_index(vp, src),
+                               t_swizzle(GET_SWZ(src->Swizzle, 0)),
+                               t_swizzle(GET_SWZ(src->Swizzle, 1)),
+                               t_swizzle(GET_SWZ(src->Swizzle, 2)),
+                               t_swizzle(GET_SWZ(src->Swizzle, 3)),
+                               t_src_class(src->File),
+                               src->NegateBase) | (src->RelAddr << 4);
+ }
+ static unsigned long t_src_scalar(struct r300_vertex_program *vp, struct prog_src_register *src)
+ {
+                       
+       return MAKE_VSF_SOURCE(t_src_index(vp, src),
+                               t_swizzle(GET_SWZ(src->Swizzle, 0)),
+                               t_swizzle(GET_SWZ(src->Swizzle, 0)),
+                               t_swizzle(GET_SWZ(src->Swizzle, 0)),
+                               t_swizzle(GET_SWZ(src->Swizzle, 0)),
+                               t_src_class(src->File),
+                               src->NegateBase ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src->RelAddr << 4);
+ }
+ static unsigned long t_opcode(enum prog_opcode opcode)
+ {
+       switch(opcode){
+               case OPCODE_ARL: return R300_VPI_OUT_OP_ARL;
+               case OPCODE_DST: return R300_VPI_OUT_OP_DST;
+               case OPCODE_EX2: return R300_VPI_OUT_OP_EX2;
+               case OPCODE_EXP: return R300_VPI_OUT_OP_EXP;
+               case OPCODE_FRC: return R300_VPI_OUT_OP_FRC;
+               case OPCODE_LG2: return R300_VPI_OUT_OP_LG2;
+               case OPCODE_LOG: return R300_VPI_OUT_OP_LOG;
+               case OPCODE_MAX: return R300_VPI_OUT_OP_MAX;
+               case OPCODE_MIN: return R300_VPI_OUT_OP_MIN;
+               case OPCODE_MUL: return R300_VPI_OUT_OP_MUL;
+               case OPCODE_RCP: return R300_VPI_OUT_OP_RCP;
+               case OPCODE_RSQ: return R300_VPI_OUT_OP_RSQ;
+               case OPCODE_SGE: return R300_VPI_OUT_OP_SGE;
+               case OPCODE_SLT: return R300_VPI_OUT_OP_SLT;
+               case OPCODE_DP4: return R300_VPI_OUT_OP_DOT;
+               
+               default: 
+                       fprintf(stderr, "%s: Should not be called with opcode %d!", __FUNCTION__, opcode);
+       }
+       exit(-1);
+       return 0;
+ }
+ static unsigned long op_operands(enum prog_opcode opcode)
+ {
+       int i;
+       
+       /* Can we trust mesas opcodes to be in order ? */
+       for(i=0; i < sizeof(op_names) / sizeof(*op_names); i++)
+               if(op_names[i].opcode == opcode)
+                       return op_names[i].ip;
+       
+       fprintf(stderr, "op %d not found in op_names\n", opcode);
+       exit(-1);
+       return 0;
+ }
+ static GLboolean valid_dst(struct r300_vertex_program *vp, struct prog_dst_register *dst)
+ {
+       if(dst->File == PROGRAM_OUTPUT && vp->outputs[dst->Index] == -1){
+               WARN_ONCE("Output %d not used by fragment program\n", dst->Index);
+               return GL_FALSE;
+       }else if(dst->File == PROGRAM_ADDRESS) {
+               assert(dst->Index == 0);
+       }
+       
+       return GL_TRUE;
+ }
+ /* TODO: Get rid of t_src_class call */
+ #define CMP_SRCS(a, b) ((a.RelAddr != b.RelAddr) || (a.Index != b.Index && \
+                      ((t_src_class(a.File) == VSF_IN_CLASS_PARAM && \
+                        t_src_class(b.File) == VSF_IN_CLASS_PARAM) || \
+                       (t_src_class(a.File) == VSF_IN_CLASS_ATTR && \
+                        t_src_class(b.File) == VSF_IN_CLASS_ATTR)))) \
+                        
+ #define ZERO_SRC_0 (MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), \
+                                   SWIZZLE_ZERO, SWIZZLE_ZERO, \
+                                   SWIZZLE_ZERO, SWIZZLE_ZERO, \
+                                   t_src_class(src[0].File), VSF_FLAG_NONE) | (src[0].RelAddr << 4))
+                                  
+ #define ZERO_SRC_1 (MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), \
+                                   SWIZZLE_ZERO, SWIZZLE_ZERO, \
+                                   SWIZZLE_ZERO, SWIZZLE_ZERO, \
+                                   t_src_class(src[1].File), VSF_FLAG_NONE) | (src[1].RelAddr << 4))
+ #define ZERO_SRC_2 (MAKE_VSF_SOURCE(t_src_index(vp, &src[2]), \
+                                   SWIZZLE_ZERO, SWIZZLE_ZERO, \
+                                   SWIZZLE_ZERO, SWIZZLE_ZERO, \
+                                   t_src_class(src[2].File), VSF_FLAG_NONE) | (src[2].RelAddr << 4))
+                                  
+ #define ONE_SRC_0 (MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), \
+                                   SWIZZLE_ONE, SWIZZLE_ONE, \
+                                   SWIZZLE_ONE, SWIZZLE_ONE, \
+                                   t_src_class(src[0].File), VSF_FLAG_NONE) | (src[0].RelAddr << 4))
+                                  
+ #define ONE_SRC_1 (MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), \
+                                   SWIZZLE_ONE, SWIZZLE_ONE, \
+                                   SWIZZLE_ONE, SWIZZLE_ONE, \
+                                   t_src_class(src[1].File), VSF_FLAG_NONE) | (src[1].RelAddr << 4))
+ #define ONE_SRC_2 (MAKE_VSF_SOURCE(t_src_index(vp, &src[2]), \
+                                   SWIZZLE_ONE, SWIZZLE_ONE, \
+                                   SWIZZLE_ONE, SWIZZLE_ONE, \
+                                   t_src_class(src[2].File), VSF_FLAG_NONE) | (src[2].RelAddr << 4))
+                                  
+ /* DP4 version seems to trigger some hw peculiarity */
+ //#define PREFER_DP4
+ #define FREE_TEMPS() \
+       do { \
+               if(u_temp_i < vp->num_temporaries) { \
+                       WARN_ONCE("Ran out of temps, num temps %d, us %d\n", vp->num_temporaries, u_temp_i); \
+                       vp->native = GL_FALSE; \
+               } \
+               u_temp_i=VSF_MAX_FRAGMENT_TEMPS-1; \
+       } while (0)
+ static void r300_translate_vertex_shader(struct r300_vertex_program *vp, struct prog_instruction *vpi)
+ {
+       int i, cur_reg=0;
+       VERTEX_SHADER_INSTRUCTION *o_inst;
+       unsigned long operands;
+       int are_srcs_scalar;
+       unsigned long hw_op;
+       /* Initial value should be last tmp reg that hw supports.
+          Strangely enough r300 doesnt mind even though these would be out of range.
+          Smart enough to realize that it doesnt need it? */
+       int u_temp_i=VSF_MAX_FRAGMENT_TEMPS-1;
+       struct prog_src_register src[3];
+       vp->pos_end=0; /* Not supported yet */
+       vp->program.length=0;
+       /*vp->num_temporaries=mesa_vp->Base.NumTemporaries;*/
+       
+       for(i=0; i < VERT_ATTRIB_MAX; i++)
+               vp->inputs[i] = -1;
+       for(i=0; i < VERT_RESULT_MAX; i++)
+               vp->outputs[i] = -1;
+       
+       assert(vp->key.OutputsWritten & (1 << VERT_RESULT_HPOS));
+       
+       /* Assign outputs */
+       if(vp->key.OutputsWritten & (1 << VERT_RESULT_HPOS))
+               vp->outputs[VERT_RESULT_HPOS] = cur_reg++;
+       
+       if(vp->key.OutputsWritten & (1 << VERT_RESULT_PSIZ))
+               vp->outputs[VERT_RESULT_PSIZ] = cur_reg++;
+       
+       if(vp->key.OutputsWritten & (1 << VERT_RESULT_COL0))
+               vp->outputs[VERT_RESULT_COL0] = cur_reg++;
+       
+       if(vp->key.OutputsWritten & (1 << VERT_RESULT_COL1))
+               vp->outputs[VERT_RESULT_COL1] = cur_reg++;
+       
+ #if 0 /* Not supported yet */
+       if(vp->key.OutputsWritten & (1 << VERT_RESULT_BFC0))
+               vp->outputs[VERT_RESULT_BFC0] = cur_reg++;
+       
+       if(vp->key.OutputsWritten & (1 << VERT_RESULT_BFC1))
+               vp->outputs[VERT_RESULT_BFC1] = cur_reg++;
+       
+       if(vp->key.OutputsWritten & (1 << VERT_RESULT_FOGC))
+               vp->outputs[VERT_RESULT_FOGC] = cur_reg++;
+ #endif
+       
+       for(i=VERT_RESULT_TEX0; i <= VERT_RESULT_TEX7; i++)
+               if(vp->key.OutputsWritten & (1 << i))
+                       vp->outputs[i] = cur_reg++;
+       
+       vp->translated = GL_TRUE;
+       vp->native = GL_TRUE;
+       
+       o_inst=vp->program.body.i;
+       for(; vpi->Opcode != OPCODE_END; vpi++, o_inst++){
+               FREE_TEMPS();
+               if(!valid_dst(vp, &vpi->DstReg))
+               {
+                       /* redirect result to unused temp */
+                       vpi->DstReg.File = PROGRAM_TEMPORARY;
+                       vpi->DstReg.Index = u_temp_i;
+               }
+               
+               operands=op_operands(vpi->Opcode);
+               are_srcs_scalar=operands & SCALAR_FLAG;
+               operands &= OP_MASK;
+               
+               for(i=0; i < operands; i++)
+                       src[i]=vpi->SrcReg[i];
+               
+               if(operands == 3){ /* TODO: scalars */
+                       if( CMP_SRCS(src[1], src[2]) || CMP_SRCS(src[0], src[2]) ){
+                               o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, u_temp_i,
+                                               VSF_FLAG_ALL, VSF_OUT_CLASS_TMP);
+                               
+                               o_inst->src1=MAKE_VSF_SOURCE(t_src_index(vp, &src[2]),
+                                               SWIZZLE_X, SWIZZLE_Y,
+                                               SWIZZLE_Z, SWIZZLE_W,
+                                               t_src_class(src[2].File), VSF_FLAG_NONE) | (src[2].RelAddr << 4);
+                               o_inst->src2=ZERO_SRC_2;
+                               o_inst->src3=ZERO_SRC_2;
+                               o_inst++;
+                                               
+                               src[2].File=PROGRAM_TEMPORARY;
+                               src[2].Index=u_temp_i;
+                               src[2].RelAddr=0;
+                               u_temp_i--;
+                       }
+                       
+               }
+               
+               if(operands >= 2){
+                       if( CMP_SRCS(src[1], src[0]) ){
+                               o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, u_temp_i,
+                                               VSF_FLAG_ALL, VSF_OUT_CLASS_TMP);
+                               
+                               o_inst->src1=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
+                                               SWIZZLE_X, SWIZZLE_Y,
+                                               SWIZZLE_Z, SWIZZLE_W,
+                                               t_src_class(src[0].File), VSF_FLAG_NONE) | (src[0].RelAddr << 4);
+                               o_inst->src2=ZERO_SRC_0;
+                               o_inst->src3=ZERO_SRC_0;
+                               o_inst++;
+                                               
+                               src[0].File=PROGRAM_TEMPORARY;
+                               src[0].Index=u_temp_i;
+                               src[0].RelAddr=0;
+                               u_temp_i--;
+                       }
+               }
+               
+               /* These ops need special handling. */
+               switch(vpi->Opcode){
+               case OPCODE_POW:
+                       o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_POW, t_dst_index(vp, &vpi->DstReg),
+                                       t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
+                       o_inst->src1=t_src_scalar(vp, &src[0]);
+                       o_inst->src2=ZERO_SRC_0;
+                       o_inst->src3=t_src_scalar(vp, &src[1]);
+                       goto next;
+                       
+               case OPCODE_MOV://ADD RESULT 1.X Y Z W PARAM 0{} {X Y Z W} PARAM 0{} {ZERO ZERO ZERO ZERO} 
+               case OPCODE_SWZ:
+ #if 1
+                       o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, t_dst_index(vp, &vpi->DstReg),
+                                       t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
+                       o_inst->src1=t_src(vp, &src[0]);
+                       o_inst->src2=ZERO_SRC_0;
+                       o_inst->src3=ZERO_SRC_0;
+ #else
+                       hw_op=(src[0].File == PROGRAM_TEMPORARY) ? R300_VPI_OUT_OP_MAD_2 : R300_VPI_OUT_OP_MAD;
+                       
+                       o_inst->op=MAKE_VSF_OP(hw_op, t_dst_index(vp, &vpi->DstReg),
+                               t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
+                       o_inst->src1=t_src(vp, &src[0]);
+                       o_inst->src2=ONE_SRC_0;
+                       o_inst->src3=ZERO_SRC_0;
+ #endif                        
+                       goto next;
+                       
+               case OPCODE_ADD:
+ #if 1
+                       hw_op=(src[0].File == PROGRAM_TEMPORARY &&
+                               src[1].File == PROGRAM_TEMPORARY) ? R300_VPI_OUT_OP_MAD_2 : R300_VPI_OUT_OP_MAD;
+                       
+                       o_inst->op=MAKE_VSF_OP(hw_op, t_dst_index(vp, &vpi->DstReg),
+                               t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
+                       o_inst->src1=ONE_SRC_0;
+                       o_inst->src2=t_src(vp, &src[0]);
+                       o_inst->src3=t_src(vp, &src[1]);
+ #else
+                       o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, t_dst_index(vp, &vpi->DstReg),
+                                       t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
+                       o_inst->src1=t_src(vp, &src[0]);
+                       o_inst->src2=t_src(vp, &src[1]);
+                       o_inst->src3=ZERO_SRC_1;
+                       
+ #endif
+                       goto next;
+                       
+               case OPCODE_MAD:
+                       hw_op=(src[0].File == PROGRAM_TEMPORARY &&
+                               src[1].File == PROGRAM_TEMPORARY &&
+                               src[2].File == PROGRAM_TEMPORARY) ? R300_VPI_OUT_OP_MAD_2 : R300_VPI_OUT_OP_MAD;
+                       
+                       o_inst->op=MAKE_VSF_OP(hw_op, t_dst_index(vp, &vpi->DstReg),
+                               t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
+                       o_inst->src1=t_src(vp, &src[0]);
+                       o_inst->src2=t_src(vp, &src[1]);
+                       o_inst->src3=t_src(vp, &src[2]);
+                       goto next;
+                       
+               case OPCODE_MUL: /* HW mul can take third arg but appears to have some other limitations. */
+                       hw_op=(src[0].File == PROGRAM_TEMPORARY &&
+                               src[1].File == PROGRAM_TEMPORARY) ? R300_VPI_OUT_OP_MAD_2 : R300_VPI_OUT_OP_MAD;
+                       
+                       o_inst->op=MAKE_VSF_OP(hw_op, t_dst_index(vp, &vpi->DstReg),
+                               t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
+                       o_inst->src1=t_src(vp, &src[0]);
+                       o_inst->src2=t_src(vp, &src[1]);
+                       o_inst->src3=ZERO_SRC_1;
+                       goto next;
+                       
+               case OPCODE_DP3://DOT RESULT 1.X Y Z W PARAM 0{} {X Y Z ZERO} PARAM 0{} {X Y Z ZERO} 
+                       o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_DOT, t_dst_index(vp, &vpi->DstReg),
+                                       t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
+                       
+                       o_inst->src1=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
+                                       t_swizzle(GET_SWZ(src[0].Swizzle, 0)),
+                                       t_swizzle(GET_SWZ(src[0].Swizzle, 1)),
+                                       t_swizzle(GET_SWZ(src[0].Swizzle, 2)),
+                                       SWIZZLE_ZERO,
+                                       t_src_class(src[0].File),
+                                       src[0].NegateBase ? VSF_FLAG_XYZ : VSF_FLAG_NONE) | (src[0].RelAddr << 4);
+                       
+                       o_inst->src2=MAKE_VSF_SOURCE(t_src_index(vp, &src[1]),
+                                       t_swizzle(GET_SWZ(src[1].Swizzle, 0)),
+                                       t_swizzle(GET_SWZ(src[1].Swizzle, 1)),
+                                       t_swizzle(GET_SWZ(src[1].Swizzle, 2)),
+                                       SWIZZLE_ZERO,
+                                       t_src_class(src[1].File),
+                                       src[1].NegateBase ? VSF_FLAG_XYZ : VSF_FLAG_NONE) | (src[1].RelAddr << 4);
+                       o_inst->src3=ZERO_SRC_1;
+                       goto next;
+               case OPCODE_SUB://ADD RESULT 1.X Y Z W TMP 0{} {X Y Z W} PARAM 1{X Y Z W } {X Y Z W} neg Xneg Yneg Zneg W
+ #if 1
+                       hw_op=(src[0].File == PROGRAM_TEMPORARY &&
+                               src[1].File == PROGRAM_TEMPORARY) ? R300_VPI_OUT_OP_MAD_2 : R300_VPI_OUT_OP_MAD;
+                       
+                       o_inst->op=MAKE_VSF_OP(hw_op, t_dst_index(vp, &vpi->DstReg),
+                               t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
+                       o_inst->src1=t_src(vp, &src[0]);
+                       o_inst->src2=ONE_SRC_0;
+                       o_inst->src3=MAKE_VSF_SOURCE(t_src_index(vp, &src[1]),
+                                       t_swizzle(GET_SWZ(src[1].Swizzle, 0)),
+                                       t_swizzle(GET_SWZ(src[1].Swizzle, 1)),
+                                       t_swizzle(GET_SWZ(src[1].Swizzle, 2)),
+                                       t_swizzle(GET_SWZ(src[1].Swizzle, 3)),
+                                       t_src_class(src[1].File),
+                                       (!src[1].NegateBase) ? VSF_FLAG_ALL : VSF_FLAG_NONE)  | (src[1].RelAddr << 4);
+ #else
+                       o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, t_dst_index(vp, &vpi->DstReg),
+                                       t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
+                       
+                       o_inst->src1=t_src(vp, &src[0]);
+                       o_inst->src2=MAKE_VSF_SOURCE(t_src_index(vp, &src[1]),
+                                       t_swizzle(GET_SWZ(src[1].Swizzle, 0)),
+                                       t_swizzle(GET_SWZ(src[1].Swizzle, 1)),
+                                       t_swizzle(GET_SWZ(src[1].Swizzle, 2)),
+                                       t_swizzle(GET_SWZ(src[1].Swizzle, 3)),
+                                       t_src_class(src[1].File),
+                                       (!src[1].NegateBase) ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src[1].RelAddr << 4);
+                       o_inst->src3=0;
+ #endif
+                       goto next;
+                       
+               case OPCODE_ABS://MAX RESULT 1.X Y Z W PARAM 0{} {X Y Z W} PARAM 0{X Y Z W } {X Y Z W} neg Xneg Yneg Zneg W
+                       o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_MAX, t_dst_index(vp, &vpi->DstReg),
+                                       t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
+                       
+                       o_inst->src1=t_src(vp, &src[0]);
+                       o_inst->src2=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
+                                       t_swizzle(GET_SWZ(src[0].Swizzle, 0)),
+                                       t_swizzle(GET_SWZ(src[0].Swizzle, 1)),
+                                       t_swizzle(GET_SWZ(src[0].Swizzle, 2)),
+                                       t_swizzle(GET_SWZ(src[0].Swizzle, 3)),
+                                       t_src_class(src[0].File),
+                                       (!src[0].NegateBase) ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src[0].RelAddr << 4);
+                       o_inst->src3=0;
+                       goto next;
+                       
+               case OPCODE_FLR:
+               /* FRC TMP 0.X Y Z W PARAM 0{} {X Y Z W} 
+                  ADD RESULT 1.X Y Z W PARAM 0{} {X Y Z W} TMP 0{X Y Z W } {X Y Z W} neg Xneg Yneg Zneg W */
+                       o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_FRC, u_temp_i,
+                                       t_dst_mask(vpi->DstReg.WriteMask), VSF_OUT_CLASS_TMP);
+                       
+                       o_inst->src1=t_src(vp, &src[0]);
+                       o_inst->src2=ZERO_SRC_0;
+                       o_inst->src3=ZERO_SRC_0;
+                       o_inst++;
+                       
+                       o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, t_dst_index(vp, &vpi->DstReg),
+                                       t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
+                       
+                       o_inst->src1=t_src(vp, &src[0]);
+                       o_inst->src2=MAKE_VSF_SOURCE(u_temp_i,
+                                       VSF_IN_COMPONENT_X,
+                                       VSF_IN_COMPONENT_Y,
+                                       VSF_IN_COMPONENT_Z,
+                                       VSF_IN_COMPONENT_W,
+                                       VSF_IN_CLASS_TMP,
+                                       /* Not 100% sure about this */
+                                       (!src[0].NegateBase) ? VSF_FLAG_ALL : VSF_FLAG_NONE/*VSF_FLAG_ALL*/);
+                       o_inst->src3=ZERO_SRC_0;
+                       u_temp_i--;
+                       goto next;
+                       
+               case OPCODE_LG2:// LG2 RESULT 1.X Y Z W PARAM 0{} {X X X X}
+                       o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_LG2, t_dst_index(vp, &vpi->DstReg),
+                                       t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
+                       
+                       o_inst->src1=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
+                                       t_swizzle(GET_SWZ(src[0].Swizzle, 0)),
+                                       t_swizzle(GET_SWZ(src[0].Swizzle, 0)),
+                                       t_swizzle(GET_SWZ(src[0].Swizzle, 0)),
+                                       t_swizzle(GET_SWZ(src[0].Swizzle, 0)),
+                                       t_src_class(src[0].File),
+                                       src[0].NegateBase ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src[0].RelAddr << 4);
+                       o_inst->src2=ZERO_SRC_0;
+                       o_inst->src3=ZERO_SRC_0;
+                       goto next;
+                       
+               case OPCODE_LIT://LIT TMP 1.Y Z TMP 1{} {X W Z Y} TMP 1{} {Y W Z X} TMP 1{} {Y X Z W} 
+                       o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_LIT, t_dst_index(vp, &vpi->DstReg),
+                                       t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
+                       /* NOTE: Users swizzling might not work. */
+                       o_inst->src1=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
+                                       t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // x
+                                       t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w
+                                       VSF_IN_COMPONENT_ZERO, // z
+                                       t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y
+                                       t_src_class(src[0].File),
+                                       src[0].NegateBase ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src[0].RelAddr << 4);
+                       o_inst->src2=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
+                                       t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y
+                                       t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w
+                                       VSF_IN_COMPONENT_ZERO, // z
+                                       t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // x
+                                       t_src_class(src[0].File),
+                                       src[0].NegateBase ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src[0].RelAddr << 4);
+                       o_inst->src3=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
+                                       t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y
+                                       t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // x
+                                       VSF_IN_COMPONENT_ZERO, // z
+                                       t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w
+                                       t_src_class(src[0].File),
+                                       src[0].NegateBase ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src[0].RelAddr << 4);
+                       goto next;
+                       
+               case OPCODE_DPH://DOT RESULT 1.X Y Z W PARAM 0{} {X Y Z ONE} PARAM 0{} {X Y Z W} 
+                       o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_DOT, t_dst_index(vp, &vpi->DstReg),
+                                       t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
+                       
+                       o_inst->src1=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
+                                       t_swizzle(GET_SWZ(src[0].Swizzle, 0)),
+                                       t_swizzle(GET_SWZ(src[0].Swizzle, 1)),
+                                       t_swizzle(GET_SWZ(src[0].Swizzle, 2)),
+                                       VSF_IN_COMPONENT_ONE,
+                                       t_src_class(src[0].File),
+                                       src[0].NegateBase ? VSF_FLAG_XYZ : VSF_FLAG_NONE) | (src[0].RelAddr << 4);
+                       o_inst->src2=t_src(vp, &src[1]);
+                       o_inst->src3=ZERO_SRC_1;
+                       goto next;
+                       
+               case OPCODE_XPD:
+                       /* mul r0, r1.yzxw, r2.zxyw
+                          mad r0, -r2.yzxw, r1.zxyw, r0
+                          NOTE: might need MAD_2
+                        */
+                       
+                       o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_MAD, u_temp_i,
+                                       t_dst_mask(vpi->DstReg.WriteMask), VSF_OUT_CLASS_TMP);
+                       
+                       o_inst->src1=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
+                                       t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y
+                                       t_swizzle(GET_SWZ(src[0].Swizzle, 2)), // z
+                                       t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // x
+                                       t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w
+                                       t_src_class(src[0].File),
+                                       src[0].NegateBase ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src[0].RelAddr << 4);
+                       
+                       o_inst->src2=MAKE_VSF_SOURCE(t_src_index(vp, &src[1]),
+                                       t_swizzle(GET_SWZ(src[1].Swizzle, 2)), // z
+                                       t_swizzle(GET_SWZ(src[1].Swizzle, 0)), // x
+                                       t_swizzle(GET_SWZ(src[1].Swizzle, 1)), // y
+                                       t_swizzle(GET_SWZ(src[1].Swizzle, 3)), // w
+                                       t_src_class(src[1].File),
+                                       src[1].NegateBase ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src[1].RelAddr << 4);
+                       
+                       o_inst->src3=ZERO_SRC_1;
+                       o_inst++;
+                       u_temp_i--;
+                       
+                       o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_MAD, t_dst_index(vp, &vpi->DstReg),
+                                       t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
+                       
+                       o_inst->src1=MAKE_VSF_SOURCE(t_src_index(vp, &src[1]),
+                                       t_swizzle(GET_SWZ(src[1].Swizzle, 1)), // y
+                                       t_swizzle(GET_SWZ(src[1].Swizzle, 2)), // z
+                                       t_swizzle(GET_SWZ(src[1].Swizzle, 0)), // x
+                                       t_swizzle(GET_SWZ(src[1].Swizzle, 3)), // w
+                                       t_src_class(src[1].File),
+                                       (!src[1].NegateBase) ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src[1].RelAddr << 4);
+                       
+                       o_inst->src2=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
+                                       t_swizzle(GET_SWZ(src[0].Swizzle, 2)), // z
+                                       t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // x
+                                       t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y
+                                       t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w
+                                       t_src_class(src[0].File),
+                                       src[0].NegateBase ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src[0].RelAddr << 4);
+                       
+                       o_inst->src3=MAKE_VSF_SOURCE(u_temp_i+1,
+                                       VSF_IN_COMPONENT_X,
+                                       VSF_IN_COMPONENT_Y,
+                                       VSF_IN_COMPONENT_Z,
+                                       VSF_IN_COMPONENT_W,
+                                       VSF_IN_CLASS_TMP,
+                                       VSF_FLAG_NONE);
+               
+                       goto next;
+               case OPCODE_RCC:
+                       fprintf(stderr, "Dont know how to handle op %d yet\n", vpi->Opcode);
+                       exit(-1);
+               break;
+               case OPCODE_END:
+                       break;
+               default:
+                       break;
+               }
+       
+               o_inst->op=MAKE_VSF_OP(t_opcode(vpi->Opcode), t_dst_index(vp, &vpi->DstReg),
+                               t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
+               
+               if(are_srcs_scalar){
+                       switch(operands){
+                               case 1:
+                                       o_inst->src1=t_src_scalar(vp, &src[0]);
+                                       o_inst->src2=ZERO_SRC_0;
+                                       o_inst->src3=ZERO_SRC_0;
+                               break;
+                               
+                               case 2:
+                                       o_inst->src1=t_src_scalar(vp, &src[0]);
+                                       o_inst->src2=t_src_scalar(vp, &src[1]);
+                                       o_inst->src3=ZERO_SRC_1;
+                               break;
+                               
+                               case 3:
+                                       o_inst->src1=t_src_scalar(vp, &src[0]);
+                                       o_inst->src2=t_src_scalar(vp, &src[1]);
+                                       o_inst->src3=t_src_scalar(vp, &src[2]);
+                               break;
+                               
+                               default:
+                                       fprintf(stderr, "scalars and op RCC not handled yet");
+                                       exit(-1);
+                               break;
+                       }
+               }else{
+                       switch(operands){
+                               case 1:
+                                       o_inst->src1=t_src(vp, &src[0]);
+                                       o_inst->src2=ZERO_SRC_0;
+                                       o_inst->src3=ZERO_SRC_0;
+                               break;
+                       
+                               case 2:
+                                       o_inst->src1=t_src(vp, &src[0]);
+                                       o_inst->src2=t_src(vp, &src[1]);
+                                       o_inst->src3=ZERO_SRC_1;
+                               break;
+                       
+                               case 3:
+                                       o_inst->src1=t_src(vp, &src[0]);
+                                       o_inst->src2=t_src(vp, &src[1]);
+                                       o_inst->src3=t_src(vp, &src[2]);
+                               break;
+                       
+                               default:
+                                       fprintf(stderr, "scalars and op RCC not handled yet");
+                                       exit(-1);
+                               break;
+                       }
+               }
+               next: ;
+       }
+       
+       /* Will most likely segfault before we get here... fix later. */
+       if(o_inst - vp->program.body.i >= VSF_MAX_FRAGMENT_LENGTH/4) {
+               vp->program.length = 0;
+               vp->native = GL_FALSE;
+               return ;
+       }
+       vp->program.length=(o_inst - vp->program.body.i) * 4;
+ #if 0
+       fprintf(stderr, "hw program:\n");
+       for(i=0; i < vp->program.length; i++)
+               fprintf(stderr, "%08x\n", vp->program.body.d[i]);
+ #endif
+ }
+ static void position_invariant(struct gl_program *prog)
+ {
+       struct prog_instruction *vpi;
+       struct gl_program_parameter_list *paramList;
+       int i;
++      gl_state_index tokens[STATE_LENGTH] = { STATE_MVP_MATRIX, 0, 0, 0, 0 };
+ #ifdef PREFER_DP4
+       tokens[5] = STATE_MATRIX;
+ #else
+       tokens[5] = STATE_MATRIX_TRANSPOSE;
+ #endif
+       paramList = prog->Parameters;
+       vpi = _mesa_alloc_instructions (prog->NumInstructions + 4);
+       _mesa_init_instructions (vpi, prog->NumInstructions + 4);
+       for (i=0; i < 4; i++) {
+               GLint idx;
+               tokens[3] = tokens[4] = i;
+               idx = _mesa_add_state_reference(paramList, tokens);
+ #ifdef PREFER_DP4
+               vpi[i].Opcode = OPCODE_DP4;
+               vpi[i].StringPos = 0;
+               vpi[i].Data = 0;
+               vpi[i].DstReg.File = PROGRAM_OUTPUT;
+               vpi[i].DstReg.Index = VERT_RESULT_HPOS;
+               vpi[i].DstReg.WriteMask = 1 << i;
+               vpi[i].DstReg.CondMask = COND_TR;
+               vpi[i].SrcReg[0].File = PROGRAM_STATE_VAR;
+               vpi[i].SrcReg[0].Index = idx;
+               vpi[i].SrcReg[0].Swizzle = SWIZZLE_XYZW;
+               vpi[i].SrcReg[1].File = PROGRAM_INPUT;
+               vpi[i].SrcReg[1].Index = VERT_ATTRIB_POS;
+               vpi[i].SrcReg[1].Swizzle = SWIZZLE_XYZW;
+ #else
+               if (i == 0)
+                       vpi[i].Opcode = OPCODE_MUL;
+               else
+                       vpi[i].Opcode = OPCODE_MAD;
+               vpi[i].StringPos = 0;
+               vpi[i].Data = 0;
+               if (i == 3)
+                       vpi[i].DstReg.File = PROGRAM_OUTPUT;
+               else
+                       vpi[i].DstReg.File = PROGRAM_TEMPORARY;
+               vpi[i].DstReg.Index = 0;
+               vpi[i].DstReg.WriteMask = 0xf;
+               vpi[i].DstReg.CondMask = COND_TR;
+               vpi[i].SrcReg[0].File = PROGRAM_STATE_VAR;
+               vpi[i].SrcReg[0].Index = idx;
+               vpi[i].SrcReg[0].Swizzle = SWIZZLE_XYZW;
+               vpi[i].SrcReg[1].File = PROGRAM_INPUT;
+               vpi[i].SrcReg[1].Index = VERT_ATTRIB_POS;
+               vpi[i].SrcReg[1].Swizzle = MAKE_SWIZZLE4(i, i, i, i);
+               if (i > 0) {
+                       vpi[i].SrcReg[2].File = PROGRAM_TEMPORARY;
+                       vpi[i].SrcReg[2].Index = 0;
+                       vpi[i].SrcReg[2].Swizzle = SWIZZLE_XYZW;
+               }
+ #endif                                        
+       }
+       _mesa_copy_instructions (&vpi[i], prog->Instructions, prog->NumInstructions);
+       free(prog->Instructions);
+       prog->Instructions = vpi;
+       prog->NumInstructions += 4;
+       vpi = &prog->Instructions[prog->NumInstructions-1];
+       assert(vpi->Opcode == OPCODE_END);
+ }
+ static void insert_wpos(struct r300_vertex_program *vp,
+                      struct gl_program *prog,
+                      GLuint temp_index)
+ {
+       struct prog_instruction *vpi;
+       struct prog_instruction *vpi_insert;
+       int i = 0;
+       
+       vpi = _mesa_alloc_instructions (prog->NumInstructions + 2);
+       _mesa_init_instructions (vpi, prog->NumInstructions + 2);
+       /* all but END */
+       _mesa_copy_instructions (vpi, prog->Instructions, prog->NumInstructions - 1);
+       /* END */
+       _mesa_copy_instructions (&vpi[prog->NumInstructions + 1],
+                                &prog->Instructions[prog->NumInstructions - 1],
+                                1);
+       vpi_insert = &vpi[prog->NumInstructions - 1];
+       vpi_insert[i].Opcode = OPCODE_MOV;
+       vpi_insert[i].DstReg.File = PROGRAM_OUTPUT;
+       vpi_insert[i].DstReg.Index = VERT_RESULT_HPOS;
+       vpi_insert[i].DstReg.WriteMask = WRITEMASK_XYZW;
+       vpi_insert[i].DstReg.CondMask = COND_TR;
+       vpi_insert[i].SrcReg[0].File = PROGRAM_TEMPORARY;
+       vpi_insert[i].SrcReg[0].Index = temp_index;
+       vpi_insert[i].SrcReg[0].Swizzle = SWIZZLE_XYZW;
+       i++;
+       vpi_insert[i].Opcode = OPCODE_MOV;
+       vpi_insert[i].DstReg.File = PROGRAM_OUTPUT;
+       vpi_insert[i].DstReg.Index = VERT_RESULT_TEX0+vp->wpos_idx;
+       vpi_insert[i].DstReg.WriteMask = WRITEMASK_XYZW;
+       vpi_insert[i].DstReg.CondMask = COND_TR;
+       vpi_insert[i].SrcReg[0].File = PROGRAM_TEMPORARY;
+       vpi_insert[i].SrcReg[0].Index = temp_index;
+       vpi_insert[i].SrcReg[0].Swizzle = SWIZZLE_XYZW;
+       i++;
+       free(prog->Instructions);
+       prog->Instructions = vpi;
+       prog->NumInstructions += i;
+       vpi = &prog->Instructions[prog->NumInstructions-1];
+       assert(vpi->Opcode == OPCODE_END);
+ }
+ static void pos_as_texcoord(struct r300_vertex_program *vp,
+                           struct gl_program *prog)
+ {
+       struct prog_instruction *vpi;
+       GLuint tempregi = prog->NumTemporaries;
+       /* should do something else if no temps left... */
+       prog->NumTemporaries++;
+       for(vpi = prog->Instructions; vpi->Opcode != OPCODE_END; vpi++){
+               if( vpi->DstReg.File == PROGRAM_OUTPUT &&
+                   vpi->DstReg.Index == VERT_RESULT_HPOS ){
+                       vpi->DstReg.File = PROGRAM_TEMPORARY;
+                       vpi->DstReg.Index = tempregi;
+               }
+       }
+       insert_wpos(vp, prog, tempregi);
+ }
+ static struct r300_vertex_program *build_program(struct r300_vertex_program_key *wanted_key,
+                                                struct gl_vertex_program *mesa_vp,
+                                                GLint wpos_idx)
+ {
+       struct r300_vertex_program *vp;
+       vp = _mesa_calloc(sizeof(*vp));
+       _mesa_memcpy(&vp->key, wanted_key, sizeof(vp->key));
+       vp->wpos_idx = wpos_idx;
+       if(mesa_vp->IsPositionInvariant) {
+               position_invariant(&mesa_vp->Base);
+       }
+       if(wpos_idx > -1)
+               pos_as_texcoord(vp, &mesa_vp->Base);
+       assert(mesa_vp->Base.NumInstructions);
+       vp->num_temporaries=mesa_vp->Base.NumTemporaries;
+       r300_translate_vertex_shader(vp, mesa_vp->Base.Instructions);
+       return vp;      
+ }
+ void r300_select_vertex_shader(r300ContextPtr r300)
+ {
+       GLcontext *ctx = ctx = r300->radeon.glCtx;
+       GLuint InputsRead;
+       struct r300_vertex_program_key wanted_key = { 0 };
+       GLint i;
+       struct r300_vertex_program_cont *vpc;
+       struct r300_vertex_program *vp;
+       GLint wpos_idx;
+       vpc = (struct r300_vertex_program_cont *)ctx->VertexProgram._Current;
+       InputsRead = ctx->FragmentProgram._Current->Base.InputsRead;
+       wanted_key.OutputsWritten |= 1 << VERT_RESULT_HPOS;
+       wpos_idx = -1;
+       if (InputsRead & FRAG_BIT_WPOS){
+               for (i = 0; i < ctx->Const.MaxTextureUnits; i++)
+                       if (!(InputsRead & (FRAG_BIT_TEX0 << i)))
+                               break;
+               
+               if(i == ctx->Const.MaxTextureUnits){
+                       fprintf(stderr, "\tno free texcoord found\n");
+                       exit(0);
+               }
+               InputsRead |= (FRAG_BIT_TEX0 << i);
+               wpos_idx = i;
+       }
+       if (InputsRead & FRAG_BIT_COL0)
+               wanted_key.OutputsWritten |= 1 << VERT_RESULT_COL0;
+       if ((InputsRead & FRAG_BIT_COL1) /*||
+           (InputsRead & FRAG_BIT_FOGC)*/)
+               wanted_key.OutputsWritten |= 1 << VERT_RESULT_COL1;
+       
+       for (i = 0; i < ctx->Const.MaxTextureUnits; i++)
+               if (InputsRead & (FRAG_BIT_TEX0 << i))
+                       wanted_key.OutputsWritten |= 1 << (VERT_RESULT_TEX0 + i);
+       wanted_key.InputsRead = vpc->mesa_program.Base.InputsRead;
+       if(vpc->mesa_program.IsPositionInvariant) {
+               /* we wan't position don't we ? */
+               wanted_key.InputsRead |= (1 << VERT_ATTRIB_POS);
+       }
+       for (vp = vpc->progs; vp; vp = vp->next)
+               if (_mesa_memcmp(&vp->key, &wanted_key, sizeof(wanted_key)) == 0) {
+                       r300->selected_vp = vp;
+                       return ;
+               }
+       //_mesa_print_program(&vpc->mesa_program.Base);
+       vp = build_program(&wanted_key, &vpc->mesa_program, wpos_idx);
+       vp->next = vpc->progs;
+       vpc->progs = vp;
+       r300->selected_vp = vp;
+ }
diff --combined src/mesa/main/colortab.c
index 2ad5c309b45891002586af3434ce0fa750d577b4,d8c4136f49ef2f6164e470879dab87d3238d33b9..610acba3068aeaa42aed4eb61de551342b9be193
@@@ -1,8 -1,8 +1,8 @@@
  /*
   * Mesa 3-D graphics library
 - * Version:  6.5.2
 + * Version:  6.5.3
   *
 - * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
 + * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
   *
   * Permission is hereby granted, free of charge, to any person obtaining a
   * copy of this software and associated documentation files (the "Software"),
@@@ -291,15 -291,17 +291,17 @@@ _mesa_ColorTable( GLenum target, GLenu
                    GLsizei width, GLenum format, GLenum type,
                    const GLvoid *data )
  {
+    static const GLfloat one[4] = { 1.0, 1.0, 1.0, 1.0 };
+    static const GLfloat zero[4] = { 0.0, 0.0, 0.0, 0.0 };
     GET_CURRENT_CONTEXT(ctx);
     struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
     struct gl_texture_object *texObj = NULL;
     struct gl_color_table *table = NULL;
     GLboolean proxy = GL_FALSE;
     GLint baseFormat;
-    GLfloat rScale = 1.0, gScale = 1.0, bScale = 1.0, aScale = 1.0;
-    GLfloat rBias  = 0.0, gBias  = 0.0, bBias  = 0.0, aBias  = 0.0;
+    const GLfloat *scale = one, *bias = zero;
     GLint comps;
     ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* too complex */
  
     switch (target) {
           table = &ctx->Texture.Palette;
           break;
        case GL_COLOR_TABLE:
-          table = &ctx->ColorTable;
-          rScale = ctx->Pixel.ColorTableScale[0];
-          gScale = ctx->Pixel.ColorTableScale[1];
-          bScale = ctx->Pixel.ColorTableScale[2];
-          aScale = ctx->Pixel.ColorTableScale[3];
-          rBias = ctx->Pixel.ColorTableBias[0];
-          gBias = ctx->Pixel.ColorTableBias[1];
-          bBias = ctx->Pixel.ColorTableBias[2];
-          aBias = ctx->Pixel.ColorTableBias[3];
+          table = &ctx->ColorTable[COLORTABLE_PRECONVOLUTION];
+          scale = ctx->Pixel.ColorTableScale[COLORTABLE_PRECONVOLUTION];
+          bias = ctx->Pixel.ColorTableBias[COLORTABLE_PRECONVOLUTION];
           break;
        case GL_PROXY_COLOR_TABLE:
-          table = &ctx->ProxyColorTable;
+          table = &ctx->ProxyColorTable[COLORTABLE_PRECONVOLUTION];
           proxy = GL_TRUE;
           break;
        case GL_TEXTURE_COLOR_TABLE_SGI:
              return;
           }
           table = &(texUnit->ColorTable);
-          rScale = ctx->Pixel.TextureColorTableScale[0];
-          gScale = ctx->Pixel.TextureColorTableScale[1];
-          bScale = ctx->Pixel.TextureColorTableScale[2];
-          aScale = ctx->Pixel.TextureColorTableScale[3];
-          rBias = ctx->Pixel.TextureColorTableBias[0];
-          gBias = ctx->Pixel.TextureColorTableBias[1];
-          bBias = ctx->Pixel.TextureColorTableBias[2];
-          aBias = ctx->Pixel.TextureColorTableBias[3];
+          scale = ctx->Pixel.TextureColorTableScale;
+          bias = ctx->Pixel.TextureColorTableBias;
           break;
        case GL_PROXY_TEXTURE_COLOR_TABLE_SGI:
           if (!ctx->Extensions.SGI_texture_color_table) {
           proxy = GL_TRUE;
           break;
        case GL_POST_CONVOLUTION_COLOR_TABLE:
-          table = &ctx->PostConvolutionColorTable;
-          rScale = ctx->Pixel.PCCTscale[0];
-          gScale = ctx->Pixel.PCCTscale[1];
-          bScale = ctx->Pixel.PCCTscale[2];
-          aScale = ctx->Pixel.PCCTscale[3];
-          rBias = ctx->Pixel.PCCTbias[0];
-          gBias = ctx->Pixel.PCCTbias[1];
-          bBias = ctx->Pixel.PCCTbias[2];
-          aBias = ctx->Pixel.PCCTbias[3];
+          table = &ctx->ColorTable[COLORTABLE_POSTCONVOLUTION];
+          scale = ctx->Pixel.ColorTableScale[COLORTABLE_POSTCONVOLUTION];
+          bias = ctx->Pixel.ColorTableBias[COLORTABLE_POSTCONVOLUTION];
           break;
        case GL_PROXY_POST_CONVOLUTION_COLOR_TABLE:
-          table = &ctx->ProxyPostConvolutionColorTable;
+          table = &ctx->ProxyColorTable[COLORTABLE_POSTCONVOLUTION];
           proxy = GL_TRUE;
           break;
        case GL_POST_COLOR_MATRIX_COLOR_TABLE:
-          table = &ctx->PostColorMatrixColorTable;
-          rScale = ctx->Pixel.PCMCTscale[0];
-          gScale = ctx->Pixel.PCMCTscale[1];
-          bScale = ctx->Pixel.PCMCTscale[2];
-          aScale = ctx->Pixel.PCMCTscale[3];
-          rBias = ctx->Pixel.PCMCTbias[0];
-          gBias = ctx->Pixel.PCMCTbias[1];
-          bBias = ctx->Pixel.PCMCTbias[2];
-          aBias = ctx->Pixel.PCMCTbias[3];
+          table = &ctx->ColorTable[COLORTABLE_POSTCOLORMATRIX];
+          scale = ctx->Pixel.ColorTableScale[COLORTABLE_POSTCOLORMATRIX];
+          bias = ctx->Pixel.ColorTableBias[COLORTABLE_POSTCOLORMATRIX];
           break;
        case GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE:
-          table = &ctx->ProxyPostColorMatrixColorTable;
+          table = &ctx->ProxyColorTable[COLORTABLE_POSTCOLORMATRIX];
           proxy = GL_TRUE;
           break;
        default:
         store_colortable_entries(ctx, table,
                                  0, width,  /* start, count */
                                  format, type, data,
-                                 rScale, rBias,
-                                 gScale, gBias,
-                                 bScale, bBias,
-                                 aScale, aBias);
+                                 scale[0], bias[0],
+                                 scale[1], bias[1],
+                                 scale[2], bias[2],
+                                 scale[3], bias[3]);
        }
     } /* proxy */
  
@@@ -510,12 -488,14 +488,14 @@@ _mesa_ColorSubTable( GLenum target, GLs
                       GLsizei count, GLenum format, GLenum type,
                       const GLvoid *data )
  {
+    static const GLfloat one[4] = { 1.0, 1.0, 1.0, 1.0 };
+    static const GLfloat zero[4] = { 0.0, 0.0, 0.0, 0.0 };
     GET_CURRENT_CONTEXT(ctx);
     struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
     struct gl_texture_object *texObj = NULL;
     struct gl_color_table *table = NULL;
-    GLfloat rScale = 1.0, gScale = 1.0, bScale = 1.0, aScale = 1.0;
-    GLfloat rBias  = 0.0, gBias  = 0.0, bBias  = 0.0, aBias  = 0.0;
+    const GLfloat *scale = one, *bias = zero;
     ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
  
     switch (target) {
           table = &ctx->Texture.Palette;
           break;
        case GL_COLOR_TABLE:
-          table = &ctx->ColorTable;
-          rScale = ctx->Pixel.ColorTableScale[0];
-          gScale = ctx->Pixel.ColorTableScale[1];
-          bScale = ctx->Pixel.ColorTableScale[2];
-          aScale = ctx->Pixel.ColorTableScale[3];
-          rBias = ctx->Pixel.ColorTableBias[0];
-          gBias = ctx->Pixel.ColorTableBias[1];
-          bBias = ctx->Pixel.ColorTableBias[2];
-          aBias = ctx->Pixel.ColorTableBias[3];
+          table = &ctx->ColorTable[COLORTABLE_PRECONVOLUTION];
+          scale = ctx->Pixel.ColorTableScale[COLORTABLE_PRECONVOLUTION];
+          bias = ctx->Pixel.ColorTableBias[COLORTABLE_PRECONVOLUTION];
           break;
        case GL_TEXTURE_COLOR_TABLE_SGI:
           if (!ctx->Extensions.SGI_texture_color_table) {
              return;
           }
           table = &(texUnit->ColorTable);
-          rScale = ctx->Pixel.TextureColorTableScale[0];
-          gScale = ctx->Pixel.TextureColorTableScale[1];
-          bScale = ctx->Pixel.TextureColorTableScale[2];
-          aScale = ctx->Pixel.TextureColorTableScale[3];
-          rBias = ctx->Pixel.TextureColorTableBias[0];
-          gBias = ctx->Pixel.TextureColorTableBias[1];
-          bBias = ctx->Pixel.TextureColorTableBias[2];
-          aBias = ctx->Pixel.TextureColorTableBias[3];
+          scale = ctx->Pixel.TextureColorTableScale;
+          bias = ctx->Pixel.TextureColorTableBias;
           break;
        case GL_POST_CONVOLUTION_COLOR_TABLE:
-          table = &ctx->PostConvolutionColorTable;
-          rScale = ctx->Pixel.PCCTscale[0];
-          gScale = ctx->Pixel.PCCTscale[1];
-          bScale = ctx->Pixel.PCCTscale[2];
-          aScale = ctx->Pixel.PCCTscale[3];
-          rBias = ctx->Pixel.PCCTbias[0];
-          gBias = ctx->Pixel.PCCTbias[1];
-          bBias = ctx->Pixel.PCCTbias[2];
-          aBias = ctx->Pixel.PCCTbias[3];
+          table = &ctx->ColorTable[COLORTABLE_POSTCONVOLUTION];
+          scale = ctx->Pixel.ColorTableScale[COLORTABLE_POSTCONVOLUTION];
+          bias = ctx->Pixel.ColorTableBias[COLORTABLE_POSTCONVOLUTION];
           break;
        case GL_POST_COLOR_MATRIX_COLOR_TABLE:
-          table = &ctx->PostColorMatrixColorTable;
-          rScale = ctx->Pixel.PCMCTscale[0];
-          gScale = ctx->Pixel.PCMCTscale[1];
-          bScale = ctx->Pixel.PCMCTscale[2];
-          aScale = ctx->Pixel.PCMCTscale[3];
-          rBias = ctx->Pixel.PCMCTbias[0];
-          gBias = ctx->Pixel.PCMCTbias[1];
-          bBias = ctx->Pixel.PCMCTbias[2];
-          aBias = ctx->Pixel.PCMCTbias[3];
+          table = &ctx->ColorTable[COLORTABLE_POSTCOLORMATRIX];
+          scale = ctx->Pixel.ColorTableScale[COLORTABLE_POSTCOLORMATRIX];
+          bias = ctx->Pixel.ColorTableBias[COLORTABLE_POSTCOLORMATRIX];
           break;
        default:
           _mesa_error(ctx, GL_INVALID_ENUM, "glColorSubTable(target)");
  
     store_colortable_entries(ctx, table, start, count,
                            format, type, data,
-                           rScale, rBias,
-                           gScale, gBias,
-                           bScale, bBias,
-                           aScale, aBias);
+                             scale[0], bias[0],
+                             scale[1], bias[1],
+                             scale[2], bias[2],
+                             scale[3], bias[3]);
  
     if (texObj || target == GL_SHARED_TEXTURE_PALETTE_EXT) {
        /* per-texture object palette */
@@@ -700,7 -656,7 +656,7 @@@ _mesa_GetColorTable( GLenum target, GLe
           table = &ctx->Texture.Palette;
           break;
        case GL_COLOR_TABLE:
-          table = &ctx->ColorTable;
+          table = &ctx->ColorTable[COLORTABLE_PRECONVOLUTION];
           break;
        case GL_TEXTURE_COLOR_TABLE_SGI:
           if (!ctx->Extensions.SGI_texture_color_table) {
           table = &(texUnit->ColorTable);
           break;
        case GL_POST_CONVOLUTION_COLOR_TABLE:
-          table = &ctx->PostConvolutionColorTable;
+          table = &ctx->ColorTable[COLORTABLE_POSTCONVOLUTION];
           break;
        case GL_POST_COLOR_MATRIX_COLOR_TABLE:
-          table = &ctx->PostColorMatrixColorTable;
+          table = &ctx->ColorTable[COLORTABLE_POSTCOLORMATRIX];
           break;
        default:
           _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTable(target)");
  
     ASSERT(table);
  
 +   if (table->Size <= 0) {
 +      return;
 +   }
 +
     switch (table->_BaseFormat) {
     case GL_ALPHA:
        {
@@@ -831,16 -783,10 +787,10 @@@ _mesa_ColorTableParameterfv(GLenum targ
     switch (target) {
        case GL_COLOR_TABLE_SGI:
           if (pname == GL_COLOR_TABLE_SCALE_SGI) {
-             ctx->Pixel.ColorTableScale[0] = params[0];
-             ctx->Pixel.ColorTableScale[1] = params[1];
-             ctx->Pixel.ColorTableScale[2] = params[2];
-             ctx->Pixel.ColorTableScale[3] = params[3];
+             COPY_4V(ctx->Pixel.ColorTableScale[COLORTABLE_PRECONVOLUTION], params);
           }
           else if (pname == GL_COLOR_TABLE_BIAS_SGI) {
-             ctx->Pixel.ColorTableBias[0] = params[0];
-             ctx->Pixel.ColorTableBias[1] = params[1];
-             ctx->Pixel.ColorTableBias[2] = params[2];
-             ctx->Pixel.ColorTableBias[3] = params[3];
+             COPY_4V(ctx->Pixel.ColorTableBias[COLORTABLE_PRECONVOLUTION], params);
           }
           else {
              _mesa_error(ctx, GL_INVALID_ENUM, "glColorTableParameterfv(pname)");
              return;
           }
           if (pname == GL_COLOR_TABLE_SCALE_SGI) {
-             ctx->Pixel.TextureColorTableScale[0] = params[0];
-             ctx->Pixel.TextureColorTableScale[1] = params[1];
-             ctx->Pixel.TextureColorTableScale[2] = params[2];
-             ctx->Pixel.TextureColorTableScale[3] = params[3];
+             COPY_4V(ctx->Pixel.TextureColorTableScale, params);
           }
           else if (pname == GL_COLOR_TABLE_BIAS_SGI) {
-             ctx->Pixel.TextureColorTableBias[0] = params[0];
-             ctx->Pixel.TextureColorTableBias[1] = params[1];
-             ctx->Pixel.TextureColorTableBias[2] = params[2];
-             ctx->Pixel.TextureColorTableBias[3] = params[3];
+             COPY_4V(ctx->Pixel.TextureColorTableBias, params);
           }
           else {
              _mesa_error(ctx, GL_INVALID_ENUM, "glColorTableParameterfv(pname)");
           break;
        case GL_POST_CONVOLUTION_COLOR_TABLE_SGI:
           if (pname == GL_COLOR_TABLE_SCALE_SGI) {
-             ctx->Pixel.PCCTscale[0] = params[0];
-             ctx->Pixel.PCCTscale[1] = params[1];
-             ctx->Pixel.PCCTscale[2] = params[2];
-             ctx->Pixel.PCCTscale[3] = params[3];
+             COPY_4V(ctx->Pixel.ColorTableScale[COLORTABLE_POSTCONVOLUTION], params);
           }
           else if (pname == GL_COLOR_TABLE_BIAS_SGI) {
-             ctx->Pixel.PCCTbias[0] = params[0];
-             ctx->Pixel.PCCTbias[1] = params[1];
-             ctx->Pixel.PCCTbias[2] = params[2];
-             ctx->Pixel.PCCTbias[3] = params[3];
+             COPY_4V(ctx->Pixel.ColorTableBias[COLORTABLE_POSTCONVOLUTION], params);
           }
           else {
              _mesa_error(ctx, GL_INVALID_ENUM, "glColorTableParameterfv(pname)");
           break;
        case GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI:
           if (pname == GL_COLOR_TABLE_SCALE_SGI) {
-             ctx->Pixel.PCMCTscale[0] = params[0];
-             ctx->Pixel.PCMCTscale[1] = params[1];
-             ctx->Pixel.PCMCTscale[2] = params[2];
-             ctx->Pixel.PCMCTscale[3] = params[3];
+             COPY_4V(ctx->Pixel.ColorTableScale[COLORTABLE_POSTCOLORMATRIX], params);
           }
           else if (pname == GL_COLOR_TABLE_BIAS_SGI) {
-             ctx->Pixel.PCMCTbias[0] = params[0];
-             ctx->Pixel.PCMCTbias[1] = params[1];
-             ctx->Pixel.PCMCTbias[2] = params[2];
-             ctx->Pixel.PCMCTbias[3] = params[3];
+             COPY_4V(ctx->Pixel.ColorTableBias[COLORTABLE_POSTCOLORMATRIX], params);
           }
           else {
              _mesa_error(ctx, GL_INVALID_ENUM, "glColorTableParameterfv(pname)");
@@@ -985,24 -913,18 +917,18 @@@ _mesa_GetColorTableParameterfv( GLenum 
           table = &ctx->Texture.Palette;
           break;
        case GL_COLOR_TABLE:
-          table = &ctx->ColorTable;
+          table = &ctx->ColorTable[COLORTABLE_PRECONVOLUTION];
           if (pname == GL_COLOR_TABLE_SCALE_SGI) {
-             params[0] = ctx->Pixel.ColorTableScale[0];
-             params[1] = ctx->Pixel.ColorTableScale[1];
-             params[2] = ctx->Pixel.ColorTableScale[2];
-             params[3] = ctx->Pixel.ColorTableScale[3];
+             COPY_4V(params, ctx->Pixel.ColorTableScale[COLORTABLE_PRECONVOLUTION]);
              return;
           }
           else if (pname == GL_COLOR_TABLE_BIAS_SGI) {
-             params[0] = ctx->Pixel.ColorTableBias[0];
-             params[1] = ctx->Pixel.ColorTableBias[1];
-             params[2] = ctx->Pixel.ColorTableBias[2];
-             params[3] = ctx->Pixel.ColorTableBias[3];
+             COPY_4V(params, ctx->Pixel.ColorTableBias[COLORTABLE_PRECONVOLUTION]);
              return;
           }
           break;
        case GL_PROXY_COLOR_TABLE:
-          table = &ctx->ProxyColorTable;
+          table = &ctx->ProxyColorTable[COLORTABLE_PRECONVOLUTION];
           break;
        case GL_TEXTURE_COLOR_TABLE_SGI:
           if (!ctx->Extensions.SGI_texture_color_table) {
           }
           table = &(texUnit->ColorTable);
           if (pname == GL_COLOR_TABLE_SCALE_SGI) {
-             params[0] = ctx->Pixel.TextureColorTableScale[0];
-             params[1] = ctx->Pixel.TextureColorTableScale[1];
-             params[2] = ctx->Pixel.TextureColorTableScale[2];
-             params[3] = ctx->Pixel.TextureColorTableScale[3];
+             COPY_4V(params, ctx->Pixel.TextureColorTableScale);
              return;
           }
           else if (pname == GL_COLOR_TABLE_BIAS_SGI) {
-             params[0] = ctx->Pixel.TextureColorTableBias[0];
-             params[1] = ctx->Pixel.TextureColorTableBias[1];
-             params[2] = ctx->Pixel.TextureColorTableBias[2];
-             params[3] = ctx->Pixel.TextureColorTableBias[3];
+             COPY_4V(params, ctx->Pixel.TextureColorTableBias);
              return;
           }
           break;
           table = &(texUnit->ProxyColorTable);
           break;
        case GL_POST_CONVOLUTION_COLOR_TABLE:
-          table = &ctx->PostConvolutionColorTable;
+          table = &ctx->ColorTable[COLORTABLE_POSTCONVOLUTION];
           if (pname == GL_COLOR_TABLE_SCALE_SGI) {
-             params[0] = ctx->Pixel.PCCTscale[0];
-             params[1] = ctx->Pixel.PCCTscale[1];
-             params[2] = ctx->Pixel.PCCTscale[2];
-             params[3] = ctx->Pixel.PCCTscale[3];
+             COPY_4V(params, ctx->Pixel.ColorTableScale[COLORTABLE_POSTCONVOLUTION]);
              return;
           }
           else if (pname == GL_COLOR_TABLE_BIAS_SGI) {
-             params[0] = ctx->Pixel.PCCTbias[0];
-             params[1] = ctx->Pixel.PCCTbias[1];
-             params[2] = ctx->Pixel.PCCTbias[2];
-             params[3] = ctx->Pixel.PCCTbias[3];
+             COPY_4V(params, ctx->Pixel.ColorTableBias[COLORTABLE_POSTCONVOLUTION]);
              return;
           }
           break;
        case GL_PROXY_POST_CONVOLUTION_COLOR_TABLE:
-          table = &ctx->ProxyPostConvolutionColorTable;
+          table = &ctx->ProxyColorTable[COLORTABLE_POSTCONVOLUTION];
           break;
        case GL_POST_COLOR_MATRIX_COLOR_TABLE:
-          table = &ctx->PostColorMatrixColorTable;
+          table = &ctx->ColorTable[COLORTABLE_POSTCOLORMATRIX];
           if (pname == GL_COLOR_TABLE_SCALE_SGI) {
-             params[0] = ctx->Pixel.PCMCTscale[0];
-             params[1] = ctx->Pixel.PCMCTscale[1];
-             params[2] = ctx->Pixel.PCMCTscale[2];
-             params[3] = ctx->Pixel.PCMCTscale[3];
+             COPY_4V(params, ctx->Pixel.ColorTableScale[COLORTABLE_POSTCOLORMATRIX]);
              return;
           }
           else if (pname == GL_COLOR_TABLE_BIAS_SGI) {
-             params[0] = ctx->Pixel.PCMCTbias[0];
-             params[1] = ctx->Pixel.PCMCTbias[1];
-             params[2] = ctx->Pixel.PCMCTbias[2];
-             params[3] = ctx->Pixel.PCMCTbias[3];
+             COPY_4V(params, ctx->Pixel.ColorTableBias[COLORTABLE_POSTCOLORMATRIX]);
              return;
           }
           break;
        case GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE:
-          table = &ctx->ProxyPostColorMatrixColorTable;
+          table = &ctx->ProxyColorTable[COLORTABLE_POSTCOLORMATRIX];
           break;
        default:
           _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameterfv(target)");
@@@ -1159,24 -1063,26 +1067,26 @@@ _mesa_GetColorTableParameteriv( GLenum 
           table = &ctx->Texture.Palette;
           break;
        case GL_COLOR_TABLE:
-          table = &ctx->ColorTable;
+          table = &ctx->ColorTable[COLORTABLE_PRECONVOLUTION];
           if (pname == GL_COLOR_TABLE_SCALE_SGI) {
-             params[0] = (GLint) ctx->Pixel.ColorTableScale[0];
-             params[1] = (GLint) ctx->Pixel.ColorTableScale[1];
-             params[2] = (GLint) ctx->Pixel.ColorTableScale[2];
-             params[3] = (GLint) ctx->Pixel.ColorTableScale[3];
+             GLfloat *scale = ctx->Pixel.ColorTableScale[COLORTABLE_PRECONVOLUTION];
+             params[0] = (GLint) scale[0];
+             params[1] = (GLint) scale[1];
+             params[2] = (GLint) scale[2];
+             params[3] = (GLint) scale[3];
              return;
           }
           else if (pname == GL_COLOR_TABLE_BIAS_SGI) {
-             params[0] = (GLint) ctx->Pixel.ColorTableBias[0];
-             params[1] = (GLint) ctx->Pixel.ColorTableBias[1];
-             params[2] = (GLint) ctx->Pixel.ColorTableBias[2];
-             params[3] = (GLint) ctx->Pixel.ColorTableBias[3];
+             GLfloat *bias = ctx->Pixel.ColorTableBias[COLORTABLE_PRECONVOLUTION];
+             params[0] = (GLint) bias[0];
+             params[1] = (GLint) bias[1];
+             params[2] = (GLint) bias[2];
+             params[3] = (GLint) bias[3];
              return;
           }
           break;
        case GL_PROXY_COLOR_TABLE:
-          table = &ctx->ProxyColorTable;
+          table = &ctx->ProxyColorTable[COLORTABLE_PRECONVOLUTION];
           break;
        case GL_TEXTURE_COLOR_TABLE_SGI:
           if (!ctx->Extensions.SGI_texture_color_table) {
           table = &(texUnit->ProxyColorTable);
           break;
        case GL_POST_CONVOLUTION_COLOR_TABLE:
-          table = &ctx->PostConvolutionColorTable;
+          table = &ctx->ColorTable[COLORTABLE_POSTCONVOLUTION];
           if (pname == GL_COLOR_TABLE_SCALE_SGI) {
-             params[0] = (GLint) ctx->Pixel.PCCTscale[0];
-             params[1] = (GLint) ctx->Pixel.PCCTscale[1];
-             params[2] = (GLint) ctx->Pixel.PCCTscale[2];
-             params[3] = (GLint) ctx->Pixel.PCCTscale[3];
+             GLfloat *scale = ctx->Pixel.ColorTableScale[COLORTABLE_POSTCONVOLUTION];
+             params[0] = (GLint) scale[0];
+             params[1] = (GLint) scale[1];
+             params[2] = (GLint) scale[2];
+             params[3] = (GLint) scale[3];
              return;
           }
           else if (pname == GL_COLOR_TABLE_BIAS_SGI) {
-             params[0] = (GLint) ctx->Pixel.PCCTbias[0];
-             params[1] = (GLint) ctx->Pixel.PCCTbias[1];
-             params[2] = (GLint) ctx->Pixel.PCCTbias[2];
-             params[3] = (GLint) ctx->Pixel.PCCTbias[3];
+             GLfloat *bias = ctx->Pixel.ColorTableBias[COLORTABLE_POSTCONVOLUTION];
+             params[0] = (GLint) bias[0];
+             params[1] = (GLint) bias[1];
+             params[2] = (GLint) bias[2];
+             params[3] = (GLint) bias[3];
              return;
           }
           break;
        case GL_PROXY_POST_CONVOLUTION_COLOR_TABLE:
-          table = &ctx->ProxyPostConvolutionColorTable;
+          table = &ctx->ProxyColorTable[COLORTABLE_POSTCONVOLUTION];
           break;
        case GL_POST_COLOR_MATRIX_COLOR_TABLE:
-          table = &ctx->PostColorMatrixColorTable;
+          table = &ctx->ColorTable[COLORTABLE_POSTCOLORMATRIX];
           if (pname == GL_COLOR_TABLE_SCALE_SGI) {
-             params[0] = (GLint) ctx->Pixel.PCMCTscale[0];
-             params[1] = (GLint) ctx->Pixel.PCMCTscale[1];
-             params[2] = (GLint) ctx->Pixel.PCMCTscale[2];
-             params[3] = (GLint) ctx->Pixel.PCMCTscale[3];
+             GLfloat *scale = ctx->Pixel.ColorTableScale[COLORTABLE_POSTCOLORMATRIX];
+             params[0] = (GLint) scale[0];
+             params[0] = (GLint) scale[1];
+             params[0] = (GLint) scale[2];
+             params[0] = (GLint) scale[3];
              return;
           }
           else if (pname == GL_COLOR_TABLE_BIAS_SGI) {
-             params[0] = (GLint) ctx->Pixel.PCMCTbias[0];
-             params[1] = (GLint) ctx->Pixel.PCMCTbias[1];
-             params[2] = (GLint) ctx->Pixel.PCMCTbias[2];
-             params[3] = (GLint) ctx->Pixel.PCMCTbias[3];
+             GLfloat *bias = ctx->Pixel.ColorTableScale[COLORTABLE_POSTCOLORMATRIX];
+             params[0] = (GLint) bias[0];
+             params[1] = (GLint) bias[1];
+             params[2] = (GLint) bias[2];
+             params[3] = (GLint) bias[3];
              return;
           }
           break;
        case GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE:
-          table = &ctx->ProxyPostColorMatrixColorTable;
+          table = &ctx->ProxyColorTable[COLORTABLE_POSTCOLORMATRIX];
           break;
        default:
           _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameteriv(target)");
@@@ -1320,13 -1230,11 +1234,11 @@@ _mesa_free_colortable_data( struct gl_c
  void
  _mesa_init_colortables( GLcontext * ctx )
  {
-    /* Color tables */
-    _mesa_init_colortable(&ctx->ColorTable);
-    _mesa_init_colortable(&ctx->ProxyColorTable);
-    _mesa_init_colortable(&ctx->PostConvolutionColorTable);
-    _mesa_init_colortable(&ctx->ProxyPostConvolutionColorTable);
-    _mesa_init_colortable(&ctx->PostColorMatrixColorTable);
-    _mesa_init_colortable(&ctx->ProxyPostColorMatrixColorTable);
+    GLuint i;
+    for (i = 0; i < COLORTABLE_MAX; i++) {
+       _mesa_init_colortable(&ctx->ColorTable[i]);
+       _mesa_init_colortable(&ctx->ProxyColorTable[i]);
+    }
  }
  
  
  void
  _mesa_free_colortables_data( GLcontext *ctx )
  {
-    _mesa_free_colortable_data(&ctx->ColorTable);
-    _mesa_free_colortable_data(&ctx->ProxyColorTable);
-    _mesa_free_colortable_data(&ctx->PostConvolutionColorTable);
-    _mesa_free_colortable_data(&ctx->ProxyPostConvolutionColorTable);
-    _mesa_free_colortable_data(&ctx->PostColorMatrixColorTable);
-    _mesa_free_colortable_data(&ctx->ProxyPostColorMatrixColorTable);
+    GLuint i;
+    for (i = 0; i < COLORTABLE_MAX; i++) {
+       _mesa_free_colortable_data(&ctx->ColorTable[i]);
+       _mesa_free_colortable_data(&ctx->ProxyColorTable[i]);
+    }
  }
diff --combined src/mesa/main/get.c
index d09e0610ab0ed12cf086c73f268e473daceb7c49,4eda3491341a6ff97f1185a18c5ad8b60d7a26ec..eb81ee4a528b99ce0f2bcef6b03c5d4ed4df8e1a
@@@ -677,34 -677,34 +677,34 @@@ _mesa_GetBooleanv( GLenum pname, GLbool
           params[0] = ENUM_TO_BOOLEAN(ctx->Hint.PerspectiveCorrection);
           break;
        case GL_PIXEL_MAP_A_TO_A_SIZE:
-          params[0] = INT_TO_BOOLEAN(ctx->Pixel.MapAtoAsize);
+          params[0] = INT_TO_BOOLEAN(ctx->PixelMaps.AtoA.Size);
           break;
        case GL_PIXEL_MAP_B_TO_B_SIZE:
-          params[0] = INT_TO_BOOLEAN(ctx->Pixel.MapBtoBsize);
+          params[0] = INT_TO_BOOLEAN(ctx->PixelMaps.BtoB.Size);
           break;
        case GL_PIXEL_MAP_G_TO_G_SIZE:
-          params[0] = INT_TO_BOOLEAN(ctx->Pixel.MapGtoGsize);
+          params[0] = INT_TO_BOOLEAN(ctx->PixelMaps.GtoG.Size);
           break;
        case GL_PIXEL_MAP_I_TO_A_SIZE:
-          params[0] = INT_TO_BOOLEAN(ctx->Pixel.MapItoAsize);
+          params[0] = INT_TO_BOOLEAN(ctx->PixelMaps.ItoA.Size);
           break;
        case GL_PIXEL_MAP_I_TO_B_SIZE:
-          params[0] = INT_TO_BOOLEAN(ctx->Pixel.MapItoBsize);
+          params[0] = INT_TO_BOOLEAN(ctx->PixelMaps.ItoB.Size);
           break;
        case GL_PIXEL_MAP_I_TO_G_SIZE:
-          params[0] = INT_TO_BOOLEAN(ctx->Pixel.MapItoGsize);
+          params[0] = INT_TO_BOOLEAN(ctx->PixelMaps.ItoG.Size);
           break;
        case GL_PIXEL_MAP_I_TO_I_SIZE:
-          params[0] = INT_TO_BOOLEAN(ctx->Pixel.MapItoIsize);
+          params[0] = INT_TO_BOOLEAN(ctx->PixelMaps.ItoI.Size);
           break;
        case GL_PIXEL_MAP_I_TO_R_SIZE:
-          params[0] = INT_TO_BOOLEAN(ctx->Pixel.MapItoRsize);
+          params[0] = INT_TO_BOOLEAN(ctx->PixelMaps.ItoR.Size);
           break;
        case GL_PIXEL_MAP_R_TO_R_SIZE:
-          params[0] = INT_TO_BOOLEAN(ctx->Pixel.MapRtoRsize);
+          params[0] = INT_TO_BOOLEAN(ctx->PixelMaps.RtoR.Size);
           break;
        case GL_PIXEL_MAP_S_TO_S_SIZE:
-          params[0] = INT_TO_BOOLEAN(ctx->Pixel.MapStoSsize);
+          params[0] = INT_TO_BOOLEAN(ctx->PixelMaps.StoS.Size);
           break;
        case GL_POINT_SIZE:
           params[0] = FLOAT_TO_BOOLEAN(ctx->Point.Size);
           break;
        case GL_COLOR_TABLE_SGI:
           CHECK_EXT1(SGI_color_table, "GetBooleanv");
-          params[0] = ctx->Pixel.ColorTableEnabled;
+          params[0] = ctx->Pixel.ColorTableEnabled[COLORTABLE_PRECONVOLUTION];
           break;
        case GL_POST_CONVOLUTION_COLOR_TABLE_SGI:
           CHECK_EXT1(SGI_color_table, "GetBooleanv");
-          params[0] = ctx->Pixel.PostConvolutionColorTableEnabled;
+          params[0] = ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCONVOLUTION];
           break;
        case GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI:
           CHECK_EXT1(SGI_color_table, "GetBooleanv");
-          params[0] = ctx->Pixel.PostColorMatrixColorTableEnabled;
+          params[0] = ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCOLORMATRIX];
           break;
        case GL_TEXTURE_COLOR_TABLE_SGI:
           CHECK_EXT1(SGI_texture_color_table, "GetBooleanv");
           break;
        case GL_MAX_VARYING_FLOATS_ARB:
           CHECK_EXT1(ARB_vertex_shader, "GetBooleanv");
 -         params[0] = INT_TO_BOOLEAN(ctx->Const.MaxVaryingFloats);
 +         params[0] = INT_TO_BOOLEAN(ctx->Const.MaxVarying * 4);
           break;
        case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB:
           CHECK_EXT1(ARB_vertex_shader, "GetBooleanv");
           CHECK_EXT1(ARB_vertex_shader, "GetBooleanv");
           params[0] = INT_TO_BOOLEAN(MAX_COMBINED_TEXTURE_IMAGE_UNITS);
           break;
 +      case GL_CURRENT_PROGRAM:
 +         CHECK_EXT1(ARB_shader_objects, "GetBooleanv");
 +         params[0] = INT_TO_BOOLEAN(ctx->Shader.CurrentProgram ? ctx->Shader.CurrentProgram->Name : 0);
 +         break;
        default:
           _mesa_error(ctx, GL_INVALID_ENUM, "glGetBooleanv(pname=0x%x)", pname);
     }
@@@ -2508,34 -2504,34 +2508,34 @@@ _mesa_GetFloatv( GLenum pname, GLfloat 
           params[0] = ENUM_TO_FLOAT(ctx->Hint.PerspectiveCorrection);
           break;
        case GL_PIXEL_MAP_A_TO_A_SIZE:
-          params[0] = (GLfloat)(ctx->Pixel.MapAtoAsize);
+          params[0] = (GLfloat)(ctx->PixelMaps.AtoA.Size);
           break;
        case GL_PIXEL_MAP_B_TO_B_SIZE:
-          params[0] = (GLfloat)(ctx->Pixel.MapBtoBsize);
+          params[0] = (GLfloat)(ctx->PixelMaps.BtoB.Size);
           break;
        case GL_PIXEL_MAP_G_TO_G_SIZE:
-          params[0] = (GLfloat)(ctx->Pixel.MapGtoGsize);
+          params[0] = (GLfloat)(ctx->PixelMaps.GtoG.Size);
           break;
        case GL_PIXEL_MAP_I_TO_A_SIZE:
-          params[0] = (GLfloat)(ctx->Pixel.MapItoAsize);
+          params[0] = (GLfloat)(ctx->PixelMaps.ItoA.Size);
           break;
        case GL_PIXEL_MAP_I_TO_B_SIZE:
-          params[0] = (GLfloat)(ctx->Pixel.MapItoBsize);
+          params[0] = (GLfloat)(ctx->PixelMaps.ItoB.Size);
           break;
        case GL_PIXEL_MAP_I_TO_G_SIZE:
-          params[0] = (GLfloat)(ctx->Pixel.MapItoGsize);
+          params[0] = (GLfloat)(ctx->PixelMaps.ItoG.Size);
           break;
        case GL_PIXEL_MAP_I_TO_I_SIZE:
-          params[0] = (GLfloat)(ctx->Pixel.MapItoIsize);
+          params[0] = (GLfloat)(ctx->PixelMaps.ItoI.Size);
           break;
        case GL_PIXEL_MAP_I_TO_R_SIZE:
-          params[0] = (GLfloat)(ctx->Pixel.MapItoRsize);
+          params[0] = (GLfloat)(ctx->PixelMaps.ItoR.Size);
           break;
        case GL_PIXEL_MAP_R_TO_R_SIZE:
-          params[0] = (GLfloat)(ctx->Pixel.MapRtoRsize);
+          params[0] = (GLfloat)(ctx->PixelMaps.RtoR.Size);
           break;
        case GL_PIXEL_MAP_S_TO_S_SIZE:
-          params[0] = (GLfloat)(ctx->Pixel.MapStoSsize);
+          params[0] = (GLfloat)(ctx->PixelMaps.StoS.Size);
           break;
        case GL_POINT_SIZE:
           params[0] = ctx->Point.Size;
           break;
        case GL_COLOR_TABLE_SGI:
           CHECK_EXT1(SGI_color_table, "GetFloatv");
-          params[0] = BOOLEAN_TO_FLOAT(ctx->Pixel.ColorTableEnabled);
+          params[0] = BOOLEAN_TO_FLOAT(ctx->Pixel.ColorTableEnabled[COLORTABLE_PRECONVOLUTION]);
           break;
        case GL_POST_CONVOLUTION_COLOR_TABLE_SGI:
           CHECK_EXT1(SGI_color_table, "GetFloatv");
-          params[0] = BOOLEAN_TO_FLOAT(ctx->Pixel.PostConvolutionColorTableEnabled);
+          params[0] = BOOLEAN_TO_FLOAT(ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCONVOLUTION]);
           break;
        case GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI:
           CHECK_EXT1(SGI_color_table, "GetFloatv");
-          params[0] = BOOLEAN_TO_FLOAT(ctx->Pixel.PostColorMatrixColorTableEnabled);
+          params[0] = BOOLEAN_TO_FLOAT(ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCOLORMATRIX]);
           break;
        case GL_TEXTURE_COLOR_TABLE_SGI:
           CHECK_EXT1(SGI_texture_color_table, "GetFloatv");
           break;
        case GL_MAX_VARYING_FLOATS_ARB:
           CHECK_EXT1(ARB_vertex_shader, "GetFloatv");
 -         params[0] = (GLfloat)(ctx->Const.MaxVaryingFloats);
 +         params[0] = (GLfloat)(ctx->Const.MaxVarying * 4);
           break;
        case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB:
           CHECK_EXT1(ARB_vertex_shader, "GetFloatv");
           CHECK_EXT1(ARB_vertex_shader, "GetFloatv");
           params[0] = (GLfloat)(MAX_COMBINED_TEXTURE_IMAGE_UNITS);
           break;
 +      case GL_CURRENT_PROGRAM:
 +         CHECK_EXT1(ARB_shader_objects, "GetFloatv");
 +         params[0] = (GLfloat)(ctx->Shader.CurrentProgram ? ctx->Shader.CurrentProgram->Name : 0);
 +         break;
        default:
           _mesa_error(ctx, GL_INVALID_ENUM, "glGetFloatv(pname=0x%x)", pname);
     }
@@@ -4339,34 -4331,34 +4339,34 @@@ _mesa_GetIntegerv( GLenum pname, GLint 
           params[0] = ENUM_TO_INT(ctx->Hint.PerspectiveCorrection);
           break;
        case GL_PIXEL_MAP_A_TO_A_SIZE:
-          params[0] = ctx->Pixel.MapAtoAsize;
+          params[0] = ctx->PixelMaps.AtoA.Size;
           break;
        case GL_PIXEL_MAP_B_TO_B_SIZE:
-          params[0] = ctx->Pixel.MapBtoBsize;
+          params[0] = ctx->PixelMaps.BtoB.Size;
           break;
        case GL_PIXEL_MAP_G_TO_G_SIZE:
-          params[0] = ctx->Pixel.MapGtoGsize;
+          params[0] = ctx->PixelMaps.GtoG.Size;
           break;
        case GL_PIXEL_MAP_I_TO_A_SIZE:
-          params[0] = ctx->Pixel.MapItoAsize;
+          params[0] = ctx->PixelMaps.ItoA.Size;
           break;
        case GL_PIXEL_MAP_I_TO_B_SIZE:
-          params[0] = ctx->Pixel.MapItoBsize;
+          params[0] = ctx->PixelMaps.ItoB.Size;
           break;
        case GL_PIXEL_MAP_I_TO_G_SIZE:
-          params[0] = ctx->Pixel.MapItoGsize;
+          params[0] = ctx->PixelMaps.ItoG.Size;
           break;
        case GL_PIXEL_MAP_I_TO_I_SIZE:
-          params[0] = ctx->Pixel.MapItoIsize;
+          params[0] = ctx->PixelMaps.ItoI.Size;
           break;
        case GL_PIXEL_MAP_I_TO_R_SIZE:
-          params[0] = ctx->Pixel.MapItoRsize;
+          params[0] = ctx->PixelMaps.ItoR.Size;
           break;
        case GL_PIXEL_MAP_R_TO_R_SIZE:
-          params[0] = ctx->Pixel.MapRtoRsize;
+          params[0] = ctx->PixelMaps.RtoR.Size;
           break;
        case GL_PIXEL_MAP_S_TO_S_SIZE:
-          params[0] = ctx->Pixel.MapStoSsize;
+          params[0] = ctx->PixelMaps.StoS.Size;
           break;
        case GL_POINT_SIZE:
           params[0] = IROUND(ctx->Point.Size);
           break;
        case GL_COLOR_TABLE_SGI:
           CHECK_EXT1(SGI_color_table, "GetIntegerv");
-          params[0] = BOOLEAN_TO_INT(ctx->Pixel.ColorTableEnabled);
+          params[0] = BOOLEAN_TO_INT(ctx->Pixel.ColorTableEnabled[COLORTABLE_PRECONVOLUTION]);
           break;
        case GL_POST_CONVOLUTION_COLOR_TABLE_SGI:
           CHECK_EXT1(SGI_color_table, "GetIntegerv");
-          params[0] = BOOLEAN_TO_INT(ctx->Pixel.PostConvolutionColorTableEnabled);
+          params[0] = BOOLEAN_TO_INT(ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCONVOLUTION]);
           break;
        case GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI:
           CHECK_EXT1(SGI_color_table, "GetIntegerv");
-          params[0] = BOOLEAN_TO_INT(ctx->Pixel.PostColorMatrixColorTableEnabled);
+          params[0] = BOOLEAN_TO_INT(ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCOLORMATRIX]);
           break;
        case GL_TEXTURE_COLOR_TABLE_SGI:
           CHECK_EXT1(SGI_texture_color_table, "GetIntegerv");
           break;
        case GL_MAX_VARYING_FLOATS_ARB:
           CHECK_EXT1(ARB_vertex_shader, "GetIntegerv");
 -         params[0] = ctx->Const.MaxVaryingFloats;
 +         params[0] = ctx->Const.MaxVarying * 4;
           break;
        case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB:
           CHECK_EXT1(ARB_vertex_shader, "GetIntegerv");
           CHECK_EXT1(ARB_vertex_shader, "GetIntegerv");
           params[0] = MAX_COMBINED_TEXTURE_IMAGE_UNITS;
           break;
 +      case GL_CURRENT_PROGRAM:
 +         CHECK_EXT1(ARB_shader_objects, "GetIntegerv");
 +         params[0] = ctx->Shader.CurrentProgram ? ctx->Shader.CurrentProgram->Name : 0;
 +         break;
        default:
           _mesa_error(ctx, GL_INVALID_ENUM, "glGetIntegerv(pname=0x%x)", pname);
     }
diff --combined src/mesa/main/get_gen.py
index 3e66946b92f5092c34ccdd1efd444bbbd64ffe94,0b6cd3e5c58ec62c6ec5171a783347b922e38a02..33be7689997816c696cf4b7e87b84a0775eeb1b6
@@@ -337,16 -337,16 +337,16 @@@ StateVars = 
        ( "GL_PACK_INVERT_MESA", GLboolean, ["ctx->Pack.Invert"], "", None ),
        ( "GL_PERSPECTIVE_CORRECTION_HINT", GLenum,
          ["ctx->Hint.PerspectiveCorrection"], "", None ),
-       ( "GL_PIXEL_MAP_A_TO_A_SIZE", GLint, ["ctx->Pixel.MapAtoAsize"], "", None ),
-       ( "GL_PIXEL_MAP_B_TO_B_SIZE", GLint, ["ctx->Pixel.MapBtoBsize"], "", None ),
-       ( "GL_PIXEL_MAP_G_TO_G_SIZE", GLint, ["ctx->Pixel.MapGtoGsize"], "", None ),
-       ( "GL_PIXEL_MAP_I_TO_A_SIZE", GLint, ["ctx->Pixel.MapItoAsize"], "", None ),
-       ( "GL_PIXEL_MAP_I_TO_B_SIZE", GLint, ["ctx->Pixel.MapItoBsize"], "", None ),
-       ( "GL_PIXEL_MAP_I_TO_G_SIZE", GLint, ["ctx->Pixel.MapItoGsize"], "", None ),
-       ( "GL_PIXEL_MAP_I_TO_I_SIZE", GLint, ["ctx->Pixel.MapItoIsize"], "", None ),
-       ( "GL_PIXEL_MAP_I_TO_R_SIZE", GLint, ["ctx->Pixel.MapItoRsize"], "", None ),
-       ( "GL_PIXEL_MAP_R_TO_R_SIZE", GLint, ["ctx->Pixel.MapRtoRsize"], "", None ),
-       ( "GL_PIXEL_MAP_S_TO_S_SIZE", GLint, ["ctx->Pixel.MapStoSsize"], "", None ),
+       ( "GL_PIXEL_MAP_A_TO_A_SIZE", GLint, ["ctx->PixelMaps.AtoA.Size"], "", None ),
+       ( "GL_PIXEL_MAP_B_TO_B_SIZE", GLint, ["ctx->PixelMaps.BtoB.Size"], "", None ),
+       ( "GL_PIXEL_MAP_G_TO_G_SIZE", GLint, ["ctx->PixelMaps.GtoG.Size"], "", None ),
+       ( "GL_PIXEL_MAP_I_TO_A_SIZE", GLint, ["ctx->PixelMaps.ItoA.Size"], "", None ),
+       ( "GL_PIXEL_MAP_I_TO_B_SIZE", GLint, ["ctx->PixelMaps.ItoB.Size"], "", None ),
+       ( "GL_PIXEL_MAP_I_TO_G_SIZE", GLint, ["ctx->PixelMaps.ItoG.Size"], "", None ),
+       ( "GL_PIXEL_MAP_I_TO_I_SIZE", GLint, ["ctx->PixelMaps.ItoI.Size"], "", None ),
+       ( "GL_PIXEL_MAP_I_TO_R_SIZE", GLint, ["ctx->PixelMaps.ItoR.Size"], "", None ),
+       ( "GL_PIXEL_MAP_R_TO_R_SIZE", GLint, ["ctx->PixelMaps.RtoR.Size"], "", None ),
+       ( "GL_PIXEL_MAP_S_TO_S_SIZE", GLint, ["ctx->PixelMaps.StoS.Size"], "", None ),
        ( "GL_POINT_SIZE", GLfloat, ["ctx->Point.Size"], "", None ),
        ( "GL_POINT_SIZE_GRANULARITY", GLfloat,
          ["ctx->Const.PointSizeGranularity"], "", None ),
  
        # GL_SGI_color_table / GL_ARB_imaging
        ( "GL_COLOR_TABLE_SGI", GLboolean,
-         ["ctx->Pixel.ColorTableEnabled"], "", ["SGI_color_table"] ),
+         ["ctx->Pixel.ColorTableEnabled[COLORTABLE_PRECONVOLUTION]"], "", ["SGI_color_table"] ),
        ( "GL_POST_CONVOLUTION_COLOR_TABLE_SGI", GLboolean,
-         ["ctx->Pixel.PostConvolutionColorTableEnabled"], "", ["SGI_color_table"] ),
+         ["ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCONVOLUTION]"], "", ["SGI_color_table"] ),
        ( "GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI", GLboolean,
-         ["ctx->Pixel.PostColorMatrixColorTableEnabled"], "", ["SGI_color_table"] ),
+         ["ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCOLORMATRIX]"], "", ["SGI_color_table"] ),
  
        # GL_SGI_texture_color_table
        ( "GL_TEXTURE_COLOR_TABLE_SGI", GLboolean,
          ["ctx->Const.VertexProgram.MaxUniformComponents"], "",
          ["ARB_vertex_shader"] ),
        ( "GL_MAX_VARYING_FLOATS_ARB", GLint,
 -        ["ctx->Const.MaxVaryingFloats"], "", ["ARB_vertex_shader"] ),
 +        ["ctx->Const.MaxVarying * 4"], "", ["ARB_vertex_shader"] ),
        ( "GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB", GLint,
          ["ctx->Const.MaxVertexTextureImageUnits"], "", ["ARB_vertex_shader"] ),
        ( "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB", GLint,
 -        ["MAX_COMBINED_TEXTURE_IMAGE_UNITS"], "", ["ARB_vertex_shader"] )
 +        ["MAX_COMBINED_TEXTURE_IMAGE_UNITS"], "", ["ARB_vertex_shader"] ),
 +
 +      # GL_ARB_shader_objects
 +      # Actually, this token isn't part of GL_ARB_shader_objects, but is
 +      # close enough for now.
 +      ( "GL_CURRENT_PROGRAM", GLint,
 +        ["ctx->Shader.CurrentProgram ? ctx->Shader.CurrentProgram->Name : 0"],
 +        "", ["ARB_shader_objects"] )
  ]
  
  
diff --combined src/mesa/main/mtypes.h
index 25a5a3cc3606322d1a70b5197f5d1b19d9fb54e5,df77c6cbf901292ac25581679db1e6b76f64a34e..0c9bf200d8c5eff777a55ac130f0788d007c6177
@@@ -7,9 -7,9 +7,9 @@@
  
  /*
   * Mesa 3-D graphics library
 - * Version:  6.5
 + * Version:  6.5.3
   *
 - * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
 + * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
   *
   * Permission is hereby granted, free of charge, to any person obtaining a
   * copy of this software and associated documentation files (the "Software"),
  #include "bitset.h"
  
  
 +/**
 + * Special, internal token
 + */
 +#define GL_SHADER_PROGRAM 0x9999
 +
 +
  /**
   * Color channel data type.
   */
@@@ -219,6 -213,22 +219,6 @@@ enu
  #define VERT_BIT_GENERIC(g)  (1 << (VERT_ATTRIB_GENERIC0 + (g)))
  /*@}*/
  
 -/**
 - * GLSL allows shader writers to allocate vertex result attributes (varyings) in
 - * single float component granularity. This is in contrast to vertex / fragment
 - * programs, where result attributes (actually texcoords) were allocated
 - * in 4-component vectors of floats granularity.
 - * For performance reasons, it would be optimal to stick with this scheme on a scalar
 - * processor. Varyings will likely be allocated as 3-component vectors, so statistically
 - * we win 2 floats.
 - * The constant VARYINGS_PER_VECTOR tells us how much of float components we pack into
 - * one result vector. For scalar processor it would be 1, for vector processor - 4.
 - * 
 - * NOTE: Currently we pack varyings into vertex attributes.
 - */
 -#define VARYINGS_PER_VECTOR 2
 -#define VARYING_EMIT_STYLE  EMIT_2F
 -#define MAX_VARYING_VECTORS ((MAX_VARYING_FLOATS + VARYINGS_PER_VECTOR - 1) / VARYINGS_PER_VECTOR)
  
  /**
   * Indexes for vertex program result attributes
  #define VERT_RESULT_BFC0 13
  #define VERT_RESULT_BFC1 14
  #define VERT_RESULT_EDGE 15
 -#define VERT_RESULT_MAX  16
 +#define VERT_RESULT_VAR0 16  /**< shader varying */
 +#define VERT_RESULT_MAX  (VERT_RESULT_VAR0 + MAX_VARYING)
  /*@}*/
  
  
@@@ -262,8 -271,7 +262,8 @@@ enu
     FRAG_ATTRIB_TEX5 = 9,
     FRAG_ATTRIB_TEX6 = 10,
     FRAG_ATTRIB_TEX7 = 11,
 -   FRAG_ATTRIB_MAX = 12
 +   FRAG_ATTRIB_VAR0 = 12,  /**< shader varying */
 +   FRAG_ATTRIB_MAX = (FRAG_ATTRIB_VAR0 + MAX_VARYING)
  };
  
  /**
  #define FRAG_BIT_TEX5  (1 << FRAG_ATTRIB_TEX5)
  #define FRAG_BIT_TEX6  (1 << FRAG_ATTRIB_TEX6)
  #define FRAG_BIT_TEX7  (1 << FRAG_ATTRIB_TEX7)
 +#define FRAG_BIT_VAR0  (1 << FRAG_ATTRIB_VAR0)
 +
 +#define FRAG_BIT_TEX(U)  (FRAG_BIT_TEX0 << (U))
 +#define FRAG_BIT_VAR(V)  (FRAG_BIT_VAR0 << (V))
  
  #define FRAG_BITS_TEX_ANY (FRAG_BIT_TEX0|     \
                           FRAG_BIT_TEX1|       \
  /**
   * Fragment program results
   */
 -/*@{*/
 -#define FRAG_RESULT_COLR  0
 -#define FRAG_RESULT_COLH  1
 -#define FRAG_RESULT_DEPR  2
 -#define FRAG_RESULT_MAX   3
 -/*@}*/
 +enum
 +{
 +   FRAG_RESULT_COLR = 0,
 +   FRAG_RESULT_COLH = 1,
 +   FRAG_RESULT_DEPR = 2,
 +   FRAG_RESULT_DATA0 = 3,
 +   FRAG_RESULT_MAX = (FRAG_RESULT_DATA0 + MAX_DRAW_BUFFERS)
 +};
  
  
  /**
@@@ -381,6 -383,13 +381,13 @@@ enum 
                              BUFFER_BIT_COLOR7)
  
  
+ /** The pixel transfer path has three color tables: */
+ /*@{*/
+ #define COLORTABLE_PRECONVOLUTION  0
+ #define COLORTABLE_POSTCONVOLUTION 1
+ #define COLORTABLE_POSTCOLORMATRIX 2
+ #define COLORTABLE_MAX 3
+ /*@}*/
  
  
  /**
@@@ -661,9 -670,7 +668,7 @@@ struct gl_enable_attri
     GLboolean Blend;
     GLbitfield ClipPlanes;
     GLboolean ColorMaterial;
-    GLboolean ColorTable;                /* SGI_color_table */
-    GLboolean PostColorMatrixColorTable; /* SGI_color_table */
-    GLboolean PostConvolutionColorTable; /* SGI_color_table */
+    GLboolean ColorTable[COLORTABLE_MAX];
     GLboolean Convolution1D;
     GLboolean Convolution2D;
     GLboolean Separable2D;
@@@ -962,75 -969,92 +967,92 @@@ struct gl_multisample_attri
  };
  
  
+ /**
+  * A pixelmap (see glPixelMap)
+  */
+ struct gl_pixelmap
+ {
+    GLint Size;
+    GLfloat Map[MAX_PIXEL_MAP_TABLE];
+    GLubyte Map8[MAX_PIXEL_MAP_TABLE];  /**< converted to 8-bit color */
+ };
+ /**
+  * Collection of all pixelmaps
+  */
+ struct gl_pixelmaps
+ {
+    struct gl_pixelmap RtoR;  /**< i.e. GL_PIXEL_MAP_R_TO_R */
+    struct gl_pixelmap GtoG;
+    struct gl_pixelmap BtoB;
+    struct gl_pixelmap AtoA;
+    struct gl_pixelmap ItoR;
+    struct gl_pixelmap ItoG;
+    struct gl_pixelmap ItoB;
+    struct gl_pixelmap ItoA;
+    struct gl_pixelmap ItoI;
+    struct gl_pixelmap StoS;
+ };
  /**
   * Pixel attribute group (GL_PIXEL_MODE_BIT).
   */
  struct gl_pixel_attrib
  {
     GLenum ReadBuffer;         /**< source buffer for glRead/CopyPixels() */
+    /*--- Begin Pixel Transfer State ---*/
+    /* Fields are in the order in which they're applied... */
+    /* Scale & Bias (index shift, offset) */
     GLfloat RedBias, RedScale;
     GLfloat GreenBias, GreenScale;
     GLfloat BlueBias, BlueScale;
     GLfloat AlphaBias, AlphaScale;
     GLfloat DepthBias, DepthScale;
     GLint IndexShift, IndexOffset;
+    /* Pixel Maps */
+    /* Note: actual pixel maps are not part of this attrib group */
     GLboolean MapColorFlag;
     GLboolean MapStencilFlag;
-    GLfloat ZoomX, ZoomY;
-    /* XXX move these out of gl_pixel_attrib */
-    GLint MapStoSsize;         /**< Size of each pixel map */
-    GLint MapItoIsize;
-    GLint MapItoRsize;
-    GLint MapItoGsize;
-    GLint MapItoBsize;
-    GLint MapItoAsize;
-    GLint MapRtoRsize;
-    GLint MapGtoGsize;
-    GLint MapBtoBsize;
-    GLint MapAtoAsize;
-    GLint MapStoS[MAX_PIXEL_MAP_TABLE];        /**< Pixel map tables */
-    GLfloat MapItoI[MAX_PIXEL_MAP_TABLE];
-    GLfloat MapItoR[MAX_PIXEL_MAP_TABLE];
-    GLfloat MapItoG[MAX_PIXEL_MAP_TABLE];
-    GLfloat MapItoB[MAX_PIXEL_MAP_TABLE];
-    GLfloat MapItoA[MAX_PIXEL_MAP_TABLE];
-    GLubyte MapItoR8[MAX_PIXEL_MAP_TABLE];  /**< converted to 8-bit color */
-    GLubyte MapItoG8[MAX_PIXEL_MAP_TABLE];
-    GLubyte MapItoB8[MAX_PIXEL_MAP_TABLE];
-    GLubyte MapItoA8[MAX_PIXEL_MAP_TABLE];
-    GLfloat MapRtoR[MAX_PIXEL_MAP_TABLE];
-    GLfloat MapGtoG[MAX_PIXEL_MAP_TABLE];
-    GLfloat MapBtoB[MAX_PIXEL_MAP_TABLE];
-    GLfloat MapAtoA[MAX_PIXEL_MAP_TABLE];
-    /** GL_EXT_histogram */
-    GLboolean HistogramEnabled;
-    GLboolean MinMaxEnabled;
-    /** GL_SGI_color_matrix */
-    GLfloat PostColorMatrixScale[4];  /**< RGBA */
-    GLfloat PostColorMatrixBias[4];   /**< RGBA */
-    /** GL_SGI_color_table */
-    GLfloat ColorTableScale[4];
-    GLfloat ColorTableBias[4];
-    GLboolean ColorTableEnabled;
-    GLfloat PCCTscale[4];
-    GLfloat PCCTbias[4];
-    GLboolean PostConvolutionColorTableEnabled;
-    GLfloat PCMCTscale[4];
-    GLfloat PCMCTbias[4];
-    GLboolean PostColorMatrixColorTableEnabled;
-    /** GL_SGI_texture_color_table */
-    GLfloat TextureColorTableScale[4];
-    GLfloat TextureColorTableBias[4];
-    /** Convolution */
+    /* There are multiple color table stages: */
+    GLboolean ColorTableEnabled[COLORTABLE_MAX];
+    GLfloat ColorTableScale[COLORTABLE_MAX][4];  /**< RGBA */
+    GLfloat ColorTableBias[COLORTABLE_MAX][4];   /**< RGBA */
+    /* Convolution (GL_EXT_convolution) */
     GLboolean Convolution1DEnabled;
     GLboolean Convolution2DEnabled;
     GLboolean Separable2DEnabled;
     GLfloat ConvolutionBorderColor[3][4];
     GLenum ConvolutionBorderMode[3];
-    GLfloat ConvolutionFilterScale[3][4];
-    GLfloat ConvolutionFilterBias[3][4];
+    GLfloat ConvolutionFilterScale[3][4];  /**< RGBA */
+    GLfloat ConvolutionFilterBias[3][4];   /**< RGBA */
     GLfloat PostConvolutionScale[4];  /**< RGBA */
     GLfloat PostConvolutionBias[4];   /**< RGBA */
+    /* Color matrix (GL_SGI_color_matrix) */
+    /* Note: the color matrix is not part of this attrib group */
+    GLfloat PostColorMatrixScale[4];  /**< RGBA */
+    GLfloat PostColorMatrixBias[4];   /**< RGBA */
+    /* Histogram & minmax (GL_EXT_histogram) */
+    /* Note: histogram and minmax data are not part of this attrib group */
+    GLboolean HistogramEnabled;
+    GLboolean MinMaxEnabled;
+    /*--- End Pixel Transfer State ---*/
+    /* Pixel Zoom */
+    GLfloat ZoomX, ZoomY;
+    /** GL_SGI_texture_color_table */
+    GLfloat TextureColorTableScale[4];
+    GLfloat TextureColorTableBias[4];
  };
  
  
@@@ -1805,31 -1829,22 +1827,31 @@@ struct gl_evaluator
  
  /**
   * Names of the various vertex/fragment program register files, etc.
 + *
   * NOTE: first four tokens must fit into 2 bits (see t_vb_arbprogram.c)
   * All values should fit in a 4-bit field.
 + *
 + * NOTE: PROGRAM_ENV_PARAM, PROGRAM_STATE_VAR, PROGRAM_NAMED_PARAM,
 + * PROGRAM_CONSTANT, and PROGRAM_UNIFORM can all be considered to
 + * be "uniform" variables since they can only be set outside glBegin/End.
 + * They're also all stored in the same Parameters array.
   */
  enum register_file
  {
 -   PROGRAM_TEMPORARY = 0,
 -   PROGRAM_LOCAL_PARAM = 1,
 -   PROGRAM_ENV_PARAM = 2,
 -   PROGRAM_STATE_VAR = 3,
 -   PROGRAM_INPUT = 4,
 -   PROGRAM_OUTPUT = 5,
 -   PROGRAM_NAMED_PARAM = 6,
 -   PROGRAM_CONSTANT = 7,
 -   PROGRAM_WRITE_ONLY = 8,
 -   PROGRAM_ADDRESS = 9,
 -   PROGRAM_UNDEFINED = 10,  /* invalid value */
 +   PROGRAM_TEMPORARY = 0,   /**< machine->Temporary[] */
 +   PROGRAM_LOCAL_PARAM = 1, /**< gl_program->LocalParams[] */
 +   PROGRAM_ENV_PARAM = 2,   /**< gl_program->Parameters[] */
 +   PROGRAM_STATE_VAR = 3,   /**< gl_program->Parameters[] */
 +   PROGRAM_INPUT = 4,       /**< machine->Inputs[] */
 +   PROGRAM_OUTPUT = 5,      /**< machine->Outputs[] */
 +   PROGRAM_NAMED_PARAM = 6, /**< gl_program->Parameters[] */
 +   PROGRAM_CONSTANT = 7,    /**< gl_program->Parameters[] */
 +   PROGRAM_UNIFORM = 8,     /**< gl_program->Parameters[] */
 +   PROGRAM_VARYING = 9,     /**< machine->Inputs[]/Outputs[] */
 +   PROGRAM_WRITE_ONLY = 10, /**< A dummy, write-only register */
 +   PROGRAM_ADDRESS = 11,    /**< machine->AddressReg */
 +   PROGRAM_SAMPLER = 12,    /**< for shader samplers, compile-time only */
 +   PROGRAM_UNDEFINED = 13,  /**< Invalid value */
     PROGRAM_FILE_MAX
  };
  
@@@ -1845,28 -1860,22 +1867,28 @@@ struct gl_program_parameter_list
  struct gl_program
  {
     GLuint Id;
 -   GLubyte *String;          /**< Null-terminated program text */
 +   GLubyte *String;  /**< Null-terminated program text */
     GLint RefCount;
 -   GLenum Target;
 -   GLenum Format;            /**< String encoding format */
 +   GLenum Target;    /**< GL_VERTEX/FRAGMENT_PROGRAM_ARB, GL_FRAGMENT_PROGRAM_NV */
 +   GLenum Format;    /**< String encoding format */
     GLboolean Resident;
  
     struct prog_instruction *Instructions;
  
 -   GLbitfield InputsRead;     /* Bitmask of which input regs are read */
 -   GLbitfield OutputsWritten; /* Bitmask of which output regs are written to */
 +   GLbitfield InputsRead;     /**< Bitmask of which input regs are read */
 +   GLbitfield OutputsWritten; /**< Bitmask of which output regs are written to */
 +   GLbitfield TexturesUsed[MAX_TEXTURE_IMAGE_UNITS];  /**< TEXTURE_x_BIT bitmask */
  
     /** Named parameters, constants, etc. from program text */
     struct gl_program_parameter_list *Parameters;
     /** Numbered local parameters */
     GLfloat LocalParams[MAX_PROGRAM_LOCAL_PARAMS][4];
  
 +   /** Vertex/fragment shader varying vars */
 +   struct gl_program_parameter_list *Varying;
 +   /** Vertex program user-defined attributes */
 +   struct gl_program_parameter_list *Attributes;
 +
     /** Logical counts */
     /*@{*/
     GLuint NumInstructions;
     GLuint NumParameters;
     GLuint NumAttributes;
     GLuint NumAddressRegs;
 +   GLuint NumAluInstructions;
 +   GLuint NumTexInstructions;
 +   GLuint NumTexIndirections;
     /*@}*/
     /** Native, actual h/w counts */
     /*@{*/
     GLuint NumNativeParameters;
     GLuint NumNativeAttributes;
     GLuint NumNativeAddressRegs;
 +   GLuint NumNativeAluInstructions;
 +   GLuint NumNativeTexInstructions;
 +   GLuint NumNativeTexIndirections;
     /*@}*/
  };
  
@@@ -1906,6 -1909,13 +1928,6 @@@ struct gl_vertex_progra
  struct gl_fragment_program
  {
     struct gl_program Base;   /**< base class */
 -   GLbitfield TexturesUsed[MAX_TEXTURE_IMAGE_UNITS];  /**< TEXTURE_x_BIT bitmask */
 -   GLuint NumAluInstructions; /**< GL_ARB_fragment_program */
 -   GLuint NumTexInstructions;
 -   GLuint NumTexIndirections;
 -   GLuint NumNativeAluInstructions; /**< GL_ARB_fragment_program */
 -   GLuint NumNativeTexInstructions;
 -   GLuint NumNativeTexIndirections;
     GLenum FogOption;
     GLboolean UsesKill;
  };
@@@ -1930,24 -1940,16 +1952,24 @@@ struct gl_vertex_program_stat
     GLboolean _Enabled;              /**< Enabled and valid program? */
     GLboolean PointSizeEnabled;      /**< GL_VERTEX_PROGRAM_POINT_SIZE_ARB/NV */
     GLboolean TwoSideEnabled;        /**< GL_VERTEX_PROGRAM_TWO_SIDE_ARB/NV */
 -   struct gl_vertex_program *Current;  /**< ptr to currently bound program */
 -   const struct gl_vertex_program *_Current;    /**< ptr to currently bound
 -                                                program, including internal
 -                                                (t_vp_build.c) programs */
 +   struct gl_vertex_program *Current;  /**< user-bound vertex program */
  
 -   GLfloat Parameters[MAX_NV_VERTEX_PROGRAM_PARAMS][4]; /**< Env params */
 +   /** Currently enabled and valid program (including internal programs
 +    * and compiled shader programs).
 +    */
 +   struct gl_vertex_program *_Current;
 +
 +   GLfloat Parameters[MAX_PROGRAM_ENV_PARAMS][4]; /**< Env params */
  
     /* For GL_NV_vertex_program only: */
 -   GLenum TrackMatrix[MAX_NV_VERTEX_PROGRAM_PARAMS / 4];
 -   GLenum TrackMatrixTransform[MAX_NV_VERTEX_PROGRAM_PARAMS / 4];
 +   GLenum TrackMatrix[MAX_PROGRAM_ENV_PARAMS / 4];
 +   GLenum TrackMatrixTransform[MAX_PROGRAM_ENV_PARAMS / 4];
 +
 +   /** Should fixed-function T&L be implemented with a vertex prog? */
 +   GLboolean _MaintainTnlProgram;
 +
 +   /** Program to emulate fixed-function T&L (see above) */
 +   struct gl_vertex_program *_TnlProgram;
  
  #if FEATURE_MESA_program_debug
     GLprogramcallbackMESA Callback;
@@@ -1965,20 -1967,11 +1987,20 @@@ struct gl_fragment_program_stat
  {
     GLboolean Enabled;     /**< User-set fragment program enable flag */
     GLboolean _Enabled;    /**< Fragment program enabled and valid? */
 -   GLboolean _Active;     /**< Is a user program or internal program active? */
 -   struct gl_fragment_program *Current;  /**< User-bound program */
 -   const struct gl_fragment_program *_Current; /**< currently active program 
 -                                             (including internal programs) */
 -   GLfloat Parameters[MAX_NV_FRAGMENT_PROGRAM_PARAMS][4]; /**< Env params */
 +   struct gl_fragment_program *Current;  /**< User-bound fragment program */
 +
 +   /** Currently enabled and valid program (including internal programs
 +    * and compiled shader programs).
 +    */
 +   struct gl_fragment_program *_Current;
 +
 +   GLfloat Parameters[MAX_PROGRAM_ENV_PARAMS][4]; /**< Env params */
 +
 +   /** Should fixed-function texturing be implemented with a fragment prog? */
 +   GLboolean _MaintainTexEnvProgram;
 +
 +   /** Program to emulate fixed-function texture env/combine (see above) */
 +   struct gl_fragment_program *_TexEnvProgram;
  
  #if FEATURE_MESA_program_debug
     GLprogramcallbackMESA Callback;
@@@ -2055,58 -2048,14 +2077,58 @@@ struct gl_query_stat
  };
  
  
 +
  /**
 - * Context state for vertex/fragment shaders.
 + * A GLSL shader object.
   */
 -struct gl_shader_objects_state
 +struct gl_shader
  {
 -   struct gl2_program_intf **CurrentProgram;
 -   GLboolean _VertexShaderPresent;
 -   GLboolean _FragmentShaderPresent;
 +   GLenum Type;  /**< GL_FRAGMENT_SHADER || GL_VERTEX_SHADER (first field!) */
 +   GLuint Name;  /**< AKA the handle */
 +   GLint RefCount;  /**< Reference count */
 +   GLboolean DeletePending;
 +
 +   const GLchar *Source;  /**< Source code string */
 +   GLboolean CompileStatus;
 +   GLuint NumPrograms;  /**< size of Programs[] array */
 +   struct gl_program **Programs;  /**< Post-compile assembly code */
 +   GLchar *InfoLog;
 +};
 +
 +
 +/**
 + * A GLSL program object.  Basically a linked collection of "shaders".
 + */
 +struct gl_shader_program
 +{
 +   GLenum Type;  /**< Always GL_SHADER_PROGRAM (internal token) */
 +   GLuint Name;  /**< aka handle or ID */
 +   GLint RefCount;  /**< Reference count */
 +   GLboolean DeletePending;
 +
 +   GLuint NumShaders;          /**< number of attached shaders */
 +   struct gl_shader **Shaders; /**< List of attached the shaders */
 +
 +   /* post-link info: */
 +   struct gl_vertex_program *VertexProgram;     /**< Linked vertex program */
 +   struct gl_fragment_program *FragmentProgram; /**< Linked fragment prog */
 +   struct gl_program_parameter_list *Uniforms; /**< Plus constants, etc */
 +   struct gl_program_parameter_list *Varying;
 +   struct gl_program_parameter_list *Attributes; /**< Vertex attributes */
 +   GLboolean LinkStatus;   /**< GL_LINK_STATUS */
 +   GLboolean Validated;
 +   GLchar *InfoLog;
 +};   
 +
 +
 +/**
 + * Context state for GLSL vertex/fragment shaders.
 + */
 +struct gl_shader_state
 +{
 +   struct gl_shader_program *CurrentProgram; /**< The user-bound program */
 +   GLboolean EmitHighLevelInstructions; /**< Driver-selectable */
 +   GLboolean EmitComments;              /**< Driver-selectable */
  };
  
  
@@@ -2167,8 -2116,7 +2189,8 @@@ struct gl_shared_stat
  #endif
  
  #if FEATURE_ARB_shader_objects
 -   struct _mesa_HashTable *GL2Objects;
 +   /** Table of both gl_shader and gl_shader_program objects */
 +   struct _mesa_HashTable *ShaderObjects;
  #endif
  
  #if FEATURE_EXT_framebuffer_object
@@@ -2213,7 -2161,7 +2235,7 @@@ struct gl_renderbuffe
     GLubyte IndexBits;
     GLubyte DepthBits;
     GLubyte StencilBits;
-    GLvoid *Data;
+    GLvoid *Data;        /**< This may not be used by some kinds of RBs */
  
     /* Used to wrap one renderbuffer around another: */
     struct gl_renderbuffer *Wrapped;
@@@ -2448,7 -2396,7 +2470,7 @@@ struct gl_constant
     GLuint MaxRenderbufferSize;
     /* GL_ARB_vertex_shader */
     GLuint MaxVertexTextureImageUnits;
 -   GLuint MaxVaryingFloats;
 +   GLuint MaxVarying;
  };
  
  
@@@ -2586,7 -2534,7 +2608,7 @@@ struct gl_extension
  /**
   * A stack of matrices (projection, modelview, color, texture, etc).
   */
 -struct matrix_stack
 +struct gl_matrix_stack
  {
     GLmatrix *Top;      /**< points into Stack */
     GLmatrix *Stack;    /**< array [MaxDepth] of GLmatrix */
  #define IMAGE_HISTOGRAM_BIT                       0x200
  #define IMAGE_MIN_MAX_BIT                         0x400
  #define IMAGE_CLAMP_BIT                           0x800 /* extra */
- #define IMAGE_RED_TO_LUMINANCE                    0x1000
  
  
  /** Pixel Transfer ops up to convolution */
@@@ -2818,7 -2765,7 +2839,7 @@@ struct mesa_display_lis
  /**
   * State used during display list compilation and execution.
   */
 -struct mesa_list_state
 +struct gl_dlist_state
  {
     struct mesa_display_list *CallStack[MAX_LIST_NESTING];
     GLuint CallDepth;          /**< Current recursion calling depth */
@@@ -2890,25 -2837,26 +2911,25 @@@ struct __GLcontextRe
     struct dd_function_table Driver;
  
     void *DriverCtx;   /**< Points to device driver context/state */
 -   void *DriverMgrCtx;        /**< Points to device driver manager (optional)*/
  
     /** Core/Driver constants */
     struct gl_constants Const;
  
     /** \name The various 4x4 matrix stacks */
     /*@{*/
 -   struct matrix_stack ModelviewMatrixStack;
 -   struct matrix_stack ProjectionMatrixStack;
 -   struct matrix_stack ColorMatrixStack;
 -   struct matrix_stack TextureMatrixStack[MAX_TEXTURE_COORD_UNITS];
 -   struct matrix_stack ProgramMatrixStack[MAX_PROGRAM_MATRICES];
 -   struct matrix_stack *CurrentStack; /**< Points to one of the above stacks */
 +   struct gl_matrix_stack ModelviewMatrixStack;
 +   struct gl_matrix_stack ProjectionMatrixStack;
 +   struct gl_matrix_stack ColorMatrixStack;
 +   struct gl_matrix_stack TextureMatrixStack[MAX_TEXTURE_COORD_UNITS];
 +   struct gl_matrix_stack ProgramMatrixStack[MAX_PROGRAM_MATRICES];
 +   struct gl_matrix_stack *CurrentStack; /**< Points to one of the above stacks */
     /*@}*/
  
     /** Combined modelview and projection matrix */
     GLmatrix _ModelProjectMatrix;
  
     /** \name Display lists */
 -   struct mesa_list_state ListState;
 +   struct gl_dlist_state ListState;
  
     GLboolean ExecuteFlag;     /**< Execute GL commands? */
     GLboolean CompileFlag;     /**< Compile GL commands into display list? */
  
     /** \name Other assorted state (not pushed/popped on attribute stack) */
     /*@{*/
+    struct gl_pixelmaps          PixelMaps;
     struct gl_histogram_attrib Histogram;
     struct gl_minmax_attrib    MinMax;
     struct gl_convolution_attrib Convolution1D;
     struct gl_feedback   Feedback;  /**< Feedback */
     struct gl_selection  Select;    /**< Selection */
  
-    struct gl_color_table ColorTable;       /**< Pre-convolution */
-    struct gl_color_table ProxyColorTable;  /**< Pre-convolution */
+    struct gl_color_table ColorTable[COLORTABLE_MAX];
+    struct gl_color_table ProxyColorTable[COLORTABLE_MAX];
+ #if 0
     struct gl_color_table PostConvolutionColorTable;
     struct gl_color_table ProxyPostConvolutionColorTable;
     struct gl_color_table PostColorMatrixColorTable;
     struct gl_color_table ProxyPostColorMatrixColorTable;
+ #endif
  
     struct gl_program_state Program;        /**< for vertex or fragment progs */
     struct gl_vertex_program_state VertexProgram;   /**< GL_ARB/NV_vertex_program */
     struct gl_fragment_program_state FragmentProgram;  /**< GL_ARB/NV_vertex_program */
     struct gl_ati_fragment_shader_state ATIFragmentShader;  /**< GL_ATI_fragment_shader */
  
 -   struct gl_fragment_program *_TexEnvProgram;     /**< Texture state as fragment program */
 -   struct gl_vertex_program *_TnlProgram;          /**< Fixed func TNL state as vertex program */
 -
 -   GLboolean _MaintainTnlProgram;
 -   GLboolean _MaintainTexEnvProgram;
 -   GLboolean _UseTexEnvProgram;
 -
     struct gl_query_state Query;  /**< GL_ARB_occlusion_query */
  
 -   struct gl_shader_objects_state ShaderObjects;      /* GL_ARB_shader_objects */
 +   struct gl_shader_state Shader; /**< GLSL shader object state */
     /*@}*/
  
  #if FEATURE_EXT_framebuffer_object
diff --combined src/mesa/main/pixel.c
index de5c7fcef010eea7970fb53ded44ef815fdef30d,b9e23d80b62c2a185b6d9ac490095388fcc6c142..eb4fd6e7c9430db857fefb9c225afa3ac0701931
@@@ -252,85 -252,76 +252,76 @@@ _mesa_PixelStoref( GLenum pname, GLfloa
  /*****                         glPixelMap                         *****/
  /**********************************************************************/
  
+ /**
+  * Return pointer to a pixelmap by name.
+  */
+ static struct gl_pixelmap *
+ get_pixelmap(GLcontext *ctx, GLenum map)
+ {
+    switch (map) {
+    case GL_PIXEL_MAP_I_TO_I:
+       return &ctx->PixelMaps.ItoI;
+    case GL_PIXEL_MAP_S_TO_S:
+       return &ctx->PixelMaps.StoS;
+    case GL_PIXEL_MAP_I_TO_R:
+       return &ctx->PixelMaps.ItoR;
+    case GL_PIXEL_MAP_I_TO_G:
+       return &ctx->PixelMaps.ItoG;
+    case GL_PIXEL_MAP_I_TO_B:
+       return &ctx->PixelMaps.ItoB;
+    case GL_PIXEL_MAP_I_TO_A:
+       return &ctx->PixelMaps.ItoA;
+    case GL_PIXEL_MAP_R_TO_R:
+       return &ctx->PixelMaps.RtoR;
+    case GL_PIXEL_MAP_G_TO_G:
+       return &ctx->PixelMaps.GtoG;
+    case GL_PIXEL_MAP_B_TO_B:
+       return &ctx->PixelMaps.BtoB;
+    case GL_PIXEL_MAP_A_TO_A:
+       return &ctx->PixelMaps.AtoA;
+    default:
+       return NULL;
+    }
+ }
  
  /**
   * Helper routine used by the other _mesa_PixelMap() functions.
   */
  static void
- pixelmap(GLcontext *ctx, GLenum map, GLsizei mapsize, const GLfloat *values)
+ store_pixelmap(GLcontext *ctx, GLenum map, GLsizei mapsize,
+                const GLfloat *values)
  {
     GLint i;
+    struct gl_pixelmap *pm = get_pixelmap(ctx, map);
+    if (!pm) {
+       _mesa_error(ctx, GL_INVALID_ENUM, "glPixelMap(map)");
+       return;
+    }
     switch (map) {
-       case GL_PIXEL_MAP_S_TO_S:
-          ctx->Pixel.MapStoSsize = mapsize;
-          for (i = 0; i < mapsize; i++) {
-           ctx->Pixel.MapStoS[i] = IROUND(values[i]);
-        }
-        break;
-       case GL_PIXEL_MAP_I_TO_I:
-          ctx->Pixel.MapItoIsize = mapsize;
-          for (i = 0; i < mapsize; i++) {
-           ctx->Pixel.MapItoI[i] = values[i];
-        }
-        break;
-       case GL_PIXEL_MAP_I_TO_R:
-          ctx->Pixel.MapItoRsize = mapsize;
-          for (i = 0; i < mapsize; i++) {
-             GLfloat val = CLAMP( values[i], 0.0F, 1.0F );
-           ctx->Pixel.MapItoR[i] = val;
-           ctx->Pixel.MapItoR8[i] = (GLint) (val * 255.0F);
-        }
-        break;
-       case GL_PIXEL_MAP_I_TO_G:
-          ctx->Pixel.MapItoGsize = mapsize;
-          for (i = 0; i < mapsize; i++) {
-             GLfloat val = CLAMP( values[i], 0.0F, 1.0F );
-           ctx->Pixel.MapItoG[i] = val;
-           ctx->Pixel.MapItoG8[i] = (GLint) (val * 255.0F);
-        }
-        break;
-       case GL_PIXEL_MAP_I_TO_B:
-          ctx->Pixel.MapItoBsize = mapsize;
-          for (i = 0; i < mapsize; i++) {
-             GLfloat val = CLAMP( values[i], 0.0F, 1.0F );
-           ctx->Pixel.MapItoB[i] = val;
-           ctx->Pixel.MapItoB8[i] = (GLint) (val * 255.0F);
-        }
-        break;
-       case GL_PIXEL_MAP_I_TO_A:
-          ctx->Pixel.MapItoAsize = mapsize;
-          for (i = 0; i < mapsize; i++) {
-             GLfloat val = CLAMP( values[i], 0.0F, 1.0F );
-           ctx->Pixel.MapItoA[i] = val;
-           ctx->Pixel.MapItoA8[i] = (GLint) (val * 255.0F);
-        }
-        break;
-       case GL_PIXEL_MAP_R_TO_R:
-          ctx->Pixel.MapRtoRsize = mapsize;
-          for (i = 0; i < mapsize; i++) {
-           ctx->Pixel.MapRtoR[i] = CLAMP( values[i], 0.0F, 1.0F );
-        }
-        break;
-       case GL_PIXEL_MAP_G_TO_G:
-          ctx->Pixel.MapGtoGsize = mapsize;
-          for (i = 0; i < mapsize; i++) {
-           ctx->Pixel.MapGtoG[i] = CLAMP( values[i], 0.0F, 1.0F );
-        }
-        break;
-       case GL_PIXEL_MAP_B_TO_B:
-          ctx->Pixel.MapBtoBsize = mapsize;
-          for (i = 0; i < mapsize; i++) {
-           ctx->Pixel.MapBtoB[i] = CLAMP( values[i], 0.0F, 1.0F );
-        }
-        break;
-       case GL_PIXEL_MAP_A_TO_A:
-          ctx->Pixel.MapAtoAsize = mapsize;
-          for (i = 0; i < mapsize; i++) {
-           ctx->Pixel.MapAtoA[i] = CLAMP( values[i], 0.0F, 1.0F );
-        }
-        break;
-       default:
-          _mesa_error( ctx, GL_INVALID_ENUM, "glPixelMap(map)" );
+    case GL_PIXEL_MAP_S_TO_S:
+       /* special case */
+       ctx->PixelMaps.StoS.Size = mapsize;
+       for (i = 0; i < mapsize; i++) {
+          ctx->PixelMaps.StoS.Map[i] = IROUND(values[i]);
+       }
+       break;
+    case GL_PIXEL_MAP_I_TO_I:
+       /* special case */
+       ctx->PixelMaps.ItoI.Size = mapsize;
+       for (i = 0; i < mapsize; i++) {
+          ctx->PixelMaps.ItoI.Map[i] = values[i];
+       }
+       break;
+    default:
+       /* general case */
+       pm->Size = mapsize;
+       for (i = 0; i < mapsize; i++) {
+          GLfloat val = CLAMP(values[i], 0.0F, 1.0F);
+          pm->Map[i] = val;
+          pm->Map8[i] = (GLint) (val * 255.0F);
+       }
     }
  }
  
@@@ -385,7 -376,7 +376,7 @@@ _mesa_PixelMapfv( GLenum map, GLsizei m
        return;
     }
  
-    pixelmap(ctx, map, mapsize, values);
+    store_pixelmap(ctx, map, mapsize, values);
  
     if (ctx->Unpack.BufferObj->Name) {
        ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
  }
  
  
  void GLAPIENTRY
  _mesa_PixelMapuiv(GLenum map, GLsizei mapsize, const GLuint *values )
  {
                                ctx->Unpack.BufferObj);
     }
  
-    pixelmap(ctx, map, mapsize, fvalues);
+    store_pixelmap(ctx, map, mapsize, fvalues);
  }
  
  
  void GLAPIENTRY
  _mesa_PixelMapusv(GLenum map, GLsizei mapsize, const GLushort *values )
  {
        return;
     }
  
-     /* convert to floats */
+    /* convert to floats */
     if (map == GL_PIXEL_MAP_I_TO_I || map == GL_PIXEL_MAP_S_TO_S) {
        GLint i;
        for (i = 0; i < mapsize; i++) {
                                ctx->Unpack.BufferObj);
     }
  
-    pixelmap(ctx, map, mapsize, fvalues);
- }
- /**
-  * Return size of the named map.
-  */
- static GLuint
- get_map_size(GLcontext *ctx, GLenum map)
- {
-    switch (map) {
-       case GL_PIXEL_MAP_I_TO_I:
-          return ctx->Pixel.MapItoIsize;
-       case GL_PIXEL_MAP_S_TO_S:
-          return ctx->Pixel.MapStoSsize;
-       case GL_PIXEL_MAP_I_TO_R:
-          return ctx->Pixel.MapItoRsize;
-       case GL_PIXEL_MAP_I_TO_G:
-          return ctx->Pixel.MapItoGsize;
-       case GL_PIXEL_MAP_I_TO_B:
-          return ctx->Pixel.MapItoBsize;
-       case GL_PIXEL_MAP_I_TO_A:
-          return ctx->Pixel.MapItoAsize;
-       case GL_PIXEL_MAP_R_TO_R:
-          return ctx->Pixel.MapRtoRsize;
-       case GL_PIXEL_MAP_G_TO_G:
-          return ctx->Pixel.MapGtoGsize;
-       case GL_PIXEL_MAP_B_TO_B:
-          return ctx->Pixel.MapBtoBsize;
-       case GL_PIXEL_MAP_A_TO_A:
-          return ctx->Pixel.MapAtoAsize;
-       default:
-          return 0;
-    }
+    store_pixelmap(ctx, map, mapsize, fvalues);
  }
  
  
@@@ -581,9 -537,17 +537,17 @@@ _mesa_GetPixelMapfv( GLenum map, GLfloa
  {
     GET_CURRENT_CONTEXT(ctx);
     GLuint mapsize, i;
+    const struct gl_pixelmap *pm;
     ASSERT_OUTSIDE_BEGIN_END(ctx);
  
-    mapsize = get_map_size(ctx, map);
+    pm = get_pixelmap(ctx, map);
+    if (!pm) {
+       _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelMapfv(map)");
+       return;
+    }
+    mapsize = pm->Size;
  
     if (ctx->Pack.BufferObj->Name) {
        /* pack pixelmap into PBO */
        return;
     }
  
-    switch (map) {
-       case GL_PIXEL_MAP_I_TO_I:
-          MEMCPY(values, ctx->Pixel.MapItoI, mapsize * sizeof(GLfloat));
-        break;
-       case GL_PIXEL_MAP_S_TO_S:
-          for (i = 0; i < mapsize; i++) {
-           values[i] = (GLfloat) ctx->Pixel.MapStoS[i];
-        }
-        break;
-       case GL_PIXEL_MAP_I_TO_R:
-          MEMCPY(values, ctx->Pixel.MapItoR, mapsize * sizeof(GLfloat));
-        break;
-       case GL_PIXEL_MAP_I_TO_G:
-          MEMCPY(values, ctx->Pixel.MapItoG, mapsize * sizeof(GLfloat));
-        break;
-       case GL_PIXEL_MAP_I_TO_B:
-          MEMCPY(values, ctx->Pixel.MapItoB, mapsize * sizeof(GLfloat));
-        break;
-       case GL_PIXEL_MAP_I_TO_A:
-          MEMCPY(values, ctx->Pixel.MapItoA, mapsize * sizeof(GLfloat));
-        break;
-       case GL_PIXEL_MAP_R_TO_R:
-          MEMCPY(values, ctx->Pixel.MapRtoR, mapsize * sizeof(GLfloat));
-        break;
-       case GL_PIXEL_MAP_G_TO_G:
-          MEMCPY(values, ctx->Pixel.MapGtoG, mapsize * sizeof(GLfloat));
-        break;
-       case GL_PIXEL_MAP_B_TO_B:
-          MEMCPY(values, ctx->Pixel.MapBtoB, mapsize * sizeof(GLfloat));
-        break;
-       case GL_PIXEL_MAP_A_TO_A:
-          MEMCPY(values, ctx->Pixel.MapAtoA, mapsize * sizeof(GLfloat));
-        break;
-       default:
-          _mesa_error( ctx, GL_INVALID_ENUM, "glGetPixelMapfv" );
+    if (map == GL_PIXEL_MAP_S_TO_S) {
+       /* special case */
+       for (i = 0; i < mapsize; i++) {
+          values[i] = (GLfloat) ctx->PixelMaps.StoS.Map[i];
+       }
+    }
+    else {
+       MEMCPY(values, pm->Map, mapsize * sizeof(GLfloat));
     }
  
     if (ctx->Pack.BufferObj->Name) {
@@@ -662,9 -599,16 +599,16 @@@ _mesa_GetPixelMapuiv( GLenum map, GLuin
  {
     GET_CURRENT_CONTEXT(ctx);
     GLint mapsize, i;
+    const struct gl_pixelmap *pm;
     ASSERT_OUTSIDE_BEGIN_END(ctx);
  
-    mapsize = get_map_size(ctx, map);
+    pm = get_pixelmap(ctx, map);
+    if (!pm) {
+       _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelMapuiv(map)");
+       return;
+    }
+    mapsize = pm->Size;
  
     if (ctx->Pack.BufferObj->Name) {
        /* pack pixelmap into PBO */
        return;
     }
  
-    switch (map) {
-       case GL_PIXEL_MAP_I_TO_I:
-        for (i = 0; i < mapsize; i++) {
-           values[i] = FLOAT_TO_UINT( ctx->Pixel.MapItoI[i] );
-        }
-        break;
-       case GL_PIXEL_MAP_S_TO_S:
-          MEMCPY(values, ctx->Pixel.MapStoS, mapsize * sizeof(GLint));
-        break;
-       case GL_PIXEL_MAP_I_TO_R:
-        for (i = 0; i < mapsize; i++) {
-           values[i] = FLOAT_TO_UINT( ctx->Pixel.MapItoR[i] );
-        }
-        break;
-       case GL_PIXEL_MAP_I_TO_G:
-        for (i = 0; i < mapsize; i++) {
-           values[i] = FLOAT_TO_UINT( ctx->Pixel.MapItoG[i] );
-        }
-        break;
-       case GL_PIXEL_MAP_I_TO_B:
-        for (i = 0; i < mapsize; i++) {
-           values[i] = FLOAT_TO_UINT( ctx->Pixel.MapItoB[i] );
-        }
-        break;
-       case GL_PIXEL_MAP_I_TO_A:
-        for (i = 0; i < mapsize; i++) {
-           values[i] = FLOAT_TO_UINT( ctx->Pixel.MapItoA[i] );
-        }
-        break;
-       case GL_PIXEL_MAP_R_TO_R:
-        for (i = 0; i < mapsize; i++) {
-           values[i] = FLOAT_TO_UINT( ctx->Pixel.MapRtoR[i] );
-        }
-        break;
-       case GL_PIXEL_MAP_G_TO_G:
-        for (i = 0; i < mapsize; i++) {
-           values[i] = FLOAT_TO_UINT( ctx->Pixel.MapGtoG[i] );
-        }
-        break;
-       case GL_PIXEL_MAP_B_TO_B:
-        for (i = 0; i < mapsize; i++) {
-           values[i] = FLOAT_TO_UINT( ctx->Pixel.MapBtoB[i] );
-        }
-        break;
-       case GL_PIXEL_MAP_A_TO_A:
-        for (i = 0; i < mapsize; i++) {
-           values[i] = FLOAT_TO_UINT( ctx->Pixel.MapAtoA[i] );
-        }
-        break;
-       default:
-          _mesa_error( ctx, GL_INVALID_ENUM, "glGetPixelMapfv" );
+    if (map == GL_PIXEL_MAP_S_TO_S) {
+       /* special case */
+       MEMCPY(values, ctx->PixelMaps.StoS.Map, mapsize * sizeof(GLint));
+    }
+    else {
+       for (i = 0; i < mapsize; i++) {
+          values[i] = FLOAT_TO_UINT( pm->Map[i] );
+       }
     }
  
     if (ctx->Pack.BufferObj->Name) {
@@@ -759,9 -660,16 +660,16 @@@ _mesa_GetPixelMapusv( GLenum map, GLush
  {
     GET_CURRENT_CONTEXT(ctx);
     GLint mapsize, i;
+    const struct gl_pixelmap *pm;
     ASSERT_OUTSIDE_BEGIN_END(ctx);
  
-    mapsize = get_map_size(ctx, map);
+    pm = get_pixelmap(ctx, map);
+    if (!pm) {
+       _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelMapusv(map)");
+       return;
+    }
+    mapsize = pm ? pm->Size : 0;
  
     if (ctx->Pack.BufferObj->Name) {
        /* pack pixelmap into PBO */
     }
  
     switch (map) {
-       case GL_PIXEL_MAP_I_TO_I:
-        for (i = 0; i < mapsize; i++) {
-             values[i] = (GLushort) CLAMP(ctx->Pixel.MapItoI[i], 0.0, 65535.0);
-        }
-        break;
-       case GL_PIXEL_MAP_S_TO_S:
-        for (i = 0; i < mapsize; i++) {
-             values[i] = (GLushort) CLAMP(ctx->Pixel.MapStoS[i], 0.0, 65535.0);
-        }
-        break;
-       case GL_PIXEL_MAP_I_TO_R:
-        for (i = 0; i < mapsize; i++) {
-           CLAMPED_FLOAT_TO_USHORT(values[i] , ctx->Pixel.MapItoR[i] );
-        }
-        break;
-       case GL_PIXEL_MAP_I_TO_G:
-        for (i = 0; i < mapsize; i++) {
-           CLAMPED_FLOAT_TO_USHORT(values[i] , ctx->Pixel.MapItoG[i] );
-        }
-        break;
-       case GL_PIXEL_MAP_I_TO_B:
-        for (i = 0; i < mapsize; i++) {
-           CLAMPED_FLOAT_TO_USHORT(values[i] , ctx->Pixel.MapItoB[i] );
-        }
-        break;
-       case GL_PIXEL_MAP_I_TO_A:
-        for (i = 0; i < mapsize; i++) {
-           CLAMPED_FLOAT_TO_USHORT(values[i] , ctx->Pixel.MapItoA[i] );
-        }
-        break;
-       case GL_PIXEL_MAP_R_TO_R:
-        for (i = 0; i < mapsize; i++) {
-           CLAMPED_FLOAT_TO_USHORT(values[i] , ctx->Pixel.MapRtoR[i] );
-        }
-        break;
-       case GL_PIXEL_MAP_G_TO_G:
-        for (i = 0; i < mapsize; i++) {
-           CLAMPED_FLOAT_TO_USHORT(values[i] , ctx->Pixel.MapGtoG[i] );
-        }
-        break;
-       case GL_PIXEL_MAP_B_TO_B:
-        for (i = 0; i < mapsize; i++) {
-           CLAMPED_FLOAT_TO_USHORT(values[i] , ctx->Pixel.MapBtoB[i] );
-        }
-        break;
-       case GL_PIXEL_MAP_A_TO_A:
-        for (i = 0; i < mapsize; i++) {
-           CLAMPED_FLOAT_TO_USHORT(values[i] , ctx->Pixel.MapAtoA[i] );
-        }
-        break;
-       default:
-          _mesa_error( ctx, GL_INVALID_ENUM, "glGetPixelMapfv" );
+    /* special cases */
+    case GL_PIXEL_MAP_I_TO_I:
+       for (i = 0; i < mapsize; i++) {
+          values[i] = (GLushort) CLAMP(ctx->PixelMaps.ItoI.Map[i], 0.0, 65535.);
+       }
+       break;
+    case GL_PIXEL_MAP_S_TO_S:
+       for (i = 0; i < mapsize; i++) {
+          values[i] = (GLushort) CLAMP(ctx->PixelMaps.StoS.Map[i], 0.0, 65535.);
+       }
+       break;
+    default:
+       for (i = 0; i < mapsize; i++) {
+          CLAMPED_FLOAT_TO_USHORT(values[i], pm->Map[i] );
+       }
     }
  
     if (ctx->Pack.BufferObj->Name) {
@@@ -1040,16 -911,16 +911,16 @@@ _mesa_PixelTransferf( GLenum pname, GLf
           ctx->Pixel.PostConvolutionBias[2] = param;
         break;
        case GL_POST_CONVOLUTION_ALPHA_SCALE:
 -         if (ctx->Pixel.PostConvolutionScale[2] == param)
 +         if (ctx->Pixel.PostConvolutionScale[3] == param)
            return;
         FLUSH_VERTICES(ctx, _NEW_PIXEL);
 -         ctx->Pixel.PostConvolutionScale[2] = param;
 +         ctx->Pixel.PostConvolutionScale[3] = param;
         break;
        case GL_POST_CONVOLUTION_ALPHA_BIAS:
 -         if (ctx->Pixel.PostConvolutionBias[2] == param)
 +         if (ctx->Pixel.PostConvolutionBias[3] == param)
            return;
         FLUSH_VERTICES(ctx, _NEW_PIXEL);
 -         ctx->Pixel.PostConvolutionBias[2] = param;
 +         ctx->Pixel.PostConvolutionBias[3] = param;
         break;
        default:
           _mesa_error( ctx, GL_INVALID_ENUM, "glPixelTransfer(pname)" );
@@@ -1113,14 -984,14 +984,14 @@@ _mesa_scale_and_bias_rgba(GLuint n, GLf
  void
  _mesa_map_rgba( const GLcontext *ctx, GLuint n, GLfloat rgba[][4] )
  {
-    const GLfloat rscale = (GLfloat) (ctx->Pixel.MapRtoRsize - 1);
-    const GLfloat gscale = (GLfloat) (ctx->Pixel.MapGtoGsize - 1);
-    const GLfloat bscale = (GLfloat) (ctx->Pixel.MapBtoBsize - 1);
-    const GLfloat ascale = (GLfloat) (ctx->Pixel.MapAtoAsize - 1);
-    const GLfloat *rMap = ctx->Pixel.MapRtoR;
-    const GLfloat *gMap = ctx->Pixel.MapGtoG;
-    const GLfloat *bMap = ctx->Pixel.MapBtoB;
-    const GLfloat *aMap = ctx->Pixel.MapAtoA;
+    const GLfloat rscale = (GLfloat) (ctx->PixelMaps.RtoR.Size - 1);
+    const GLfloat gscale = (GLfloat) (ctx->PixelMaps.GtoG.Size - 1);
+    const GLfloat bscale = (GLfloat) (ctx->PixelMaps.BtoB.Size - 1);
+    const GLfloat ascale = (GLfloat) (ctx->PixelMaps.AtoA.Size - 1);
+    const GLfloat *rMap = ctx->PixelMaps.RtoR.Map;
+    const GLfloat *gMap = ctx->PixelMaps.GtoG.Map;
+    const GLfloat *bMap = ctx->PixelMaps.BtoB.Map;
+    const GLfloat *aMap = ctx->PixelMaps.AtoA.Map;
     GLuint i;
     for (i=0;i<n;i++) {
        GLfloat r = CLAMP(rgba[i][RCOMP], 0.0F, 1.0F);
  _mesa_map_ci_to_rgba( const GLcontext *ctx, GLuint n,
                        const GLuint index[], GLfloat rgba[][4] )
  {
-    GLuint rmask = ctx->Pixel.MapItoRsize - 1;
-    GLuint gmask = ctx->Pixel.MapItoGsize - 1;
-    GLuint bmask = ctx->Pixel.MapItoBsize - 1;
-    GLuint amask = ctx->Pixel.MapItoAsize - 1;
-    const GLfloat *rMap = ctx->Pixel.MapItoR;
-    const GLfloat *gMap = ctx->Pixel.MapItoG;
-    const GLfloat *bMap = ctx->Pixel.MapItoB;
-    const GLfloat *aMap = ctx->Pixel.MapItoA;
+    GLuint rmask = ctx->PixelMaps.ItoR.Size - 1;
+    GLuint gmask = ctx->PixelMaps.ItoG.Size - 1;
+    GLuint bmask = ctx->PixelMaps.ItoB.Size - 1;
+    GLuint amask = ctx->PixelMaps.ItoA.Size - 1;
+    const GLfloat *rMap = ctx->PixelMaps.ItoR.Map;
+    const GLfloat *gMap = ctx->PixelMaps.ItoG.Map;
+    const GLfloat *bMap = ctx->PixelMaps.ItoB.Map;
+    const GLfloat *aMap = ctx->PixelMaps.ItoA.Map;
     GLuint i;
     for (i=0;i<n;i++) {
        rgba[i][RCOMP] = rMap[index[i] & rmask];
  _mesa_map_ci8_to_rgba8(const GLcontext *ctx, GLuint n, const GLubyte index[],
                         GLubyte rgba[][4])
  {
-    GLuint rmask = ctx->Pixel.MapItoRsize - 1;
-    GLuint gmask = ctx->Pixel.MapItoGsize - 1;
-    GLuint bmask = ctx->Pixel.MapItoBsize - 1;
-    GLuint amask = ctx->Pixel.MapItoAsize - 1;
-    const GLubyte *rMap = ctx->Pixel.MapItoR8;
-    const GLubyte *gMap = ctx->Pixel.MapItoG8;
-    const GLubyte *bMap = ctx->Pixel.MapItoB8;
-    const GLubyte *aMap = ctx->Pixel.MapItoA8;
+    GLuint rmask = ctx->PixelMaps.ItoR.Size - 1;
+    GLuint gmask = ctx->PixelMaps.ItoG.Size - 1;
+    GLuint bmask = ctx->PixelMaps.ItoB.Size - 1;
+    GLuint amask = ctx->PixelMaps.ItoA.Size - 1;
+    const GLubyte *rMap = ctx->PixelMaps.ItoR.Map8;
+    const GLubyte *gMap = ctx->PixelMaps.ItoG.Map8;
+    const GLubyte *bMap = ctx->PixelMaps.ItoB.Map8;
+    const GLubyte *aMap = ctx->PixelMaps.ItoA.Map8;
     GLuint i;
     for (i=0;i<n;i++) {
        rgba[i][RCOMP] = rMap[index[i] & rmask];
@@@ -1496,7 -1367,7 +1367,7 @@@ update_image_transfer_state(GLcontext *
     if (ctx->Pixel.MapColorFlag)
        mask |= IMAGE_MAP_COLOR_BIT;
  
-    if (ctx->Pixel.ColorTableEnabled)
+    if (ctx->Pixel.ColorTableEnabled[COLORTABLE_PRECONVOLUTION])
        mask |= IMAGE_COLOR_TABLE_BIT;
  
     if (ctx->Pixel.Convolution1DEnabled ||
        }
     }
  
-    if (ctx->Pixel.PostConvolutionColorTableEnabled)
+    if (ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCONVOLUTION])
        mask |= IMAGE_POST_CONVOLUTION_COLOR_TABLE_BIT;
  
     if (ctx->ColorMatrixStack.Top->type != MATRIX_IDENTITY ||
         ctx->Pixel.PostColorMatrixBias[3]  != 0.0F)
        mask |= IMAGE_COLOR_MATRIX_BIT;
  
-    if (ctx->Pixel.PostColorMatrixColorTableEnabled)
+    if (ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCOLORMATRIX])
        mask |= IMAGE_POST_COLOR_MATRIX_COLOR_TABLE_BIT;
  
     if (ctx->Pixel.HistogramEnabled)
@@@ -1558,6 -1429,14 +1429,14 @@@ void _mesa_update_pixel( GLcontext *ctx
  /*****                      Initialization                        *****/
  /**********************************************************************/
  
+ static void
+ init_pixelmap(struct gl_pixelmap *map)
+ {
+    map->Size = 1;
+    map->Map[0] = 0.0;
+    map->Map8[0] = 0;
+ }
  
  /**
   * Initialize the context's PIXEL attribute group.
@@@ -1584,43 -1463,25 +1463,25 @@@ _mesa_init_pixel( GLcontext *ctx 
     ctx->Pixel.ZoomY = 1.0;
     ctx->Pixel.MapColorFlag = GL_FALSE;
     ctx->Pixel.MapStencilFlag = GL_FALSE;
-    ctx->Pixel.MapStoSsize = 1;
-    ctx->Pixel.MapItoIsize = 1;
-    ctx->Pixel.MapItoRsize = 1;
-    ctx->Pixel.MapItoGsize = 1;
-    ctx->Pixel.MapItoBsize = 1;
-    ctx->Pixel.MapItoAsize = 1;
-    ctx->Pixel.MapRtoRsize = 1;
-    ctx->Pixel.MapGtoGsize = 1;
-    ctx->Pixel.MapBtoBsize = 1;
-    ctx->Pixel.MapAtoAsize = 1;
-    ctx->Pixel.MapStoS[0] = 0;
-    ctx->Pixel.MapItoI[0] = 0.0;
-    ctx->Pixel.MapItoR[0] = 0.0;
-    ctx->Pixel.MapItoG[0] = 0.0;
-    ctx->Pixel.MapItoB[0] = 0.0;
-    ctx->Pixel.MapItoA[0] = 0.0;
-    ctx->Pixel.MapItoR8[0] = 0;
-    ctx->Pixel.MapItoG8[0] = 0;
-    ctx->Pixel.MapItoB8[0] = 0;
-    ctx->Pixel.MapItoA8[0] = 0;
-    ctx->Pixel.MapRtoR[0] = 0.0;
-    ctx->Pixel.MapGtoG[0] = 0.0;
-    ctx->Pixel.MapBtoB[0] = 0.0;
-    ctx->Pixel.MapAtoA[0] = 0.0;
+    init_pixelmap(&ctx->PixelMaps.StoS);
+    init_pixelmap(&ctx->PixelMaps.ItoI);
+    init_pixelmap(&ctx->PixelMaps.ItoR);
+    init_pixelmap(&ctx->PixelMaps.ItoG);
+    init_pixelmap(&ctx->PixelMaps.ItoB);
+    init_pixelmap(&ctx->PixelMaps.ItoA);
+    init_pixelmap(&ctx->PixelMaps.RtoR);
+    init_pixelmap(&ctx->PixelMaps.GtoG);
+    init_pixelmap(&ctx->PixelMaps.BtoB);
+    init_pixelmap(&ctx->PixelMaps.AtoA);
     ctx->Pixel.HistogramEnabled = GL_FALSE;
     ctx->Pixel.MinMaxEnabled = GL_FALSE;
     ASSIGN_4V(ctx->Pixel.PostColorMatrixScale, 1.0, 1.0, 1.0, 1.0);
     ASSIGN_4V(ctx->Pixel.PostColorMatrixBias, 0.0, 0.0, 0.0, 0.0);
-    ASSIGN_4V(ctx->Pixel.ColorTableScale, 1.0, 1.0, 1.0, 1.0);
-    ASSIGN_4V(ctx->Pixel.ColorTableBias, 0.0, 0.0, 0.0, 0.0);
-    ASSIGN_4V(ctx->Pixel.PCCTscale, 1.0, 1.0, 1.0, 1.0);
-    ASSIGN_4V(ctx->Pixel.PCCTbias, 0.0, 0.0, 0.0, 0.0);
-    ASSIGN_4V(ctx->Pixel.PCMCTscale, 1.0, 1.0, 1.0, 1.0);
-    ASSIGN_4V(ctx->Pixel.PCMCTbias, 0.0, 0.0, 0.0, 0.0);
-    ctx->Pixel.ColorTableEnabled = GL_FALSE;
-    ctx->Pixel.PostConvolutionColorTableEnabled = GL_FALSE;
-    ctx->Pixel.PostColorMatrixColorTableEnabled = GL_FALSE;
+    for (i = 0; i < COLORTABLE_MAX; i++) {
+       ASSIGN_4V(ctx->Pixel.ColorTableScale[i], 1.0, 1.0, 1.0, 1.0);
+       ASSIGN_4V(ctx->Pixel.ColorTableBias[i], 0.0, 0.0, 0.0, 0.0);
+       ctx->Pixel.ColorTableEnabled[i] = GL_FALSE;
+    }
     ctx->Pixel.Convolution1DEnabled = GL_FALSE;
     ctx->Pixel.Convolution2DEnabled = GL_FALSE;
     ctx->Pixel.Separable2DEnabled = GL_FALSE;
index fb546a0217b2c1fab0e581185988358432a14559,6d395c6011e17335ff0a86c10105a20618dc69fa..0bc0c055dad52dee7e3bf088fa30d4e5269dea17
  
  #include "glheader.h"
  #include "context.h"
 -#include "hash.h"
  #include "imports.h"
  #include "macros.h"
 -#include "mtypes.h"
  #include "nvprogram.h"
  #include "nvvertparse.h"
 -#include "program_instruction.h"
 +#include "prog_instruction.h"
  #include "program.h"
  
  
@@@ -684,13 -686,13 +684,13 @@@ Parse_SwizzleSrcReg(struct parse_state 
        if (token[1] == 0) {
           /* single letter swizzle */
           if (token[0] == 'x')
-             srcReg->Swizzle = MAKE_SWIZZLE4(0, 0, 0, 0);
+             srcReg->Swizzle = SWIZZLE_XXXX;
           else if (token[0] == 'y')
-             srcReg->Swizzle = MAKE_SWIZZLE4(1, 1, 1, 1);
+             srcReg->Swizzle = SWIZZLE_YYYY;
           else if (token[0] == 'z')
-             srcReg->Swizzle = MAKE_SWIZZLE4(2, 2, 2, 2);
+             srcReg->Swizzle = SWIZZLE_ZZZZ;
           else if (token[0] == 'w')
-             srcReg->Swizzle = MAKE_SWIZZLE4(3, 3, 3, 3);
+             srcReg->Swizzle = SWIZZLE_WWWW;
           else
              RETURN_ERROR1("Expected x, y, z, or w");
        }
index c67831385f688c96608a2a816ca3e89bb5c8b335,0000000000000000000000000000000000000000..ed479a7f614b29432c9e799fce685e5f6520f783
mode 100644,000000..100644
--- /dev/null
@@@ -1,225 -1,0 +1,239 @@@
 +/*
 + * Mesa 3-D graphics library
 + * Version:  6.5.3
 + *
 + * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
 + *
 + * Permission is hereby granted, free of charge, to any person obtaining a
 + * copy of this software and associated documentation files (the "Software"),
 + * to deal in the Software without restriction, including without limitation
 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 + * and/or sell copies of the Software, and to permit persons to whom the
 + * Software is furnished to do so, subject to the following conditions:
 + *
 + * The above copyright notice and this permission notice shall be included
 + * in all copies or substantial portions of the Software.
 + *
 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 + */
 +
 +
 +#include "glheader.h"
 +#include "imports.h"
 +#include "mtypes.h"
 +#include "prog_instruction.h"
 +
 +
 +/**
 + * Initialize program instruction fields to defaults.
 + * \param inst  first instruction to initialize
 + * \param count  number of instructions to initialize
 + */
 +void
 +_mesa_init_instructions(struct prog_instruction *inst, GLuint count)
 +{
 +   GLuint i;
 +
 +   _mesa_bzero(inst, count * sizeof(struct prog_instruction));
 +
 +   for (i = 0; i < count; i++) {
 +      inst[i].SrcReg[0].File = PROGRAM_UNDEFINED;
 +      inst[i].SrcReg[0].Swizzle = SWIZZLE_NOOP;
 +      inst[i].SrcReg[1].File = PROGRAM_UNDEFINED;
 +      inst[i].SrcReg[1].Swizzle = SWIZZLE_NOOP;
 +      inst[i].SrcReg[2].File = PROGRAM_UNDEFINED;
 +      inst[i].SrcReg[2].Swizzle = SWIZZLE_NOOP;
 +
 +      inst[i].DstReg.File = PROGRAM_UNDEFINED;
 +      inst[i].DstReg.WriteMask = WRITEMASK_XYZW;
 +      inst[i].DstReg.CondMask = COND_TR;
 +      inst[i].DstReg.CondSwizzle = SWIZZLE_NOOP;
 +
 +      inst[i].SaturateMode = SATURATE_OFF;
 +      inst[i].Precision = FLOAT32;
 +   }
 +}
 +
 +
 +/**
 + * Allocate an array of program instructions.
 + * \param numInst  number of instructions
 + * \return pointer to instruction memory
 + */
 +struct prog_instruction *
 +_mesa_alloc_instructions(GLuint numInst)
 +{
 +   return (struct prog_instruction *)
 +      _mesa_calloc(numInst * sizeof(struct prog_instruction));
 +}
 +
 +
 +/**
 + * Reallocate memory storing an array of program instructions.
 + * This is used when we need to append additional instructions onto an
 + * program.
 + * \param oldInst  pointer to first of old/src instructions
 + * \param numOldInst  number of instructions at <oldInst>
 + * \param numNewInst  desired size of new instruction array.
 + * \return  pointer to start of new instruction array.
 + */
 +struct prog_instruction *
 +_mesa_realloc_instructions(struct prog_instruction *oldInst,
 +                           GLuint numOldInst, GLuint numNewInst)
 +{
 +   struct prog_instruction *newInst;
 +
 +   newInst = (struct prog_instruction *)
 +      _mesa_realloc(oldInst,
 +                    numOldInst * sizeof(struct prog_instruction),
 +                    numNewInst * sizeof(struct prog_instruction));
 +
 +   return newInst;
 +}
 +
 +
++/**
++ * Copy an array of program instructions.
++ * \param dest  pointer to destination.
++ * \param src  pointer to source.
++ * \param n  number of instructions to copy.
++ * \return pointer to destination.
++ */
++struct prog_instruction *
++_mesa_copy_instructions(struct prog_instruction *dest,
++                        const struct prog_instruction *src, GLuint n)
++{
++   return _mesa_memcpy(dest, src, n * sizeof(struct prog_instruction));
++}
++
 +
 +/**
 + * Basic info about each instruction
 + */
 +struct instruction_info
 +{
 +   gl_inst_opcode Opcode;
 +   const char *Name;
 +   GLuint NumSrcRegs;
 +};
 +
 +/**
 + * Instruction info
 + * \note Opcode should equal array index!
 + */
 +static const struct instruction_info InstInfo[MAX_OPCODE] = {
 +   { OPCODE_NOP,    "NOP",   0 },
 +   { OPCODE_ABS,    "ABS",   1 },
 +   { OPCODE_ADD,    "ADD",   2 },
 +   { OPCODE_ARA,    "ARA",   1 },
 +   { OPCODE_ARL,    "ARL",   1 },
 +   { OPCODE_ARL_NV, "ARL",   1 },
 +   { OPCODE_ARR,    "ARL",   1 },
 +   { OPCODE_BGNLOOP,"BGNLOOP", 0 },
 +   { OPCODE_BGNSUB, "BGNSUB", 0 },
 +   { OPCODE_BRA,    "BRA",   0 },
 +   { OPCODE_BRK,    "BRK",   0 },
 +   { OPCODE_CAL,    "CAL",   0 },
 +   { OPCODE_CMP,    "CMP",   3 },
 +   { OPCODE_CONT,   "CONT",  1 },
 +   { OPCODE_COS,    "COS",   1 },
 +   { OPCODE_DDX,    "DDX",   1 },
 +   { OPCODE_DDY,    "DDY",   1 },
 +   { OPCODE_DP3,    "DP3",   2 },
 +   { OPCODE_DP4,    "DP4",   2 },
 +   { OPCODE_DPH,    "DPH",   2 },
 +   { OPCODE_DST,    "DST",   2 },
 +   { OPCODE_ELSE,   "ELSE",  0 },
 +   { OPCODE_END,    "END",   0 },
 +   { OPCODE_ENDIF,  "ENDIF", 0 },
 +   { OPCODE_ENDLOOP,"ENDLOOP", 0 },
 +   { OPCODE_ENDSUB, "ENDSUB", 0 },
 +   { OPCODE_EX2,    "EX2",   1 },
 +   { OPCODE_EXP,    "EXP",   1 },
 +   { OPCODE_FLR,    "FLR",   1 },
 +   { OPCODE_FRC,    "FRC",   1 },
 +   { OPCODE_IF,     "IF",    0 },
 +   { OPCODE_INT,    "INT",   1 },
 +   { OPCODE_KIL,    "KIL",   1 },
 +   { OPCODE_KIL_NV, "KIL",   0 },
 +   { OPCODE_LG2,    "LG2",   1 },
 +   { OPCODE_LIT,    "LIT",   1 },
 +   { OPCODE_LOG,    "LOG",   1 },
 +   { OPCODE_LRP,    "LRP",   3 },
 +   { OPCODE_MAD,    "MAD",   3 },
 +   { OPCODE_MAX,    "MAX",   2 },
 +   { OPCODE_MIN,    "MIN",   2 },
 +   { OPCODE_MOV,    "MOV",   1 },
 +   { OPCODE_MUL,    "MUL",   2 },
 +   { OPCODE_NOISE1, "NOISE1", 1 },
 +   { OPCODE_NOISE2, "NOISE2", 1 },
 +   { OPCODE_NOISE3, "NOISE3", 1 },
 +   { OPCODE_NOISE4, "NOISE4", 1 },
 +   { OPCODE_PK2H,   "PK2H",  1 },
 +   { OPCODE_PK2US,  "PK2US", 1 },
 +   { OPCODE_PK4B,   "PK4B",  1 },
 +   { OPCODE_PK4UB,  "PK4UB", 1 },
 +   { OPCODE_POW,    "POW",   2 },
 +   { OPCODE_POPA,   "POPA",  0 },
 +   { OPCODE_PRINT,  "PRINT", 1 },
 +   { OPCODE_PUSHA,  "PUSHA", 0 },
 +   { OPCODE_RCC,    "RCC",   1 },
 +   { OPCODE_RCP,    "RCP",   1 },
 +   { OPCODE_RET,    "RET",   0 },
 +   { OPCODE_RFL,    "RFL",   1 },
 +   { OPCODE_RSQ,    "RSQ",   1 },
 +   { OPCODE_SCS,    "SCS",   1 },
 +   { OPCODE_SEQ,    "SEQ",   2 },
 +   { OPCODE_SFL,    "SFL",   0 },
 +   { OPCODE_SGE,    "SGE",   2 },
 +   { OPCODE_SGT,    "SGT",   2 },
 +   { OPCODE_SIN,    "SIN",   1 },
 +   { OPCODE_SLE,    "SLE",   2 },
 +   { OPCODE_SLT,    "SLT",   2 },
 +   { OPCODE_SNE,    "SNE",   2 },
 +   { OPCODE_SSG,    "SSG",   1 },
 +   { OPCODE_STR,    "STR",   0 },
 +   { OPCODE_SUB,    "SUB",   2 },
 +   { OPCODE_SWZ,    "SWZ",   1 },
 +   { OPCODE_TEX,    "TEX",   1 },
 +   { OPCODE_TXB,    "TXB",   1 },
 +   { OPCODE_TXD,    "TXD",   3 },
 +   { OPCODE_TXL,    "TXL",   1 },
 +   { OPCODE_TXP,    "TXP",   1 },
 +   { OPCODE_TXP_NV, "TXP",   1 },
 +   { OPCODE_UP2H,   "UP2H",  1 },
 +   { OPCODE_UP2US,  "UP2US", 1 },
 +   { OPCODE_UP4B,   "UP4B",  1 },
 +   { OPCODE_UP4UB,  "UP4UB", 1 },
 +   { OPCODE_X2D,    "X2D",   3 },
 +   { OPCODE_XPD,    "XPD",   2 }
 +};
 +
 +
 +/**
 + * Return the number of src registers for the given instruction/opcode.
 + */
 +GLuint
 +_mesa_num_inst_src_regs(gl_inst_opcode opcode)
 +{
 +   ASSERT(opcode == InstInfo[opcode].Opcode);
 +   ASSERT(OPCODE_XPD == InstInfo[OPCODE_XPD].Opcode);
 +   return InstInfo[opcode].NumSrcRegs;
 +}
 +
 +
 +/**
 + * Return string name for given program opcode.
 + */
 +const char *
 +_mesa_opcode_string(gl_inst_opcode opcode)
 +{
 +   ASSERT(opcode < MAX_OPCODE);
 +   return InstInfo[opcode].Name;
 +}
 +
index 14305f17d384bbdef13768c9194251a8a6318511,0000000000000000000000000000000000000000..66abb10cdb8f1930594affcc9dc02a0454ce300c
mode 100644,000000..100644
--- /dev/null
@@@ -1,442 -1,0 +1,446 @@@
 +/*
 + * Mesa 3-D graphics library
 + * Version:  6.5.3
 + *
 + * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
 + *
 + * Permission is hereby granted, free of charge, to any person obtaining a
 + * copy of this software and associated documentation files (the "Software"),
 + * to deal in the Software without restriction, including without limitation
 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 + * and/or sell copies of the Software, and to permit persons to whom the
 + * Software is furnished to do so, subject to the following conditions:
 + *
 + * The above copyright notice and this permission notice shall be included
 + * in all copies or substantial portions of the Software.
 + *
 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 + */
 +
 +
 +/**
 + * \file prog_instruction.h
 + *
 + * Vertex/fragment program instruction datatypes and constants.
 + *
 + * \author Brian Paul
 + * \author Keith Whitwell
 + * \author Ian Romanick <idr@us.ibm.com>
 + */
 +
 +
 +#ifndef PROG_INSTRUCTION_H
 +#define PROG_INSTRUCTION_H
 +
 +
 +/**
 + * Swizzle indexes.
 + * Do not change!
 + */
 +/*@{*/
 +#define SWIZZLE_X    0
 +#define SWIZZLE_Y    1
 +#define SWIZZLE_Z    2
 +#define SWIZZLE_W    3
 +#define SWIZZLE_ZERO 4   /**< For SWZ instruction only */
 +#define SWIZZLE_ONE  5   /**< For SWZ instruction only */
 +#define SWIZZLE_NIL  7   /**< used during shader code gen (undefined value) */
 +/*@}*/
 +
 +#define MAKE_SWIZZLE4(a,b,c,d) (((a)<<0) | ((b)<<3) | ((c)<<6) | ((d)<<9))
 +#define SWIZZLE_NOOP           MAKE_SWIZZLE4(0,1,2,3)
 +#define GET_SWZ(swz, idx)      (((swz) >> ((idx)*3)) & 0x7)
 +#define GET_BIT(msk, idx)      (((msk) >> (idx)) & 0x1)
 +
 +#define SWIZZLE_XXXX MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X)
 +#define SWIZZLE_YYYY MAKE_SWIZZLE4(SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y)
 +#define SWIZZLE_ZZZZ MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z)
 +#define SWIZZLE_WWWW MAKE_SWIZZLE4(SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W)
 +
 +
 +/**
 + * Writemask values, 1 bit per component.
 + */
 +/*@{*/
 +#define WRITEMASK_X     0x1
 +#define WRITEMASK_Y     0x2
 +#define WRITEMASK_XY    0x3
 +#define WRITEMASK_Z     0x4
 +#define WRITEMASK_XZ    0x5
 +#define WRITEMASK_YZ    0x6
 +#define WRITEMASK_XYZ   0x7
 +#define WRITEMASK_W     0x8
 +#define WRITEMASK_XW    0x9
 +#define WRITEMASK_YW    0xa
 +#define WRITEMASK_XYW   0xb
 +#define WRITEMASK_ZW    0xc
 +#define WRITEMASK_XZW   0xd
 +#define WRITEMASK_YZW   0xe
 +#define WRITEMASK_XYZW  0xf
 +/*@}*/
 +
 +
 +/**
 + * Condition codes
 + */
 +/*@{*/
 +#define COND_GT  1  /**< greater than zero */
 +#define COND_EQ  2  /**< equal to zero */
 +#define COND_LT  3  /**< less than zero */
 +#define COND_UN  4  /**< unordered (NaN) */
 +#define COND_GE  5  /**< greater then or equal to zero */
 +#define COND_LE  6  /**< less then or equal to zero */
 +#define COND_NE  7  /**< not equal to zero */
 +#define COND_TR  8  /**< always true */
 +#define COND_FL  9  /**< always false */
 +/*@}*/
 +
 +
 +/**
 + * Instruction precision for GL_NV_fragment_program
 + */
 +/*@{*/
 +#define FLOAT32  0x1
 +#define FLOAT16  0x2
 +#define FIXED12  0x4
 +/*@}*/
 +
 +
 +/**
 + * Saturation modes when storing values.
 + */
 +/*@{*/
 +#define SATURATE_OFF            0
 +#define SATURATE_ZERO_ONE       1
 +#define SATURATE_PLUS_MINUS_ONE 2
 +/*@}*/
 +
 +
 +/**
 + * Per-component negation masks
 + */
 +/*@{*/
 +#define NEGATE_X    0x1
 +#define NEGATE_Y    0x2
 +#define NEGATE_Z    0x4
 +#define NEGATE_W    0x8
 +#define NEGATE_XYZW 0xf
 +#define NEGATE_NONE 0x0
 +/*@}*/
 +
 +
 +/**
 + * Program instruction opcodes, for both vertex and fragment programs.
 + * \note changes to this opcode list must be reflected in t_vb_arbprogram.c
 + */
 +typedef enum prog_opcode {
 +                     /* ARB_vp   ARB_fp   NV_vp   NV_fp     GLSL */
 +                     /*------------------------------------------*/
 +   OPCODE_NOP = 0,   /*                                      X   */
 +   OPCODE_ABS,       /*   X        X       1.1               X   */
 +   OPCODE_ADD,       /*   X        X       X       X         X   */
 +   OPCODE_ARA,       /*                    2                     */
 +   OPCODE_ARL,       /*   X                X                     */
 +   OPCODE_ARL_NV,    /*                    2                     */
 +   OPCODE_ARR,       /*                    2                     */
 +   OPCODE_BGNLOOP,   /*                                     opt  */
 +   OPCODE_BGNSUB,    /*                                     opt  */
 +   OPCODE_BRA,       /*                    2                 X   */
 +   OPCODE_BRK,       /*                    2                opt  */
 +   OPCODE_CAL,       /*                    2       2             */
 +   OPCODE_CMP,       /*            X                             */
 +   OPCODE_CONT,      /*                                     opt  */
 +   OPCODE_COS,       /*            X       2       X         X   */
 +   OPCODE_DDX,       /*                            X         X   */
 +   OPCODE_DDY,       /*                            X         X   */
 +   OPCODE_DP3,       /*   X        X       X       X         X   */
 +   OPCODE_DP4,       /*   X        X       X       X         X   */
 +   OPCODE_DPH,       /*   X        X       1.1                   */
 +   OPCODE_DST,       /*   X        X       X       X             */
 +   OPCODE_ELSE,      /*                                      X   */
 +   OPCODE_END,       /*   X        X       X       X        opt  */
 +   OPCODE_ENDIF,     /*                                     opt  */
 +   OPCODE_ENDLOOP,   /*                                     opt  */
 +   OPCODE_ENDSUB,    /*                                     opt  */
 +   OPCODE_EX2,       /*   X        X       2       X         X   */
 +   OPCODE_EXP,       /*   X                X                 X   */
 +   OPCODE_FLR,       /*   X        X       2       X         X   */
 +   OPCODE_FRC,       /*   X        X       2       X         X   */
 +   OPCODE_IF,        /*                                     opt  */
 +   OPCODE_INT,       /*                                      X   */
 +   OPCODE_KIL,       /*            X                             */
 +   OPCODE_KIL_NV,    /*                            X         X   */
 +   OPCODE_LG2,       /*   X        X       2       X         X   */
 +   OPCODE_LIT,       /*   X        X       X       X             */
 +   OPCODE_LOG,       /*   X                X                 X   */
 +   OPCODE_LRP,       /*            X               X             */
 +   OPCODE_MAD,       /*   X        X       X       X         X   */
 +   OPCODE_MAX,       /*   X        X       X       X         X   */
 +   OPCODE_MIN,       /*   X        X       X       X         X   */
 +   OPCODE_MOV,       /*   X        X       X       X         X   */
 +   OPCODE_MUL,       /*   X        X       X       X         X   */
 +   OPCODE_NOISE1,    /*                                      X   */
 +   OPCODE_NOISE2,    /*                                      X   */
 +   OPCODE_NOISE3,    /*                                      X   */
 +   OPCODE_NOISE4,    /*                                      X   */
 +   OPCODE_PK2H,      /*                            X             */
 +   OPCODE_PK2US,     /*                            X             */
 +   OPCODE_PK4B,      /*                            X             */
 +   OPCODE_PK4UB,     /*                            X             */
 +   OPCODE_POW,       /*   X        X               X         X   */
 +   OPCODE_POPA,      /*                    3                     */
 +   OPCODE_PRINT,     /*                    X       X             */
 +   OPCODE_PUSHA,     /*                    3                     */
 +   OPCODE_RCC,       /*                    1.1                   */
 +   OPCODE_RCP,       /*   X        X       X       X         X   */
 +   OPCODE_RET,       /*                    2       2             */
 +   OPCODE_RFL,       /*            X               X             */
 +   OPCODE_RSQ,       /*   X        X       X       X         X   */
 +   OPCODE_SCS,       /*            X                             */
 +   OPCODE_SEQ,       /*                    2       X         X   */
 +   OPCODE_SFL,       /*                    2       X             */
 +   OPCODE_SGE,       /*   X        X       X       X         X   */
 +   OPCODE_SGT,       /*                    2       X         X   */
 +   OPCODE_SIN,       /*            X       2       X         X   */
 +   OPCODE_SLE,       /*                    2       X         X   */
 +   OPCODE_SLT,       /*   X        X       X       X         X   */
 +   OPCODE_SNE,       /*                    2       X         X   */
 +   OPCODE_SSG,       /*                    2                     */
 +   OPCODE_STR,       /*                    2       X             */
 +   OPCODE_SUB,       /*   X        X       1.1     X         X   */
 +   OPCODE_SWZ,       /*   X        X                             */
 +   OPCODE_TEX,       /*            X       3       X         X   */
 +   OPCODE_TXB,       /*            X       3                 X   */
 +   OPCODE_TXD,       /*                            X         X   */
 +   OPCODE_TXL,       /*                    3       2         X   */
 +   OPCODE_TXP,       /*            X                         X   */
 +   OPCODE_TXP_NV,    /*                    3       X             */
 +   OPCODE_UP2H,      /*                            X             */
 +   OPCODE_UP2US,     /*                            X             */
 +   OPCODE_UP4B,      /*                            X             */
 +   OPCODE_UP4UB,     /*                            X             */
 +   OPCODE_X2D,       /*                            X             */
 +   OPCODE_XPD,       /*   X        X                         X   */
 +   MAX_OPCODE
 +} gl_inst_opcode;
 +
 +
 +/**
 + * Instruction source register.
 + */
 +struct prog_src_register
 +{
 +   GLuint File:4;     /**< One of the PROGRAM_* register file values. */
 +   GLint Index:9;     /**< May be negative for relative addressing. */
 +   GLuint Swizzle:12;
 +   GLuint RelAddr:1;
 +
 +   /**
 +    * \name Source register "sign" control.
 +    *
 +    * The ARB and NV extensions allow varrying degrees of control over the
 +    * sign of the source vector components.  These values allow enough control
 +    * for all flavors of the extensions.
 +    */
 +   /*@{*/
 +   /**
 +    * Per-component negation for the SWZ instruction.  For non-SWZ
 +    * instructions the only possible values are NEGATE_XYZW and NEGATE_NONE.
 +    *
 +    * \since
 +    * ARB_vertex_program, ARB_fragment_program
 +    */
 +   GLuint NegateBase:4;
 +
 +   /**
 +    * Take the component-wise absolute value.
 +    *
 +    * \since
 +    * NV_fragment_program, NV_fragment_program_option, NV_vertex_program2,
 +    * NV_vertex_program2_option.
 +    */
 +   GLuint Abs:1;
 +
 +   /**
 +    * Post-absolute value negation (all components).
 +    */
 +   GLuint NegateAbs:1;
 +   /*@}*/
 +};
 +
 +
 +/**
 + * Instruction destination register.
 + */
 +struct prog_dst_register
 +{
 +   /**
 +    * One of the PROGRAM_* register file values.
 +    */
 +   GLuint File:4;
 +
 +   GLuint Index:8;
 +   GLuint WriteMask:4;
 +
 +   /**
 +    * \name Conditional destination update control.
 +    *
 +    * \since
 +    * NV_fragment_program, NV_fragment_program_option, NV_vertex_program2,
 +    * NV_vertex_program2_option.
 +    */
 +   /*@{*/
 +   /**
 +    * Takes one of the 9 possible condition values (EQ, FL, GT, GE, LE, LT,
 +    * NE, TR, or UN).  Destination update is enabled if the matching
 +    * (swizzled) condition code value passes.  When a conditional update mask
 +    * is not specified, this will be \c COND_TR.
 +    */
 +   GLuint CondMask:4;
 +
 +   /**
 +    * Condition code swizzle value.
 +    */
 +   GLuint CondSwizzle:12;
 +   
 +   /**
 +    * Selects the condition code register to use for conditional destination
 +    * update masking.  In NV_fragmnet_program or NV_vertex_program2 mode, only
 +    * condition code register 0 is available.  In NV_vertex_program3 mode, 
 +    * condition code registers 0 and 1 are available.
 +    */
 +   GLuint CondSrc:1;
 +   /*@}*/
 +
 +   GLuint pad:31;
 +};
 +
 +
 +/**
 + * Vertex/fragment program instruction.
 + */
 +struct prog_instruction
 +{
 +   gl_inst_opcode Opcode;
 +#if FEATURE_MESA_program_debug
 +   GLshort StringPos;
 +#endif
 +   /**
 +    * Arbitrary data.  Used for the PRINT, CAL, and BRA instructions.
 +    */
 +   void *Data;
 +
 +   struct prog_src_register SrcReg[3];
 +   struct prog_dst_register DstReg;
 +
 +   /**
 +    * Indicates that the instruction should update the condition code
 +    * register.
 +    *
 +    * \since
 +    * NV_fragment_program, NV_fragment_program_option, NV_vertex_program2,
 +    * NV_vertex_program2_option.
 +    */
 +   GLuint CondUpdate:1;
 +
 +   /**
 +    * If prog_instruction::CondUpdate is \c GL_TRUE, this value selects the
 +    * condition code register that is to be updated.
 +    *
 +    * In GL_NV_fragment_program or GL_NV_vertex_program2 mode, only condition
 +    * code register 0 is available.  In GL_NV_vertex_program3 mode, condition
 +    * code registers 0 and 1 are available.
 +    *
 +    * \since
 +    * NV_fragment_program, NV_fragment_program_option, NV_vertex_program2,
 +    * NV_vertex_program2_option.
 +    */
 +   GLuint CondDst:1;
 +
 +   /**
 +    * Saturate each value of the vectored result to the range [0,1] or the
 +    * range [-1,1].  \c SSAT mode (i.e., saturation to the range [-1,1]) is
 +    * only available in NV_fragment_program2 mode.
 +    * Value is one of the SATURATE_* tokens.
 +    *
 +    * \since
 +    * NV_fragment_program, NV_fragment_program_option, NV_vertex_program3.
 +    */
 +   GLuint SaturateMode:2;
 +   
 +   /**
 +    * Per-instruction selectable precision.
 +    *
 +    * \since
 +    * NV_fragment_program, NV_fragment_program_option.
 +    */
 +   GLuint Precision:3;
 +
 +   /**
 +    * \name Texture source controls.
 +    * 
 +    * The texture source controls are only used with the \c TEX, \c TXD,
 +    * \c TXL, and \c TXP instructions.
 +    *
 +    * \since
 +    * ARB_fragment_program, NV_fragment_program, NV_vertex_program3.
 +    */
 +   /*@{*/
 +   /**
 +    * Source texture unit.  OpenGL supports a maximum of 32 texture
 +    * units.
 +    */
 +   GLuint TexSrcUnit:5;
 +   
 +   /**
 +    * Source texture target, one of TEXTURE_{1D,2D,3D,CUBE,RECT}_INDEX.
 +    */
 +   GLuint TexSrcTarget:3;
 +   /*@}*/
 +
 +   /**
 +    * For BRA and CAL instructions, the location to jump to.
 +    * For BGNLOOP, points to ENDLOOP (and vice-versa).
 +    * For BRK, points to BGNLOOP (which points to ENDLOOP).
 +    * For IF, points to else or endif.
 +    * For ELSE, points to endif.
 +    */
 +   GLint BranchTarget;
 +
 +   /**
 +    * For TEX instructions in shaders, the sampler to use for the
 +    * texture lookup.
 +    */
 +   GLint Sampler;
 +
 +   const char *Comment;
 +};
 +
 +
 +extern void
 +_mesa_init_instructions(struct prog_instruction *inst, GLuint count);
 +
 +extern struct prog_instruction *
 +_mesa_alloc_instructions(GLuint numInst);
 +
 +extern struct prog_instruction *
 +_mesa_realloc_instructions(struct prog_instruction *oldInst,
 +                           GLuint numOldInst, GLuint numNewInst);
 +
++extern struct prog_instruction *
++_mesa_copy_instructions(struct prog_instruction *dest,
++                        const struct prog_instruction *src, GLuint n);
++
 +extern GLuint
 +_mesa_num_inst_src_regs(gl_inst_opcode opcode);
 +
 +extern const char *
 +_mesa_opcode_string(gl_inst_opcode opcode);
 +
 +
 +#endif /* PROG_INSTRUCTION_H */
index 2d14cd385502ed9187afb835a91755102ca3bdc4,fed8e5b758be357fd36dad1e1f2072480e30e7d4..d427ee38f8165b22778c576c12241248ff37fdcb
@@@ -1,8 -1,8 +1,8 @@@
  /*
   * Mesa 3-D graphics library
 - * Version:  6.5.2
 + * Version:  6.5.3
   *
 - * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
 + * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
   *
   * Permission is hereby granted, free of charge, to any person obtaining a
   * copy of this software and associated documentation files (the "Software"),
  
  #include "glheader.h"
  #include "context.h"
 -#include "imports.h"
 -#include "mtypes.h"
 -#include "program.h"
 +#include "prog_parameter.h"
 +#include "prog_statevars.h"
  #include "programopt.h"
 -#include "program_instruction.h"
 +#include "prog_instruction.h"
  
  
  /**
@@@ -56,11 -57,11 +56,11 @@@ _mesa_insert_mvp_code(GLcontext *ctx, s
      * Setup state references for the modelview/projection matrix.
      * XXX we should check if these state vars are already declared.
      */
 -   static const GLint mvpState[4][5] = {
 -      { STATE_MATRIX, STATE_MVP, 0, 0, 0 },  /* state.matrix.mvp.row[0] */
 -      { STATE_MATRIX, STATE_MVP, 0, 1, 1 },  /* state.matrix.mvp.row[1] */
 -      { STATE_MATRIX, STATE_MVP, 0, 2, 2 },  /* state.matrix.mvp.row[2] */
 -      { STATE_MATRIX, STATE_MVP, 0, 3, 3 },  /* state.matrix.mvp.row[3] */
 +   static const gl_state_index mvpState[4][STATE_LENGTH] = {
 +      { STATE_MVP_MATRIX, 0, 0, 0, 0 },  /* state.matrix.mvp.row[0] */
 +      { STATE_MVP_MATRIX, 0, 1, 1, 0 },  /* state.matrix.mvp.row[1] */
 +      { STATE_MVP_MATRIX, 0, 2, 2, 0 },  /* state.matrix.mvp.row[2] */
 +      { STATE_MVP_MATRIX, 0, 3, 3, 0 },  /* state.matrix.mvp.row[3] */
     };
     GLint mvpRef[4];
  
     }
  
     /* Append original instructions after new instructions */
-    _mesa_memcpy(newInst + 4, vprog->Base.Instructions,
-                 origLen * sizeof(struct prog_instruction));
+    _mesa_copy_instructions (newInst + 4, vprog->Base.Instructions, origLen);
  
     /* free old instructions */
     _mesa_free(vprog->Base.Instructions);
  void
  _mesa_append_fog_code(GLcontext *ctx, struct gl_fragment_program *fprog)
  {
 -   static const GLint fogPStateOpt[] = { STATE_INTERNAL,
 -                                       STATE_FOG_PARAMS_OPTIMIZED, 0, 0, 0 };
 -   static const GLint fogColorState[] = { STATE_FOG_COLOR, 0, 0, 0, 0 };
 +   static const gl_state_index fogPStateOpt[STATE_LENGTH]
 +      = { STATE_INTERNAL, STATE_FOG_PARAMS_OPTIMIZED, 0, 0, 0 };
 +   static const gl_state_index fogColorState[STATE_LENGTH]
 +      = { STATE_FOG_COLOR, 0, 0, 0, 0};
     struct prog_instruction *newInst, *inst;
     const GLuint origLen = fprog->Base.NumInstructions;
     const GLuint newLen = origLen + 5;
     fprog->Base.InputsRead |= FRAG_BIT_FOGC;
     /* XXX do this?  fprog->FogOption = GL_NONE; */
  }
 +
 +
 +
 +static GLboolean
 +is_texture_instruction(const struct prog_instruction *inst)
 +{
 +   switch (inst->Opcode) {
 +   case OPCODE_TEX:
 +   case OPCODE_TXB:
 +   case OPCODE_TXD:
 +   case OPCODE_TXL:
 +   case OPCODE_TXP:
 +   case OPCODE_TXP_NV:
 +      return GL_TRUE;
 +   default:
 +      return GL_FALSE;
 +   }
 +}
 +      
 +
 +/**
 + * Count the number of texure indirections in the given program.
 + * The program's NumTexIndirections field will be updated.
 + * See the GL_ARB_fragment_program spec (issue 24) for details.
 + * XXX we count texture indirections in texenvprogram.c (maybe use this code
 + * instead and elsewhere).
 + */
 +void
 +_mesa_count_texture_indirections(struct gl_program *prog)
 +{
 +   GLuint indirections = 1;
 +   GLbitfield tempsOutput = 0x0;
 +   GLbitfield aluTemps = 0x0;
 +   GLuint i;
 +
 +   for (i = 0; i < prog->NumInstructions; i++) {
 +      const struct prog_instruction *inst = prog->Instructions + i;
 +
 +      if (is_texture_instruction(inst)) {
 +         if (((inst->SrcReg[0].File == PROGRAM_TEMPORARY) && 
 +              (tempsOutput & (1 << inst->SrcReg[0].Index))) ||
 +             ((inst->Opcode != OPCODE_KIL) &&
 +              (inst->DstReg.File == PROGRAM_TEMPORARY) && 
 +              (aluTemps & (1 << inst->DstReg.Index)))) 
 +            {
 +               indirections++;
 +               tempsOutput = 0x0;
 +               aluTemps = 0x0;
 +            }
 +      }
 +      else {
 +         GLuint j;
 +         for (j = 0; j < 3; j++) {
 +            if (inst->SrcReg[j].File == PROGRAM_TEMPORARY)
 +               aluTemps |= (1 << inst->SrcReg[j].Index);
 +         }
 +         if (inst->DstReg.File == PROGRAM_TEMPORARY)
 +            aluTemps |= (1 << inst->DstReg.Index);
 +      }
 +
 +      if ((inst->Opcode != OPCODE_KIL) && (inst->DstReg.File == PROGRAM_TEMPORARY))
 +         tempsOutput |= (1 << inst->DstReg.Index);
 +   }
 +
 +   prog->NumTexIndirections = indirections;
 +}
 +
 +
 +/**
 + * Count number of texture instructions in given program and update the
 + * program's NumTexInstructions field.
 + */
 +void
 +_mesa_count_texture_instructions(struct gl_program *prog)
 +{
 +   GLuint i;
 +   prog->NumTexInstructions = 0;
 +   for (i = 0; i < prog->NumInstructions; i++) {
 +      prog->NumTexInstructions += is_texture_instruction(prog->Instructions + i);
 +   }
 +}
 +
index afab7c4d37aac15e2ea0454be17fbb4afc02640f,b318777072ae43c0fcd8578371c51cfc5182bdca..2051e1f3b73579832c51c9f3c3059455b3c7c313
@@@ -199,7 -199,7 +199,7 @@@ copy_rgba_pixels(GLcontext *ctx, GLint 
     GLint sy, dy, stepy, row;
     const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
     GLint overlapping;
-    const GLuint transferOps = ctx->_ImageTransferState;
+    GLuint transferOps = ctx->_ImageTransferState;
     SWspan span;
  
     if (!ctx->ReadBuffer->_ColorReadBuffer) {
        copy_conv_rgba_pixels(ctx, srcx, srcy, width, height, destx, desty);
        return;
     }
+    else if (ctx->Pixel.Convolution1DEnabled) {
+       /* make sure we don't apply 1D convolution */
+       transferOps &= ~(IMAGE_CONVOLUTION_BIT |
+                        IMAGE_POST_CONVOLUTION_SCALE_BIAS);
+    }
  
     /* Determine if copy should be done bottom-to-top or top-to-bottom */
     if (srcy < desty) {
     ASSERT(width < MAX_WIDTH);
  
     for (row = 0; row < height; row++, sy += stepy, dy += stepy) {
 -      GLvoid *rgba = span.array->color.sz4.rgba;
 +      GLvoid *rgba = span.array->attribs[FRAG_ATTRIB_COL0];
  
        /* Get row/span of source pixels */
        if (overlapping) {
index 595fd5c5cde11417256314e5246756c69e5cfc19,99ad71143e04cbab682334fe6e9084210872fc70..50147f329f6c47543bb81a2fc1655f108f5d808a
@@@ -452,7 -452,8 +452,8 @@@ draw_depth_pixels( GLcontext *ctx, GLin
         && !scaleOrBias
         && !zoom
         && ctx->Visual.rgbMode
-        && width <= MAX_WIDTH) {
+        && width <= MAX_WIDTH
+        && !unpack->SwapBytes) {
        /* Special case: directly write 16-bit depth values */
        GLint row;
        for (row = 0; row < height; row++) {
              && !scaleOrBias
              && !zoom
              && ctx->Visual.rgbMode
-             && width <= MAX_WIDTH) {
+             && width <= MAX_WIDTH
+             && !unpack->SwapBytes) {
        /* Special case: shift 32-bit values down to Visual.depthBits */
        const GLint shift = 32 - ctx->DrawBuffer->Visual.depthBits;
        GLint row;
@@@ -617,6 -619,11 +619,11 @@@ draw_rgba_pixels( GLcontext *ctx, GLin
        type = GL_FLOAT;
        transferOps &= IMAGE_POST_CONVOLUTION_BITS;
     }
+    else if (ctx->Pixel.Convolution1DEnabled) {
+       /* we only want to apply 1D convolution to glTexImage1D */
+       transferOps &= ~(IMAGE_CONVOLUTION_BIT |
+                        IMAGE_POST_CONVOLUTION_SCALE_BIAS);
+    }
  
     if (ctx->DrawBuffer->_NumColorDrawBuffers[0] > 0 &&
         ctx->DrawBuffer->_ColorDrawBuffers[0][0]->DataType != GL_FLOAT &&
           = _mesa_image_row_stride(unpack, width, format, type);
        GLint skipPixels = 0;
        /* use span array for temp color storage */
 -      GLfloat *rgba = (GLfloat *) span.array->color.sz4.rgba;
 +      GLfloat *rgba = (GLfloat *) span.array->attribs[FRAG_ATTRIB_COL0];
  
        /* if the span is wider than MAX_WIDTH we have to do it in chunks */
        while (skipPixels < width) {
index 383d61ce06e128d5021b10dd917b08a3d21ba326,7dc48aec6819123125b62306f98c585e9f311fee..fe9a70f4eae03932dc91a58be33e373c479c8f37
@@@ -119,7 -119,7 +119,7 @@@ read_depth_pixels( GLcontext *ctx
              && !biasOrScale && !packing->SwapBytes) {
        /* Special case: directly read 24-bit unsigned depth values. */
        GLint j;
-       ASSERT(rb->InternalFormat == GL_DEPTH_COMPONENT32);
+       ASSERT(rb->InternalFormat == GL_DEPTH_COMPONENT24);
        ASSERT(rb->DataType == GL_UNSIGNED_INT);
        for (j = 0; j < height; j++, y++) {
           GLuint *dest = (GLuint *)
@@@ -404,12 -404,16 +404,16 @@@ read_rgba_pixels( GLcontext *ctx
        /* no convolution */
        const GLint dstStride
           = _mesa_image_row_stride(packing, width, format, type);
 -      GLfloat (*rgba)[4] = swrast->SpanArrays->color.sz4.rgba;
 +      GLfloat (*rgba)[4] = swrast->SpanArrays->attribs[FRAG_ATTRIB_COL0];
        GLint row;
        GLubyte *dst
           = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
                                               format, type, 0, 0);
  
+       /* make sure we don't apply 1D convolution */
+       transferOps &= ~(IMAGE_CONVOLUTION_BIT |
+                        IMAGE_POST_CONVOLUTION_SCALE_BIAS);
        for (row = 0; row < height; row++, y++) {
  
           /* Get float rgba pixels */
index f9e5045be71855ac3f01a0bc3614e4165f11f6be,2663d993049ffe77f820c27c680f311a4ed4b389..8b8bb3a173ac74943d74c637385dff5313a82a6e
  #include "glheader.h"
  #include "macros.h"
  #include "enums.h"
 +#include "program.h"
 +#include "prog_instruction.h"
 +#include "prog_parameter.h"
 +#include "prog_print.h"
 +#include "prog_statevars.h"
  #include "t_context.h" /* NOTE: very light dependency on this */
  #include "t_vp_build.h"
  
 -#include "shader/program.h"
 -#include "shader/program_instruction.h"
  
  struct state_key {
     unsigned light_global_enabled:1;
@@@ -385,14 -382,11 +385,14 @@@ static struct ureg register_const4f( st
  {
     GLfloat values[4];
     GLint idx;
 +   GLuint swizzle;
     values[0] = s0;
     values[1] = s1;
     values[2] = s2;
     values[3] = s3;
 -   idx = _mesa_add_unnamed_constant( p->program->Base.Parameters, values, 4 );
 +   idx = _mesa_add_unnamed_constant( p->program->Base.Parameters, values, 4,
 +                                     &swizzle );
 +   ASSERT(swizzle == SWIZZLE_NOOP);
     return make_ureg(PROGRAM_STATE_VAR, idx);
  }
  
@@@ -414,37 -408,40 +414,37 @@@ static struct ureg get_identity_param( 
     return p->identity;
  }
  
 -static struct ureg register_param6( struct tnl_program *p, 
 +static struct ureg register_param5(struct tnl_program *p, 
                                   GLint s0,
                                   GLint s1,
                                   GLint s2,
                                   GLint s3,
 -                                 GLint s4,
 -                                 GLint s5)
 +                                   GLint s4)
  {
 -   GLint tokens[6];
 +   gl_state_index tokens[STATE_LENGTH];
     GLint idx;
     tokens[0] = s0;
     tokens[1] = s1;
     tokens[2] = s2;
     tokens[3] = s3;
     tokens[4] = s4;
 -   tokens[5] = s5;
     idx = _mesa_add_state_reference( p->program->Base.Parameters, tokens );
     return make_ureg(PROGRAM_STATE_VAR, idx);
  }
  
  
 -#define register_param1(p,s0)          register_param6(p,s0,0,0,0,0,0)
 -#define register_param2(p,s0,s1)       register_param6(p,s0,s1,0,0,0,0)
 -#define register_param3(p,s0,s1,s2)    register_param6(p,s0,s1,s2,0,0,0)
 -#define register_param4(p,s0,s1,s2,s3) register_param6(p,s0,s1,s2,s3,0,0)
 +#define register_param1(p,s0)          register_param5(p,s0,0,0,0,0)
 +#define register_param2(p,s0,s1)       register_param5(p,s0,s1,0,0,0)
 +#define register_param3(p,s0,s1,s2)    register_param5(p,s0,s1,s2,0,0)
 +#define register_param4(p,s0,s1,s2,s3) register_param5(p,s0,s1,s2,s3,0)
  
  
 -static void register_matrix_param6( struct tnl_program *p,
 -                                  GLint s0,
 -                                  GLint s1,
 -                                  GLint s2,
 -                                  GLint s3,
 -                                  GLint s4,
 -                                  GLint s5,
 +static void register_matrix_param5( struct tnl_program *p,
 +                                  GLint s0, /* modelview, projection, etc */
 +                                  GLint s1, /* texture matrix number */
 +                                  GLint s2, /* first row */
 +                                  GLint s3, /* last row */
 +                                  GLint s4, /* inverse, transpose, etc */
                                    struct ureg *matrix )
  {
     GLint i;
     /* This is a bit sad as the support is there to pull the whole
      * matrix out in one go:
      */
 -   for (i = 0; i <= s4 - s3; i++) 
 -      matrix[i] = register_param6( p, s0, s1, s2, i, i, s5 );
 +   for (i = 0; i <= s3 - s2; i++) 
 +      matrix[i] = register_param5( p, s0, s1, i, i, s4 );
  }
  
  
@@@ -633,13 -630,13 +633,13 @@@ static struct ureg get_eye_position( st
        p->eye_position = reserve_temp(p);
  
        if (PREFER_DP4) {
 -       register_matrix_param6( p, STATE_MATRIX, STATE_MODELVIEW, 0, 0, 3, 
 -                               STATE_MATRIX, modelview );
 +       register_matrix_param5( p, STATE_MODELVIEW_MATRIX, 0, 0, 3,
 +                                 0, modelview );
  
         emit_matrix_transform_vec4(p, p->eye_position, modelview, pos);
        }
        else {
 -       register_matrix_param6( p, STATE_MATRIX, STATE_MODELVIEW, 0, 0, 3, 
 +       register_matrix_param5( p, STATE_MODELVIEW_MATRIX, 0, 0, 3,
                                 STATE_MATRIX_TRANSPOSE, modelview );
  
         emit_transpose_matrix_transform_vec4(p, p->eye_position, modelview, pos);
@@@ -668,7 -665,7 +668,7 @@@ static struct ureg get_eye_normal( stru
        struct ureg normal = register_input(p, VERT_ATTRIB_NORMAL );
        struct ureg mvinv[3];
  
 -      register_matrix_param6( p, STATE_MATRIX, STATE_MODELVIEW, 0, 0, 2,
 +      register_matrix_param5( p, STATE_MODELVIEW_MATRIX, 0, 0, 2,
                              STATE_MATRIX_INVTRANS, mvinv );
  
        p->eye_normal = reserve_temp(p);
@@@ -703,12 -700,12 +703,12 @@@ static void build_hpos( struct tnl_prog
     struct ureg mvp[4];
  
     if (PREFER_DP4) {
 -      register_matrix_param6( p, STATE_MATRIX, STATE_MVP, 0, 0, 3, 
 -                            STATE_MATRIX, mvp );
 +      register_matrix_param5( p, STATE_MVP_MATRIX, 0, 0, 3, 
 +                            0, mvp );
        emit_matrix_transform_vec4( p, hpos, mvp, pos );
     }
     else {
 -      register_matrix_param6( p, STATE_MATRIX, STATE_MVP, 0, 0, 3, 
 +      register_matrix_param5( p, STATE_MVP_MATRIX, 0, 0, 3, 
                              STATE_MATRIX_TRANSPOSE, mvp );
        emit_transpose_matrix_transform_vec4( p, hpos, mvp, pos );
     }
@@@ -853,7 -850,7 +853,7 @@@ static struct ureg calculate_light_atte
  
  
  /* Need to add some addtional parameters to allow lighting in object
-- * space - STATE_SPOT_DIRECTION and STATE_HALF implicitly assume eye
++ * space - STATE_SPOT_DIRECTION and STATE_HALF_VECTOR implicitly assume eye
   * space lighting.
   */
  static void build_lighting( struct tnl_program *p )
             */
            VPpli = register_param3(p, STATE_LIGHT, i, 
                                    STATE_POSITION_NORMALIZED); 
-           half = register_param3(p, STATE_LIGHT, i, STATE_HALF_VECTOR);
+             if (p->state->light_local_viewer) {
+                 struct ureg eye_hat = get_eye_position_normalized(p);
+                 half = get_temp(p);
+                 emit_op2(p, OPCODE_SUB, half, 0, VPpli, eye_hat);
+                 emit_normalize_vec3(p, half, half);
+             } else {
 -                half = register_param3(p, STATE_LIGHT, i, STATE_HALF);
++                half = register_param3(p, STATE_LIGHT, i, STATE_HALF_VECTOR);
+             }
         } 
         else {
            struct ureg Ppli = register_param3(p, STATE_LIGHT, i, 
@@@ -1207,7 -1211,7 +1214,7 @@@ static void build_texture_transform( st
  
     for (i = 0; i < MAX_TEXTURE_UNITS; i++) {
  
 -      if (!(p->state->fragprog_inputs_read & (FRAG_BIT_TEX0<<i)))
 +      if (!(p->state->fragprog_inputs_read & FRAG_BIT_TEX(i)))
         continue;
                                                             
        if (p->state->unit[i].texgen_enabled || 
                              out_texgen : 
                              register_input(p, VERT_ATTRIB_TEX0+i));
            if (PREFER_DP4) {
 -             register_matrix_param6( p, STATE_MATRIX, STATE_TEXTURE, i, 
 -                                     0, 3, STATE_MATRIX, texmat );
 +             register_matrix_param5( p, STATE_TEXTURE_MATRIX, i, 0, 3,
 +                                     0, texmat );
               emit_matrix_transform_vec4( p, out, texmat, in );
            }
            else {
 -             register_matrix_param6( p, STATE_MATRIX, STATE_TEXTURE, i, 
 -                                     0, 3, STATE_MATRIX_TRANSPOSE, texmat );
 +             register_matrix_param5( p, STATE_TEXTURE_MATRIX, i, 0, 3,
 +                                     STATE_MATRIX_TRANSPOSE, texmat );
               emit_transpose_matrix_transform_vec4( p, out, texmat, in );
            }
         }
@@@ -1325,14 -1329,16 +1332,16 @@@ static void build_pointsize( struct tnl
     struct ureg out = register_output(p, VERT_RESULT_PSIZ);
     struct ureg ut = get_temp(p);
  
+    /* dist = |eyez| */
+    emit_op1(p, OPCODE_ABS, ut, WRITEMASK_Y, swizzle1(eye, Z));
     /* p1 + dist * (p2 + dist * p3); */
-    emit_op3(p, OPCODE_MAD, ut, 0, negate(swizzle1(eye, Z)),
+    emit_op3(p, OPCODE_MAD, ut, WRITEMASK_X, swizzle1(ut, Y),
                swizzle1(state_attenuation, Z), swizzle1(state_attenuation, Y));
-    emit_op3(p, OPCODE_MAD, ut, 0, negate(swizzle1(eye, Z)),
+    emit_op3(p, OPCODE_MAD, ut, WRITEMASK_X, swizzle1(ut, Y),
                ut, swizzle1(state_attenuation, X));
  
     /* 1 / sqrt(factor) */
-    emit_op1(p, OPCODE_RSQ, ut, 0, ut );
+    emit_op1(p, OPCODE_RSQ, ut, WRITEMASK_X, ut );
  
  #if 1
     /* out = pointSize / sqrt(factor) */
  #else
     /* not sure, might make sense to do clamping here,
        but it's not done in t_vb_points neither */
-    emit_op2(p, OPCODE_MUL, ut, 0, ut, state_size);
-    emit_op2(p, OPCODE_MAX, ut, 0, ut, swizzle1(state_size, Y));
+    emit_op2(p, OPCODE_MUL, ut, WRITEMASK_X, ut, state_size);
+    emit_op2(p, OPCODE_MAX, ut, WRITEMASK_X, ut, swizzle1(state_size, Y));
     emit_op2(p, OPCODE_MIN, out, WRITEMASK_X, ut, swizzle1(state_size, Z));
  #endif
  
@@@ -1498,7 -1504,7 +1507,7 @@@ void _tnl_UpdateFixedFunctionProgram( G
     GLuint hash;
     const struct gl_vertex_program *prev = ctx->VertexProgram._Current;
  
 -   if (ctx->VertexProgram._Enabled == GL_FALSE) { 
 +   if (!ctx->VertexProgram._Current) {
        /* Grab all the relevent state and put it in a single structure:
         */
        key = make_state_key(ctx);
  
        /* Look for an already-prepared program for this state:
         */
 -      ctx->_TnlProgram = (struct gl_vertex_program *)
 +      ctx->VertexProgram._TnlProgram = (struct gl_vertex_program *)
         search_cache( tnl->vp_cache, hash, key, sizeof(*key) );
     
        /* OK, we'll have to build a new one:
         */
 -      if (!ctx->_TnlProgram) {
 +      if (!ctx->VertexProgram._TnlProgram) {
         if (0)
            _mesa_printf("Build new TNL program\n");
         
 -       ctx->_TnlProgram = (struct gl_vertex_program *)
 +       ctx->VertexProgram._TnlProgram = (struct gl_vertex_program *)
            ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0); 
  
 -       create_new_program( key, ctx->_TnlProgram, 
 +       create_new_program( key, ctx->VertexProgram._TnlProgram, 
                             ctx->Const.VertexProgram.MaxTemps );
  
         if (ctx->Driver.ProgramStringNotify)
            ctx->Driver.ProgramStringNotify( ctx, GL_VERTEX_PROGRAM_ARB, 
 -                                           &ctx->_TnlProgram->Base );
 +                                       &ctx->VertexProgram._TnlProgram->Base );
  
 -       cache_item(tnl->vp_cache, hash, key, ctx->_TnlProgram );
 +       cache_item(tnl->vp_cache, hash, key, ctx->VertexProgram._TnlProgram );
        }
        else {
         FREE(key);
         if (0) 
            _mesa_printf("Found existing TNL program for key %x\n", hash);
        }
 -      ctx->VertexProgram._Current = ctx->_TnlProgram;
 -   }
 -   else {
 -      ctx->VertexProgram._Current = ctx->VertexProgram.Current;
 +      ctx->VertexProgram._Current = ctx->VertexProgram._TnlProgram;
     }
  
     /* Tell the driver about the change.  Could define a new target for
      * this?
      */
 -   if (ctx->VertexProgram._Current != prev &&
 -       ctx->Driver.BindProgram) 
 +   if (ctx->VertexProgram._Current != prev && ctx->Driver.BindProgram) {
        ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB,
                              (struct gl_program *) ctx->VertexProgram._Current);
 +   }
  }
  
  void _tnl_ProgramCacheInit( GLcontext *ctx )