From e946688edac5cdf153652defae3ef732a3487416 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Fri, 23 Apr 2004 20:20:07 +0000 Subject: [PATCH] Convert R200 driver to use the t_vertex interface. --- src/mesa/drivers/dri/r200/r200_context.h | 40 +- src/mesa/drivers/dri/r200/r200_swtcl.c | 766 +++++++---------------- src/mesa/drivers/dri/r200/r200_tcl.c | 2 - 3 files changed, 256 insertions(+), 552 deletions(-) diff --git a/src/mesa/drivers/dri/r200/r200_context.h b/src/mesa/drivers/dri/r200/r200_context.h index b147e250fa4..ae7d2f47bd3 100644 --- a/src/mesa/drivers/dri/r200/r200_context.h +++ b/src/mesa/drivers/dri/r200/r200_context.h @@ -39,6 +39,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #ifdef GLX_DIRECT_RENDERING #include +#include "tnl/t_vertex.h" #include "drm.h" #include "radeon_drm.h" #include "dri_util.h" @@ -611,12 +612,28 @@ struct r200_tcl_info { /* r200_swtcl.c */ struct r200_swtcl_info { - GLuint SetupIndex; - GLuint SetupNewInputs; GLuint RenderIndex; + + /** + * Size of a hardware vertex. This is calculated when \c ::vertex_attrs is + * installed in the Mesa state vector. + */ GLuint vertex_size; - GLuint vertex_stride_shift; - GLuint vertex_format; + + /** + * Attributes instructing the Mesa TCL pipeline where / how to put vertex + * data in the hardware buffer. + */ + struct tnl_attr_map vertex_attrs[VERT_ATTRIB_MAX]; + + /** + * Number of elements of \c ::vertex_attrs that are actually used. + */ + GLuint vertex_attr_count; + + /** + * Cached pointer to the buffer where Mesa will store vertex data. + */ GLubyte *verts; /* Fallback rasterization functions @@ -629,6 +646,21 @@ struct r200_swtcl_info { GLenum render_primitive; GLuint numverts; + /** + * Offset of the 4UB color data within a hardware (swtcl) vertex. + */ + GLuint coloroffset; + + /** + * Offset of the 3UB specular color data within a hardware (swtcl) vertex. + */ + GLuint specoffset; + + /** + * Should Mesa project vertex data or will the hardware do it? + */ + GLboolean needproj; + struct r200_dma_region indexed_verts; }; diff --git a/src/mesa/drivers/dri/r200/r200_swtcl.c b/src/mesa/drivers/dri/r200/r200_swtcl.c index a66879fe75d..2a0cd5b9d15 100644 --- a/src/mesa/drivers/dri/r200/r200_swtcl.c +++ b/src/mesa/drivers/dri/r200/r200_swtcl.c @@ -56,323 +56,192 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "r200_swtcl.h" #include "r200_tcl.h" -/*********************************************************************** - * Build render functions from dd templates * - ***********************************************************************/ - - -#define R200_XYZW_BIT 0x01 -#define R200_RGBA_BIT 0x02 -#define R200_SPEC_BIT 0x04 -#define R200_TEX0_BIT 0x08 -#define R200_TEX1_BIT 0x10 -#define R200_PTEX_BIT 0x20 -#define R200_MAX_SETUP 0x40 static void flush_last_swtcl_prim( r200ContextPtr rmesa ); -static struct { - void (*emit)( GLcontext *, GLuint, GLuint, void *, GLuint ); - interp_func interp; - copy_pv_func copy_pv; - GLboolean (*check_tex_sizes)( GLcontext *ctx ); - GLuint vertex_size; - GLuint vertex_format; -} setup_tab[R200_MAX_SETUP]; - - -static int se_vtx_fmt_0[] = { - 0, - - (R200_VTX_XY | - R200_VTX_Z0 | - (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT)), - - (R200_VTX_XY | - R200_VTX_Z0 | - R200_VTX_W0 | - (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT) | - (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT)), - - (R200_VTX_XY | - R200_VTX_Z0 | - R200_VTX_W0 | - (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT) | - (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT)), - - (R200_VTX_XY | - R200_VTX_Z0 | - R200_VTX_W0 | - (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT) | - (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT)), - - (R200_VTX_XY | - R200_VTX_Z0 | - R200_VTX_W0 | - (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT) | - (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT)) -}; - -static int se_vtx_fmt_1[] = { - 0, - 0, - 0, - ((2 << R200_VTX_TEX0_COMP_CNT_SHIFT)), - ((2 << R200_VTX_TEX0_COMP_CNT_SHIFT) | - (2 << R200_VTX_TEX1_COMP_CNT_SHIFT)), - ((3 << R200_VTX_TEX0_COMP_CNT_SHIFT) | - (3 << R200_VTX_TEX1_COMP_CNT_SHIFT)), -}; - -#define TINY_VERTEX_FORMAT 1 -#define NOTEX_VERTEX_FORMAT 2 -#define TEX0_VERTEX_FORMAT 3 -#define TEX1_VERTEX_FORMAT 4 -#define PROJ_TEX1_VERTEX_FORMAT 5 -#define TEX2_VERTEX_FORMAT 0 -#define TEX3_VERTEX_FORMAT 0 -#define PROJ_TEX3_VERTEX_FORMAT 0 - -#define DO_XYZW (IND & R200_XYZW_BIT) -#define DO_RGBA (IND & R200_RGBA_BIT) -#define DO_SPEC (IND & R200_SPEC_BIT) -#define DO_FOG (IND & R200_SPEC_BIT) -#define DO_TEX0 (IND & R200_TEX0_BIT) -#define DO_TEX1 (IND & R200_TEX1_BIT) -#define DO_TEX2 0 -#define DO_TEX3 0 -#define DO_PTEX (IND & R200_PTEX_BIT) - -#define VERTEX r200Vertex -#define VERTEX_COLOR r200_color_t -#define GET_VIEWPORT_MAT() 0 -#define GET_TEXSOURCE(n) n -#define GET_VERTEX_FORMAT() R200_CONTEXT(ctx)->swtcl.vertex_format -#define GET_VERTEX_STORE() R200_CONTEXT(ctx)->swtcl.verts -#define GET_VERTEX_SIZE() R200_CONTEXT(ctx)->swtcl.vertex_size * sizeof(GLuint) - -#define HAVE_HW_VIEWPORT 1 -#define HAVE_HW_DIVIDE (IND & ~(R200_XYZW_BIT|R200_RGBA_BIT)) -#define HAVE_TINY_VERTICES 1 -#define HAVE_RGBA_COLOR 1 -#define HAVE_NOTEX_VERTICES 1 -#define HAVE_TEX0_VERTICES 1 -#define HAVE_TEX1_VERTICES 1 -#define HAVE_TEX2_VERTICES 0 -#define HAVE_TEX3_VERTICES 0 -#define HAVE_PTEX_VERTICES 1 - -#define CHECK_HW_DIVIDE (!(ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE| \ - DD_TRI_UNFILLED))) - -#define INTERP_VERTEX setup_tab[R200_CONTEXT(ctx)->swtcl.SetupIndex].interp -#define COPY_PV_VERTEX setup_tab[R200_CONTEXT(ctx)->swtcl.SetupIndex].copy_pv - - -/*********************************************************************** - * Generate pv-copying and translation functions * - ***********************************************************************/ - -#define TAG(x) r200_##x -#define IND ~0 -#include "tnl_dd/t_dd_vb.c" -#undef IND - - -/*********************************************************************** - * Generate vertex emit and interp functions * - ***********************************************************************/ - -#define IND (R200_XYZW_BIT|R200_RGBA_BIT) -#define TAG(x) x##_wg -#include "tnl_dd/t_dd_vbtmp.h" - -#define IND (R200_XYZW_BIT|R200_RGBA_BIT|R200_TEX0_BIT) -#define TAG(x) x##_wgt0 -#include "tnl_dd/t_dd_vbtmp.h" - -#define IND (R200_XYZW_BIT|R200_RGBA_BIT|R200_TEX0_BIT|R200_PTEX_BIT) -#define TAG(x) x##_wgpt0 -#include "tnl_dd/t_dd_vbtmp.h" - -#define IND (R200_XYZW_BIT|R200_RGBA_BIT|R200_TEX0_BIT|R200_TEX1_BIT) -#define TAG(x) x##_wgt0t1 -#include "tnl_dd/t_dd_vbtmp.h" - -#define IND (R200_XYZW_BIT|R200_RGBA_BIT|R200_TEX0_BIT|R200_TEX1_BIT|\ - R200_PTEX_BIT) -#define TAG(x) x##_wgpt0t1 -#include "tnl_dd/t_dd_vbtmp.h" - -#define IND (R200_XYZW_BIT|R200_RGBA_BIT|R200_SPEC_BIT) -#define TAG(x) x##_wgfs -#include "tnl_dd/t_dd_vbtmp.h" - -#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" - -#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" - -#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" - /*********************************************************************** * Initialization ***********************************************************************/ -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(); -} - - - -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," : ""); -} - +#define EMIT_SZ(sz) (EMIT_1F + (sz) - 1) +#define EMIT_ATTR( ATTR, STYLE, F0 ) \ +do { \ + rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].attrib = (ATTR); \ + rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].format = (STYLE); \ + rmesa->swtcl.vertex_attr_count++; \ + fmt_0 |= F0; \ +} while (0) +#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) -static void r200SetVertexFormat( GLcontext *ctx, GLuint ind ) +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 = 0; + int fmt_1 = 0; + int offset = 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; + /* Important: + */ + if ( VB->NdcPtr != NULL ) { + VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr; } else { - tnl->Driver.Render.Interp = setup_tab[ind].interp; - tnl->Driver.Render.CopyPV = setup_tab[ind].copy_pv; + VB->AttribPtr[VERT_ATTRIB_POS] = VB->ClipPtr; } - if (setup_tab[ind].vertex_format != rmesa->swtcl.vertex_format) { - int i; - R200_NEWPRIM(rmesa); - i = rmesa->swtcl.vertex_format = setup_tab[ind].vertex_format; - rmesa->swtcl.vertex_size = setup_tab[ind].vertex_size; + assert( VB->AttribPtr[VERT_ATTRIB_POS] != NULL ); + rmesa->swtcl.vertex_attr_count = 0; - 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]; + /* EMIT_ATTR's must be in order as they tell t_vertex.c how to + * build up a hardware vertex. + */ + if ( !rmesa->swtcl.needproj ) { + EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F, R200_VTX_XY | R200_VTX_Z0 | R200_VTX_W0 ); + offset = 4; + } + else { + EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F, R200_VTX_XY | R200_VTX_Z0 ); + offset = 3; } - { - GLuint vte = rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL]; - GLuint vap = rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL]; - GLuint needproj; - - /* HW perspective divide is a win, but tiny vertex formats are a - * bigger one. - */ - if (setup_tab[ind].vertex_format == TINY_VERTEX_FORMAT || - (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) { - needproj = GL_TRUE; - vte |= R200_VTX_XY_FMT | R200_VTX_Z_FMT; - vte &= ~R200_VTX_W0_FMT; - vap |= R200_VAP_FORCE_W_TO_ONE; + rmesa->swtcl.coloroffset = offset; + EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_RGBA, (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT) ); + offset += 1; + + rmesa->swtcl.specoffset = 0; + if (index & (_TNL_BIT_COLOR1|_TNL_BIT_FOG)) { + + if (index & _TNL_BIT_COLOR1) { + rmesa->swtcl.specoffset = offset; + EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_RGB, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) ); } else { - needproj = GL_FALSE; - vte &= ~(R200_VTX_XY_FMT | R200_VTX_Z_FMT); - vte |= R200_VTX_W0_FMT; - vap &= ~R200_VAP_FORCE_W_TO_ONE; + EMIT_PAD( 3 ); } - _tnl_need_projected_coords( ctx, needproj ); - if (vte != rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL]) { - R200_STATECHANGE( rmesa, vte ); - rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] = vte; + if (index & _TNL_BIT_FOG) { + EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) ); } - if (vap != rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL]) { - R200_STATECHANGE( rmesa, vap ); - rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] = vap; + else { + EMIT_PAD( 1 ); } } -} -static void r200RenderStart( GLcontext *ctx ) -{ - r200ContextPtr rmesa = R200_CONTEXT( ctx ); + if (index & _TNL_BITS_TEX_ANY) { + int i; + + for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { + if (index & _TNL_BIT_TEX(i)) { + GLuint sz = VB->TexCoordPtr[i]->size; + GLuint emit; - if (!setup_tab[rmesa->swtcl.SetupIndex].check_tex_sizes(ctx)) { - r200SetVertexFormat( ctx, rmesa->swtcl.SetupIndex | R200_PTEX_BIT); + /* 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 ); + } + } + } + + + + if ( (rmesa->hw.vtx.cmd[VTX_VTXFMT_0] != fmt_0) + || (rmesa->hw.vtx.cmd[VTX_VTXFMT_1] != fmt_1) ) { + R200_NEWPRIM(rmesa); + R200_STATECHANGE( rmesa, vtx ); + 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, + NULL, 0 ); + rmesa->swtcl.vertex_size /= 4; } - - if (rmesa->dma.flush != 0 && - rmesa->dma.flush != flush_last_swtcl_prim) - rmesa->dma.flush( rmesa ); } -void r200BuildVertices( GLcontext *ctx, GLuint start, GLuint count, - GLuint newinputs ) +static void r200RenderStart( GLcontext *ctx ) { r200ContextPtr rmesa = R200_CONTEXT( ctx ); - GLuint stride = rmesa->swtcl.vertex_size * sizeof(int); - GLubyte *v = ((GLubyte *)rmesa->swtcl.verts + (start * stride)); - newinputs |= rmesa->swtcl.SetupNewInputs; - rmesa->swtcl.SetupNewInputs = 0; + r200SetVertexFormat( ctx ); - if (!newinputs) - return; - - setup_tab[rmesa->swtcl.SetupIndex].emit( ctx, start, count, v, stride ); + if (rmesa->dma.flush != 0 && + rmesa->dma.flush != flush_last_swtcl_prim) + rmesa->dma.flush( rmesa ); } +/** + * Set vertex state for SW TCL. The primary purpose of this function is to + * determine in advance whether or not the hardware can / should do the + * projection divide or Mesa should do it. + */ void r200ChooseVertexState( GLcontext *ctx ) { r200ContextPtr rmesa = R200_CONTEXT( ctx ); - GLuint ind = (R200_XYZW_BIT | R200_RGBA_BIT); + TNLcontext *tnl = TNL_CONTEXT(ctx); - if (!rmesa->TclFallback || rmesa->Fallback) - return; + GLuint vte = rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL]; + GLuint vap = rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL]; - if (ctx->Fog.Enabled || (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)) - ind |= R200_SPEC_BIT; + /* HW perspective divide is a win, but tiny vertex formats are a + * bigger one. + */ + if ( ((tnl->render_inputs & _TNL_BITS_TEX_ANY) == 0) + || (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) { + rmesa->swtcl.needproj = GL_TRUE; + vte |= R200_VTX_XY_FMT | R200_VTX_Z_FMT; + vte &= ~R200_VTX_W0_FMT; + vap |= R200_VAP_FORCE_W_TO_ONE; + } + else { + rmesa->swtcl.needproj = GL_FALSE; + vte &= ~(R200_VTX_XY_FMT | R200_VTX_Z_FMT); + vte |= R200_VTX_W0_FMT; + vap &= ~R200_VAP_FORCE_W_TO_ONE; + } - if (ctx->Texture._EnabledUnits & 0x2) /* unit 1 enabled */ - ind |= R200_TEX0_BIT|R200_TEX1_BIT; - else if (ctx->Texture._EnabledUnits & 0x1) /* unit 1 enabled */ - ind |= R200_TEX0_BIT; + _tnl_need_projected_coords( ctx, rmesa->swtcl.needproj ); - r200SetVertexFormat( ctx, ind ); + if (vte != rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL]) { + R200_STATECHANGE( rmesa, vte ); + rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] = vte; + } + + if (vap != rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL]) { + R200_STATECHANGE( rmesa, vap ); + rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] = vap; + } } @@ -445,251 +314,6 @@ static __inline void *r200AllocDmaLowVerts( r200ContextPtr rmesa, } - - -static void *r200_emit_contiguous_verts( GLcontext *ctx, - GLuint start, - GLuint count, - void *dest) -{ - r200ContextPtr rmesa = R200_CONTEXT(ctx); - GLuint stride = rmesa->swtcl.vertex_size * 4; - setup_tab[rmesa->swtcl.SetupIndex].emit( ctx, start, count, dest, stride ); - return (void *)((char *)dest + stride * (count - start)); -} - - - -void r200_emit_indexed_verts( GLcontext *ctx, GLuint start, GLuint count ) -{ - r200ContextPtr rmesa = R200_CONTEXT(ctx); - - r200AllocDmaRegionVerts( rmesa, - &rmesa->swtcl.indexed_verts, - count - start, - rmesa->swtcl.vertex_size * 4, - 64); - - setup_tab[rmesa->swtcl.SetupIndex].emit( - ctx, start, count, - rmesa->swtcl.indexed_verts.address + rmesa->swtcl.indexed_verts.start, - rmesa->swtcl.vertex_size * 4 ); -} - - -/* - * Render unclipped vertex buffers by emitting vertices directly to - * dma buffers. Use strip/fan hardware primitives where possible. - * Try to simulate missing primitives with indexed vertices. - */ -#define HAVE_POINTS 1 -#define HAVE_LINES 1 -#define HAVE_LINE_STRIPS 1 -#define HAVE_TRIANGLES 1 -#define HAVE_TRI_STRIPS 1 -#define HAVE_TRI_STRIP_1 0 -#define HAVE_TRI_FANS 1 -#define HAVE_QUADS 1 -#define HAVE_QUAD_STRIPS 1 -#define HAVE_POLYGONS 1 -#define HAVE_ELTS 1 - -static const GLuint hw_prim[GL_POLYGON+1] = { - R200_VF_PRIM_POINTS, - R200_VF_PRIM_LINES, - 0, - R200_VF_PRIM_LINE_STRIP, - R200_VF_PRIM_TRIANGLES, - R200_VF_PRIM_TRIANGLE_STRIP, - R200_VF_PRIM_TRIANGLE_FAN, - R200_VF_PRIM_QUADS, - R200_VF_PRIM_QUAD_STRIP, - R200_VF_PRIM_POLYGON -}; - -static __inline void r200DmaPrimitive( r200ContextPtr rmesa, GLenum prim ) -{ - R200_NEWPRIM( rmesa ); - rmesa->swtcl.hw_primitive = hw_prim[prim]; - assert(rmesa->dma.current.ptr == rmesa->dma.current.start); -} - -static __inline void r200EltPrimitive( r200ContextPtr rmesa, GLenum prim ) -{ - R200_NEWPRIM( rmesa ); - rmesa->swtcl.hw_primitive = hw_prim[prim] | R200_VF_PRIM_WALK_IND; -} - - - - -#define LOCAL_VARS r200ContextPtr rmesa = R200_CONTEXT(ctx) -#define ELTS_VARS(buf) GLushort *dest = buf -#define INIT( prim ) r200DmaPrimitive( rmesa, prim ) -#define ELT_INIT(prim) r200EltPrimitive( rmesa, prim ) -#define FLUSH() R200_NEWPRIM( rmesa ) -#define GET_CURRENT_VB_MAX_VERTS() \ - (((int)rmesa->dma.current.end - (int)rmesa->dma.current.ptr) / (rmesa->swtcl.vertex_size*4)) -#define GET_SUBSEQUENT_VB_MAX_VERTS() \ - ((RADEON_BUFFER_SIZE) / (rmesa->swtcl.vertex_size*4)) - -#define GET_CURRENT_VB_MAX_ELTS() \ - ((R200_CMD_BUF_SZ - (rmesa->store.cmd_used + 16)) / 2) -#define GET_SUBSEQUENT_VB_MAX_ELTS() \ - ((R200_CMD_BUF_SZ - 1024) / 2) - -static void *r200_alloc_elts( r200ContextPtr rmesa, int nr ) -{ - if (rmesa->dma.flush == r200FlushElts && - rmesa->store.cmd_used + nr*2 < R200_CMD_BUF_SZ) { - - rmesa->store.cmd_used += nr*2; - - return (void *)(rmesa->store.cmd_buf + rmesa->store.cmd_used); - } - else { - if (rmesa->dma.flush) { - rmesa->dma.flush( rmesa ); - } - - r200EmitVertexAOS( rmesa, - rmesa->swtcl.vertex_size, - (rmesa->r200Screen->gart_buffer_offset + - rmesa->swtcl.indexed_verts.buf->buf->idx * - RADEON_BUFFER_SIZE + - rmesa->swtcl.indexed_verts.start)); - - return (void *) r200AllocEltsOpenEnded( rmesa, - rmesa->swtcl.hw_primitive, - nr ); - } -} - -#define ALLOC_ELTS(nr) r200_alloc_elts(rmesa, nr) - - - -#ifdef MESA_BIG_ENDIAN -/* We could do without (most of) this ugliness if dest was always 32 bit word aligned... */ -#define EMIT_ELT(offset, x) do { \ - int off = offset + ( ( (GLuint)dest & 0x2 ) >> 1 ); \ - GLushort *des = (GLushort *)( (GLuint)dest & ~0x2 ); \ - (des)[ off + 1 - 2 * ( off & 1 ) ] = (GLushort)(x); } while (0) -#else -#define EMIT_ELT(offset, x) (dest)[offset] = (GLushort) (x) -#endif -#define EMIT_TWO_ELTS(offset, x, y) *(GLuint *)(dest+offset) = ((y)<<16)|(x); -#define INCR_ELTS( nr ) dest += nr -#define ELTPTR dest -#define RELEASE_ELT_VERTS() \ - r200ReleaseDmaRegion( rmesa, &rmesa->swtcl.indexed_verts, __FUNCTION__ ) - -#define EMIT_INDEXED_VERTS( ctx, start, count ) \ - r200_emit_indexed_verts( ctx, start, count ) - - -#define ALLOC_VERTS( nr ) \ - r200AllocDmaLowVerts( rmesa, nr, rmesa->swtcl.vertex_size * 4 ) -#define EMIT_VERTS( ctx, j, nr, buf ) \ - r200_emit_contiguous_verts(ctx, j, (j)+(nr), buf) - - - -#define TAG(x) r200_dma_##x -#include "tnl_dd/t_dd_dmatmp.h" - - -/**********************************************************************/ -/* Render pipeline stage */ -/**********************************************************************/ - - - -static GLboolean r200_run_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; - render_func *tab = TAG(render_tab_verts); - - if (rmesa->swtcl.indexed_verts.buf && (!VB->Elts || stage->changed_inputs)) - RELEASE_ELT_VERTS(); - - - - if ((R200_DEBUG & DEBUG_VERTS) || - rmesa->swtcl.RenderIndex != 0 || - !r200_dma_validate_render( ctx, VB )) - return GL_TRUE; - - if (VB->Elts) { - tab = TAG(render_tab_elts); - if (!rmesa->swtcl.indexed_verts.buf) { - if (VB->Count > GET_SUBSEQUENT_VB_MAX_VERTS()) - return GL_TRUE; - EMIT_INDEXED_VERTS(ctx, 0, VB->Count); - } - } - - tnl->Driver.Render.Start( ctx ); - - for (i = 0 ; i < VB->PrimitiveCount ; i++) - { - GLuint prim = VB->Primitive[i].mode; - GLuint start = VB->Primitive[i].start; - GLuint length = VB->Primitive[i].count; - - if (!length) - continue; - - if (R200_DEBUG & DEBUG_PRIMS) - fprintf(stderr, "r200_render.c: prim %s %d..%d\n", - _mesa_lookup_enum_by_nr(prim & PRIM_MODE_MASK), - start, start+length); - - tab[prim & PRIM_MODE_MASK]( ctx, start, start + length, prim ); - } - - tnl->Driver.Render.Finish( ctx ); - - return GL_FALSE; /* finished the pipe */ -} - - - -static void r200_check_render( GLcontext *ctx, - struct tnl_pipeline_stage *stage ) -{ - stage->inputs = TNL_CONTEXT(ctx)->render_inputs; -} - - -static void dtr( struct tnl_pipeline_stage *stage ) -{ - (void)stage; -} - - -const struct tnl_pipeline_stage _r200_render_stage = -{ - "r200 render", - (_DD_NEW_SEPARATE_SPECULAR | - _NEW_TEXTURE| - _NEW_FOG| - _NEW_RENDERMODE), /* re-check (new inputs) */ - 0, /* re-run (always runs) */ - GL_TRUE, /* active */ - 0, 0, /* inputs (set in check_render), outputs */ - 0, 0, /* changed_inputs, private */ - dtr, /* destructor */ - r200_check_render, /* check - initially set to alloc data */ - r200_run_render /* run */ -}; - - - /**************************************************************************/ @@ -710,16 +334,22 @@ static void r200RasterPrimitive( GLcontext *ctx, GLuint hwprim ); static void r200RenderPrimitive( GLcontext *ctx, GLenum prim ); static void r200ResetLineStipple( GLcontext *ctx ); -#undef HAVE_QUADS -#define HAVE_QUADS 0 - -#undef HAVE_QUAD_STRIPS -#define HAVE_QUAD_STRIPS 0 - /*********************************************************************** * Emit primitives as inline vertices * ***********************************************************************/ +#define HAVE_POINTS 1 +#define HAVE_LINES 1 +#define HAVE_LINE_STRIPS 1 +#define HAVE_TRIANGLES 1 +#define HAVE_TRI_STRIPS 1 +#define HAVE_TRI_STRIP_1 0 +#define HAVE_TRI_FANS 1 +#define HAVE_QUADS 0 +#define HAVE_QUAD_STRIPS 0 +#define HAVE_POLYGONS 1 +#define HAVE_ELTS 0 + #undef LOCAL_VARS #undef ALLOC_VERTS #define CTX_ARG r200ContextPtr rmesa @@ -732,7 +362,7 @@ static void r200ResetLineStipple( GLcontext *ctx ); #define VERT(x) (r200Vertex *)(r200verts + ((x) * vertsize * sizeof(int))) #define VERTEX r200Vertex #define DO_DEBUG_VERTS (1 && (R200_DEBUG & DEBUG_VERTS)) -#define PRINT_VERTEX(v) r200_print_vertex(rmesa->glCtx, v) + #undef TAG #define TAG(x) r200_##x #include "tnl_dd/t_dd_triemit.h" @@ -802,20 +432,23 @@ do { \ #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset] -#define VERT_SET_SPEC( v0, c ) \ +#define VERT_SET_SPEC( v, c ) \ do { \ - if (havespec) { \ - UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.red, (c)[0]); \ - UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.green, (c)[1]); \ - UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.blue, (c)[2]); \ + if (specoffset) { \ + r200_color_t *spec = (r200_color_t *)&((v)->ui[specoffset]); \ + UNCLAMPED_FLOAT_TO_UBYTE(spec->red, (c)[0]); \ + UNCLAMPED_FLOAT_TO_UBYTE(spec->green, (c)[1]); \ + UNCLAMPED_FLOAT_TO_UBYTE(spec->blue, (c)[2]); \ } \ } while (0) #define VERT_COPY_SPEC( v0, v1 ) \ do { \ - if (havespec) { \ - v0->v.specular.red = v1->v.specular.red; \ - v0->v.specular.green = v1->v.specular.green; \ - v0->v.specular.blue = v1->v.specular.blue; \ + if (specoffset) { \ + r200_color_t *spec0 = (r200_color_t *)&((v0)->ui[specoffset]); \ + r200_color_t *spec1 = (r200_color_t *)&((v1)->ui[specoffset]); \ + spec0->red = spec1->red; \ + spec0->green = spec1->green; \ + spec0->blue = spec1->blue; \ } \ } while (0) @@ -824,8 +457,8 @@ do { \ */ #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset] #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx] -#define VERT_SAVE_SPEC( idx ) if (havespec) spec[idx] = v[idx]->ui[5] -#define VERT_RESTORE_SPEC( idx ) if (havespec) v[idx]->ui[5] = spec[idx] +#define VERT_SAVE_SPEC( idx ) if (specoffset) spec[idx] = v[idx]->ui[specoffset] +#define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->ui[specoffset] = spec[idx] #undef LOCAL_VARS #undef TAG @@ -834,9 +467,9 @@ do { \ #define LOCAL_VARS(n) \ r200ContextPtr rmesa = R200_CONTEXT(ctx); \ GLuint color[n], spec[n]; \ - GLuint coloroffset = (rmesa->swtcl.vertex_size == 4 ? 3 : 4); \ - GLboolean havespec = (rmesa->swtcl.vertex_size > 4); \ - (void) color; (void) spec; (void) coloroffset; (void) havespec; + GLuint coloroffset = rmesa->swtcl.coloroffset; \ + GLuint specoffset = rmesa->swtcl.specoffset; \ + (void) color; (void) spec; (void) coloroffset; (void) specoffset; /*********************************************************************** * Helpers for rendering unfilled primitives * @@ -1041,11 +674,16 @@ void r200Fallback( GLcontext *ctx, GLuint bit, GLboolean mode ) else { rmesa->Fallback &= ~bit; if (oldfallback == bit) { + _swrast_flush( ctx ); tnl->Driver.Render.Start = r200RenderStart; tnl->Driver.Render.PrimitiveNotify = r200RenderPrimitive; tnl->Driver.Render.Finish = r200RenderFinish; - tnl->Driver.Render.BuildVertices = r200BuildVertices; + + tnl->Driver.Render.BuildVertices = _tnl_build_vertices; + tnl->Driver.Render.CopyPV = _tnl_copy_pv; + tnl->Driver.Render.Interp = _tnl_interp; + tnl->Driver.Render.ResetLineStipple = r200ResetLineStipple; TCL_FALLBACK( ctx, R200_TCL_FALLBACK_RASTER, GL_FALSE ); if (rmesa->TclFallback) { @@ -1067,7 +705,15 @@ void r200Fallback( GLcontext *ctx, GLuint bit, GLboolean mode ) -/* Cope with depth operations by drawing individual pixels as points??? +/** + * Cope with depth operations by drawing individual pixels as points. + * + * \todo + * The way the vertex state is set in this routine is hokey. It seems to + * work, but it's very hackish. This whole routine is pretty hackish. If + * the bitmap is small enough, it seems like it would be faster to copy it + * to AGP memory and use it as a non-power-of-two texture (i.e., + * NV_texture_rectangle). */ void r200PointsBitmap( GLcontext *ctx, GLint px, GLint py, @@ -1089,7 +735,37 @@ r200PointsBitmap( GLcontext *ctx, GLint px, GLint py, /* Choose tiny vertex format */ - r200SetVertexFormat( ctx, R200_XYZW_BIT | R200_RGBA_BIT ); + { + const GLuint fmt_0 = R200_VTX_XY | R200_VTX_Z0 | R200_VTX_W0 + | (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT); + const GLuint fmt_1 = 0; + GLuint vte = rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL]; + GLuint vap = rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL]; + + vte &= ~(R200_VTX_XY_FMT | R200_VTX_Z_FMT); + vte |= R200_VTX_W0_FMT; + vap &= ~R200_VAP_FORCE_W_TO_ONE; + + rmesa->swtcl.vertex_size = 5; + + if ( (rmesa->hw.vtx.cmd[VTX_VTXFMT_0] != fmt_0) + || (rmesa->hw.vtx.cmd[VTX_VTXFMT_1] != fmt_1) ) { + R200_NEWPRIM(rmesa); + R200_STATECHANGE( rmesa, vtx ); + rmesa->hw.vtx.cmd[VTX_VTXFMT_0] = fmt_0; + rmesa->hw.vtx.cmd[VTX_VTXFMT_1] = fmt_1; + } + + if (vte != rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL]) { + R200_STATECHANGE( rmesa, vte ); + rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] = vte; + } + + if (vap != rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL]) { + R200_STATECHANGE( rmesa, vap ); + rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] = vap; + } + } /* Ready for point primitives: */ @@ -1226,12 +902,10 @@ void r200InitSwtcl( GLcontext *ctx ) { TNLcontext *tnl = TNL_CONTEXT(ctx); r200ContextPtr rmesa = R200_CONTEXT(ctx); - GLuint size = tnl->vb.Size; static int firsttime = 1; if (firsttime) { init_rast_tab(); - init_setup_tab(); firsttime = 0; } @@ -1239,9 +913,14 @@ void r200InitSwtcl( GLcontext *ctx ) tnl->Driver.Render.Finish = r200RenderFinish; tnl->Driver.Render.PrimitiveNotify = r200RenderPrimitive; tnl->Driver.Render.ResetLineStipple = r200ResetLineStipple; - tnl->Driver.Render.BuildVertices = r200BuildVertices; + tnl->Driver.Render.BuildVertices = _tnl_build_vertices; + tnl->Driver.Render.CopyPV = _tnl_copy_pv; + tnl->Driver.Render.Interp = _tnl_interp; - rmesa->swtcl.verts = (GLubyte *)ALIGN_MALLOC( size * 16 * 4, 32 ); + _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12, + 22 * sizeof(GLfloat) ); + + rmesa->swtcl.verts = (GLubyte *)tnl->clipspace.vertex_buf; rmesa->swtcl.RenderIndex = ~0; rmesa->swtcl.render_primitive = GL_TRIANGLES; rmesa->swtcl.hw_primitive = 0; @@ -1254,9 +933,4 @@ void r200DestroySwtcl( GLcontext *ctx ) if (rmesa->swtcl.indexed_verts.buf) r200ReleaseDmaRegion( rmesa, &rmesa->swtcl.indexed_verts, __FUNCTION__ ); - - if (rmesa->swtcl.verts) { - ALIGN_FREE(rmesa->swtcl.verts); - rmesa->swtcl.verts = 0; - } } diff --git a/src/mesa/drivers/dri/r200/r200_tcl.c b/src/mesa/drivers/dri/r200/r200_tcl.c index 9b1f522e2c5..daf44906088 100644 --- a/src/mesa/drivers/dri/r200/r200_tcl.c +++ b/src/mesa/drivers/dri/r200/r200_tcl.c @@ -403,7 +403,6 @@ static void transition_to_swtnl( GLcontext *ctx ) TNLcontext *tnl = TNL_CONTEXT(ctx); R200_NEWPRIM( rmesa ); - rmesa->swtcl.vertex_format = 0; r200ChooseVertexState( ctx ); r200ChooseRenderState( ctx ); @@ -446,7 +445,6 @@ static void transition_to_hwtnl( GLcontext *ctx ) rmesa->dma.flush( rmesa ); rmesa->dma.flush = 0; - rmesa->swtcl.vertex_format = 0; if (rmesa->swtcl.indexed_verts.buf) r200ReleaseDmaRegion( rmesa, &rmesa->swtcl.indexed_verts, -- 2.30.2