r300 side support for fixed function pipeline. This isnt functional with current Mesa.

This commit is contained in:
Aapo Tahkola
2005-04-30 11:06:14 +00:00
parent 47d18cbb64
commit 7d33053e47
8 changed files with 117 additions and 95 deletions
+2 -2
View File
@@ -62,7 +62,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "utils.h"
#include "xmlpool.h" /* for symbolic values of enum-type options */
int hw_vertprog_on=1;
int hw_tcl_on=1;
/* Extension strings exported by the R300 driver.
*/
@@ -109,7 +109,7 @@ static const struct tnl_pipeline_stage *r300_pipeline[] = {
/* Try and go straight to t&l
*/
//&_r300_tcl_stage,
&_r300_tcl_stage,
/* Catch any t&l fallbacks
*/
+9 -7
View File
@@ -566,10 +566,15 @@ struct r300_vertex_shader_state {
int unknown_ptr3; /* pointer within program space */
};
extern int hw_vertprog_on;
#define VERTPROG_ACTIVE(ctx) ( ctx->VertexProgram._Enabled && (R300_CONTEXT(ctx)->current_vp != NULL) && \
(R300_CONTEXT(ctx)->current_vp->translated) && hw_vertprog_on)
extern int hw_tcl_on;
#define CURRENT_VERTEX_SHADER(ctx) (ctx->VertexProgram._Enabled ? ctx->VertexProgram.Current : &ctx->_TnlProgram)
//#define TMU_ENABLED(ctx, unit) (hw_tcl_on ? ctx->Texture.Unit[unit]._ReallyEnabled && (OutputsWritten & (1<<(VERT_RESULT_TEX0+(unit)))) : \
// (r300->state.render_inputs & (_TNL_BIT_TEX0<<(unit))))
#define TMU_ENABLED(ctx, unit) (hw_tcl_on ? ctx->Texture.Unit[unit]._ReallyEnabled && OutputsWritten & (1<<(VERT_RESULT_TEX0+(unit))) : \
ctx->Texture.Unit[unit]._ReallyEnabled && r300->state.render_inputs & (_TNL_BIT_TEX0<<(unit)))
/* r300_vertex_shader_state and r300_vertex_program should probably be merged together someday.
* Keeping them them seperate for now should ensure fixed pipeline keeps functioning properly.
*/
@@ -583,7 +588,6 @@ struct r300_vertex_program {
int t2rs;
unsigned long num_temporaries; /* Number of temp vars used by program */
int inputs[VERT_ATTRIB_MAX];
GLuint outputs;
};
/* 64 appears to be the maximum */
@@ -738,8 +742,6 @@ struct r300_context {
GLuint TexGenInputs;
GLuint TexGenCompSel;
GLmatrix tmpmat;
struct r300_vertex_program *current_vp;
};
#define R300_CONTEXT(ctx) ((r300ContextPtr)(ctx->DriverCtx))
+46 -35
View File
@@ -240,7 +240,8 @@ void r300EmitArrays(GLcontext * ctx, GLboolean immd)
GLuint vic_1 = 0; /* R300_VAP_INPUT_CNTL_1 */
GLuint aa_vap_reg = 0; /* VAP register assignment */
GLuint i;
GLuint inputs = 0, outputs = 0;
GLuint inputs = 0;
GLuint InputsRead = CURRENT_VERTEX_SHADER(ctx)->InputsRead;
#define CONFIGURE_AOS(r, f, v, sz, cn) { \
@@ -251,7 +252,7 @@ void r300EmitArrays(GLcontext * ctx, GLboolean immd)
exit(-1); \
} \
\
if (VERTPROG_ACTIVE(ctx) == GL_FALSE) \
if (hw_tcl_on == GL_FALSE) \
rmesa->state.aos[nr-1].aos_reg = aa_vap_reg++; \
rmesa->state.aos[nr-1].aos_format = f; \
if (immd) { \
@@ -269,48 +270,41 @@ void r300EmitArrays(GLcontext * ctx, GLboolean immd)
} \
}
if (VERTPROG_ACTIVE(ctx)) {
if (rmesa->current_vp->inputs[VERT_ATTRIB_POS] != -1) {
if (hw_tcl_on) {
struct r300_vertex_program *prog=(struct r300_vertex_program *)CURRENT_VERTEX_SHADER(ctx);
if (InputsRead & (1<<VERT_ATTRIB_POS)) {
inputs |= _TNL_BIT_POS;
rmesa->state.aos[nr++].aos_reg = rmesa->current_vp->inputs[VERT_ATTRIB_POS];
rmesa->state.aos[nr++].aos_reg = prog->inputs[VERT_ATTRIB_POS];
}
if (rmesa->current_vp->inputs[VERT_ATTRIB_NORMAL] != -1) {
if (InputsRead & (1<<VERT_ATTRIB_NORMAL)) {
inputs |= _TNL_BIT_NORMAL;
rmesa->state.aos[nr++].aos_reg = rmesa->current_vp->inputs[VERT_ATTRIB_NORMAL];
rmesa->state.aos[nr++].aos_reg = prog->inputs[VERT_ATTRIB_NORMAL];
}
if (rmesa->current_vp->inputs[VERT_ATTRIB_COLOR0] != -1) {
if (InputsRead & (1<<VERT_ATTRIB_COLOR0)) {
inputs |= _TNL_BIT_COLOR0;
rmesa->state.aos[nr++].aos_reg = rmesa->current_vp->inputs[VERT_ATTRIB_COLOR0];
rmesa->state.aos[nr++].aos_reg = prog->inputs[VERT_ATTRIB_COLOR0];
}
if (rmesa->current_vp->inputs[VERT_ATTRIB_COLOR1] != -1) {
if (InputsRead & (1<<VERT_ATTRIB_COLOR1)) {
inputs |= _TNL_BIT_COLOR1;
rmesa->state.aos[nr++].aos_reg = rmesa->current_vp->inputs[VERT_ATTRIB_COLOR1];
rmesa->state.aos[nr++].aos_reg = prog->inputs[VERT_ATTRIB_COLOR1];
}
if (rmesa->current_vp->inputs[VERT_ATTRIB_FOG] != -1) {
if (InputsRead & (1<<VERT_ATTRIB_FOG)) {
inputs |= _TNL_BIT_FOG;
rmesa->state.aos[nr++].aos_reg = rmesa->current_vp->inputs[VERT_ATTRIB_FOG];
rmesa->state.aos[nr++].aos_reg = prog->inputs[VERT_ATTRIB_FOG];
}
if(ctx->Const.MaxTextureUnits > 8) { /* Not sure if this can even happen... */
fprintf(stderr, "%s: Cant handle that many inputs\n", __FUNCTION__);
exit(-1);
}
for (i=0;i<ctx->Const.MaxTextureUnits;i++) {
if (rmesa->current_vp->inputs[VERT_ATTRIB_TEX0+i] != -1) {
if (InputsRead & (1<<(VERT_ATTRIB_TEX0+i))) {
inputs |= _TNL_BIT_TEX0<<i;
rmesa->state.aos[nr++].aos_reg = rmesa->current_vp->inputs[VERT_ATTRIB_TEX0+i];
rmesa->state.aos[nr++].aos_reg = prog->inputs[VERT_ATTRIB_TEX0+i];
}
}
nr = 0;
} else {
inputs = TNL_CONTEXT(ctx)->render_inputs;
/* Hack to see what would happen if we would enable tex units according to their enabled values.
Why arent we doing this?
As for vertex programs tex coords should be passed if program wants them as some programs might deliver
some other values to the program with them. Futher more some programs might generate output tex coords
without taking them as inputs. */
/*for (i=0;i<ctx->Const.MaxTextureUnits;i++)
if(ctx->Texture.Unit[i].Enabled == 0)
inputs &= ~ (_TNL_BIT_TEX0<<i);*/
}
rmesa->state.render_inputs = inputs;
@@ -494,23 +488,40 @@ drm_radeon_cmd_header_t *cmd = NULL;
#endif
/* Stage 3: VAP output */
if (VERTPROG_ACTIVE(ctx))
outputs = rmesa->current_vp->outputs;
else
outputs = inputs;
R300_STATECHANGE(r300, vof);
r300->hw.vof.cmd[R300_VOF_CNTL_0]=0;
if(outputs & _TNL_BIT_POS)
r300->hw.vof.cmd[R300_VOF_CNTL_0] |= R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT;
if(outputs & _TNL_BIT_COLOR0)
r300->hw.vof.cmd[R300_VOF_CNTL_0] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_PRESENT;
r300->hw.vof.cmd[R300_VOF_CNTL_1]=0;
for(i=0;i < ctx->Const.MaxTextureUnits;i++)
if(outputs & (_TNL_BIT_TEX0<<i))
r300->hw.vof.cmd[R300_VOF_CNTL_1]|=(4<<(3*i));
if (hw_tcl_on){
GLuint OutputsWritten = CURRENT_VERTEX_SHADER(ctx)->OutputsWritten;
if(OutputsWritten & (1<<VERT_RESULT_HPOS))
r300->hw.vof.cmd[R300_VOF_CNTL_0] |= R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT;
if(OutputsWritten & (1<<VERT_RESULT_COL0))
r300->hw.vof.cmd[R300_VOF_CNTL_0] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_PRESENT;
/*if(OutputsWritten & (1<<VERT_RESULT_COL1))
r300->hw.vof.cmd[R300_VOF_CNTL_0] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_1_PRESENT;
if(OutputsWritten & (1<<VERT_RESULT_BFC0))
r300->hw.vof.cmd[R300_VOF_CNTL_0] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_2_PRESENT;
if(OutputsWritten & (1<<VERT_RESULT_BFC1))
r300->hw.vof.cmd[R300_VOF_CNTL_0] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_3_PRESENT;*/
//if(OutputsWritten & (1<<VERT_RESULT_FOGC))
//if(OutputsWritten & (1<<VERT_RESULT_PSIZ))
for(i=0;i < ctx->Const.MaxTextureUnits;i++)
if(OutputsWritten & (1<<(VERT_RESULT_TEX0+i)))
r300->hw.vof.cmd[R300_VOF_CNTL_1] |= (4<<(3*i));
} else {
if(inputs & _TNL_BIT_POS)
r300->hw.vof.cmd[R300_VOF_CNTL_0] |= R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT;
if(inputs & _TNL_BIT_COLOR0)
r300->hw.vof.cmd[R300_VOF_CNTL_0] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_PRESENT;
for(i=0;i < ctx->Const.MaxTextureUnits;i++)
if(inputs & (_TNL_BIT_TEX0<<i))
r300->hw.vof.cmd[R300_VOF_CNTL_1]|=(4<<(3*i));
}
rmesa->state.aos_count = nr;
}
+6 -6
View File
@@ -748,6 +748,12 @@ static GLboolean r300_run_tcl_render(GLcontext *ctx,
if (RADEON_DEBUG & DEBUG_PRIMS)
fprintf(stderr, "%s\n", __FUNCTION__);
if(hw_tcl_on == GL_FALSE)
return GL_TRUE;
if(ctx->VertexProgram._Enabled == GL_FALSE){
_tnl_UpdateFixedFunctionProgram(ctx);
r300ProgramStringNotify(ctx, GL_VERTEX_PROGRAM_ARB, &ctx->_TnlProgram);
}
return r300_run_vb_render(ctx, stage);
}
@@ -765,12 +771,6 @@ static void r300_check_tcl_render(GLcontext *ctx, struct tnl_pipeline_stage *sta
//stage->active = GL_FALSE;
return;
}
if(VERTPROG_ACTIVE(ctx)) {
//stage->active = GL_TRUE;
//stage->inputs = ctx->VertexProgram.Current->InputsRead;
} else {
//stage->active = GL_FALSE;
}
}
const struct tnl_pipeline_stage _r300_tcl_stage = {
+4 -4
View File
@@ -13,7 +13,7 @@ static void r300BindProgram(GLcontext *ctx, GLenum target, struct program *prog)
switch(target){
case GL_VERTEX_PROGRAM_ARB:
rmesa->current_vp = vp;
//rmesa->current_vp = vp;
break;
default:
WARN_ONCE("Target not supported yet!\n");
@@ -59,13 +59,13 @@ static void r300DeleteProgram(GLcontext *ctx, struct program *prog)
r300ContextPtr rmesa = R300_CONTEXT(ctx);
struct r300_vertex_program *vp=(void *)prog;
if(rmesa->current_vp == vp)
rmesa->current_vp = NULL;
/*if(rmesa->current_vp == vp)
rmesa->current_vp = NULL;*/
_mesa_delete_program(ctx, prog);
}
static void r300ProgramStringNotify(GLcontext *ctx, GLenum target,
void r300ProgramStringNotify(GLcontext *ctx, GLenum target,
struct program *prog)
{
struct r300_vertex_program *vp=(void *)prog;
+19 -23
View File
@@ -1024,7 +1024,7 @@ static void r300PolygonOffset(GLcontext * ctx, GLfloat factor, GLfloat units)
}
/* Routing and texture-related */
#if 0
void r300_setup_routing(GLcontext *ctx, GLboolean immediate)
{
int i, count=0,reg=0;
@@ -1241,7 +1241,7 @@ void r300_setup_routing(GLcontext *ctx, GLboolean immediate)
r300->hw.vof.cmd[R300_VOF_CNTL_1]|=(4<<(3*i));
}
#endif
static r300TexObj default_tex_obj={
filter:R300_TX_MAG_FILTER_LINEAR | R300_TX_MIN_FILTER_LINEAR,
pitch: 0x8000,
@@ -1354,6 +1354,7 @@ void r300_setup_textures(GLcontext *ctx)
r300ContextPtr r300 = R300_CONTEXT(ctx);
int max_texture_unit=-1; /* -1 translates into no setup costs for fields */
struct gl_texture_unit *texUnit;
GLuint OutputsWritten = CURRENT_VERTEX_SHADER(ctx)->OutputsWritten;
R300_STATECHANGE(r300, txe);
R300_STATECHANGE(r300, tex.filter);
@@ -1379,14 +1380,12 @@ void r300_setup_textures(GLcontext *ctx)
}
for(i=0; i < mtu; i++) {
/*if(ctx->Texture.Unit[i].Enabled == 0)
continue;*/
if( ((r300->state.render_inputs & (_TNL_BIT_TEX0<<i))!=0) != ((ctx->Texture.Unit[i].Enabled)!=0) ) {
/*if( ((r300->state.render_inputs & (_TNL_BIT_TEX0<<i))!=0) != ((ctx->Texture.Unit[i].Enabled)!=0) ) {
WARN_ONCE("Mismatch between render_inputs and ctx->Texture.Unit[i].Enabled value(%d vs %d).\n",
((r300->state.render_inputs & (_TNL_BIT_TEX0<<i))!=0), ((ctx->Texture.Unit[i].Enabled)!=0));
}
}*/
if(r300->state.render_inputs & (_TNL_BIT_TEX0<<i)) {
if(TMU_ENABLED(ctx, i)) {
t=r300->state.texture.unit[i].texobj;
//fprintf(stderr, "format=%08x\n", r300->state.texture.unit[i].format);
r300->state.texture.tc_count++;
@@ -1449,7 +1448,7 @@ void r300_setup_rs_unit(GLcontext *ctx)
0x00,
0x00
};
GLuint vap_outputs;
GLuint OutputsWritten = CURRENT_VERTEX_SHADER(ctx)->OutputsWritten;
/* This needs to be rewritten - it is a hack at best */
@@ -1461,11 +1460,6 @@ void r300_setup_rs_unit(GLcontext *ctx)
cur_reg = 0;
r300->hw.rr.cmd[R300_RR_ROUTE_0] = 0;
if (VERTPROG_ACTIVE(ctx))
vap_outputs = r300->current_vp->outputs;
else
vap_outputs = r300->state.render_inputs;
for (i=0;i<ctx->Const.MaxTextureUnits;i++) {
r300->hw.ri.cmd[R300_RI_INTERP_0+i] = 0
| R300_RS_INTERP_USED
@@ -1473,7 +1467,7 @@ void r300_setup_rs_unit(GLcontext *ctx)
| interp_magic[i];
// fprintf(stderr, "RS_INTERP[%d] = 0x%x\n", i, r300->hw.ri.cmd[R300_RI_INTERP_0+i]);
if (r300->state.render_inputs & (_TNL_BIT_TEX0<<i)) {
if (TMU_ENABLED(ctx, i)) {
assert(r300->state.texture.tc_count != 0);
r300->hw.rr.cmd[R300_RR_ROUTE_0 + cur_reg] = 0
| R300_RS_ROUTE_ENABLE
@@ -1483,7 +1477,7 @@ void r300_setup_rs_unit(GLcontext *ctx)
cur_reg++;
}
}
if (vap_outputs & _TNL_BIT_COLOR0)
if (hw_tcl_on ? OutputsWritten & (1<<VERT_RESULT_COL0) : r300->state.render_inputs & _TNL_BIT_COLOR0)
r300->hw.rr.cmd[R300_RR_ROUTE_0] |= 0
| R300_RS_ROUTE_0_COLOR
| (cur_reg << R300_RS_ROUTE_0_COLOR_DEST_SHIFT);
@@ -1719,7 +1713,7 @@ void r300SetupVertexShader(r300ContextPtr rmesa)
0x400 area might have something to do with pixel shaders as it appears right after pfs programming.
0x406 is set to { 0.0, 0.0, 1.0, 0.0 } most of the time but should change with smooth points and in other rare cases. */
//setup_vertex_shader_fragment(rmesa, 0x406, &unk4);
if(VERTPROG_ACTIVE(ctx)){
if(hw_tcl_on && ((struct r300_vertex_program *)CURRENT_VERTEX_SHADER(ctx))->translated){
r300SetupVertexProgram(rmesa);
return ;
}
@@ -1780,6 +1774,7 @@ void r300SetupVertexProgram(r300ContextPtr rmesa)
int inst_count;
int param_count;
LOCAL_VARS
struct r300_vertex_program *prog=(struct r300_vertex_program *)CURRENT_VERTEX_SHADER(ctx);
/* Reset state, in case we don't use something */
@@ -1787,19 +1782,19 @@ void r300SetupVertexProgram(r300ContextPtr rmesa)
((drm_r300_cmd_header_t*)rmesa->hw.vpi.cmd)->vpu.count = 0;
((drm_r300_cmd_header_t*)rmesa->hw.vps.cmd)->vpu.count = 0;
r300VertexProgUpdateParams(ctx, rmesa->current_vp);
r300VertexProgUpdateParams(ctx, prog);
setup_vertex_shader_fragment(rmesa, VSF_DEST_PROGRAM, &(rmesa->current_vp->program));
setup_vertex_shader_fragment(rmesa, VSF_DEST_PROGRAM, &(prog->program));
setup_vertex_shader_fragment(rmesa, VSF_DEST_MATRIX0, &(rmesa->current_vp->params));
setup_vertex_shader_fragment(rmesa, VSF_DEST_MATRIX0, &(prog->params));
#if 0
setup_vertex_shader_fragment(rmesa, VSF_DEST_UNKNOWN1, &(rmesa->state.vertex_shader.unknown1));
setup_vertex_shader_fragment(rmesa, VSF_DEST_UNKNOWN2, &(rmesa->state.vertex_shader.unknown2));
#endif
inst_count=rmesa->current_vp->program.length/4 - 1;
param_count=rmesa->current_vp->params.length/4;
inst_count=prog->program.length/4 - 1;
param_count=prog->params.length/4;
R300_STATECHANGE(rmesa, pvs);
rmesa->hw.pvs.cmd[R300_PVS_CNTL_1]=(0 << R300_PVS_CNTL_1_PROGRAM_START_SHIFT)
@@ -1808,7 +1803,7 @@ void r300SetupVertexProgram(r300ContextPtr rmesa)
rmesa->hw.pvs.cmd[R300_PVS_CNTL_2]=(0 << R300_PVS_CNTL_2_PARAM_OFFSET_SHIFT)
| (param_count << R300_PVS_CNTL_2_PARAM_COUNT_SHIFT);
rmesa->hw.pvs.cmd[R300_PVS_CNTL_3]=(0/*rmesa->state.vertex_shader.unknown_ptr2*/ << R300_PVS_CNTL_3_PROGRAM_UNKNOWN_SHIFT)
| ((inst_count-rmesa->current_vp->t2rs) /*rmesa->state.vertex_shader.unknown_ptr3*/ << 0);
| (inst_count /*rmesa->state.vertex_shader.unknown_ptr3*/ << 0);
/* This is done for vertex shader fragments, but also needs to be done for vap_pvs,
so I leave it as a reminder */
@@ -1825,12 +1820,13 @@ void r300GenerateTexturePixelShader(r300ContextPtr r300)
int i, mtu;
mtu = r300->radeon.glCtx->Const.MaxTextureUnits;
GLenum envMode;
GLuint OutputsWritten = CURRENT_VERTEX_SHADER(r300->radeon.glCtx)->OutputsWritten;
int tex_inst=0, alu_inst=0;
for(i=0;i<mtu;i++){
/* No need to proliferate {} */
if(! (r300->state.render_inputs & (_TNL_BIT_TEX0<<i)))continue;
if(!TMU_ENABLED(r300->radeon.glCtx, i))continue;
envMode = r300->radeon.glCtx->Texture.Unit[i].EnvMode;
//fprintf(stderr, "envMode=%s\n", _mesa_lookup_enum_by_nr(envMode));
+2 -1
View File
@@ -223,6 +223,7 @@ void r300GenerateTextureFragmentShader(r300ContextPtr r300)
struct r300_pixel_shader_program *p = &ps->program;
GLcontext *ctx = r300->radeon.glCtx;
int i, tc_reg;
GLuint OutputsWritten = CURRENT_VERTEX_SHADER(ctx)->OutputsWritten;
p->tex.length = 0;
p->alu.length = 0;
@@ -235,7 +236,7 @@ void r300GenerateTextureFragmentShader(r300ContextPtr r300)
tc_reg = 0;
for (i=0;i<ctx->Const.MaxTextureUnits;i++) {
if (r300->state.render_inputs & (_TNL_BIT_TEX0<<i)) {
if (TMU_ENABLED(ctx, i)) {
ps->have_sample = 0;
ps->src_previous = emit_texenv(r300, tc_reg, i);
tc_reg++;
+29 -17
View File
@@ -313,6 +313,35 @@ static unsigned long t_dst_class(enum register_file file)
static unsigned long t_dst_index(struct r300_vertex_program *vp, struct vp_dst_register *dst)
{
if(dst->File == PROGRAM_OUTPUT)
switch(dst->Index){
case VERT_RESULT_HPOS:
return 0;
case VERT_RESULT_COL0:
return 1;
case VERT_RESULT_TEX0:
return 2;
case VERT_RESULT_TEX1:
return 3;
case VERT_RESULT_TEX2:
return 4;
case VERT_RESULT_TEX3:
return 5;
case VERT_RESULT_TEX4:
return 6;
case VERT_RESULT_TEX5:
return 7;
case VERT_RESULT_TEX6:
return 8;
case VERT_RESULT_TEX7:
return 9;
case VERT_RESULT_COL1:
case VERT_RESULT_BFC0:
case VERT_RESULT_BFC1:
case VERT_RESULT_FOGC:
case VERT_RESULT_PSIZ:
default: WARN_ONCE("Unknown output\n"); return 1;
}
return dst->Index;
}
@@ -495,23 +524,6 @@ void translate_vertex_shader(struct r300_vertex_program *vp)
for(i=0; i < VERT_ATTRIB_MAX; i++)
vp->inputs[i]=-1;
vp->outputs = 0;
/* FIXME: hardcoded values in arbprogparse.c:parse_result_binding ()
We might want to use these constants for VAP output in general as well once they have been added to
mesa headers.
*/
if(mesa_vp->OutputsWritten & (1<<0))
vp->outputs |= _TNL_BIT_POS;
if(mesa_vp->OutputsWritten & (1<<1))
vp->outputs |= _TNL_BIT_COLOR0;
if(mesa_vp->OutputsWritten & (1<<2))
vp->outputs |= _TNL_BIT_COLOR1;
for(i=0; i < 8/*ctx->Const.MaxTextureUnits*/; i++)
if(mesa_vp->OutputsWritten & (1<<(7+i)))
vp->outputs |= _TNL_BIT_TEX(i);
if(mesa_vp->OutputsWritten & ~(0x7 | 0x3f80))
fprintf(stderr, "%s:Odd bits(0x%08x)\n", __FUNCTION__, mesa_vp->OutputsWritten);
o_inst=vp->program.body.i;
for(vpi=mesa_vp->Instructions; vpi->Opcode != VP_OPCODE_END; vpi++, o_inst++){