#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;
+ }
}
}
-
-
-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 */
-};
-
-
-
/**************************************************************************/
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
#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"
#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)
*/
#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
#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 *
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) {
-/* 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,
/* 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:
*/
{
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;
}
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;
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;
- }
}