[Mesa-dev] [PATCH] st/atifs: merge gl_program and ati_fragment_shader

Miklós Máté mtmkls at gmail.com
Sat Nov 11 17:10:44 UTC 2017


Hi,

this breaks a few things. The patch below gets rid of the assertion 
failures, but the reference counting needs a proper fix, and swrast 
draws blackness when ATIfs is enabled.

MM

diff --git a/src/mesa/program/program.c b/src/mesa/program/program.c
index faf5b7fa28..b71917d7b1 100644
--- a/src/mesa/program/program.c
+++ b/src/mesa/program/program.c
@@ -258,7 +258,6 @@ _mesa_delete_program(struct gl_context *ctx, struct 
gl_program *prog)
  {
     (void) ctx;
     assert(prog);
-   assert(prog->RefCount==0);

     if (prog == &_mesa_DummyProgram)
        return;
@@ -320,7 +319,8 @@ _mesa_reference_program_(struct gl_context *ctx,
           assert(prog->Target == GL_VERTEX_PROGRAM_ARB);
        else if ((*ptr)->Target == GL_FRAGMENT_PROGRAM_ARB)
           assert(prog->Target == GL_FRAGMENT_PROGRAM_ARB ||
-                prog->Target == GL_FRAGMENT_PROGRAM_NV);
+                prog->Target == GL_FRAGMENT_PROGRAM_NV ||
+                prog->Target == GL_FRAGMENT_SHADER_ATI);
        else if ((*ptr)->Target == GL_GEOMETRY_PROGRAM_NV)
           assert(prog->Target == GL_GEOMETRY_PROGRAM_NV);
     }
diff --git a/src/mesa/state_tracker/st_program.c 
b/src/mesa/state_tracker/st_program.c
index e3649a8b7c..fe0724d331 100644
--- a/src/mesa/state_tracker/st_program.c
+++ b/src/mesa/state_tracker/st_program.c
@@ -1843,6 +1843,7 @@ destroy_program_variants(struct st_context *st, 
struct gl_program *target)
           }
        }
        break;
+   case GL_FRAGMENT_SHADER_ATI:
     case GL_FRAGMENT_PROGRAM_ARB:
        {
           struct st_fragment_program *stfp =
@@ -2029,6 +2030,7 @@ st_precompile_shader_variant(struct st_context *st,
        break;
     }

+   case GL_FRAGMENT_SHADER_ATI:
     case GL_FRAGMENT_PROGRAM_ARB: {
        struct st_fragment_program *p = (struct st_fragment_program *)prog;
        struct st_fp_variant_key key;
diff --git a/src/mesa/swrast/s_context.c b/src/mesa/swrast/s_context.c
index 9f3d21f91d..b8160509c7 100644
--- a/src/mesa/swrast/s_context.c
+++ b/src/mesa/swrast/s_context.c
@@ -251,7 +251,7 @@ _swrast_update_fog_state( struct gl_context *ctx )
     SWcontext *swrast = SWRAST_CONTEXT(ctx);
     const struct gl_program *fp = ctx->FragmentProgram._Current;

-   assert(fp == NULL || fp->Target == GL_FRAGMENT_PROGRAM_ARB);
+   assert(fp == NULL || fp->Target == GL_FRAGMENT_PROGRAM_ARB || 
fp->Target == GL_FRAGMENT_SHADER_ATI);
     (void) fp; /* silence unused var warning */

     /* determine if fog is needed, and if so, which fog mode */


On 10/11/17 11:35, Timothy Arceri wrote:
> This increases the size of gl_program but in future a union
> can be used to offset this increase in memory use. Combining
> the two reduces code and make it easier to follow.
>
> Cc: Miklós Máté <mtmkls at gmail.com>
> ---
>
>   NOTE: compile tested only.
>
>   src/mesa/drivers/common/driverfuncs.c       |   3 -
>   src/mesa/drivers/dri/r200/r200_context.h    |   2 +-
>   src/mesa/drivers/dri/r200/r200_fragshader.c |  86 ++++++-------
>   src/mesa/drivers/dri/r200/r200_state_init.c |   2 +-
>   src/mesa/drivers/dri/r200/r200_vertprog.c   |   1 +
>   src/mesa/main/atifragshader.c               | 193 +++++++++++++---------------
>   src/mesa/main/atifragshader.h               |   4 +-
>   src/mesa/main/dd.h                          |   6 +-
>   src/mesa/main/mtypes.h                      |  57 ++++----
>   src/mesa/main/shared.c                      |   2 +-
>   src/mesa/main/state.c                       |   4 +-
>   src/mesa/main/state.h                       |   2 +-
>   src/mesa/program/program.c                  |   3 +-
>   src/mesa/state_tracker/st_atifs_to_tgsi.c   |  28 ++--
>   src/mesa/state_tracker/st_atifs_to_tgsi.h   |   2 -
>   src/mesa/state_tracker/st_atom_constbuf.c   |   9 +-
>   src/mesa/state_tracker/st_atom_shader.c     |   8 +-
>   src/mesa/state_tracker/st_cb_program.c      |  20 +--
>   src/mesa/state_tracker/st_program.c         |   7 +-
>   src/mesa/state_tracker/st_program.h         |   1 -
>   src/mesa/swrast/s_atifragshader.c           |  18 +--
>   21 files changed, 206 insertions(+), 252 deletions(-)
>
> diff --git a/src/mesa/drivers/common/driverfuncs.c b/src/mesa/drivers/common/driverfuncs.c
> index ddb4bb6d6a..a8b4d9857f 100644
> --- a/src/mesa/drivers/common/driverfuncs.c
> +++ b/src/mesa/drivers/common/driverfuncs.c
> @@ -110,23 +110,20 @@ _mesa_init_driver_functions(struct dd_function_table *driver)
>      driver->AllocTextureImageBuffer = _swrast_alloc_texture_image_buffer;
>      driver->FreeTextureImageBuffer = _swrast_free_texture_image_buffer;
>      driver->MapTextureImage = _swrast_map_teximage;
>      driver->UnmapTextureImage = _swrast_unmap_teximage;
>      driver->DrawTex = _mesa_meta_DrawTex;
>   
>      /* Vertex/fragment programs */
>      driver->NewProgram = _mesa_new_program;
>      driver->DeleteProgram = _mesa_delete_program;
>   
> -   /* ATI_fragment_shader */
> -   driver->NewATIfs = NULL;
> -
>      /* simple state commands */
>      driver->AlphaFunc = NULL;
>      driver->BlendColor = NULL;
>      driver->BlendEquationSeparate = NULL;
>      driver->BlendFuncSeparate = NULL;
>      driver->ClipPlane = NULL;
>      driver->ColorMask = NULL;
>      driver->ColorMaterial = NULL;
>      driver->CullFace = NULL;
>      driver->DrawBuffer = NULL;
> diff --git a/src/mesa/drivers/dri/r200/r200_context.h b/src/mesa/drivers/dri/r200/r200_context.h
> index f9ba6835e8..e164c5d186 100644
> --- a/src/mesa/drivers/dri/r200/r200_context.h
> +++ b/src/mesa/drivers/dri/r200/r200_context.h
> @@ -606,21 +606,21 @@ struct r200_context {
>      /* r200_tcl.c
>       */
>      struct r200_tcl_info tcl;
>   
>      /* r200_swtcl.c
>       */
>      struct r200_swtcl_info swtcl;
>   
>      GLboolean using_hyperz;
>   
> -  struct ati_fragment_shader *afs_loaded;
> +  struct gl_program *afs_loaded;
>   };
>   
>   
>   static inline r200ContextPtr
>   R200_CONTEXT(struct gl_context *ctx)
>   {
>      return (r200ContextPtr) ctx;
>   }
>   
>   
> diff --git a/src/mesa/drivers/dri/r200/r200_fragshader.c b/src/mesa/drivers/dri/r200/r200_fragshader.c
> index ca772f1c87..1eb9c7e4ec 100644
> --- a/src/mesa/drivers/dri/r200/r200_fragshader.c
> +++ b/src/mesa/drivers/dri/r200/r200_fragshader.c
> @@ -118,38 +118,38 @@ static GLuint dstmask_table[8] =
>      R200_TXC_OUTPUT_MASK_B,
>      R200_TXC_OUTPUT_MASK_RB,
>      R200_TXC_OUTPUT_MASK_GB,
>      R200_TXC_OUTPUT_MASK_RGB
>   };
>   
>   static void r200UpdateFSArith( struct gl_context *ctx )
>   {
>      r200ContextPtr rmesa = R200_CONTEXT(ctx);
>      GLuint *afs_cmd;
> -   const struct ati_fragment_shader *shader = ctx->ATIFragmentShader.Current;
> +   const struct gl_program *shader = ctx->ATIFragmentShader.Current;
>      GLuint pass;
>   
>      R200_STATECHANGE( rmesa, afs[0] );
>      R200_STATECHANGE( rmesa, afs[1] );
>   
> -   if (shader->NumPasses < 2) {
> +   if (shader->ati.NumPasses < 2) {
>         afs_cmd = (GLuint *) rmesa->hw.afs[1].cmd;
>      }
>      else {
>         afs_cmd = (GLuint *) rmesa->hw.afs[0].cmd;
>      }
> -   for (pass = 0; pass < shader->NumPasses; pass++) {
> +   for (pass = 0; pass < shader->ati.NumPasses; pass++) {
>         GLuint opnum = 0;
>         GLuint pc;
> -      for (pc = 0; pc < shader->numArithInstr[pass]; pc++) {
> +      for (pc = 0; pc < shader->ati.numArithInstr[pass]; pc++) {
>            GLuint optype;
> -	 struct atifs_instruction *inst = &shader->Instructions[pass][pc];
> +	 struct atifs_instruction *inst = &shader->ati.Instructions[pass][pc];
>   
>   	 SET_INST(opnum, 0) = 0;
>   	 SET_INST_2(opnum, 0) = 0;
>   	 SET_INST(opnum, 1) = 0;
>   	 SET_INST_2(opnum, 1) = 0;
>   
>   	 for (optype = 0; optype < 2; optype++) {
>   	    GLuint tfactor = 0;
>   
>   	    if (inst->Opcode[optype]) {
> @@ -274,22 +274,22 @@ static void r200UpdateFSArith( struct gl_context *ctx )
>   	       GLuint dstmod = inst->DstReg[optype].dstMod;
>   
>   	       dstmod &= ~GL_SATURATE_BIT_ATI;
>   
>   	       SET_INST_2(opnum, optype) |= (dstreg + 1) << R200_TXC_OUTPUT_REG_SHIFT;
>   	       SET_INST_2(opnum, optype) |= dstmask_table[dstmask];
>   
>   		/* fglrx does clamp the last instructions to 0_1 it seems */
>   		/* this won't necessarily catch the last instruction
>   		   which writes to reg0 */
> -	       if (sat || (pc == (shader->numArithInstr[pass] - 1) &&
> -			((pass == 1) || (shader->NumPasses == 1))))
> +	       if (sat || (pc == (shader->ati.numArithInstr[pass] - 1) &&
> +			((pass == 1) || (shader->ati.NumPasses == 1))))
>   		  SET_INST_2(opnum, optype) |= R200_TXC_CLAMP_0_1;
>   	       else
>   		/*should we clamp or not? spec is vague, I would suppose yes but fglrx doesn't */
>   		  SET_INST_2(opnum, optype) |= R200_TXC_CLAMP_8_8;
>   /*		  SET_INST_2(opnum, optype) |= R200_TXC_CLAMP_WRAP;*/
>   	       switch(dstmod) {
>   	       case GL_2X_BIT_ATI:
>   		  SET_INST_2(opnum, optype) |= R200_TXC_SCALE_2X;
>   		  break;
>   	       case GL_4X_BIT_ATI:
> @@ -317,172 +317,172 @@ static void r200UpdateFSArith( struct gl_context *ctx )
>   		SET_INST(opnum, 1), SET_INST_2(opnum, 1));*/
>            opnum++;
>         }
>         afs_cmd = (GLuint *) rmesa->hw.afs[1].cmd;
>      }
>      rmesa->afs_loaded = ctx->ATIFragmentShader.Current;
>   }
>   
>   static void r200UpdateFSRouting( struct gl_context *ctx ) {
>      r200ContextPtr rmesa = R200_CONTEXT(ctx);
> -   const struct ati_fragment_shader *shader = ctx->ATIFragmentShader.Current;
> +   const struct gl_program *shader = ctx->ATIFragmentShader.Current;
>      GLuint reg;
>   
>      R200_STATECHANGE( rmesa, ctx );
>      R200_STATECHANGE( rmesa, cst );
>   
>      for (reg = 0; reg < R200_MAX_TEXTURE_UNITS; reg++) {
> -      if (shader->swizzlerq & (1 << (2 * reg)))
> +      if (shader->ati.swizzlerq & (1 << (2 * reg)))
>   	 /* r coord */
>   	 set_re_cntl_d3d( ctx, reg, 1);
>   	 /* q coord */
>         else set_re_cntl_d3d( ctx, reg, 0);
>      }
>   
>      rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~(R200_MULTI_PASS_ENABLE |
>   				       R200_TEX_BLEND_ENABLE_MASK |
>   				       R200_TEX_ENABLE_MASK);
>      rmesa->hw.cst.cmd[CST_PP_CNTL_X] &= ~(R200_PPX_PFS_INST_ENABLE_MASK |
>   					 R200_PPX_TEX_ENABLE_MASK |
>   					 R200_PPX_OUTPUT_REG_MASK);
>   
>      /* first pass registers use slots 8 - 15
>         but single pass shaders use slots 0 - 7 */
> -   if (shader->NumPasses < 2) {
> -      rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= shader->numArithInstr[0] == 8 ?
> +   if (shader->ati.NumPasses < 2) {
> +      rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= shader->ati.numArithInstr[0] == 8 ?
>   	 0xff << (R200_TEX_BLEND_0_ENABLE_SHIFT - 1) :
> -	 (0xff >> (8 - shader->numArithInstr[0])) << R200_TEX_BLEND_0_ENABLE_SHIFT;
> +	 (0xff >> (8 - shader->ati.numArithInstr[0])) << R200_TEX_BLEND_0_ENABLE_SHIFT;
>      } else {
>         rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_MULTI_PASS_ENABLE;
> -      rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= shader->numArithInstr[1] == 8 ?
> +      rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= shader->ati.numArithInstr[1] == 8 ?
>   	 0xff << (R200_TEX_BLEND_0_ENABLE_SHIFT - 1) :
> -	 (0xff >> (8 - shader->numArithInstr[1])) << R200_TEX_BLEND_0_ENABLE_SHIFT;
> +	 (0xff >> (8 - shader->ati.numArithInstr[1])) << R200_TEX_BLEND_0_ENABLE_SHIFT;
>         rmesa->hw.cst.cmd[CST_PP_CNTL_X] |=
> -	 (0xff >> (8 - shader->numArithInstr[0])) << R200_PPX_FPS_INST0_ENABLE_SHIFT;
> +	 (0xff >> (8 - shader->ati.numArithInstr[0])) << R200_PPX_FPS_INST0_ENABLE_SHIFT;
>      }
>   
> -   if (shader->NumPasses < 2) {
> +   if (shader->ati.NumPasses < 2) {
>         for (reg = 0; reg < R200_MAX_TEXTURE_UNITS; reg++) {
>            struct gl_texture_object *texObj = ctx->Texture.Unit[reg]._Current;
>            R200_STATECHANGE( rmesa, tex[reg] );
>   	 rmesa->hw.tex[reg].cmd[TEX_PP_TXMULTI_CTL] = 0;
> -	 if (shader->SetupInst[0][reg].Opcode) {
> +	 if (shader->ati.SetupInst[0][reg].Opcode) {
>   	    GLuint txformat = rmesa->hw.tex[reg].cmd[TEX_PP_TXFORMAT]
>   		& ~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE);
>   	    GLuint txformat_x = rmesa->hw.tex[reg].cmd[TEX_PP_TXFORMAT_X] & ~R200_TEXCOORD_MASK;
> -	    txformat |= (shader->SetupInst[0][reg].src - GL_TEXTURE0_ARB)
> +	    txformat |= (shader->ati.SetupInst[0][reg].src - GL_TEXTURE0_ARB)
>   		<< R200_TXFORMAT_ST_ROUTE_SHIFT;
>   	    /* fix up texcoords for proj/non-proj 2d (3d and cube are not defined when
>   	       using projection so don't have to worry there).
>   	       When passing coords, need R200_TEXCOORD_VOLUME, otherwise loose a coord */
>   	    /* FIXME: someone might rely on default tex coords r/q, which we unfortunately
>   	       don't provide (we have the same problem without shaders) */
> -	    if (shader->SetupInst[0][reg].Opcode == ATI_FRAGMENT_SHADER_PASS_OP) {
> +	    if (shader->ati.SetupInst[0][reg].Opcode == ATI_FRAGMENT_SHADER_PASS_OP) {
>   	       txformat |= R200_TXFORMAT_LOOKUP_DISABLE;
> -	       if (shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STR_ATI ||
> -		  shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STQ_ATI) {
> +	       if (shader->ati.SetupInst[0][reg].swizzle == GL_SWIZZLE_STR_ATI ||
> +		  shader->ati.SetupInst[0][reg].swizzle == GL_SWIZZLE_STQ_ATI) {
>   		  txformat_x |= R200_TEXCOORD_VOLUME;
>   	       }
>   	       else {
>   		  txformat_x |= R200_TEXCOORD_PROJ;
>   	       }
>   	       rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_0_ENABLE << reg;
>   	    }
>   	    else if (texObj && texObj->Target == GL_TEXTURE_3D) {
>   	       txformat_x |= R200_TEXCOORD_VOLUME;
>   	    }
>   	    else if (texObj && texObj->Target == GL_TEXTURE_CUBE_MAP) {
>   	       txformat_x |= R200_TEXCOORD_CUBIC_ENV;
>   	    }
> -	    else if (shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STR_ATI ||
> -	       shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STQ_ATI) {
> +	    else if (shader->ati.SetupInst[0][reg].swizzle == GL_SWIZZLE_STR_ATI ||
> +	       shader->ati.SetupInst[0][reg].swizzle == GL_SWIZZLE_STQ_ATI) {
>   	       txformat_x |= R200_TEXCOORD_NONPROJ;
>   	    }
>   	    else {
>   	       txformat_x |= R200_TEXCOORD_PROJ;
>   	    }
>   	    rmesa->hw.tex[reg].cmd[TEX_PP_TXFORMAT] = txformat;
>   	    rmesa->hw.tex[reg].cmd[TEX_PP_TXFORMAT_X] = txformat_x;
>   	    /* enabling texturing when unit isn't correctly configured may not be safe */
>   	    if (texObj)
>   	       rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_0_ENABLE << reg;
>   	 }
>         }
>   
>      } else {
>         /* setup 1st pass */
>         for (reg = 0; reg < R200_MAX_TEXTURE_UNITS; reg++) {
>   	 struct gl_texture_object *texObj = ctx->Texture.Unit[reg]._Current;
>   	 R200_STATECHANGE( rmesa, tex[reg] );
>   	 GLuint txformat_multi = 0;
> -	 if (shader->SetupInst[0][reg].Opcode) {
> -	    txformat_multi |= (shader->SetupInst[0][reg].src - GL_TEXTURE0_ARB)
> +	 if (shader->ati.SetupInst[0][reg].Opcode) {
> +	    txformat_multi |= (shader->ati.SetupInst[0][reg].src - GL_TEXTURE0_ARB)
>   		<< R200_PASS1_ST_ROUTE_SHIFT;
> -	    if (shader->SetupInst[0][reg].Opcode == ATI_FRAGMENT_SHADER_PASS_OP) {
> +	    if (shader->ati.SetupInst[0][reg].Opcode == ATI_FRAGMENT_SHADER_PASS_OP) {
>   	       txformat_multi |= R200_PASS1_TXFORMAT_LOOKUP_DISABLE;
> -	       if (shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STR_ATI ||
> -		  shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STQ_ATI) {
> +	       if (shader->ati.SetupInst[0][reg].swizzle == GL_SWIZZLE_STR_ATI ||
> +		  shader->ati.SetupInst[0][reg].swizzle == GL_SWIZZLE_STQ_ATI) {
>   		  txformat_multi |= R200_PASS1_TEXCOORD_VOLUME;
>   	       }
>   	       else {
>   		  txformat_multi |= R200_PASS1_TEXCOORD_PROJ;
>   	       }
>   	       rmesa->hw.cst.cmd[CST_PP_CNTL_X] |= R200_PPX_TEX_0_ENABLE << reg;
>   	    }
>   	    else if (texObj && texObj->Target == GL_TEXTURE_3D) {
>   	       txformat_multi |= R200_PASS1_TEXCOORD_VOLUME;
>   	    }
>   	    else if (texObj && texObj->Target == GL_TEXTURE_CUBE_MAP) {
>   	       txformat_multi |= R200_PASS1_TEXCOORD_CUBIC_ENV;
>   	    }
> -	    else if (shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STR_ATI ||
> -		  shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STQ_ATI) {
> +	    else if (shader->ati.SetupInst[0][reg].swizzle == GL_SWIZZLE_STR_ATI ||
> +		  shader->ati.SetupInst[0][reg].swizzle == GL_SWIZZLE_STQ_ATI) {
>   		  txformat_multi |= R200_PASS1_TEXCOORD_NONPROJ;
>   	    }
>   	    else {
>   	       txformat_multi |= R200_PASS1_TEXCOORD_PROJ;
>   	    }
>   	    if (texObj)
>   	       rmesa->hw.cst.cmd[CST_PP_CNTL_X] |= R200_PPX_TEX_0_ENABLE << reg;
>   	 }
>            rmesa->hw.tex[reg].cmd[TEX_PP_TXMULTI_CTL] = txformat_multi;
>         }
>   
>         /* setup 2nd pass */
>         for (reg=0; reg < R200_MAX_TEXTURE_UNITS; reg++) {
>   	 struct gl_texture_object *texObj = ctx->Texture.Unit[reg]._Current;
> -	 if (shader->SetupInst[1][reg].Opcode) {
> -	    GLuint coord = shader->SetupInst[1][reg].src;
> +	 if (shader->ati.SetupInst[1][reg].Opcode) {
> +	    GLuint coord = shader->ati.SetupInst[1][reg].src;
>   	    GLuint txformat = rmesa->hw.tex[reg].cmd[TEX_PP_TXFORMAT]
>   		& ~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE);
>   	    GLuint txformat_x = rmesa->hw.tex[reg].cmd[TEX_PP_TXFORMAT_X] & ~R200_TEXCOORD_MASK;
>   	    R200_STATECHANGE( rmesa, tex[reg] );
> -	    if (shader->SetupInst[1][reg].Opcode == ATI_FRAGMENT_SHADER_PASS_OP) {
> +	    if (shader->ati.SetupInst[1][reg].Opcode == ATI_FRAGMENT_SHADER_PASS_OP) {
>   	       txformat |= R200_TXFORMAT_LOOKUP_DISABLE;
>   	       txformat_x |= R200_TEXCOORD_VOLUME;
> -	       if (shader->SetupInst[1][reg].swizzle == GL_SWIZZLE_STR_ATI ||
> -		  shader->SetupInst[1][reg].swizzle == GL_SWIZZLE_STQ_ATI) {
> +	       if (shader->ati.SetupInst[1][reg].swizzle == GL_SWIZZLE_STR_ATI ||
> +		  shader->ati.SetupInst[1][reg].swizzle == GL_SWIZZLE_STQ_ATI) {
>   	          txformat_x |= R200_TEXCOORD_VOLUME;
>   	       }
>   	       else {
>   		  txformat_x |= R200_TEXCOORD_PROJ;
>   	       }
>   	       rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_0_ENABLE << reg;
>   	    }
>   	    else if (texObj && texObj->Target == GL_TEXTURE_3D) {
>   	       txformat_x |= R200_TEXCOORD_VOLUME;
>   	    }
>   	    else if (texObj && texObj->Target == GL_TEXTURE_CUBE_MAP) {
>   	       txformat_x |= R200_TEXCOORD_CUBIC_ENV;
>   	    }
> -	    else if (shader->SetupInst[1][reg].swizzle == GL_SWIZZLE_STR_ATI ||
> -	       shader->SetupInst[1][reg].swizzle == GL_SWIZZLE_STQ_ATI) {
> +	    else if (shader->ati.SetupInst[1][reg].swizzle == GL_SWIZZLE_STR_ATI ||
> +	       shader->ati.SetupInst[1][reg].swizzle == GL_SWIZZLE_STQ_ATI) {
>   	       txformat_x |= R200_TEXCOORD_NONPROJ;
>   	    }
>   	    else {
>   	       txformat_x |= R200_TEXCOORD_PROJ;
>   	    }
>   	    if (coord >= GL_REG_0_ATI) {
>   	       GLuint txformat_multi = rmesa->hw.tex[reg].cmd[TEX_PP_TXMULTI_CTL];
>   	       txformat_multi |= (coord - GL_REG_0_ATI + 2) << R200_PASS2_COORDS_REG_SHIFT;
>   	       rmesa->hw.tex[reg].cmd[TEX_PP_TXMULTI_CTL] = txformat_multi;
>   	       rmesa->hw.cst.cmd[CST_PP_CNTL_X] |= 1 <<
> @@ -495,33 +495,33 @@ static void r200UpdateFSRouting( struct gl_context *ctx ) {
>   	    if (texObj)
>   	       rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_0_ENABLE << reg;
>   	 }
>         }
>      }
>   }
>   
>   static void r200UpdateFSConstants( struct gl_context *ctx )
>   {
>      r200ContextPtr rmesa = R200_CONTEXT(ctx);
> -   const struct ati_fragment_shader *shader = ctx->ATIFragmentShader.Current;
> +   const struct gl_program *shader = ctx->ATIFragmentShader.Current;
>      GLuint i;
>   
>      /* update constants */
>      R200_STATECHANGE(rmesa, atf);
>      for (i = 0; i < 8; i++)
>      {
>         GLubyte con_byte[4];
> -      if ((shader->LocalConstDef >> i) & 1) {
> -	 CLAMPED_FLOAT_TO_UBYTE(con_byte[0], shader->Constants[i][0]);
> -	 CLAMPED_FLOAT_TO_UBYTE(con_byte[1], shader->Constants[i][1]);
> -	 CLAMPED_FLOAT_TO_UBYTE(con_byte[2], shader->Constants[i][2]);
> -	 CLAMPED_FLOAT_TO_UBYTE(con_byte[3], shader->Constants[i][3]);
> +      if ((shader->ati.LocalConstDef >> i) & 1) {
> +	 CLAMPED_FLOAT_TO_UBYTE(con_byte[0], shader->ati.Constants[i][0]);
> +	 CLAMPED_FLOAT_TO_UBYTE(con_byte[1], shader->ati.Constants[i][1]);
> +	 CLAMPED_FLOAT_TO_UBYTE(con_byte[2], shader->ati.Constants[i][2]);
> +	 CLAMPED_FLOAT_TO_UBYTE(con_byte[3], shader->ati.Constants[i][3]);
>         }
>         else {
>   	 CLAMPED_FLOAT_TO_UBYTE(con_byte[0], ctx->ATIFragmentShader.GlobalConstants[i][0]);
>   	 CLAMPED_FLOAT_TO_UBYTE(con_byte[1], ctx->ATIFragmentShader.GlobalConstants[i][1]);
>   	 CLAMPED_FLOAT_TO_UBYTE(con_byte[2], ctx->ATIFragmentShader.GlobalConstants[i][2]);
>   	 CLAMPED_FLOAT_TO_UBYTE(con_byte[3], ctx->ATIFragmentShader.GlobalConstants[i][3]);
>         }
>         rmesa->hw.atf.cmd[ATF_TFACTOR_0 + i] = radeonPackColor (
>   	 4, con_byte[0], con_byte[1], con_byte[2], con_byte[3] );
>      }
> diff --git a/src/mesa/drivers/dri/r200/r200_state_init.c b/src/mesa/drivers/dri/r200/r200_state_init.c
> index 4b589cd8b8..48ac7f4fd1 100644
> --- a/src/mesa/drivers/dri/r200/r200_state_init.c
> +++ b/src/mesa/drivers/dri/r200/r200_state_init.c
> @@ -248,21 +248,21 @@ static int check_##NM( struct gl_context *ctx, struct radeon_state_atom *atom )
>      return (!rmesa->radeon.TclFallback && _mesa_arb_vertex_program_enabled(ctx) && (FLAG)) ? atom->cmd_size + (ADD) : 0; \
>   }
>   
>   CHECK( always, GL_TRUE, 0 )
>   CHECK( always_add4, GL_TRUE, 4 )
>   CHECK( never, GL_FALSE, 0 )
>   CHECK( tex_any, ctx->Texture._MaxEnabledTexImageUnit != -1, 0 )
>   CHECK( tf, (ctx->Texture._MaxEnabledTexImageUnit != -1 && !_mesa_ati_fragment_shader_enabled(ctx)), 0 );
>   CHECK( pix_zero, !_mesa_ati_fragment_shader_enabled(ctx), 0 )
>   CHECK( texenv, (rmesa->state.envneeded & (1 << (atom->idx)) && !_mesa_ati_fragment_shader_enabled(ctx)), 0 )
> -CHECK( afs_pass1, (_mesa_ati_fragment_shader_enabled(ctx) && (ctx->ATIFragmentShader.Current->NumPasses > 1)), 0 )
> +CHECK( afs_pass1, (_mesa_ati_fragment_shader_enabled(ctx) && (ctx->ATIFragmentShader.Current->ati.NumPasses > 1)), 0 )
>   CHECK( afs, _mesa_ati_fragment_shader_enabled(ctx), 0 )
>   CHECK( tex_cube, rmesa->state.texture.unit[atom->idx].unitneeded & TEXTURE_CUBE_BIT, 3 + 3*5 - CUBE_STATE_SIZE )
>   CHECK( tex_cube_cs, rmesa->state.texture.unit[atom->idx].unitneeded & TEXTURE_CUBE_BIT, 2 + 4*5 - CUBE_STATE_SIZE )
>   TCL_CHECK( tcl_fog_add4, ctx->Fog.Enabled, 4 )
>   TCL_CHECK( tcl, GL_TRUE, 0 )
>   TCL_CHECK( tcl_add8, GL_TRUE, 8 )
>   TCL_CHECK( tcl_add4, GL_TRUE, 4 )
>   TCL_CHECK( tcl_tex_add4, rmesa->state.texture.unit[atom->idx].unitneeded, 4 )
>   TCL_CHECK( tcl_lighting_add4, ctx->Light.Enabled, 4 )
>   TCL_CHECK( tcl_lighting_add6, ctx->Light.Enabled, 6 )
> diff --git a/src/mesa/drivers/dri/r200/r200_vertprog.c b/src/mesa/drivers/dri/r200/r200_vertprog.c
> index bb8550332b..1340fd0a3c 100644
> --- a/src/mesa/drivers/dri/r200/r200_vertprog.c
> +++ b/src/mesa/drivers/dri/r200/r200_vertprog.c
> @@ -1186,20 +1186,21 @@ void r200SetupVertexProg( struct gl_context *ctx ) {
>   static struct gl_program *
>   r200NewProgram(struct gl_context *ctx, GLenum target, GLuint id,
>                  bool is_arb_asm)
>   {
>      switch(target){
>      case GL_VERTEX_PROGRAM_ARB: {
>         struct r200_vertex_program *vp = rzalloc(NULL,
>                                                  struct r200_vertex_program);
>         return _mesa_init_gl_program(&vp->mesa_program, target, id, is_arb_asm);
>      }
> +   case GL_FRAGMENT_SHADER_ATI:
>      case GL_FRAGMENT_PROGRAM_ARB: {
>         struct gl_program *prog = rzalloc(NULL, struct gl_program);
>         return _mesa_init_gl_program(prog, target, id, is_arb_asm);
>      }
>      default:
>         _mesa_problem(ctx, "Bad target in r200NewProgram");
>         return NULL;
>      }
>   }
>   
> diff --git a/src/mesa/main/atifragshader.c b/src/mesa/main/atifragshader.c
> index 49ddb6e5af..b0b2f93d65 100644
> --- a/src/mesa/main/atifragshader.c
> +++ b/src/mesa/main/atifragshader.c
> @@ -27,78 +27,71 @@
>   #include "main/imports.h"
>   #include "main/macros.h"
>   #include "main/enums.h"
>   #include "main/mtypes.h"
>   #include "main/dispatch.h"
>   #include "main/atifragshader.h"
>   #include "program/program.h"
>   
>   #define MESA_DEBUG_ATI_FS 0
>   
> -static struct ati_fragment_shader DummyShader;
> +static struct gl_program DummyShader;
>   
>   
>   /**
>    * Allocate and initialize a new ATI fragment shader object.
>    */
> -struct ati_fragment_shader *
> +struct gl_program *
>   _mesa_new_ati_fragment_shader(struct gl_context *ctx, GLuint id)
>   {
> -   struct ati_fragment_shader *s = CALLOC_STRUCT(ati_fragment_shader);
> -   (void) ctx;
> -   if (s) {
> -      s->Id = id;
> -      s->RefCount = 1;
> -   }
> -   return s;
> +   return ctx->Driver.NewProgram(ctx, GL_FRAGMENT_SHADER_ATI, id, true);
>   }
>   
>   
>   /**
>    * Delete the given ati fragment shader
>    */
>   void
> -_mesa_delete_ati_fragment_shader(struct gl_context *ctx, struct ati_fragment_shader *s)
> +_mesa_delete_ati_fragment_shader(struct gl_context *ctx, struct gl_program *s)
>   {
>      GLuint i;
>   
>      if (s == &DummyShader)
>         return;
>   
>      for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
> -      free(s->Instructions[i]);
> -      free(s->SetupInst[i]);
> +      free(s->ati.Instructions[i]);
> +      free(s->ati.SetupInst[i]);
>      }
> -   _mesa_reference_program(ctx, &s->Program, NULL);
> -   free(s);
> +   ctx->Driver.DeleteProgram(ctx, s);
>   }
>   
>   
>   
>   static void
> -new_arith_inst(struct ati_fragment_shader *prog)
> +new_arith_inst(struct gl_program *prog)
>   {
>   /* set "default" instruction as not all may get defined.
>      there is no specified way to express a nop with ati fragment shaders we use
>      GL_NONE as the op enum and just set some params to 0 - so nothing to do here */
> -   prog->numArithInstr[prog->cur_pass >> 1]++;
> +   prog->ati.numArithInstr[prog->ati.cur_pass >> 1]++;
>   }
>   
>   static void
> -new_tex_inst(struct ati_fragment_shader *prog)
> +new_tex_inst(struct gl_program *prog)
>   {
>   }
>   
> -static void match_pair_inst(struct ati_fragment_shader *curProg, GLuint optype)
> +static void match_pair_inst(struct gl_program *curProg, GLuint optype)
>   {
> -   if (optype == curProg->last_optype) {
> -      curProg->last_optype = 1;
> +   if (optype == curProg->ati.last_optype) {
> +      curProg->ati.last_optype = 1;
>      }
>   }
>   
>   #if MESA_DEBUG_ATI_FS
>   static char *
>   create_dst_mod_str(GLuint mod)
>   {
>      static char ret_str[1024];
>   
>      memset(ret_str, 0, 1024);
> @@ -152,21 +145,21 @@ static void debug_op(GLint optype, GLuint arg_count, GLenum op, GLuint dst,
>   	      _mesa_enum_to_string(arg2Rep), arg2Mod);
>     if (arg_count>2)
>       fprintf(stderr, ", %s, %s, %d", _mesa_enum_to_string(arg3),
>   	      _mesa_enum_to_string(arg3Rep), arg3Mod);
>   
>     fprintf(stderr,")\n");
>   
>   }
>   #endif
>   
> -static int check_arith_arg(struct ati_fragment_shader *curProg,
> +static int check_arith_arg(struct gl_program *curProg,
>   			GLuint optype, GLuint arg, GLuint argRep)
>   {
>      GET_CURRENT_CONTEXT(ctx);
>   
>      if (((arg < GL_CON_0_ATI) || (arg > GL_CON_7_ATI)) &&
>         ((arg < GL_REG_0_ATI) || (arg > GL_REG_5_ATI)) &&
>         (arg != GL_ZERO) && (arg != GL_ONE) &&
>         (arg != GL_PRIMARY_COLOR_ARB) && (arg != GL_SECONDARY_INTERPOLATOR_ATI)) {
>         _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(arg)");
>         return 0;
> @@ -174,23 +167,23 @@ static int check_arith_arg(struct ati_fragment_shader *curProg,
>      if ((arg == GL_SECONDARY_INTERPOLATOR_ATI) && (((optype == 0) && (argRep == GL_ALPHA)) ||
>         ((optype == 1) && ((arg == GL_ALPHA) || (argRep == GL_NONE))))) {
>         _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)");
>         return 0;
>      }
>      if ((arg == GL_SECONDARY_INTERPOLATOR_ATI) && (((optype == 0) && (argRep == GL_ALPHA)) ||
>         ((optype == 1) && ((arg == GL_ALPHA) || (argRep == GL_NONE))))) {
>         _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)");
>         return 0;
>      }
> -   if ((curProg->cur_pass == 1) &&
> +   if ((curProg->ati.cur_pass == 1) &&
>         ((arg == GL_PRIMARY_COLOR_ARB) || (arg == GL_SECONDARY_INTERPOLATOR_ATI))) {
> -      curProg->interpinp1 = GL_TRUE;
> +      curProg->ati.interpinp1 = GL_TRUE;
>      }
>      return 1;
>   }
>   
>   GLuint GLAPIENTRY
>   _mesa_GenFragmentShadersATI(GLuint range)
>   {
>      GLuint first;
>      GLuint i;
>      GET_CURRENT_CONTEXT(ctx);
> @@ -214,22 +207,22 @@ _mesa_GenFragmentShadersATI(GLuint range)
>   
>      _mesa_HashUnlockMutex(ctx->Shared->ATIShaders);
>   
>      return first;
>   }
>   
>   void GLAPIENTRY
>   _mesa_BindFragmentShaderATI(GLuint id)
>   {
>      GET_CURRENT_CONTEXT(ctx);
> -   struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
> -   struct ati_fragment_shader *newProg;
> +   struct gl_program *curProg = ctx->ATIFragmentShader.Current;
> +   struct gl_program *newProg;
>   
>      if (ctx->ATIFragmentShader.Compiling) {
>         _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFragmentShaderATI(insideShader)");
>         return;
>      }
>   
>      FLUSH_VERTICES(ctx, _NEW_PROGRAM);
>   
>      if (curProg->Id == id) {
>         return;
> @@ -241,21 +234,21 @@ _mesa_BindFragmentShaderATI(GLuint id)
>         if (curProg->RefCount <= 0) {
>   	 _mesa_HashRemove(ctx->Shared->ATIShaders, id);
>         }
>      }
>   
>      /* find new shader */
>      if (id == 0) {
>         newProg = ctx->Shared->DefaultFragmentShader;
>      }
>      else {
> -      newProg = (struct ati_fragment_shader *)
> +      newProg = (struct gl_program *)
>            _mesa_HashLookup(ctx->Shared->ATIShaders, id);
>         if (!newProg || newProg == &DummyShader) {
>   	 /* allocate a new program now */
>   	 newProg = _mesa_new_ati_fragment_shader(ctx, id);
>   	 if (!newProg) {
>   	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFragmentShaderATI");
>   	    return;
>   	 }
>   	 _mesa_HashInsert(ctx->Shared->ATIShaders, id, newProg);
>         }
> @@ -274,21 +267,21 @@ void GLAPIENTRY
>   _mesa_DeleteFragmentShaderATI(GLuint id)
>   {
>      GET_CURRENT_CONTEXT(ctx);
>   
>      if (ctx->ATIFragmentShader.Compiling) {
>         _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteFragmentShaderATI(insideShader)");
>         return;
>      }
>   
>      if (id != 0) {
> -      struct ati_fragment_shader *prog = (struct ati_fragment_shader *)
> +      struct gl_program *prog = (struct gl_program *)
>   	 _mesa_HashLookup(ctx->Shared->ATIShaders, id);
>         if (prog == &DummyShader) {
>   	 _mesa_HashRemove(ctx->Shared->ATIShaders, id);
>         }
>         else if (prog) {
>   	 if (ctx->ATIFragmentShader.Current &&
>   	     ctx->ATIFragmentShader.Current->Id == id) {
>   	     FLUSH_VERTICES(ctx, _NEW_PROGRAM);
>   	    _mesa_BindFragmentShaderATI(0);
>   	 }
> @@ -316,310 +309,302 @@ _mesa_BeginFragmentShaderATI(void)
>         _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginFragmentShaderATI(insideShader)");
>         return;
>      }
>   
>      FLUSH_VERTICES(ctx, _NEW_PROGRAM);
>   
>      /* if the shader was already defined free instructions and get new ones
>         (or, could use the same mem but would need to reinitialize) */
>      /* no idea if it's allowed to redefine a shader */
>      for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
> -         free(ctx->ATIFragmentShader.Current->Instructions[i]);
> -         free(ctx->ATIFragmentShader.Current->SetupInst[i]);
> +         free(ctx->ATIFragmentShader.Current->ati.Instructions[i]);
> +         free(ctx->ATIFragmentShader.Current->ati.SetupInst[i]);
>      }
>   
> -   _mesa_reference_program(ctx, &ctx->ATIFragmentShader.Current->Program, NULL);
> -
>      /* malloc the instructions here - not sure if the best place but its
>         a start */
>      for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
> -      ctx->ATIFragmentShader.Current->Instructions[i] =
> +      ctx->ATIFragmentShader.Current->ati.Instructions[i] =
>   	 calloc(sizeof(struct atifs_instruction),
>                   MAX_NUM_INSTRUCTIONS_PER_PASS_ATI);
> -      ctx->ATIFragmentShader.Current->SetupInst[i] =
> +      ctx->ATIFragmentShader.Current->ati.SetupInst[i] =
>   	 calloc(sizeof(struct atifs_setupinst),
>                   MAX_NUM_FRAGMENT_REGISTERS_ATI);
>      }
>   
>   /* can't rely on calloc for initialization as it's possible to redefine a shader (?) */
> -   ctx->ATIFragmentShader.Current->LocalConstDef = 0;
> -   ctx->ATIFragmentShader.Current->numArithInstr[0] = 0;
> -   ctx->ATIFragmentShader.Current->numArithInstr[1] = 0;
> -   ctx->ATIFragmentShader.Current->regsAssigned[0] = 0;
> -   ctx->ATIFragmentShader.Current->regsAssigned[1] = 0;
> -   ctx->ATIFragmentShader.Current->NumPasses = 0;
> -   ctx->ATIFragmentShader.Current->cur_pass = 0;
> -   ctx->ATIFragmentShader.Current->last_optype = 0;
> -   ctx->ATIFragmentShader.Current->interpinp1 = GL_FALSE;
> -   ctx->ATIFragmentShader.Current->isValid = GL_FALSE;
> -   ctx->ATIFragmentShader.Current->swizzlerq = 0;
> +   ctx->ATIFragmentShader.Current->ati.LocalConstDef = 0;
> +   ctx->ATIFragmentShader.Current->ati.numArithInstr[0] = 0;
> +   ctx->ATIFragmentShader.Current->ati.numArithInstr[1] = 0;
> +   ctx->ATIFragmentShader.Current->ati.regsAssigned[0] = 0;
> +   ctx->ATIFragmentShader.Current->ati.regsAssigned[1] = 0;
> +   ctx->ATIFragmentShader.Current->ati.NumPasses = 0;
> +   ctx->ATIFragmentShader.Current->ati.cur_pass = 0;
> +   ctx->ATIFragmentShader.Current->ati.last_optype = 0;
> +   ctx->ATIFragmentShader.Current->ati.interpinp1 = GL_FALSE;
> +   ctx->ATIFragmentShader.Current->ati.isValid = GL_FALSE;
> +   ctx->ATIFragmentShader.Current->ati.swizzlerq = 0;
>      ctx->ATIFragmentShader.Compiling = 1;
>   #if MESA_DEBUG_ATI_FS
>      _mesa_debug(ctx, "%s %u\n", __func__, ctx->ATIFragmentShader.Current->Id);
>   #endif
>   }
>   
>   void GLAPIENTRY
>   _mesa_EndFragmentShaderATI(void)
>   {
>      GET_CURRENT_CONTEXT(ctx);
> -   struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
> +   struct gl_program *curProg = ctx->ATIFragmentShader.Current;
>   #if MESA_DEBUG_ATI_FS
>      GLint i, j;
>   #endif
>   
>      if (!ctx->ATIFragmentShader.Compiling) {
>         _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(outsideShader)");
>         return;
>      }
> -   if (curProg->interpinp1 && (ctx->ATIFragmentShader.Current->cur_pass > 1)) {
> +   if (curProg->ati.interpinp1 && (ctx->ATIFragmentShader.Current->ati.cur_pass > 1)) {
>         _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(interpinfirstpass)");
>      /* according to spec, DON'T return here */
>      }
>   
>      match_pair_inst(curProg, 0);
>      ctx->ATIFragmentShader.Compiling = 0;
> -   ctx->ATIFragmentShader.Current->isValid = GL_TRUE;
> -   if ((ctx->ATIFragmentShader.Current->cur_pass == 0) ||
> -      (ctx->ATIFragmentShader.Current->cur_pass == 2)) {
> +   ctx->ATIFragmentShader.Current->ati.isValid = GL_TRUE;
> +   if ((ctx->ATIFragmentShader.Current->ati.cur_pass == 0) ||
> +      (ctx->ATIFragmentShader.Current->ati.cur_pass == 2)) {
>         _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(noarithinst)");
>      }
> -   if (ctx->ATIFragmentShader.Current->cur_pass > 1)
> -      ctx->ATIFragmentShader.Current->NumPasses = 2;
> +   if (ctx->ATIFragmentShader.Current->ati.cur_pass > 1)
> +      ctx->ATIFragmentShader.Current->ati.NumPasses = 2;
>      else
> -      ctx->ATIFragmentShader.Current->NumPasses = 1;
> +      ctx->ATIFragmentShader.Current->ati.NumPasses = 1;
>   
> -   ctx->ATIFragmentShader.Current->cur_pass = 0;
> +   ctx->ATIFragmentShader.Current->ati.cur_pass = 0;
>   
>   #if MESA_DEBUG_ATI_FS
>      for (j = 0; j < MAX_NUM_PASSES_ATI; j++) {
>         for (i = 0; i < MAX_NUM_FRAGMENT_REGISTERS_ATI; i++) {
> -	 GLuint op = curProg->SetupInst[j][i].Opcode;
> +	 GLuint op = curProg->ati.SetupInst[j][i].Opcode;
>   	 const char *op_enum = op > 5 ? _mesa_enum_to_string(op) : "0";
> -	 GLuint src = curProg->SetupInst[j][i].src;
> -	 GLuint swizzle = curProg->SetupInst[j][i].swizzle;
> +	 GLuint src = curProg->ati.SetupInst[j][i].src;
> +	 GLuint swizzle = curProg->ati.SetupInst[j][i].swizzle;
>   	 fprintf(stderr, "%2d %04X %s %d %04X\n", i, op, op_enum, src,
>   	      swizzle);
>         }
> -      for (i = 0; i < curProg->numArithInstr[j]; i++) {
> -	 GLuint op0 = curProg->Instructions[j][i].Opcode[0];
> -	 GLuint op1 = curProg->Instructions[j][i].Opcode[1];
> +      for (i = 0; i < curProg->ati.numArithInstr[j]; i++) {
> +	 GLuint op0 = curProg->ati.Instructions[j][i].Opcode[0];
> +	 GLuint op1 = curProg->ati.Instructions[j][i].Opcode[1];
>   	 const char *op0_enum = op0 > 5 ? _mesa_enum_to_string(op0) : "0";
>   	 const char *op1_enum = op1 > 5 ? _mesa_enum_to_string(op1) : "0";
> -	 GLuint count0 = curProg->Instructions[j][i].ArgCount[0];
> -	 GLuint count1 = curProg->Instructions[j][i].ArgCount[1];
> +	 GLuint count0 = curProg->ati.Instructions[j][i].ArgCount[0];
> +	 GLuint count1 = curProg->ati.Instructions[j][i].ArgCount[1];
>   	 fprintf(stderr, "%2d %04X %s %d %04X %s %d\n", i, op0, op0_enum, count0,
>   	      op1, op1_enum, count1);
>         }
>      }
>   #endif
>   
> -   if (ctx->Driver.NewATIfs) {
> -      struct gl_program *prog = ctx->Driver.NewATIfs(ctx,
> -                                                     ctx->ATIFragmentShader.Current);
> -      _mesa_reference_program(ctx, &ctx->ATIFragmentShader.Current->Program, prog);
> -   }
> -
>      if (!ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_SHADER_ATI,
> -                                        curProg->Program)) {
> -      ctx->ATIFragmentShader.Current->isValid = GL_FALSE;
> +                                        curProg)) {
> +      ctx->ATIFragmentShader.Current->ati.isValid = GL_FALSE;
>         /* XXX is this the right error? */
>         _mesa_error(ctx, GL_INVALID_OPERATION,
>                     "glEndFragmentShaderATI(driver rejected shader)");
>      }
>   }
>   
>   void GLAPIENTRY
>   _mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle)
>   {
>      GET_CURRENT_CONTEXT(ctx);
> -   struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
> +   struct gl_program *curProg = ctx->ATIFragmentShader.Current;
>      struct atifs_setupinst *curI;
>   
>      if (!ctx->ATIFragmentShader.Compiling) {
>         _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(outsideShader)");
>         return;
>      }
>   
> -   if (curProg->cur_pass == 1) {
> +   if (curProg->ati.cur_pass == 1) {
>         match_pair_inst(curProg, 0);
> -      curProg->cur_pass = 2;
> +      curProg->ati.cur_pass = 2;
>      }
> -   if ((curProg->cur_pass > 2) ||
> -      ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[curProg->cur_pass >> 1])) {
> +   if ((curProg->ati.cur_pass > 2) ||
> +      ((1 << (dst - GL_REG_0_ATI)) & curProg->ati.regsAssigned[curProg->ati.cur_pass >> 1])) {
>         _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoord(pass)");
>         return;
>      }
>      if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) ||
>         ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) {
>         _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(dst)");
>         return;
>      }
>      if (((coord < GL_REG_0_ATI) || (coord > GL_REG_5_ATI)) &&
>          ((coord < GL_TEXTURE0_ARB) || (coord > GL_TEXTURE7_ARB) ||
>          ((coord - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) {
>         _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(coord)");
>         return;
>      }
> -   if ((curProg->cur_pass == 0) && (coord >= GL_REG_0_ATI)) {
> +   if ((curProg->ati.cur_pass == 0) && (coord >= GL_REG_0_ATI)) {
>         _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(coord)");
>         return;
>      }
>      if (!(swizzle >= GL_SWIZZLE_STR_ATI) && (swizzle <= GL_SWIZZLE_STQ_DQ_ATI)) {
>         _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(swizzle)");
>         return;
>      }
>      if ((swizzle & 1) && (coord >= GL_REG_0_ATI)) {
>         _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)");
>         return;
>      }
>      if (coord <= GL_TEXTURE7_ARB) {
>         GLuint tmp = coord - GL_TEXTURE0_ARB;
> -      if ((((curProg->swizzlerq >> (tmp * 2)) & 3) != 0) &&
> -	   (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (tmp * 2)) & 3))) {
> +      if ((((curProg->ati.swizzlerq >> (tmp * 2)) & 3) != 0) &&
> +	   (((swizzle & 1) + 1) != ((curProg->ati.swizzlerq >> (tmp * 2)) & 3))) {
>   	 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)");
>   	 return;
>         } else {
> -	 curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
> +	 curProg->ati.swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
>         }
>      }
>   
> -   curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
> +   curProg->ati.regsAssigned[curProg->ati.cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
>      new_tex_inst(curProg);
>   
>      /* add the instructions */
> -   curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
> +   curI = &curProg->ati.SetupInst[curProg->ati.cur_pass >> 1][dst - GL_REG_0_ATI];
>   
>      curI->Opcode = ATI_FRAGMENT_SHADER_PASS_OP;
>      curI->src = coord;
>      curI->swizzle = swizzle;
>   
>   #if MESA_DEBUG_ATI_FS
>      _mesa_debug(ctx, "%s(%s, %s, %s)\n", __func__,
>   	       _mesa_enum_to_string(dst), _mesa_enum_to_string(coord),
>   	       _mesa_enum_to_string(swizzle));
>   #endif
>   }
>   
>   void GLAPIENTRY
>   _mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle)
>   {
>      GET_CURRENT_CONTEXT(ctx);
> -   struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
> +   struct gl_program *curProg = ctx->ATIFragmentShader.Current;
>      struct atifs_setupinst *curI;
>   
>      if (!ctx->ATIFragmentShader.Compiling) {
>         _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(outsideShader)");
>         return;
>      }
>   
> -   if (curProg->cur_pass == 1) {
> +   if (curProg->ati.cur_pass == 1) {
>         match_pair_inst(curProg, 0);
> -      curProg->cur_pass = 2;
> +      curProg->ati.cur_pass = 2;
>      }
> -   if ((curProg->cur_pass > 2) ||
> -      ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[curProg->cur_pass >> 1])) {
> +   if ((curProg->ati.cur_pass > 2) ||
> +      ((1 << (dst - GL_REG_0_ATI)) & curProg->ati.regsAssigned[curProg->ati.cur_pass >> 1])) {
>         _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(pass)");
>         return;
>      }
>      if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) ||
>         ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) {
>         _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(dst)");
>         return;
>      }
>      if (((interp < GL_REG_0_ATI) || (interp > GL_REG_5_ATI)) &&
>          ((interp < GL_TEXTURE0_ARB) || (interp > GL_TEXTURE7_ARB) ||
>          ((interp - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) {
>      /* is this texture5 or texture7? spec is a bit unclear there */
>         _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(interp)");
>         return;
>      }
> -   if ((curProg->cur_pass == 0) && (interp >= GL_REG_0_ATI)) {
> +   if ((curProg->ati.cur_pass == 0) && (interp >= GL_REG_0_ATI)) {
>         _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(interp)");
>         return;
>      }
>      if (!(swizzle >= GL_SWIZZLE_STR_ATI) && (swizzle <= GL_SWIZZLE_STQ_DQ_ATI)) {
>         _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(swizzle)");
>         return;
>      }
>      if ((swizzle & 1) && (interp >= GL_REG_0_ATI)) {
>         _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
>         return;
>      }
>      if (interp <= GL_TEXTURE7_ARB) {
>         GLuint tmp = interp - GL_TEXTURE0_ARB;
> -      if ((((curProg->swizzlerq >> (tmp * 2)) & 3) != 0) &&
> -	   (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (tmp * 2)) & 3))) {
> +      if ((((curProg->ati.swizzlerq >> (tmp * 2)) & 3) != 0) &&
> +	   (((swizzle & 1) + 1) != ((curProg->ati.swizzlerq >> (tmp * 2)) & 3))) {
>   	 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
>   	 return;
>         } else {
> -	 curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
> +	 curProg->ati.swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
>         }
>      }
>   
> -   curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
> +   curProg->ati.regsAssigned[curProg->ati.cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
>      new_tex_inst(curProg);
>   
>      /* add the instructions */
> -   curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
> +   curI = &curProg->ati.SetupInst[curProg->ati.cur_pass >> 1][dst - GL_REG_0_ATI];
>   
>      curI->Opcode = ATI_FRAGMENT_SHADER_SAMPLE_OP;
>      curI->src = interp;
>      curI->swizzle = swizzle;
>   
>   #if MESA_DEBUG_ATI_FS
>      _mesa_debug(ctx, "%s(%s, %s, %s)\n", __func__,
>   	       _mesa_enum_to_string(dst), _mesa_enum_to_string(interp),
>   	       _mesa_enum_to_string(swizzle));
>   #endif
>   }
>   
>   static void
>   _mesa_FragmentOpXATI(GLint optype, GLuint arg_count, GLenum op, GLuint dst,
>   		     GLuint dstMask, GLuint dstMod, GLuint arg1,
>   		     GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
>   		     GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
>   		     GLuint arg3Rep, GLuint arg3Mod)
>   {
>      GET_CURRENT_CONTEXT(ctx);
> -   struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
> +   struct gl_program *curProg = ctx->ATIFragmentShader.Current;
>      GLint ci;
>      struct atifs_instruction *curI;
>      GLuint modtemp = dstMod & ~GL_SATURATE_BIT_ATI;
>   
>      if (!ctx->ATIFragmentShader.Compiling) {
>         _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(outsideShader)");
>         return;
>      }
>   
> -   if (curProg->cur_pass==0)
> -      curProg->cur_pass=1;
> +   if (curProg->ati.cur_pass==0)
> +      curProg->ati.cur_pass=1;
>   
> -   else if (curProg->cur_pass==2)
> -      curProg->cur_pass=3;
> +   else if (curProg->ati.cur_pass==2)
> +      curProg->ati.cur_pass=3;
>   
>      /* decide whether this is a new instruction or not ... all color instructions are new,
>         and alpha instructions might also be new if there was no preceding color inst */
> -   if ((optype == 0) || (curProg->last_optype == optype)) {
> -      if (curProg->numArithInstr[curProg->cur_pass >> 1] > 7) {
> +   if ((optype == 0) || (curProg->ati.last_optype == optype)) {
> +      if (curProg->ati.numArithInstr[curProg->ati.cur_pass >> 1] > 7) {
>   	 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(instrCount)");
>   	 return;
>         }
>         /* easier to do that here slight side effect invalid instr will still be inserted as nops */
>         match_pair_inst(curProg, optype);
>         new_arith_inst(curProg);
>      }
> -   curProg->last_optype = optype;
> -   ci = curProg->numArithInstr[curProg->cur_pass >> 1] - 1;
> +   curProg->ati.last_optype = optype;
> +   ci = curProg->ati.numArithInstr[curProg->ati.cur_pass >> 1] - 1;
>   
>      /* add the instructions */
> -   curI = &curProg->Instructions[curProg->cur_pass >> 1][ci];
> +   curI = &curProg->ati.Instructions[curProg->ati.cur_pass >> 1][ci];
>   
>      /* error checking */
>      if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI)) {
>         _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dst)");
>         return;
>      }
>      if ((modtemp != GL_NONE) && (modtemp != GL_2X_BIT_ATI) &&
>         (modtemp != GL_4X_BIT_ATI) && (modtemp != GL_8X_BIT_ATI) &&
>         (modtemp != GL_HALF_BIT_ATI) && !(modtemp != GL_QUARTER_BIT_ATI) &&
>         (modtemp != GL_EIGHTH_BIT_ATI)) {
> @@ -765,19 +750,19 @@ _mesa_SetFragmentShaderConstantATI(GLuint dst, const GLfloat * value)
>      GET_CURRENT_CONTEXT(ctx);
>   
>      if ((dst < GL_CON_0_ATI) || (dst > GL_CON_7_ATI)) {
>         /* spec says nothing about what should happen here but we can't just segfault...*/
>         _mesa_error(ctx, GL_INVALID_ENUM, "glSetFragmentShaderConstantATI(dst)");
>         return;
>      }
>   
>      dstindex = dst - GL_CON_0_ATI;
>      if (ctx->ATIFragmentShader.Compiling) {
> -      struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
> -      COPY_4V(curProg->Constants[dstindex], value);
> -      curProg->LocalConstDef |= 1 << dstindex;
> +      struct gl_program *curProg = ctx->ATIFragmentShader.Current;
> +      COPY_4V(curProg->ati.Constants[dstindex], value);
> +      curProg->ati.LocalConstDef |= 1 << dstindex;
>      }
>      else {
>         FLUSH_VERTICES(ctx, _NEW_PROGRAM);
>         COPY_4V(ctx->ATIFragmentShader.GlobalConstants[dstindex], value);
>      }
>   }
> diff --git a/src/mesa/main/atifragshader.h b/src/mesa/main/atifragshader.h
> index 0e32795da3..492e6db705 100644
> --- a/src/mesa/main/atifragshader.h
> +++ b/src/mesa/main/atifragshader.h
> @@ -55,26 +55,26 @@ struct atifs_instruction
>   
>   /* different from arithmetic shader instruction */
>   struct atifs_setupinst
>   {
>      GLenum Opcode;
>      GLuint src;
>      GLenum swizzle;
>   };
>   
>   
> -extern struct ati_fragment_shader *
> +extern struct gl_program *
>   _mesa_new_ati_fragment_shader(struct gl_context *ctx, GLuint id);
>   
>   extern void
>   _mesa_delete_ati_fragment_shader(struct gl_context *ctx,
> -                                 struct ati_fragment_shader *s);
> +                                 struct gl_program *s);
>   
>   
>   extern GLuint GLAPIENTRY _mesa_GenFragmentShadersATI(GLuint range);
>   
>   extern void GLAPIENTRY _mesa_BindFragmentShaderATI(GLuint id);
>   
>   extern void GLAPIENTRY _mesa_DeleteFragmentShaderATI(GLuint id);
>   
>   extern void GLAPIENTRY _mesa_BeginFragmentShaderATI(void);
>   
> diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h
> index da03b2e8b9..1d77145942 100644
> --- a/src/mesa/main/dd.h
> +++ b/src/mesa/main/dd.h
> @@ -452,25 +452,21 @@ struct dd_function_table {
>   
>      /**
>       * \name Vertex/fragment program functions
>       */
>      /*@{*/
>      /** Allocate a new program */
>      struct gl_program * (*NewProgram)(struct gl_context *ctx, GLenum target,
>                                        GLuint id, bool is_arb_asm);
>      /** Delete a program */
>      void (*DeleteProgram)(struct gl_context *ctx, struct gl_program *prog);
> -   /**
> -    * Allocate a program to associate with the new ATI fragment shader (optional)
> -    */
> -   struct gl_program * (*NewATIfs)(struct gl_context *ctx,
> -                                   struct ati_fragment_shader *curProg);
> +
>      /**
>       * Notify driver that a program string (and GPU code) has been specified
>       * or modified.  Return GL_TRUE or GL_FALSE to indicate if the program is
>       * supported by the driver.
>       */
>      GLboolean (*ProgramStringNotify)(struct gl_context *ctx, GLenum target,
>                                       struct gl_program *prog);
>   
>      /**
>       * Notify driver that the sampler uniforms for the current program have
> diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
> index 6b5c5bbb36..7c357b07ee 100644
> --- a/src/mesa/main/mtypes.h
> +++ b/src/mesa/main/mtypes.h
> @@ -2058,20 +2058,27 @@ typedef enum
>      PROGRAM_UNDEFINED,   /**< Invalid/TBD value */
>      PROGRAM_IMMEDIATE,   /**< Immediate value, used by TGSI */
>      PROGRAM_BUFFER,      /**< for shader buffers, compile-time only */
>      PROGRAM_MEMORY,      /**< for shared, global and local memory */
>      PROGRAM_IMAGE,       /**< for shader images, compile-time only */
>      PROGRAM_HW_ATOMIC,   /**< for hw atomic counters, compile-time only */
>      PROGRAM_FILE_MAX
>   } gl_register_file;
>   
>   
> +/**
> + * ATI_fragment_shader runtime state
> + */
> +struct atifs_instruction;
> +struct atifs_setupinst;
> +
> +
>   /**
>    * Base class for any kind of program object
>    */
>   struct gl_program
>   {
>      /** FIXME: This must be first until we split shader_info from nir_shader */
>      struct shader_info info;
>   
>      GLuint Id;
>      GLint RefCount;
> @@ -2236,20 +2243,37 @@ struct gl_program
>            GLuint NumNativeAluInstructions;
>            GLuint NumNativeTexInstructions;
>            GLuint NumNativeTexIndirections;
>            /*@}*/
>   
>            /** Used by ARB assembly-style programs. Can only be true for vertex
>             * programs.
>             */
>            GLboolean IsPositionInvariant;
>         } arb;
> +
> +      /**  ATI fragment shader fields */
> +      struct {
> +         struct atifs_instruction *Instructions[2];
> +         struct atifs_setupinst *SetupInst[2];
> +         GLfloat Constants[8][4];
> +         /** Indicates which constants have been set */
> +         GLbitfield LocalConstDef;
> +         GLubyte numArithInstr[2];
> +         GLubyte regsAssigned[2];
> +         GLubyte NumPasses;         /**< 1 or 2 */
> +         GLubyte cur_pass;
> +         GLubyte last_optype;
> +         GLboolean interpinp1;
> +         GLboolean isValid;
> +         GLuint swizzlerq;
> +      } ati;
>      };
>   };
>   
>   
>   /**
>    * State common to vertex and fragment programs.
>    */
>   struct gl_program_state
>   {
>      GLint ErrorPos;                       /* GL_PROGRAM_ERROR_POSITION_ARB/NV */
> @@ -2352,58 +2376,29 @@ struct gl_fragment_program_state
>    */
>   struct gl_compute_program_state
>   {
>      /** Currently enabled and valid program (including internal programs
>       * and compiled shader programs).
>       */
>      struct gl_program *_Current;
>   };
>   
>   
> -/**
> - * ATI_fragment_shader runtime state
> - */
> -
> -struct atifs_instruction;
> -struct atifs_setupinst;
> -
> -/**
> - * ATI fragment shader
> - */
> -struct ati_fragment_shader
> -{
> -   GLuint Id;
> -   GLint RefCount;
> -   struct atifs_instruction *Instructions[2];
> -   struct atifs_setupinst *SetupInst[2];
> -   GLfloat Constants[8][4];
> -   GLbitfield LocalConstDef;  /**< Indicates which constants have been set */
> -   GLubyte numArithInstr[2];
> -   GLubyte regsAssigned[2];
> -   GLubyte NumPasses;         /**< 1 or 2 */
> -   GLubyte cur_pass;
> -   GLubyte last_optype;
> -   GLboolean interpinp1;
> -   GLboolean isValid;
> -   GLuint swizzlerq;
> -   struct gl_program *Program;
> -};
> -
>   /**
>    * Context state for GL_ATI_fragment_shader
>    */
>   struct gl_ati_fragment_shader_state
>   {
>      GLboolean Enabled;
>      GLboolean Compiling;
>      GLfloat GlobalConstants[8][4];
> -   struct ati_fragment_shader *Current;
> +   struct gl_program *Current;
>   };
>   
>   /**
>    *  Shader subroutine function definition
>    */
>   struct gl_subroutine_function
>   {
>      char *name;
>      int index;
>      int num_compat_types;
> @@ -3250,21 +3245,21 @@ struct gl_shared_state
>       * \name Vertex/geometry/fragment programs
>       */
>      /*@{*/
>      struct _mesa_HashTable *Programs; /**< All vertex/fragment programs */
>      struct gl_program *DefaultVertexProgram;
>      struct gl_program *DefaultFragmentProgram;
>      /*@}*/
>   
>      /* GL_ATI_fragment_shader */
>      struct _mesa_HashTable *ATIShaders;
> -   struct ati_fragment_shader *DefaultFragmentShader;
> +   struct gl_program *DefaultFragmentShader;
>   
>      struct _mesa_HashTable *BufferObjects;
>   
>      /** Table of both gl_shader and gl_shader_program objects */
>      struct _mesa_HashTable *ShaderObjects;
>   
>      /* GL_EXT_framebuffer_object */
>      struct _mesa_HashTable *RenderBuffers;
>      struct _mesa_HashTable *FrameBuffers;
>   
> diff --git a/src/mesa/main/shared.c b/src/mesa/main/shared.c
> index e3417a4df3..94148e5122 100644
> --- a/src/mesa/main/shared.c
> +++ b/src/mesa/main/shared.c
> @@ -196,21 +196,21 @@ delete_program_cb(GLuint id, void *data, void *userData)
>   }
>   
>   
>   /**
>    * Callback for deleting an ATI fragment shader object.
>    * Called by _mesa_HashDeleteAll().
>    */
>   static void
>   delete_fragshader_cb(GLuint id, void *data, void *userData)
>   {
> -   struct ati_fragment_shader *shader = (struct ati_fragment_shader *) data;
> +   struct gl_program *shader = (struct gl_program *) data;
>      struct gl_context *ctx = (struct gl_context *) userData;
>      _mesa_delete_ati_fragment_shader(ctx, shader);
>   }
>   
>   
>   /**
>    * Callback for deleting a buffer object.  Called by _mesa_HashDeleteAll().
>    */
>   static void
>   delete_bufferobj_cb(GLuint id, void *data, void *userData)
> diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c
> index 7aec98e578..508cb57e7a 100644
> --- a/src/mesa/main/state.c
> +++ b/src/mesa/main/state.c
> @@ -115,24 +115,24 @@ update_program(struct gl_context *ctx)
>                                 NULL);
>      }
>      else if (_mesa_arb_fragment_program_enabled(ctx)) {
>         /* Use user-defined fragment program */
>         _mesa_reference_program(ctx, &ctx->FragmentProgram._Current,
>                                 ctx->FragmentProgram.Current);
>         _mesa_reference_program(ctx, &ctx->FragmentProgram._TexEnvProgram,
>   			      NULL);
>      }
>      else if (_mesa_ati_fragment_shader_enabled(ctx) &&
> -            ctx->ATIFragmentShader.Current->Program) {
> +            ctx->ATIFragmentShader.Current) {
>          /* Use the enabled ATI fragment shader's associated program */
>         _mesa_reference_program(ctx, &ctx->FragmentProgram._Current,
> -                              ctx->ATIFragmentShader.Current->Program);
> +                              ctx->ATIFragmentShader.Current);
>         _mesa_reference_program(ctx, &ctx->FragmentProgram._TexEnvProgram,
>                                 NULL);
>      }
>      else if (ctx->FragmentProgram._MaintainTexEnvProgram) {
>         /* Use fragment program generated from fixed-function state */
>         struct gl_shader_program *f = _mesa_get_fixed_func_fragment_program(ctx);
>   
>         _mesa_reference_program(ctx, &ctx->FragmentProgram._Current,
>   			      f->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program);
>         _mesa_reference_program(ctx, &ctx->FragmentProgram._TexEnvProgram,
> diff --git a/src/mesa/main/state.h b/src/mesa/main/state.h
> index b719f39296..beee001381 100644
> --- a/src/mesa/main/state.h
> +++ b/src/mesa/main/state.h
> @@ -104,14 +104,14 @@ static inline bool
>   _mesa_arb_fragment_program_enabled(const struct gl_context *ctx)
>   {
>      return ctx->FragmentProgram.Enabled &&
>             ctx->FragmentProgram.Current->arb.Instructions;
>   }
>   
>   static inline bool
>   _mesa_ati_fragment_shader_enabled(const struct gl_context *ctx)
>   {
>      return ctx->ATIFragmentShader.Enabled &&
> -          ctx->ATIFragmentShader.Current->Instructions[0];
> +          ctx->ATIFragmentShader.Current->ati.Instructions[0];
>   }
>   
>   #endif
> diff --git a/src/mesa/program/program.c b/src/mesa/program/program.c
> index faf5b7fa28..7f88cbed54 100644
> --- a/src/mesa/program/program.c
> +++ b/src/mesa/program/program.c
> @@ -147,21 +147,21 @@ _mesa_update_default_objects_program(struct gl_context *ctx)
>                               ctx->Shared->DefaultFragmentProgram);
>      assert(ctx->FragmentProgram.Current);
>   
>      /* XXX probably move this stuff */
>      if (ctx->ATIFragmentShader.Current) {
>         ctx->ATIFragmentShader.Current->RefCount--;
>         if (ctx->ATIFragmentShader.Current->RefCount <= 0) {
>            free(ctx->ATIFragmentShader.Current);
>         }
>      }
> -   ctx->ATIFragmentShader.Current = (struct ati_fragment_shader *) ctx->Shared->DefaultFragmentShader;
> +   ctx->ATIFragmentShader.Current = ctx->Shared->DefaultFragmentShader;
>      assert(ctx->ATIFragmentShader.Current);
>      ctx->ATIFragmentShader.Current->RefCount++;
>   }
>   
>   
>   /**
>    * Set the vertex/fragment program error state (position and error string).
>    * This is generally called from within the parsers.
>    */
>   void
> @@ -229,20 +229,21 @@ _mesa_init_gl_program(struct gl_program *prog, GLenum target, GLuint id,
>   struct gl_program *
>   _mesa_new_program(struct gl_context *ctx, GLenum target, GLuint id,
>                     bool is_arb_asm)
>   {
>      switch (target) {
>      case GL_VERTEX_PROGRAM_ARB: /* == GL_VERTEX_PROGRAM_NV */
>      case GL_GEOMETRY_PROGRAM_NV:
>      case GL_TESS_CONTROL_PROGRAM_NV:
>      case GL_TESS_EVALUATION_PROGRAM_NV:
>      case GL_FRAGMENT_PROGRAM_ARB:
> +   case GL_FRAGMENT_SHADER_ATI:
>      case GL_COMPUTE_PROGRAM_NV: {
>         struct gl_program *prog = rzalloc(NULL, struct gl_program);
>         return _mesa_init_gl_program(prog, target, id, is_arb_asm);
>      }
>      default:
>         _mesa_problem(ctx, "bad target in _mesa_new_program");
>         return NULL;
>      }
>   }
>   
> diff --git a/src/mesa/state_tracker/st_atifs_to_tgsi.c b/src/mesa/state_tracker/st_atifs_to_tgsi.c
> index 8affbdc8d1..0bd082e6ff 100644
> --- a/src/mesa/state_tracker/st_atifs_to_tgsi.c
> +++ b/src/mesa/state_tracker/st_atifs_to_tgsi.c
> @@ -30,21 +30,21 @@
>   #include "tgsi/tgsi_transform.h"
>   
>   #include "st_program.h"
>   #include "st_atifs_to_tgsi.h"
>   
>   /**
>    * Intermediate state used during shader translation.
>    */
>   struct st_translate {
>      struct ureg_program *ureg;
> -   struct ati_fragment_shader *atifs;
> +   struct gl_program *atifs;
>   
>      struct ureg_dst temps[MAX_PROGRAM_TEMPS];
>      struct ureg_src *constants;
>      struct ureg_dst outputs[PIPE_MAX_SHADER_OUTPUTS];
>      struct ureg_src inputs[PIPE_MAX_SHADER_INPUTS];
>      struct ureg_src samplers[PIPE_MAX_SAMPLERS];
>   
>      const ubyte *inputMapping;
>      const ubyte *outputMapping;
>   
> @@ -414,21 +414,20 @@ finalize_shader(struct st_translate *t, unsigned numPasses)
>      ureg_insn(t->ureg, TGSI_OPCODE_END, dst, 0, src, 0, 0);
>   }
>   
>   /**
>    * Called when a new variant is needed, we need to translate
>    * the ATI fragment shader to TGSI
>    */
>   enum pipe_error
>   st_translate_atifs_program(
>      struct ureg_program *ureg,
> -   struct ati_fragment_shader *atifs,
>      struct gl_program *program,
>      GLuint numInputs,
>      const ubyte inputMapping[],
>      const ubyte inputSemanticName[],
>      const ubyte inputSemanticIndex[],
>      const ubyte interpMode[],
>      GLuint numOutputs,
>      const ubyte outputMapping[],
>      const ubyte outputSemanticName[],
>      const ubyte outputSemanticIndex[])
> @@ -437,21 +436,20 @@ st_translate_atifs_program(
>   
>      unsigned pass, i, r;
>   
>      struct st_translate translate, *t;
>      t = &translate;
>      memset(t, 0, sizeof *t);
>   
>      t->inputMapping = inputMapping;
>      t->outputMapping = outputMapping;
>      t->ureg = ureg;
> -   t->atifs = atifs;
>   
>      /*
>       * Declare input attributes.
>       */
>      for (i = 0; i < numInputs; i++) {
>         t->inputs[i] = ureg_DECL_fs_input(ureg,
>                                           inputSemanticName[i],
>                                           inputSemanticIndex[i],
>                                           interpMode[i]);
>      }
> @@ -500,90 +498,86 @@ st_translate_atifs_program(
>            /* the texture target is still unknown, it will be fixed in the draw call */
>            ureg_DECL_sampler_view(ureg, i, TGSI_TEXTURE_2D,
>                                   TGSI_RETURN_TYPE_FLOAT,
>                                   TGSI_RETURN_TYPE_FLOAT,
>                                   TGSI_RETURN_TYPE_FLOAT,
>                                   TGSI_RETURN_TYPE_FLOAT);
>         }
>      }
>   
>      /* emit instructions */
> -   for (pass = 0; pass < atifs->NumPasses; pass++) {
> +   for (pass = 0; pass < program->ati.NumPasses; pass++) {
>         t->current_pass = pass;
>         for (r = 0; r < MAX_NUM_FRAGMENT_REGISTERS_ATI; r++) {
> -         struct atifs_setupinst *texinst = &atifs->SetupInst[pass][r];
> +         struct atifs_setupinst *texinst = &program->ati.SetupInst[pass][r];
>            compile_setupinst(t, r, texinst);
>         }
> -      for (i = 0; i < atifs->numArithInstr[pass]; i++) {
> -         struct atifs_instruction *inst = &atifs->Instructions[pass][i];
> +      for (i = 0; i < program->ati.numArithInstr[pass]; i++) {
> +         struct atifs_instruction *inst = &program->ati.Instructions[pass][i];
>            compile_instruction(t, inst);
>         }
>      }
>   
> -   finalize_shader(t, atifs->NumPasses);
> +   finalize_shader(t, program->ati.NumPasses);
>   
>   out:
>      free(t->constants);
>   
>      if (t->error) {
>         debug_printf("%s: translate error flag set\n", __func__);
>      }
>   
>      return ret;
>   }
>   
>   /**
>    * Called in ProgramStringNotify, we need to fill the metadata of the
>    * gl_program attached to the ati_fragment_shader
>    */
>   void
>   st_init_atifs_prog(struct gl_context *ctx, struct gl_program *prog)
>   {
> -   /* we know this is st_fragment_program, because of st_new_ati_fs() */
> -   struct st_fragment_program *stfp = (struct st_fragment_program *) prog;
> -   struct ati_fragment_shader *atifs = stfp->ati_fs;
> -
>      unsigned pass, i, r, optype, arg;
>   
>      static const gl_state_index fog_params_state[STATE_LENGTH] =
>         {STATE_INTERNAL, STATE_FOG_PARAMS_OPTIMIZED, 0, 0, 0};
>      static const gl_state_index fog_color[STATE_LENGTH] =
>         {STATE_FOG_COLOR, 0, 0, 0, 0};
>   
>      prog->info.inputs_read = 0;
>      prog->info.outputs_written = BITFIELD64_BIT(FRAG_RESULT_COLOR);
>      prog->SamplersUsed = 0;
>      prog->Parameters = _mesa_new_parameter_list();
>   
>      /* fill in inputs_read, SamplersUsed, TexturesUsed */
> -   for (pass = 0; pass < atifs->NumPasses; pass++) {
> +   for (pass = 0; pass < prog->ati.NumPasses; pass++) {
>         for (r = 0; r < MAX_NUM_FRAGMENT_REGISTERS_ATI; r++) {
> -         struct atifs_setupinst *texinst = &atifs->SetupInst[pass][r];
> +         struct atifs_setupinst *texinst = &prog->ati.SetupInst[pass][r];
>            GLuint pass_tex = texinst->src;
>   
>            if (texinst->Opcode == ATI_FRAGMENT_SHADER_SAMPLE_OP) {
>               /* mark which texcoords are used */
>               prog->info.inputs_read |= BITFIELD64_BIT(VARYING_SLOT_TEX0 + pass_tex - GL_TEXTURE0_ARB);
>               /* by default there is 1:1 mapping between samplers and textures */
>               prog->SamplersUsed |= (1 << r);
>               /* the target is unknown here, it will be fixed in the draw call */
>               prog->TexturesUsed[r] = TEXTURE_2D_BIT;
>            } else if (texinst->Opcode == ATI_FRAGMENT_SHADER_PASS_OP) {
>               if (pass_tex >= GL_TEXTURE0_ARB && pass_tex <= GL_TEXTURE7_ARB) {
>                  prog->info.inputs_read |= BITFIELD64_BIT(VARYING_SLOT_TEX0 + pass_tex - GL_TEXTURE0_ARB);
>               }
>            }
>         }
>      }
> -   for (pass = 0; pass < atifs->NumPasses; pass++) {
> -      for (i = 0; i < atifs->numArithInstr[pass]; i++) {
> -         struct atifs_instruction *inst = &atifs->Instructions[pass][i];
> +   for (pass = 0; pass < prog->ati.NumPasses; pass++) {
> +      for (i = 0; i < prog->ati.numArithInstr[pass]; i++) {
> +         struct atifs_instruction *inst = &prog->ati.Instructions[pass][i];
>   
>            for (optype = 0; optype < 2; optype++) { /* color, alpha */
>               if (inst->Opcode[optype]) {
>                  for (arg = 0; arg < inst->ArgCount[optype]; arg++) {
>                     GLint index = inst->SrcReg[optype][arg].Index;
>                     if (index == GL_PRIMARY_COLOR_EXT) {
>                        prog->info.inputs_read |= BITFIELD64_BIT(VARYING_SLOT_COL0);
>                     } else if (index == GL_SECONDARY_INTERPOLATOR_ATI) {
>                        /* note: ATI_fragment_shader.txt never specifies what
>                         * GL_SECONDARY_INTERPOLATOR_ATI is, swrast uses
> diff --git a/src/mesa/state_tracker/st_atifs_to_tgsi.h b/src/mesa/state_tracker/st_atifs_to_tgsi.h
> index ce547911cf..f532c654f6 100644
> --- a/src/mesa/state_tracker/st_atifs_to_tgsi.h
> +++ b/src/mesa/state_tracker/st_atifs_to_tgsi.h
> @@ -27,27 +27,25 @@
>   #include "pipe/p_defines.h"
>   
>   #if defined __cplusplus
>   extern "C" {
>   #endif
>   
>   struct gl_context;
>   struct gl_program;
>   struct ureg_program;
>   struct tgsi_token;
> -struct ati_fragment_shader;
>   struct st_fp_variant_key;
>   
>   enum pipe_error
>   st_translate_atifs_program(
>       struct ureg_program *ureg,
> -    struct ati_fragment_shader *atifs,
>       struct gl_program *program,
>       GLuint numInputs,
>       const ubyte inputMapping[],
>       const ubyte inputSemanticName[],
>       const ubyte inputSemanticIndex[],
>       const ubyte interpMode[],
>       GLuint numOutputs,
>       const ubyte outputMapping[],
>       const ubyte outputSemanticName[],
>       const ubyte outputSemanticIndex[]);
> diff --git a/src/mesa/state_tracker/st_atom_constbuf.c b/src/mesa/state_tracker/st_atom_constbuf.c
> index 497d33fc34..910370b785 100644
> --- a/src/mesa/state_tracker/st_atom_constbuf.c
> +++ b/src/mesa/state_tracker/st_atom_constbuf.c
> @@ -59,28 +59,29 @@ void st_upload_constants(struct st_context *st, struct gl_program *prog)
>      enum pipe_shader_type shader_type = pipe_shader_type_from_mesa(stage);
>   
>      assert(shader_type == PIPE_SHADER_VERTEX ||
>             shader_type == PIPE_SHADER_FRAGMENT ||
>             shader_type == PIPE_SHADER_GEOMETRY ||
>             shader_type == PIPE_SHADER_TESS_CTRL ||
>             shader_type == PIPE_SHADER_TESS_EVAL ||
>             shader_type == PIPE_SHADER_COMPUTE);
>   
>      /* update the ATI constants before rendering */
> -   if (shader_type == PIPE_SHADER_FRAGMENT && st->fp->ati_fs) {
> -      struct ati_fragment_shader *ati_fs = st->fp->ati_fs;
> +   if (shader_type == PIPE_SHADER_FRAGMENT &&
> +       st->fp->Base.Target == GL_FRAGMENT_SHADER_ATI) {
> +      struct gl_program *ati_fs = &st->fp->Base;
>         unsigned c;
>   
>         for (c = 0; c < MAX_NUM_FRAGMENT_CONSTANTS_ATI; c++) {
> -         if (ati_fs->LocalConstDef & (1 << c))
> +         if (ati_fs->ati.LocalConstDef & (1 << c))
>               memcpy(params->ParameterValues[c],
> -                   ati_fs->Constants[c], sizeof(GLfloat) * 4);
> +                   ati_fs->ati.Constants[c], sizeof(GLfloat) * 4);
>            else
>               memcpy(params->ParameterValues[c],
>                      st->ctx->ATIFragmentShader.GlobalConstants[c], sizeof(GLfloat) * 4);
>         }
>      }
>   
>      /* Make all bindless samplers/images bound texture/image units resident in
>       * the context.
>       */
>      st_make_bound_samplers_resident(st, prog);
> diff --git a/src/mesa/state_tracker/st_atom_shader.c b/src/mesa/state_tracker/st_atom_shader.c
> index c6faa3f07f..1b1205cfb2 100644
> --- a/src/mesa/state_tracker/st_atom_shader.c
> +++ b/src/mesa/state_tracker/st_atom_shader.c
> @@ -94,26 +94,28 @@ get_texture_target(struct gl_context *ctx, const unsigned unit)
>    * Mesa fragment program into a gallium fragment program and binding it.
>    */
>   void
>   st_update_fp( struct st_context *st )
>   {
>      struct st_fragment_program *stfp;
>      struct st_fp_variant_key key;
>   
>      assert(st->ctx->FragmentProgram._Current);
>      stfp = st_fragment_program(st->ctx->FragmentProgram._Current);
> -   assert(stfp->Base.Target == GL_FRAGMENT_PROGRAM_ARB);
> +   assert(stfp->Base.Target == GL_FRAGMENT_PROGRAM_ARB ||
> +          stfp->Base.Target == GL_FRAGMENT_SHADER_ATI);
>   
>      void *shader;
>   
>      if (st->shader_has_one_variant[MESA_SHADER_FRAGMENT] &&
> -       !stfp->ati_fs && /* ATI_fragment_shader always has multiple variants */
> +       /* ATI_fragment_shader always has multiple variants */
> +       stfp->Base.Target != GL_FRAGMENT_SHADER_ATI &&
>          !stfp->Base.ExternalSamplersUsed && /* external samplers need variants */
>          stfp->variants &&
>          !stfp->variants->key.drawpixels &&
>          !stfp->variants->key.bitmap) {
>         shader = stfp->variants->driver_shader;
>      } else {
>         memset(&key, 0, sizeof(key));
>         key.st = st->has_shareable_shaders ? NULL : st;
>   
>         /* _NEW_FRAG_CLAMP */
> @@ -121,21 +123,21 @@ st_update_fp( struct st_context *st )
>                           st->ctx->Color._ClampFragmentColor;
>   
>         /* _NEW_MULTISAMPLE | _NEW_BUFFERS */
>         key.persample_shading =
>            st->force_persample_in_shader &&
>            _mesa_is_multisample_enabled(st->ctx) &&
>            st->ctx->Multisample.SampleShading &&
>            st->ctx->Multisample.MinSampleShadingValue *
>            _mesa_geometric_samples(st->ctx->DrawBuffer) > 1;
>   
> -      if (stfp->ati_fs) {
> +      if (stfp->Base.Target == GL_FRAGMENT_SHADER_ATI) {
>            key.fog = st->ctx->Fog._PackedEnabledMode;
>   
>            for (unsigned u = 0; u < MAX_NUM_FRAGMENT_REGISTERS_ATI; u++) {
>               key.texture_targets[u] = get_texture_target(st->ctx, u);
>            }
>         }
>   
>         key.external = st_get_external_sampler_key(st, &stfp->Base);
>   
>         shader = st_get_fp_variant(st, stfp, &key)->driver_shader;
> diff --git a/src/mesa/state_tracker/st_cb_program.c b/src/mesa/state_tracker/st_cb_program.c
> index 555fc5d5ad..062812c939 100644
> --- a/src/mesa/state_tracker/st_cb_program.c
> +++ b/src/mesa/state_tracker/st_cb_program.c
> @@ -56,20 +56,21 @@
>   static struct gl_program *
>   st_new_program(struct gl_context *ctx, GLenum target, GLuint id,
>                  bool is_arb_asm)
>   {
>      switch (target) {
>      case GL_VERTEX_PROGRAM_ARB: {
>         struct st_vertex_program *prog = rzalloc(NULL,
>                                                  struct st_vertex_program);
>         return _mesa_init_gl_program(&prog->Base, target, id, is_arb_asm);
>      }
> +   case GL_FRAGMENT_SHADER_ATI:
>      case GL_FRAGMENT_PROGRAM_ARB: {
>         struct st_fragment_program *prog = rzalloc(NULL,
>                                                    struct st_fragment_program);
>         return _mesa_init_gl_program(&prog->Base, target, id, is_arb_asm);
>      }
>      case GL_TESS_CONTROL_PROGRAM_NV:
>      case GL_TESS_EVALUATION_PROGRAM_NV:
>      case GL_GEOMETRY_PROGRAM_NV: {
>         struct st_common_program *prog = rzalloc(NULL,
>                                                  struct st_common_program);
> @@ -111,20 +112,21 @@ st_delete_program(struct gl_context *ctx, struct gl_program *prog)
>         {
>            struct st_common_program *p = st_common_program(prog);
>   
>            st_release_basic_variants(st, p->Base.Target, &p->variants,
>                                      &p->tgsi);
>            
>            if (p->glsl_to_tgsi)
>               free_glsl_to_tgsi_visitor(p->glsl_to_tgsi);
>         }
>         break;
> +   case GL_FRAGMENT_SHADER_ATI:
>      case GL_FRAGMENT_PROGRAM_ARB:
>         {
>            struct st_fragment_program *stfp =
>               (struct st_fragment_program *) prog;
>   
>            st_release_fp_variants(st, stfp);
>            
>            if (stfp->glsl_to_tgsi)
>               free_glsl_to_tgsi_visitor(stfp->glsl_to_tgsi);
>         }
> @@ -225,57 +227,41 @@ st_program_string_notify( struct gl_context *ctx,
>         if (!st_translate_compute_program(st, stcp))
>            return false;
>   
>         if (st->cp == stcp)
>            st->dirty |= stcp->affected_states;
>      }
>      else if (target == GL_FRAGMENT_SHADER_ATI) {
>         assert(prog);
>   
>         struct st_fragment_program *stfp = (struct st_fragment_program *) prog;
> -      assert(stfp->ati_fs);
> -      assert(stfp->ati_fs->Program == prog);
> +      assert(stfp->Base.Target == GL_FRAGMENT_SHADER_ATI);
>   
>         st_init_atifs_prog(ctx, prog);
>   
>         st_release_fp_variants(st, stfp);
>         if (!st_translate_fragment_program(st, stfp))
>            return false;
>   
>         if (st->fp == stfp)
>            st->dirty |= stfp->affected_states;
>      }
>   
>      if (ST_DEBUG & DEBUG_PRECOMPILE ||
>          st->shader_has_one_variant[stage])
>         st_precompile_shader_variant(st, prog);
>   
>      return GL_TRUE;
>   }
>   
> -/**
> - * Called via ctx->Driver.NewATIfs()
> - * Called in glEndFragmentShaderATI()
> - */
> -static struct gl_program *
> -st_new_ati_fs(struct gl_context *ctx, struct ati_fragment_shader *curProg)
> -{
> -   struct gl_program *prog = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB,
> -         curProg->Id, true);
> -   struct st_fragment_program *stfp = (struct st_fragment_program *)prog;
> -   stfp->ati_fs = curProg;
> -   return prog;
> -}
> -
>   /**
>    * Plug in the program and shader-related device driver functions.
>    */
>   void
>   st_init_program_functions(struct dd_function_table *functions)
>   {
>      functions->NewProgram = st_new_program;
>      functions->DeleteProgram = st_delete_program;
>      functions->ProgramStringNotify = st_program_string_notify;
> -   functions->NewATIfs = st_new_ati_fs;
>      
>      functions->LinkShader = st_link_shader;
>   }
> diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c
> index e3649a8b7c..cdadd88ed0 100644
> --- a/src/mesa/state_tracker/st_program.c
> +++ b/src/mesa/state_tracker/st_program.c
> @@ -662,21 +662,21 @@ st_translate_fragment_program(struct st_context *st,
>   
>         /* This determines which states will be updated when the assembly
>          * shader is bound.
>          *
>          * fragment.position and glDrawPixels always use constants.
>          */
>         stfp->affected_states = ST_NEW_FS_STATE |
>                                 ST_NEW_SAMPLE_SHADING |
>                                 ST_NEW_FS_CONSTANTS;
>   
> -      if (stfp->ati_fs) {
> +      if (stfp->Base.Target == GL_FRAGMENT_SHADER_ATI) {
>            /* Just set them for ATI_fs unconditionally. */
>            stfp->affected_states |= ST_NEW_FS_SAMPLER_VIEWS |
>                                     ST_NEW_FS_SAMPLERS;
>         } else {
>            /* ARB_fp */
>            if (stfp->Base.SamplersUsed)
>               stfp->affected_states |= ST_NEW_FS_SAMPLER_VIEWS |
>                                        ST_NEW_FS_SAMPLERS;
>         }
>      }
> @@ -941,23 +941,22 @@ st_translate_fragment_program(struct st_context *st,
>                              input_semantic_name,
>                              input_semantic_index,
>                              interpMode,
>                              /* outputs */
>                              fs_num_outputs,
>                              outputMapping,
>                              fs_output_semantic_name,
>                              fs_output_semantic_index);
>   
>         free_glsl_to_tgsi_visitor(stfp->glsl_to_tgsi);
> -   } else if (stfp->ati_fs)
> +   } else if (stfp->Base.Target == GL_FRAGMENT_SHADER_ATI)
>         st_translate_atifs_program(ureg,
> -                                 stfp->ati_fs,
>                                    &stfp->Base,
>                                    /* inputs */
>                                    fs_num_inputs,
>                                    inputMapping,
>                                    input_semantic_name,
>                                    input_semantic_index,
>                                    interpMode,
>                                    /* outputs */
>                                    fs_num_outputs,
>                                    outputMapping,
> @@ -1091,21 +1090,21 @@ st_create_fp_variant(struct st_context *st,
>         variant->key = *key;
>   
>         return variant;
>      }
>   
>      tgsi.tokens = stfp->tgsi.tokens;
>   
>      assert(!(key->bitmap && key->drawpixels));
>   
>      /* Fix texture targets and add fog for ATI_fs */
> -   if (stfp->ati_fs) {
> +   if (stfp->Base.Target == GL_FRAGMENT_SHADER_ATI) {
>         const struct tgsi_token *tokens = st_fixup_atifs(tgsi.tokens, key);
>   
>         if (tokens)
>            tgsi.tokens = tokens;
>         else
>            fprintf(stderr, "mesa: cannot post-process ATI_fs\n");
>      }
>   
>      /* Emulate features. */
>      if (key->clamp_color || key->persample_shading) {
> diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h
> index 6049fba517..b834a1f368 100644
> --- a/src/mesa/state_tracker/st_program.h
> +++ b/src/mesa/state_tracker/st_program.h
> @@ -136,21 +136,20 @@ struct st_fp_variant
>   
>   
>   /**
>    * Derived from Mesa gl_program:
>    */
>   struct st_fragment_program
>   {
>      struct gl_program Base;
>      struct pipe_shader_state tgsi;
>      struct glsl_to_tgsi_visitor* glsl_to_tgsi;
> -   struct ati_fragment_shader *ati_fs;
>      uint64_t affected_states; /**< ST_NEW_* flags to mark dirty when binding */
>   
>      /* used when bypassing glsl_to_tgsi: */
>      struct gl_shader_program *shader_program;
>   
>      struct st_fp_variant *variants;
>   
>      /** SHA1 hash of linked tgsi shader program, used for on-disk cache */
>      unsigned char sha1[20];
>   };
> diff --git a/src/mesa/swrast/s_atifragshader.c b/src/mesa/swrast/s_atifragshader.c
> index 414a4144e2..21d480fee4 100644
> --- a/src/mesa/swrast/s_atifragshader.c
> +++ b/src/mesa/swrast/s_atifragshader.c
> @@ -292,62 +292,62 @@ do {						\
>   /**
>    * Execute the given fragment shader.
>    * NOTE: we do everything in single-precision floating point
>    * \param ctx - rendering context
>    * \param shader - the shader to execute
>    * \param machine - virtual machine state
>    * \param span - the SWspan we're operating on
>    * \param column - which pixel [i] we're operating on in the span
>    */
>   static void
> -execute_shader(struct gl_context *ctx, const struct ati_fragment_shader *shader,
> +execute_shader(struct gl_context *ctx, const struct gl_program *shader,
>   	       struct atifs_machine *machine, const SWspan *span,
>                  GLuint column)
>   {
>      GLuint pc;
>      struct atifs_instruction *inst;
>      struct atifs_setupinst *texinst;
>      GLint optype;
>      GLuint i;
>      GLint j, pass;
>      GLint dstreg;
>      GLfloat src[2][3][4];
>      GLfloat zeros[4] = { 0.0, 0.0, 0.0, 0.0 };
>      GLfloat ones[4] = { 1.0, 1.0, 1.0, 1.0 };
>      GLfloat dst[2][4], *dstp;
>   
> -   for (pass = 0; pass < shader->NumPasses; pass++) {
> +   for (pass = 0; pass < shader->ati.NumPasses; pass++) {
>         if (pass > 0)
>   	 finish_pass(machine);
>         for (j = 0; j < MAX_NUM_FRAGMENT_REGISTERS_ATI; j++) {
> -	 texinst = &shader->SetupInst[pass][j];
> +	 texinst = &shader->ati.SetupInst[pass][j];
>   	 if (texinst->Opcode == ATI_FRAGMENT_SHADER_PASS_OP)
>   	    handle_pass_op(machine, texinst, span, column, j);
>   	 else if (texinst->Opcode == ATI_FRAGMENT_SHADER_SAMPLE_OP)
>   	    handle_sample_op(ctx, machine, texinst, span, column, j);
>         }
>   
> -      for (pc = 0; pc < shader->numArithInstr[pass]; pc++) {
> -	 inst = &shader->Instructions[pass][pc];
> +      for (pc = 0; pc < shader->ati.numArithInstr[pass]; pc++) {
> +	 inst = &shader->ati.Instructions[pass][pc];
>   
>   	 /* setup the source registers for color and alpha ops */
>   	 for (optype = 0; optype < 2; optype++) {
>    	    for (i = 0; i < inst->ArgCount[optype]; i++) {
>   	       GLint index = inst->SrcReg[optype][i].Index;
>   
>   	       if (index >= GL_REG_0_ATI && index <= GL_REG_5_ATI)
>   		  SETUP_SRC_REG(optype, i,
>   				machine->Registers[index - GL_REG_0_ATI]);
>   	       else if (index >= GL_CON_0_ATI && index <= GL_CON_7_ATI) {
> -		  if (shader->LocalConstDef & (1 << (index - GL_CON_0_ATI))) {
> +		  if (shader->ati.LocalConstDef & (1 << (index - GL_CON_0_ATI))) {
>   		     SETUP_SRC_REG(optype, i,
> -				shader->Constants[index - GL_CON_0_ATI]);
> +				shader->ati.Constants[index - GL_CON_0_ATI]);
>   		  } else {
>   		     SETUP_SRC_REG(optype, i,
>   				ctx->ATIFragmentShader.GlobalConstants[index - GL_CON_0_ATI]);
>   		  }
>   	       }
>   	       else if (index == GL_ONE)
>   		  SETUP_SRC_REG(optype, i, ones);
>   	       else if (index == GL_ZERO)
>   		  SETUP_SRC_REG(optype, i, zeros);
>   	       else if (index == GL_PRIMARY_COLOR_EXT)
> @@ -537,21 +537,21 @@ execute_shader(struct gl_context *ctx, const struct ati_fragment_shader *shader,
>         }
>      }
>   }
>   
>   
>   /**
>    * Init fragment shader virtual machine state.
>    */
>   static void
>   init_machine(struct gl_context * ctx, struct atifs_machine *machine,
> -	     const struct ati_fragment_shader *shader,
> +	     const struct gl_program *shader,
>   	     const SWspan *span, GLuint col)
>   {
>      GLfloat (*inputs)[4] = machine->Inputs;
>      GLint i, j;
>   
>      for (i = 0; i < 6; i++) {
>         for (j = 0; j < 4; j++)
>   	 machine->Registers[i][j] = 0.0;
>      }
>   
> @@ -560,21 +560,21 @@ init_machine(struct gl_context * ctx, struct atifs_machine *machine,
>   }
>   
>   
>   
>   /**
>    * Execute the current ATI shader program, operating on the given span.
>    */
>   void
>   _swrast_exec_fragment_shader(struct gl_context * ctx, SWspan *span)
>   {
> -   const struct ati_fragment_shader *shader = ctx->ATIFragmentShader.Current;
> +   const struct gl_program *shader = ctx->ATIFragmentShader.Current;
>      struct atifs_machine machine;
>      GLuint i;
>   
>      /* incoming colors should be floats */
>      assert(span->array->ChanType == GL_FLOAT);
>   
>      for (i = 0; i < span->end; i++) {
>         if (span->array->mask[i]) {
>   	 init_machine(ctx, &machine, shader, span, i);
>   




More information about the mesa-dev mailing list