/*
 * Author: Max Lingua <sunmax@libero.it>
 */

#include "main/glheader.h"
#include "main/context.h"
#include "main/macros.h"
#include "main/mtypes.h"

#include "tnl/t_context.h"

#include "s3v_context.h"
#include "s3v_tris.h"
#include "s3v_vb.h"


#define HAVE_POINTS      0
#define HAVE_LINES       0
#define HAVE_LINE_STRIPS 0
#define HAVE_TRIANGLES   0
#define HAVE_TRI_STRIPS  0
#define HAVE_TRI_STRIP_1 0
#define HAVE_TRI_FANS    0
#define HAVE_QUADS       0
#define HAVE_QUAD_STRIPS 0
#define HAVE_POLYGONS    0

#define HAVE_ELTS        0

#if 0
static void VERT_FALLBACK( GLcontext *ctx,
			   GLuint start,
			   GLuint count,
			   GLuint flags )
{
	TNLcontext *tnl = TNL_CONTEXT(ctx);
/*	s3vContextPtr vmesa = S3V_CONTEXT(ctx); */
	int _flags;
   
	DEBUG(("VERT_FALLBACK: flags & PRIM_MODE_MASK = %i\n",
		flags & PRIM_MODE_MASK));
	DEBUG(("VERT_FALLBACK: flags=%i PRIM_MODE_MASK=%i\n",
		flags, PRIM_MODE_MASK));
#if 0
	tnl->Driver.Render.PrimitiveNotify( ctx, flags & PRIM_MODE_MASK );
#endif
	tnl->Driver.Render.BuildVertices( ctx, start, count, ~0 );

	_flags = flags & PRIM_MODE_MASK;

	tnl->Driver.Render.PrimTabVerts[_flags]( ctx, start, count, flags );
	S3V_CONTEXT(ctx)->SetupNewInputs = VERT_BIT_POS;
}
#endif

static const GLuint hw_prim[GL_POLYGON+1] = {
	PrimType_Points,
	PrimType_Lines,
	PrimType_LineLoop,
	PrimType_LineStrip,
	PrimType_Triangles,
	PrimType_TriangleStrip,
	PrimType_TriangleFan,
	PrimType_Quads,
	PrimType_QuadStrip,
	PrimType_Polygon
};

static INLINE void s3vStartPrimitive( s3vContextPtr vmesa, GLenum prim )
{
	__DRIdrawablePrivate *dPriv = vmesa->driDrawable;

	int _hw_prim = hw_prim[prim];

	DEBUG(("s3vStartPrimitive (new #%i) ", prim));

	if (_hw_prim != vmesa->restore_primitive) {

		if (prim == 4) { /* TRI */
			DEBUG(("switching to tri\n"));
			vmesa->prim_cmd = vmesa->_tri[vmesa->_3d_mode];
			vmesa->alpha_cmd = vmesa->_alpha[vmesa->_3d_mode];
			DMAOUT_CHECK(3DTRI_Z_BASE, 12);
		} else if (prim == 1) { /* LINE */
			DEBUG(("switching to line\n"));
			vmesa->prim_cmd = DO_3D_LINE;
			vmesa->alpha_cmd = vmesa->_alpha[0];
			DMAOUT_CHECK(3DLINE_Z_BASE, 12);
		} else {
			DEBUG(("Never mind the bollocks!\n"));
		}

        	DMAOUT(vmesa->s3vScreen->depthOffset & 0x003FFFF8);
	        DMAOUT(vmesa->DestBase);
		/* DMAOUT(vmesa->ScissorLR); */
		/* DMAOUT(vmesa->ScissorTB); */
		DMAOUT( (0 << 16) | (dPriv->w-1) );
		DMAOUT( (0 << 16) | (dPriv->h-1) );
		DMAOUT( (vmesa->SrcStride << 16) | vmesa->TexStride );
		DMAOUT(vmesa->SrcStride);
		DMAOUT(vmesa->TexOffset);
		DMAOUT(vmesa->TextureBorderColor);
		DMAOUT(0); /* FOG */
		DMAOUT(0);
		DMAOUT(0);
	        DMAOUT(vmesa->CMD | vmesa->prim_cmd | vmesa->alpha_cmd);
		DMAFINISH();
   	}

	vmesa->restore_primitive = _hw_prim;
}

static INLINE void s3vEndPrimitive( s3vContextPtr vmesa )
{
/*	GLcontext *ctx = vmesa->glCtx; */
	DEBUG(("s3vEndPrimitive\n"));
}

#define LOCAL_VARS s3vContextPtr vmesa = S3V_CONTEXT(ctx)
#define INIT( prim ) s3vStartPrimitive( vmesa, prim )
#define FINISH s3vEndPrimitive( vmesa )
#define NEW_PRIMITIVE() (void) vmesa
#define NEW_BUFFER() (void) vmesa
#define FIRE_VERTICES() (void) vmesa
#define GET_CURRENT_VB_MAX_VERTS() \
	(vmesa->bufSize - vmesa->bufCount) / 2
#define GET_SUBSEQUENT_VB_MAX_VERTS() \
	S3V_DMA_BUF_SZ / 2
/* XXX */
#define ALLOC_VERTS(nr) NULL
#define EMIT_VERTS(ctx, start, count, buf) NULL
#define FLUSH() s3vEndPrimitive( vmesa )

#define TAG(x) s3v_##x

#include "tnl_dd/t_dd_dmatmp.h"

/**********************************************************************/
/*                          Render pipeline stage                     */
/**********************************************************************/


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 */
}



const struct tnl_pipeline_stage _s3v_render_stage =
{
	"s3v render",
	NULL,
	NULL,
	NULL,
	NULL,
	 s3v_run_render		/* run */
};
