This is what I have done so far to convert the R200 driver to use t_vertex. It is only a conversion for SW TCL, and it's not quite complete. I've managed to clean up all the crashes that I could find, but I've only tested with gears, geartrain, and tunnel. There are some known problems:
- The textures in tunnel are not quite right. They're sort of zig-zaggy.
- The colors of two of the gears in gears are swapped. The red gear is blue and the blue gear is red. The green gear is correct.
I chopped out all of the _r200_render_stage stuff from r200_swtcl.c. It is unused (due to bad interactions with UT2k3), and was only confusing me. When this patch gets committed, that code can go back in, I think.
There are two hacks that I had to do to get things working. Neither of these needed to be done by the i830 or savage drivers. First, I had to add a "viewport" matrix that remains an identity matrix. This is because the Radeon chips do the viewport transform in hardware. tnl_dd/t_dd_vbtmp.h had the ability to handle hardware like this, but t_vertex apparently does not.
Just specify that element as 'EMIT_4F' or 'EMIT_3F', rather than 'EMIT_4F_VIEWPORT'.
Second, I had to force TNL to always produce project coordinates. Again, the Radeon hardware can do the final projection in hardware almost all the time, but due to the way the i830 and savage drivers use use tnl->vb.NdcPtr (actually VB->NdcPtr) I couldn't see a way around this. I may just be missing something there.
I do have one other question that probably only Keith or Daniel can answer. :) Can t_vertex replace the immediate-mode API code-gen in the radeon and r200 drivers? It seems like it should be able to, but I'm not sure I can see exactly how. Does the HW TCL side just need a tnl_attr_map just like the SW TCL side? I think looking at the SW TCL code for so long has fried my brain...
The immediate-mode codegen pretty much cuts out the tnl module altogether and builds hardware vertices directly. The t_vertex.c code would be redundant in that case. If you just mean using this logic to determine the vertex format, I suppose it's possible, but you'll run into differences between what is needed pre-TCL vs. what is being calculated here for vertices post-TCL.
In any case, I won't have a chance to look at this again in until probably next Wednesday. If someone could pick this up and finish it off, that would be cool. I think it's more important to get it done soon than have my name in the commit log. :)
-#define IND (R200_XYZW_BIT|R200_RGBA_BIT|R200_SPEC_BIT)
-#define TAG(x) x##_wgfs
-#include "tnl_dd/t_dd_vbtmp.h"
+#define EMIT_PAD( N ) \
+do { \
+ rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].attrib = 0; \
+ rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].format = EMIT_PAD; \
+ rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].offset = (N); \
+ rmesa->swtcl.vertex_attr_count++; \
+} while (0)
-#define IND (R200_XYZW_BIT|R200_RGBA_BIT|R200_SPEC_BIT|\
- R200_TEX0_BIT)
-#define TAG(x) x##_wgfst0
-#include "tnl_dd/t_dd_vbtmp.h"
+static void r200SetVertexFormat( GLcontext *ctx )
+{
+ r200ContextPtr rmesa = R200_CONTEXT( ctx );
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ GLuint index = tnl->render_inputs;
+ int fmt_0;
+ int fmt_1;
+ GLboolean is_tiny = GL_TRUE;
-#define IND (R200_XYZW_BIT|R200_RGBA_BIT|R200_SPEC_BIT|\
- R200_TEX0_BIT|R200_PTEX_BIT)
-#define TAG(x) x##_wgfspt0
-#include "tnl_dd/t_dd_vbtmp.h"
-#define IND (R200_XYZW_BIT|R200_RGBA_BIT|R200_SPEC_BIT|\
- R200_TEX0_BIT|R200_TEX1_BIT)
-#define TAG(x) x##_wgfst0t1
-#include "tnl_dd/t_dd_vbtmp.h"
+ /* Important:
+ */
+ VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
+ assert( VB->NdcPtr != NULL );
+ rmesa->swtcl.vertex_attr_count = 0;
-#define IND (R200_XYZW_BIT|R200_RGBA_BIT|R200_SPEC_BIT|\
- R200_TEX0_BIT|R200_TEX1_BIT|R200_PTEX_BIT)
-#define TAG(x) x##_wgfspt0t1
-#include "tnl_dd/t_dd_vbtmp.h"
+ fmt_0 = R200_VTX_XY | R200_VTX_Z0;
+ fmt_1 = 0;
+ /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
+ * build up a hardware vertex.
+ */
+ if (index & (_TNL_BITS_TEX_ANY | _TNL_BIT_COLOR1 | _TNL_BIT_FOG)) {
+ EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, R200_VTX_W0 );
+ is_tiny = GL_FALSE;
+ }
+ else {
+ EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, 0 );
+ }
Here specifically -- if you don't want to do viewport transform in sw, don't tell t_vertex.c to EMIT_xF_VIEWPORT.
Also - I'm not sure why you feel that COLOR1 or FOG (vertex fog, right?) require the W coordinate, though certainly the old code did work that way, this new code will differ from the old code in other respects so why maintain this old limitiation?
-/***********************************************************************
- * Initialization - ***********************************************************************/
+ EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_RGBA, (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT) );
-static void init_setup_tab( void )
-{
- init_wg();
- init_wgt0();
- init_wgpt0();
- init_wgt0t1();
- init_wgpt0t1();
- init_wgfs();
- init_wgfst0();
- init_wgfspt0();
- init_wgfst0t1();
- init_wgfspt0t1();
-}
+ if (index & (_TNL_BIT_COLOR1|_TNL_BIT_FOG)) {
+ is_tiny = GL_FALSE;
+ if (index & _TNL_BIT_COLOR1) {
+ EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_RGB, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) );
+ }
+ else {
+ EMIT_PAD( 3 );
+ }
+ if (index & _TNL_BIT_FOG) {
+ EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) );
+ }
+ else {
+ EMIT_PAD( 1 );
+ }
+ }
-void r200PrintSetupFlags(char *msg, GLuint flags )
-{
- fprintf(stderr, "%s(%x): %s%s%s%s%s%s\n",
- msg,
- (int)flags,
- (flags & R200_XYZW_BIT) ? " xyzw," : "",
- (flags & R200_RGBA_BIT) ? " rgba," : "",
- (flags & R200_SPEC_BIT) ? " spec/fog," : "",
- (flags & R200_TEX0_BIT) ? " tex-0," : "",
- (flags & R200_TEX1_BIT) ? " tex-1," : "",
- (flags & R200_PTEX_BIT) ? " proj-tex," : "");
-}
+ if (index & _TNL_BITS_TEX_ANY) {
+ int i, last_stage = 0;
+ /* Still using 2 as max tex units, but this code is fine for all
+ * 8 units supported by mesa:
+ */
+ for (i = 0; i < 2 ; i++) + if (index & _TNL_BIT_TEX(i))
+ last_stage = i+1;
+ + for (i = 0; i < last_stage; i++) {
+ GLuint sz = VB->TexCoordPtr[i]->size;
+ GLuint emit;
-static void r200SetVertexFormat( GLcontext *ctx, GLuint ind ) -{
- r200ContextPtr rmesa = R200_CONTEXT( ctx );
- TNLcontext *tnl = TNL_CONTEXT(ctx);
+ /* r200 doesn't like 1D or 4D texcoords (is that true?):
+ */
+ switch (sz) {
+ case 1: + case 2: + case 3: /* no attempt at cube texturing so far */
+ emit = EMIT_2F; + sz = 2; + break;
+ case 4: + emit = EMIT_3F_XYW; + sz = 3; + break;
+ default: + continue;
+ };
+
+ fmt_1 |= sz << (3 * i);
+ EMIT_ATTR( _TNL_ATTRIB_TEX0+i, EMIT_SZ(sz), 0 );
+ }
+ }
- rmesa->swtcl.SetupIndex = ind;
- if (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED)) {
- tnl->Driver.Render.Interp = r200_interp_extras;
- tnl->Driver.Render.CopyPV = r200_copy_pv_extras;
- }
- else {
- tnl->Driver.Render.Interp = setup_tab[ind].interp;
- tnl->Driver.Render.CopyPV = setup_tab[ind].copy_pv;
- }
- if (setup_tab[ind].vertex_format != rmesa->swtcl.vertex_format) {
- int i;
+ if ( (rmesa->hw.vtx.cmd[VTX_VTXFMT_0] != fmt_0)
+ || (rmesa->hw.vtx.cmd[VTX_VTXFMT_1] != fmt_1) ) {
R200_NEWPRIM(rmesa);
- i = rmesa->swtcl.vertex_format = setup_tab[ind].vertex_format;
- rmesa->swtcl.vertex_size = setup_tab[ind].vertex_size;
-
R200_STATECHANGE( rmesa, vtx );
- rmesa->hw.vtx.cmd[VTX_VTXFMT_0] = se_vtx_fmt_0[i];
- rmesa->hw.vtx.cmd[VTX_VTXFMT_1] = se_vtx_fmt_1[i];
+ rmesa->hw.vtx.cmd[VTX_VTXFMT_0] = fmt_0;
+ rmesa->hw.vtx.cmd[VTX_VTXFMT_1] = fmt_1;
+
+ rmesa->swtcl.vertex_size =
+ _tnl_install_attrs( ctx,
+ rmesa->swtcl.vertex_attrs, + rmesa->swtcl.vertex_attr_count,
+ rmesa->swtcl.ViewportMatrix.m, 0 );
+ rmesa->swtcl.vertex_size /= 4;
}
{
@@ -299,7 +194,7 @@
/* HW perspective divide is a win, but tiny vertex formats are a
* bigger one.
*/
- if (setup_tab[ind].vertex_format == TINY_VERTEX_FORMAT ||
+ if (1 || is_tiny ||
(ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
needproj = GL_TRUE;
vte |= R200_VTX_XY_FMT | R200_VTX_Z_FMT;
It all looks like you're on the right track. I can see you're getting tied up with trying to maintain the idea of a "tiny" vertex format rather than looking at what that really meant & identifying the situations where a W coordinate really is necessary. Specifically, if there's no texture and no pixel fog (which r200 doesn't enable), you can do the perspective divide in software and send a smaller vertex. Otherwise, you'll want to send XYZW anyway, so the hardware might as well do the divide.
I think I'll take a look at this & try & get it up and running.
Keith
------------------------------------------------------- This SF.Net email is sponsored by: IBM Linux Tutorials Free Linux tutorial presented by Daniel Robbins, President and CEO of GenToo technologies. Learn everything from fundamentals to system administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click -- _______________________________________________ Dri-devel mailing list [EMAIL PROTECTED] https://lists.sourceforge.net/lists/listinfo/dri-devel
