Exemplo n.º 1
0
static GLboolean via_run_fastrender(GLcontext *ctx,
                                    struct tnl_pipeline_stage *stage)
{
    struct via_context *vmesa = VIA_CONTEXT(ctx);
    TNLcontext *tnl = TNL_CONTEXT(ctx);
    struct vertex_buffer *VB = &tnl->vb;
    GLuint i;
    

    tnl->Driver.Render.Start(ctx);
    
    if (VB->ClipOrMask || 
	vmesa->renderIndex != 0 || 
	!via_fastvalidate_render( ctx, VB )) {
	tnl->Driver.Render.Finish(ctx);
        return GL_TRUE;
    }

    tnl->clipspace.new_inputs |= VERT_BIT_POS;

    for (i = 0; i < VB->PrimitiveCount; ++i) {
        GLuint mode = _tnl_translate_prim(&VB->Primitive[i]);
        GLuint start = VB->Primitive[i].start;
        GLuint length = VB->Primitive[i].count;
        if (length)
            via_fastrender_tab_verts[mode & PRIM_MODE_MASK](ctx, start, start+length, mode);
    }

    tnl->Driver.Render.Finish(ctx);

    return GL_FALSE;            /* finished the pipe */
}
static GLboolean mga_run_render( GLcontext *ctx,
				  struct tnl_pipeline_stage *stage )
{
   mgaContextPtr mmesa = MGA_CONTEXT(ctx);
   TNLcontext *tnl = TNL_CONTEXT(ctx);
   struct vertex_buffer *VB = &tnl->vb; 
   GLuint i;

   /* Don't handle clipping or indexed vertices or vertex manipulations.
    */
   if (mmesa->RenderIndex != 0 || 
       !mga_validate_render( ctx, VB )) {
      return GL_TRUE;
   }
   
   tnl->Driver.Render.Start( ctx );
   mmesa->SetupNewInputs = ~0;      

   for (i = 0 ; i < VB->PrimitiveCount ; i++)
   {
      GLuint prim = _tnl_translate_prim(&VB->Primitive[i]);
      GLuint start = VB->Primitive[i].start;
      GLuint length = VB->Primitive[i].count;

      if (!length)
	 continue;

      mga_render_tab_verts[prim & PRIM_MODE_MASK]( ctx, start, start + length, 
						   prim);
   } 

   tnl->Driver.Render.Finish( ctx );

   return GL_FALSE;		/* finished the pipe */
}
Exemplo n.º 3
0
static GLboolean r300RunRender(GLcontext * ctx,
			       struct tnl_pipeline_stage *stage)
{
	r300ContextPtr rmesa = R300_CONTEXT(ctx);
	struct radeon_vertex_buffer *VB = &rmesa->state.VB;
	int i;
	int cmd_reserved = 0;
	int cmd_written = 0;
	drm_radeon_cmd_header_t *cmd = NULL;

	if (RADEON_DEBUG & DEBUG_PRIMS)
		fprintf(stderr, "%s\n", __FUNCTION__);

	if (stage) {
		TNLcontext *tnl = TNL_CONTEXT(ctx);
		radeon_vb_to_rvb(rmesa, VB, &tnl->vb);
	}

	r300UpdateShaders(rmesa);
	if (r300EmitArrays(ctx))
		return GL_TRUE;

	r300UpdateShaderStates(rmesa);

	reg_start(R300_RB3D_DSTCACHE_CTLSTAT, 0);
	e32(R300_RB3D_DSTCACHE_UNKNOWN_0A);

	reg_start(R300_RB3D_ZCACHE_CTLSTAT, 0);
	e32(R300_RB3D_ZCACHE_UNKNOWN_03);

	r300EmitState(rmesa);

	for (i = 0; i < VB->PrimitiveCount; i++) {
		GLuint prim = _tnl_translate_prim(&VB->Primitive[i]);
		GLuint start = VB->Primitive[i].start;
		GLuint end = VB->Primitive[i].start + VB->Primitive[i].count;
		r300RunRenderPrimitive(rmesa, ctx, start, end, prim);
	}

	reg_start(R300_RB3D_DSTCACHE_CTLSTAT, 0);
	e32(R300_RB3D_DSTCACHE_UNKNOWN_0A);

	reg_start(R300_RB3D_ZCACHE_CTLSTAT, 0);
	e32(R300_RB3D_ZCACHE_UNKNOWN_03);

#ifdef USER_BUFFERS
	r300UseArrays(ctx);
#endif

	r300ReleaseArrays(ctx);

	return GL_FALSE;
}
Exemplo n.º 4
0
static GLboolean s3v_run_render( GLcontext *ctx,
				  struct tnl_pipeline_stage *stage )
{
	s3vContextPtr vmesa = S3V_CONTEXT(ctx);
	TNLcontext *tnl = TNL_CONTEXT(ctx);
	struct vertex_buffer *VB = &tnl->vb;
	GLuint i;
	tnl_render_func *tab;

	DEBUG(("s3v_run_render\n"));
	
	/* FIXME: hw clip */
	if (VB->ClipOrMask || vmesa->RenderIndex != 0) {
		DEBUG(("*** CLIPPED in render ***\n"));
#if 1
		return GL_TRUE;	/* don't handle clipping here */
#endif
	}


	/* We don't do elts */
	if (VB->Elts)
		return GL_TRUE;

	tab = TAG(render_tab_verts);

	tnl->Driver.Render.Start( ctx );

	for (i = 0 ; i < VB->PrimitiveCount ; i++ )
	{
		GLuint prim = _tnl_translate_prim(&VB->Primitive[i]);
		GLuint start = VB->Primitive[i].start;
		GLuint length = VB->Primitive[i].count;

		DEBUG(("s3v_run_render (loop=%i) (lenght=%i)\n", i, length));

		if (length) {
			tnl->Driver.Render.BuildVertices( ctx, start,
                                start+length, ~0 /*stage->inputs*/); /* XXX */
			tnl->Driver.Render.PrimTabVerts[prim & PRIM_MODE_MASK]
				( ctx, start, start + length, prim );
			vmesa->SetupNewInputs = VERT_BIT_POS;
		}
	}
	
	tnl->Driver.Render.Finish( ctx );

	return GL_FALSE; /* finished the pipe */
}
Exemplo n.º 5
0
static GLboolean
intel_run_render(GLcontext * ctx, struct tnl_pipeline_stage *stage)
{
   struct intel_context *intel = intel_context(ctx);
   TNLcontext *tnl = TNL_CONTEXT(ctx);
   struct vertex_buffer *VB = &tnl->vb;
   GLuint i;

   intel->vtbl.render_prevalidate( intel );

   /* Don't handle clipping or indexed vertices.
    */
   if (intel->RenderIndex != 0 ||
       !intel_validate_render(ctx, VB) || !choose_render(intel, VB)) {
      return GL_TRUE;
   }

   tnl->clipspace.new_inputs |= VERT_BIT_POS;

   tnl->Driver.Render.Start(ctx);

   for (i = 0; i < VB->PrimitiveCount; i++) {
      GLuint prim = _tnl_translate_prim(&VB->Primitive[i]);
      GLuint start = VB->Primitive[i].start;
      GLuint length = VB->Primitive[i].count;

      if (!length)
         continue;

      intel_render_tab_verts[prim & PRIM_MODE_MASK] (ctx, start,
                                                     start + length, prim);
   }

   tnl->Driver.Render.Finish(ctx);

   INTEL_FIREVERTICES(intel);

   return GL_FALSE;             /* finished the pipe */
}
static GLboolean r300RunRender(GLcontext * ctx,
			       struct tnl_pipeline_stage *stage)
{
	r300ContextPtr rmesa = R300_CONTEXT(ctx);
	int i;
	TNLcontext *tnl = TNL_CONTEXT(ctx);
	struct vertex_buffer *vb = &tnl->vb;


	if (RADEON_DEBUG & DEBUG_PRIMS)
		fprintf(stderr, "%s\n", __FUNCTION__);

	r300UpdateShaders(rmesa);
	if (r300EmitArrays(ctx))
		return GL_TRUE;

	r300UpdateShaderStates(rmesa);

	r300EmitCacheFlush(rmesa);
	r300EmitState(rmesa);

	for (i = 0; i < vb->PrimitiveCount; i++) {
		GLuint prim = _tnl_translate_prim(&vb->Primitive[i]);
		GLuint start = vb->Primitive[i].start;
		GLuint end = vb->Primitive[i].start + vb->Primitive[i].count;
		r300RunRenderPrimitive(rmesa, ctx, start, end, prim);
	}

	r300EmitCacheFlush(rmesa);

#ifdef USER_BUFFERS
	r300UseArrays(ctx);
#endif

	r300ReleaseArrays(ctx);

	return GL_FALSE;
}
Exemplo n.º 7
0
static GLboolean savage_run_render( GLcontext *ctx,
				    struct tnl_pipeline_stage *stage )
{
   savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
   TNLcontext *tnl = TNL_CONTEXT(ctx);
   struct vertex_buffer *VB = &tnl->vb; 
   tnl_render_func *tab, *tab_elts;
   GLboolean valid;
   GLuint i;

   if (savageHaveIndexedVerts(imesa))
      savageReleaseIndexedVerts(imesa);

   if (imesa->savageScreen->chipset < S3_SAVAGE4 &&
       (ctx->_TriangleCaps & DD_FLATSHADE)) {
      tab = savage_flat_render_tab_verts_s3d;
      tab_elts = savage_flat_render_tab_elts_s3d;
      valid = savage_flat_validate_render_s3d( ctx, VB );
   } else {
      tab = savage_render_tab_verts;
      tab_elts = savage_render_tab_elts;
      valid = savage_validate_render( ctx, VB );
   }

   /* Don't handle clipping or vertex manipulations.
    */
   if (imesa->RenderIndex != 0 || !valid) {
      return GL_TRUE;
   }
   
   tnl->Driver.Render.Start( ctx );
   /* Check RenderIndex again. The ptexHack is detected late in RenderStart.
    * Also check for ptex fallbacks detected late.
    */
   if (imesa->RenderIndex != 0 || imesa->Fallback != 0) {
      return GL_TRUE;
   }

   /* setup for hardware culling */
   imesa->raster_primitive = GL_TRIANGLES;
   imesa->new_state |= SAVAGE_NEW_CULL;

   /* update and emit state */
   savageDDUpdateHwState(ctx);
   savageEmitChangedState(imesa);

   if (VB->Elts) {
      tab = tab_elts;
      if (!savageHaveIndexedVerts(imesa)) {
	 if (VB->Count > GET_SUBSEQUENT_VB_MAX_VERTS())
	    return GL_TRUE;
	 EMIT_INDEXED_VERTS(ctx, 0, VB->Count);
      }
   }

   for (i = 0 ; i < VB->PrimitiveCount ; i++)
   {
      GLuint prim = _tnl_translate_prim(&VB->Primitive[i]);
      GLuint start = VB->Primitive[i].start;
      GLuint length = VB->Primitive[i].count;

      if (length)
	 tab[prim & PRIM_MODE_MASK]( ctx, start, start+length, prim);
   }

   tnl->Driver.Render.Finish( ctx );

   return GL_FALSE;		/* finished the pipe */
}
Exemplo n.º 8
0
/* TCL render.
 */
static GLboolean r200_run_tcl_render( struct gl_context *ctx,
				      struct tnl_pipeline_stage *stage )
{
   r200ContextPtr rmesa = R200_CONTEXT(ctx);
   TNLcontext *tnl = TNL_CONTEXT(ctx);
   struct vertex_buffer *VB = &tnl->vb;
   GLuint i;
   GLubyte *vimap_rev;
/* use hw fixed order for simplicity, pos 0, weight 1, normal 2, fog 3, 
   color0 - color3 4-7, texcoord0 - texcoord5 8-13, pos 1 14. Must not use
   more than 12 of those at the same time. */
   GLubyte map_rev_fixed[15] = {255, 255, 255, 255, 255, 255, 255, 255,
			    255, 255, 255, 255, 255, 255, 255};


   /* TODO: separate this from the swtnl pipeline 
    */
   if (rmesa->radeon.TclFallback)
      return GL_TRUE;	/* fallback to software t&l */

   radeon_print(RADEON_RENDER, RADEON_NORMAL, "%s\n", __func__);

   if (VB->Count == 0)
      return GL_FALSE;

   /* Validate state:
    */
   if (rmesa->radeon.NewGLState)
      if (!r200ValidateState( ctx ))
         return GL_TRUE; /* fallback to sw t&l */

   if (!_mesa_arb_vertex_program_enabled(ctx)) {
   /* NOTE: inputs != tnl->render_inputs - these are the untransformed
    * inputs.
    */
      map_rev_fixed[0] = VERT_ATTRIB_POS;
      /* technically there is no reason we always need VA_COLOR0. In theory
         could disable it depending on lighting, color materials, texturing... */
      map_rev_fixed[4] = VERT_ATTRIB_COLOR0;

      if (ctx->Light.Enabled) {
	 map_rev_fixed[2] = VERT_ATTRIB_NORMAL;
      }

      /* this also enables VA_COLOR1 when using separate specular
         lighting model, which is unnecessary.
         FIXME: OTOH, we're missing the case where a ATI_fragment_shader accesses
         the secondary color (if lighting is disabled). The chip seems
         misconfigured for that though elsewhere (tcl output, might lock up) */
      if (_mesa_need_secondary_color(ctx)) {
	 map_rev_fixed[5] = VERT_ATTRIB_COLOR1;
      }

      if ( (ctx->Fog.FogCoordinateSource == GL_FOG_COORD) && ctx->Fog.Enabled ) {
	 map_rev_fixed[3] = VERT_ATTRIB_FOG;
      }

      for (i = 0 ; i < ctx->Const.MaxTextureUnits; i++) {
	 if (ctx->Texture.Unit[i]._Current) {
	    if (rmesa->TexGenNeedNormals[i]) {
	       map_rev_fixed[2] = VERT_ATTRIB_NORMAL;
	    }
	    map_rev_fixed[8 + i] = VERT_ATTRIB_TEX0 + i;
	 }
      }
      vimap_rev = &map_rev_fixed[0];
   }
   else {
      /* vtx_tcl_output_vtxfmt_0/1 need to match configuration of "fragment
	 part", since using some vertex interpolator later which is not in
	 out_vtxfmt0/1 will lock up. It seems to be ok to write in vertex
	 prog to a not enabled output however, so just don't mess with it.
	 We only need to change compsel. */
      GLuint out_compsel = 0;
      const GLbitfield64 vp_out =
	 rmesa->curr_vp_hw->mesa_program.info.outputs_written;

      vimap_rev = &rmesa->curr_vp_hw->inputmap_rev[0];
      assert(vp_out & BITFIELD64_BIT(VARYING_SLOT_POS));
      out_compsel = R200_OUTPUT_XYZW;
      if (vp_out & BITFIELD64_BIT(VARYING_SLOT_COL0)) {
	 out_compsel |= R200_OUTPUT_COLOR_0;
      }
      if (vp_out & BITFIELD64_BIT(VARYING_SLOT_COL1)) {
	 out_compsel |= R200_OUTPUT_COLOR_1;
      }
      if (vp_out & BITFIELD64_BIT(VARYING_SLOT_FOGC)) {
         out_compsel |= R200_OUTPUT_DISCRETE_FOG;
      }
      if (vp_out & BITFIELD64_BIT(VARYING_SLOT_PSIZ)) {
	 out_compsel |= R200_OUTPUT_PT_SIZE;
      }
      for (i = VARYING_SLOT_TEX0; i < VARYING_SLOT_TEX6; i++) {
	 if (vp_out & BITFIELD64_BIT(i)) {
	    out_compsel |= R200_OUTPUT_TEX_0 << (i - VARYING_SLOT_TEX0);
	 }
      }
      if (rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] != out_compsel) {
	 R200_STATECHANGE( rmesa, vtx );
	 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] = out_compsel;
      }
   }

   /* Do the actual work:
    */
   radeonReleaseArrays( ctx, ~0 /* stage->changed_inputs */ );
   GLuint emit_end = r200EnsureEmitSize( ctx, vimap_rev )
     + rmesa->radeon.cmdbuf.cs->cdw;
   r200EmitArrays( ctx, vimap_rev );

   for (i = 0 ; i < VB->PrimitiveCount ; i++)
   {
      GLuint prim = _tnl_translate_prim(&VB->Primitive[i]);
      GLuint start = VB->Primitive[i].start;
      GLuint length = VB->Primitive[i].count;

      if (!length)
	 continue;

      if (VB->Elts)
	 r200EmitEltPrimitive( ctx, start, start+length, prim );
      else
	 r200EmitPrimitive( ctx, start, start+length, prim );
   }
   if ( emit_end < rmesa->radeon.cmdbuf.cs->cdw )
     WARN_ONCE("Rendering was %d commands larger than predicted size."
	 " We might overflow  command buffer.\n", rmesa->radeon.cmdbuf.cs->cdw - emit_end);

   return GL_FALSE;		/* finished the pipe */
}
Exemplo n.º 9
0
static GLboolean run_render( struct gl_context *ctx,
			     struct tnl_pipeline_stage *stage )
{
   TNLcontext *tnl = TNL_CONTEXT(ctx);
   struct vertex_buffer *VB = &tnl->vb;
   tnl_render_func *tab;
   GLint pass = 0;

   /* Allow the drivers to lock before projected verts are built so
    * that window coordinates are guarenteed not to change before
    * rendering.
    */
   ASSERT(tnl->Driver.Render.Start);

   tnl->Driver.Render.Start( ctx );

   ASSERT(tnl->Driver.Render.BuildVertices);
   ASSERT(tnl->Driver.Render.PrimitiveNotify);
   ASSERT(tnl->Driver.Render.Points);
   ASSERT(tnl->Driver.Render.Line);
   ASSERT(tnl->Driver.Render.Triangle);
   ASSERT(tnl->Driver.Render.Quad);
   ASSERT(tnl->Driver.Render.ResetLineStipple);
   ASSERT(tnl->Driver.Render.Interp);
   ASSERT(tnl->Driver.Render.CopyPV);
   ASSERT(tnl->Driver.Render.ClippedLine);
   ASSERT(tnl->Driver.Render.ClippedPolygon);
   ASSERT(tnl->Driver.Render.Finish);

   tnl->Driver.Render.BuildVertices( ctx, 0, VB->Count, ~0 );

   if (VB->ClipOrMask) {
      tab = VB->Elts ? clip_render_tab_elts : clip_render_tab_verts;
      clip_render_tab_elts[GL_TRIANGLES] = clip_elt_triangles;
   }
   else {
      tab = (VB->Elts ? 
	     tnl->Driver.Render.PrimTabElts : 
	     tnl->Driver.Render.PrimTabVerts);
   }

   do
   {
      GLuint i;

      for (i = 0 ; i < VB->PrimitiveCount ; i++)
      {
	 GLuint prim = _tnl_translate_prim(&VB->Primitive[i]);
	 GLuint start = VB->Primitive[i].start;
	 GLuint length = VB->Primitive[i].count;

	 assert((prim & PRIM_MODE_MASK) <= GL_POLYGON);

	 if (MESA_VERBOSE & VERBOSE_PRIMS) 
	    _mesa_debug(NULL, "MESA prim %s %d..%d\n", 
			_mesa_lookup_enum_by_nr(prim & PRIM_MODE_MASK), 
			start, start+length);

	 if (length)
	    tab[prim & PRIM_MODE_MASK]( ctx, start, start + length, prim );
      }
   } while (tnl->Driver.Render.Multipass &&
	    tnl->Driver.Render.Multipass( ctx, ++pass ));

   tnl->Driver.Render.Finish( ctx );

   return GL_FALSE;		/* finished the pipe */
}
Exemplo n.º 10
0
/* TCL render.
 */
static GLboolean radeon_run_tcl_render( struct gl_context *ctx,
                                        struct tnl_pipeline_stage *stage )
{
    r100ContextPtr rmesa = R100_CONTEXT(ctx);
    TNLcontext *tnl = TNL_CONTEXT(ctx);
    struct vertex_buffer *VB = &tnl->vb;
    GLuint inputs = VERT_BIT_POS | VERT_BIT_COLOR0;
    GLuint i;

    /* TODO: separate this from the swtnl pipeline
     */
    if (rmesa->radeon.TclFallback)
        return GL_TRUE;	/* fallback to software t&l */

    if (VB->Count == 0)
        return GL_FALSE;

    /* NOTE: inputs != tnl->render_inputs - these are the untransformed
     * inputs.
     */
    if (ctx->Light.Enabled) {
        inputs |= VERT_BIT_NORMAL;
    }

    if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) {
        inputs |= VERT_BIT_COLOR1;
    }

    if ( (ctx->Fog.FogCoordinateSource == GL_FOG_COORD) && ctx->Fog.Enabled ) {
        inputs |= VERT_BIT_FOG;
    }

    for (i = 0 ; i < ctx->Const.MaxTextureUnits; i++) {
        if (ctx->Texture.Unit[i]._ReallyEnabled) {
            /* TODO: probably should not emit texture coords when texgen is enabled */
            if (rmesa->TexGenNeedNormals[i]) {
                inputs |= VERT_BIT_NORMAL;
            }
            inputs |= VERT_BIT_TEX(i);
        }
    }

    radeonReleaseArrays( ctx, ~0 );
    GLuint emit_end = radeonEnsureEmitSize( ctx, inputs )
                      + rmesa->radeon.cmdbuf.cs->cdw;
    radeonEmitArrays( ctx, inputs );

    rmesa->tcl.Elts = VB->Elts;

    for (i = 0 ; i < VB->PrimitiveCount ; i++)
    {
        GLuint prim = _tnl_translate_prim(&VB->Primitive[i]);
        GLuint start = VB->Primitive[i].start;
        GLuint length = VB->Primitive[i].count;

        if (!length)
            continue;

        if (rmesa->tcl.Elts)
            radeonEmitEltPrimitive( ctx, start, start+length, prim );
        else
            radeonEmitPrimitive( ctx, start, start+length, prim );
    }

    if (emit_end < rmesa->radeon.cmdbuf.cs->cdw)
        WARN_ONCE("Rendering was %d commands larger than predicted size."
                  " We might overflow  command buffer.\n", rmesa->radeon.cmdbuf.cs->cdw - emit_end);

    return GL_FALSE;		/* finished the pipe */
}
Exemplo n.º 11
0
/* TCL render.
 */
static GLboolean r200_run_tcl_render( GLcontext *ctx,
				      struct tnl_pipeline_stage *stage )
{
   r200ContextPtr rmesa = R200_CONTEXT(ctx);
   TNLcontext *tnl = TNL_CONTEXT(ctx);
   struct vertex_buffer *VB = &tnl->vb;
   GLuint i;
   GLubyte *vimap_rev;
/* use hw fixed order for simplicity, pos 0, weight 1, normal 2, fog 3, 
   color0 - color3 4-7, texcoord0 - texcoord5 8-13, pos 1 14. Must not use
   more than 12 of those at the same time. */
   GLubyte map_rev_fixed[15] = {255, 255, 255, 255, 255, 255, 255, 255,
			    255, 255, 255, 255, 255, 255, 255};


   /* TODO: separate this from the swtnl pipeline 
    */
   if (rmesa->TclFallback)
      return GL_TRUE;	/* fallback to software t&l */

   if (R200_DEBUG & DEBUG_PRIMS)
      fprintf(stderr, "%s\n", __FUNCTION__);

   if (VB->Count == 0)
      return GL_FALSE;

   /* Validate state:
    */
   if (rmesa->NewGLState)
      r200ValidateState( ctx );

   if (!ctx->VertexProgram._Enabled) {
   /* NOTE: inputs != tnl->render_inputs - these are the untransformed
    * inputs.
    */
      map_rev_fixed[0] = VERT_ATTRIB_POS;
      /* technically there is no reason we always need VA_COLOR0. In theory
         could disable it depending on lighting, color materials, texturing... */
      map_rev_fixed[4] = VERT_ATTRIB_COLOR0;

      if (ctx->Light.Enabled) {
	 map_rev_fixed[2] = VERT_ATTRIB_NORMAL;
      }

      /* this also enables VA_COLOR1 when using separate specular
         lighting model, which is unnecessary.
         FIXME: OTOH, we're missing the case where a ATI_fragment_shader accesses
         the secondary color (if lighting is disabled). The chip seems
         misconfigured for that though elsewhere (tcl output, might lock up) */
      if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) {
	 map_rev_fixed[5] = VERT_ATTRIB_COLOR1;
      }

      if ( (ctx->Fog.FogCoordinateSource == GL_FOG_COORD) && ctx->Fog.Enabled ) {
	 map_rev_fixed[3] = VERT_ATTRIB_FOG;
      }

      for (i = 0 ; i < ctx->Const.MaxTextureUnits; i++) {
	 if (ctx->Texture.Unit[i]._ReallyEnabled) {
	    if (rmesa->TexGenNeedNormals[i]) {
	       map_rev_fixed[2] = VERT_ATTRIB_NORMAL;
	    }
	    map_rev_fixed[8 + i] = VERT_ATTRIB_TEX0 + i;
	 }
      }
      vimap_rev = &map_rev_fixed[0];
   }
   else {
      /* vtx_tcl_output_vtxfmt_0/1 need to match configuration of "fragment
	 part", since using some vertex interpolator later which is not in
	 out_vtxfmt0/1 will lock up. It seems to be ok to write in vertex
	 prog to a not enabled output however, so just don't mess with it.
	 We only need to change compsel. */
      GLuint out_compsel = 0;
      GLuint vp_out = rmesa->curr_vp_hw->mesa_program.Base.OutputsWritten;

      vimap_rev = &rmesa->curr_vp_hw->inputmap_rev[0];
      assert(vp_out & (1 << VERT_RESULT_HPOS));
      out_compsel = R200_OUTPUT_XYZW;
      if (vp_out & (1 << VERT_RESULT_COL0)) {
	 out_compsel |= R200_OUTPUT_COLOR_0;
      }
      if (vp_out & (1 << VERT_RESULT_COL1)) {
	 out_compsel |= R200_OUTPUT_COLOR_1;
      }
      if (vp_out & (1 << VERT_RESULT_FOGC)) {
         out_compsel |= R200_OUTPUT_DISCRETE_FOG;
      }
      if (vp_out & (1 << VERT_RESULT_PSIZ)) {
	 out_compsel |= R200_OUTPUT_PT_SIZE;
      }
      for (i = VERT_RESULT_TEX0; i < VERT_RESULT_TEX6; i++) {
	 if (vp_out & (1 << i)) {
	    out_compsel |= R200_OUTPUT_TEX_0 << (i - VERT_RESULT_TEX0);
	 }
      }
      if (rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] != out_compsel) {
	 R200_STATECHANGE( rmesa, vtx );
	 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] = out_compsel;
      }
   }

   /* Do the actual work:
    */
   r200ReleaseArrays( ctx, ~0 /* stage->changed_inputs */ );
   r200EmitArrays( ctx, vimap_rev );

   rmesa->tcl.Elts = VB->Elts;

   for (i = 0 ; i < VB->PrimitiveCount ; i++)
   {
      GLuint prim = _tnl_translate_prim(&VB->Primitive[i]);
      GLuint start = VB->Primitive[i].start;
      GLuint length = VB->Primitive[i].count;

      if (!length)
	 continue;

      if (rmesa->tcl.Elts)
	 r200EmitEltPrimitive( ctx, start, start+length, prim );
      else
	 r200EmitPrimitive( ctx, start, start+length, prim );
   }

   return GL_FALSE;		/* finished the pipe */
}