#include "glheader.h"
#include "imports.h"
#include "mtypes.h"
#include "enums.h"
#include "colormac.h"
#include "light.h"
#include "array_cache/acache.h"
#include "tnl/tnl.h"
#include "tnl/t_pipeline.h"
#include "r200_context.h"
#include "r200_state.h"
#include "r200_ioctl.h"
#include "r200_tex.h"
#include "r200_tcl.h"
#include "r200_swtcl.h"
#include "r200_maos.h"
#define HAVE_POINTS 1
#define HAVE_LINES 1
#define HAVE_LINE_LOOP 0
#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 1
#define HAVE_POLYGONS 1
#define HAVE_ELTS 1
#define HW_POINTS R200_VF_PRIM_POINTS
#define HW_LINES R200_VF_PRIM_LINES
#define HW_LINE_LOOP 0
#define HW_LINE_STRIP R200_VF_PRIM_LINE_STRIP
#define HW_TRIANGLES R200_VF_PRIM_TRIANGLES
#define HW_TRIANGLE_STRIP_0 R200_VF_PRIM_TRIANGLE_STRIP
#define HW_TRIANGLE_STRIP_1 0
#define HW_TRIANGLE_FAN R200_VF_PRIM_TRIANGLE_FAN
#define HW_QUADS R200_VF_PRIM_QUADS
#define HW_QUAD_STRIP R200_VF_PRIM_QUAD_STRIP
#define HW_POLYGON R200_VF_PRIM_POLYGON
static GLboolean discrete_prim[0x10] = {
0,
1,
1,
0,
1,
0,
0,
0,
1,
1,
1,
0,
0,
1,
0,
0,
};
#define LOCAL_VARS r200ContextPtr rmesa = R200_CONTEXT(ctx)
#define ELT_TYPE GLushort
#define ELT_INIT(prim, hw_prim) \
r200TclPrimitive( ctx, prim, hw_prim | R200_VF_PRIM_WALK_IND )
#define GET_MESA_ELTS() rmesa->tcl.Elts
#define GET_MAX_HW_ELTS() 300
#define RESET_STIPPLE() do { \
R200_STATECHANGE( rmesa, lin ); \
r200EmitState( rmesa ); \
} while (0)
#define AUTO_STIPPLE( mode ) do { \
R200_STATECHANGE( rmesa, lin ); \
if (mode) \
rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] |= \
R200_LINE_PATTERN_AUTO_RESET; \
else \
rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] &= \
~R200_LINE_PATTERN_AUTO_RESET; \
r200EmitState( rmesa ); \
} while (0)
#define ALLOC_ELTS(nr) r200AllocElts( rmesa, nr )
static GLushort *r200AllocElts( r200ContextPtr rmesa, GLuint nr )
{
if (rmesa->dma.flush)
rmesa->dma.flush( rmesa );
r200EmitAOS( rmesa,
rmesa->tcl.aos_components,
rmesa->tcl.nr_aos_components, 0 );
return r200AllocEltsOpenEnded( rmesa, rmesa->tcl.hw_primitive, nr );
}
#define CLOSE_ELTS() R200_NEWPRIM( rmesa )
static void EMIT_PRIM( GLcontext *ctx,
GLenum prim,
GLuint hwprim,
GLuint start,
GLuint count)
{
r200ContextPtr rmesa = R200_CONTEXT( ctx );
r200TclPrimitive( ctx, prim, hwprim );
r200EmitAOS( rmesa,
rmesa->tcl.aos_components,
rmesa->tcl.nr_aos_components,
start );
r200EmitVbufPrim( rmesa,
rmesa->tcl.hw_primitive,
count - start );
}
#if 0
#define PREFER_DISCRETE_ELT_PRIM( NR, PRIM ) 0
#else
#define PREFER_DISCRETE_ELT_PRIM( NR, PRIM ) \
((NR) < 20 || \
((NR) < 40 && \
rmesa->tcl.hw_primitive == (PRIM| \
R200_VF_TCL_OUTPUT_VTX_ENABLE| \
R200_VF_PRIM_WALK_IND)))
#endif
#ifdef MESA_BIG_ENDIAN
#define EMIT_ELT(dest, 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(dest, offset, x) (dest)[offset] = (GLushort) (x)
#endif
#define EMIT_TWO_ELTS(dest, offset, x, y) *(GLuint *)((dest)+offset) = ((y)<<16)|(x);
#define TAG(x) tcl_##x
#include "tnl_dd/t_dd_dmatmp2.h"
void r200EmitPrimitive( GLcontext *ctx,
GLuint first,
GLuint last,
GLuint flags )
{
tcl_render_tab_verts[flags&PRIM_MODE_MASK]( ctx, first, last, flags );
}
void r200EmitEltPrimitive( GLcontext *ctx,
GLuint first,
GLuint last,
GLuint flags )
{
tcl_render_tab_elts[flags&PRIM_MODE_MASK]( ctx, first, last, flags );
}
void r200TclPrimitive( GLcontext *ctx,
GLenum prim,
int hw_prim )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
GLuint newprim = hw_prim | R200_VF_TCL_OUTPUT_VTX_ENABLE;
if (newprim != rmesa->tcl.hw_primitive ||
!discrete_prim[hw_prim&0xf]) {
R200_NEWPRIM( rmesa );
rmesa->tcl.hw_primitive = newprim;
}
}
static GLboolean r200_run_tcl_render( GLcontext *ctx,
struct gl_pipeline_stage *stage )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
GLuint i,flags = 0,length;
if (rmesa->TclFallback)
return GL_TRUE;
if (R200_DEBUG & DEBUG_PRIMS)
fprintf(stderr, "%s\n", __FUNCTION__);
if (VB->Count == 0)
return GL_FALSE;
r200ReleaseArrays( ctx, ~0 );
r200EmitArrays( ctx, stage->inputs );
rmesa->tcl.Elts = VB->Elts;
for (i = VB->FirstPrimitive ; !(flags & PRIM_LAST) ; i += length)
{
flags = VB->Primitive[i];
length = VB->PrimitiveLength[i];
if (R200_DEBUG & DEBUG_PRIMS)
fprintf(stderr, "%s: prim %s %d..%d\n",
__FUNCTION__,
_mesa_lookup_enum_by_nr(flags & PRIM_MODE_MASK),
i, i+length);
if (!length)
continue;
if (rmesa->tcl.Elts)
r200EmitEltPrimitive( ctx, i, i+length, flags );
else
r200EmitPrimitive( ctx, i, i+length, flags );
}
return GL_FALSE;
}
static void r200_check_tcl_render( GLcontext *ctx,
struct gl_pipeline_stage *stage )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
GLuint inputs = VERT_BIT_POS;
if (rmesa->NewGLState)
r200ValidateState( ctx );
if (ctx->RenderMode == GL_RENDER) {
if (ctx->Light.Enabled) {
inputs |= VERT_BIT_NORMAL;
if (1 || ctx->Light.ColorMaterialEnabled) {
inputs |= VERT_BIT_COLOR0;
}
}
else {
inputs |= VERT_BIT_COLOR0;
if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) {
inputs |= VERT_BIT_COLOR1;
}
}
if (ctx->Texture.Unit[0]._ReallyEnabled) {
if (ctx->Texture.Unit[0].TexGenEnabled) {
if (rmesa->TexGenNeedNormals[0]) {
inputs |= VERT_BIT_NORMAL;
}
} else {
inputs |= VERT_BIT_TEX0;
}
}
if (ctx->Texture.Unit[1]._ReallyEnabled) {
if (ctx->Texture.Unit[1].TexGenEnabled) {
if (rmesa->TexGenNeedNormals[1]) {
inputs |= VERT_BIT_NORMAL;
}
} else {
inputs |= VERT_BIT_TEX1;
}
}
stage->inputs = inputs;
stage->active = 1;
}
else
stage->active = 0;
}
static void r200_init_tcl_render( GLcontext *ctx,
struct gl_pipeline_stage *stage )
{
stage->check = r200_check_tcl_render;
stage->check( ctx, stage );
}
static void dtr( struct gl_pipeline_stage *stage )
{
(void)stage;
}
const struct gl_pipeline_stage _r200_tcl_stage =
{
"r200 render",
(_DD_NEW_SEPARATE_SPECULAR |
_NEW_LIGHT|
_NEW_TEXTURE|
_NEW_FOG|
_NEW_RENDERMODE),
0,
GL_TRUE,
0, 0,
0, 0,
dtr,
r200_init_tcl_render,
r200_run_tcl_render
};
static void transition_to_swtnl( GLcontext *ctx )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
R200_NEWPRIM( rmesa );
rmesa->swtcl.vertex_format = 0;
r200ChooseVertexState( ctx );
r200ChooseRenderState( ctx );
_mesa_validate_all_lighting_tables( ctx );
tnl->Driver.NotifyMaterialChange =
_mesa_validate_all_lighting_tables;
r200ReleaseArrays( ctx, ~0 );
R200_STATECHANGE( rmesa, vap );
rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] &= ~R200_VAP_TCL_ENABLE;
rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] |= R200_VAP_D3D_TEX_DEFAULT;
R200_STATECHANGE( rmesa, vte );
rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] &= ~R200_VTX_W0_FMT;
R200_STATECHANGE( rmesa, set );
rmesa->hw.set.cmd[SET_RE_CNTL] |= (R200_VTX_STQ0_D3D |
R200_VTX_STQ1_D3D);
}
static void transition_to_hwtnl( GLcontext *ctx )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
_tnl_need_projected_coords( ctx, GL_FALSE );
r200UpdateMaterial( ctx );
tnl->Driver.NotifyMaterialChange = r200UpdateMaterial;
if ( rmesa->dma.flush )
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,
__FUNCTION__ );
R200_STATECHANGE( rmesa, vap );
rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] |= R200_VAP_TCL_ENABLE;
rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] &= ~(R200_VAP_FORCE_W_TO_ONE |
R200_VAP_D3D_TEX_DEFAULT);
R200_STATECHANGE( rmesa, vte );
rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] &= ~(R200_VTX_XY_FMT|R200_VTX_Z_FMT);
rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] |= R200_VTX_W0_FMT;
R200_STATECHANGE( rmesa, set );
rmesa->hw.set.cmd[SET_RE_CNTL] &= ~(R200_VTX_STQ0_D3D |
R200_VTX_STQ1_D3D);
if (R200_DEBUG & DEBUG_FALLBACKS)
fprintf(stderr, "R200 end tcl fallback\n");
}
static char *fallbackStrings[] = {
"Rasterization fallback",
"Unfilled triangles",
"Twosided lighting, differing materials",
"Materials in VB (maybe between begin/end)",
"Texgen unit 0",
"Texgen unit 1",
"Texgen unit 2",
"User disable"
};
static char *getFallbackString(GLuint bit)
{
int i = 0;
while (bit > 1) {
i++;
bit >>= 1;
}
return fallbackStrings[i];
}
void r200TclFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
GLuint oldfallback = rmesa->TclFallback;
if (mode) {
rmesa->TclFallback |= bit;
if (oldfallback == 0) {
if (R200_DEBUG & DEBUG_FALLBACKS)
fprintf(stderr, "R200 begin tcl fallback %s\n",
getFallbackString( bit ));
transition_to_swtnl( ctx );
}
}
else {
rmesa->TclFallback &= ~bit;
if (oldfallback == bit) {
if (R200_DEBUG & DEBUG_FALLBACKS)
fprintf(stderr, "R200 end tcl fallback %s\n",
getFallbackString( bit ));
transition_to_hwtnl( ctx );
}
}
}