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

Timothy Arceri tarceri at itsqueeze.com
Fri Nov 10 10:35:52 UTC 2017


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);
 
-- 
2.14.3



More information about the mesa-dev mailing list