/****************************************************************************\
*                                                                           *
* tpKamui.c -   TrueMotion player video hardware/system specific interface  *
*              Based on Kamui texture sample 6 provided by NEC/VideoLogic   *
*                                                                           *
*                                                                           *
*       for TruePlay2 (mpve 7.0.0)                                          *
*                                                                           *
*       Created: 12/23/98                                                   *
*                                                                           *
\***************************************************************************/
#include	<stdio.h>

#ifndef _KM_USE_VERTEX_MACRO_L3_
	#define _KM_USE_VERTEX_MACRO_L3_
#endif

#include	"kamui.h"				/* for Kamui Calls */
#include	"kamuix.h"		/* for Kamui calls */

#include "tpApi.h"

#define GET_AVGE 1

/* Size of vertex buffer. */
#define VBUFFER_SIZE    8*3*2000

/****************************************************************************/
/**	Valuables for KAMUI *****************************************************/
/****************************************************************************/
static	KMSTATUS			status;
static	KMVERSIONINFO		VersionInfo;			/* KAMUI Version information */
static	KMSURFACEDESC		PrimarySurfaceDesc;		/* Primary frame buffer */
static	KMSURFACEDESC		BackSurfaceDesc;		/* Back-buffer frame buffer */
KMSURFACEDESC		vidTexSurfaceDesc1;		/* texture surface */
extern	KMVERTEXBUFFDESC	VertexBufferDesc;		/* Vertex-buffer */
static	KMVERTEXCONTEXT		VertexContext01;		/* Vertex context */
static	KMVERTEX_05			V[4];					/* Vertex */
static	PKMDWORD			pTexture01;				/* Pointer to texture */
static	KMTEXTURETYPE		nTextureType;			/* texture type definition */
static	KMINT32				nStrideWidth;			/* texture stride width */

/* System Configuration */

static PKMSURFACEDESC          psurface[2];            /* array of pointers to surfaces */
static KMPACKEDARGB            border;

static KMSYSTEMCONFIGSTRUCT kmsc = {
		sizeof(KMSYSTEMCONFIGSTRUCT),
		KM_CONFIGFLAG_ENABLE_CLEAR_FRAMEBUFFER |
		KM_CONFIGFLAG_NOWAIT_FINISH_TEXTUREDMA,	/* set any special flags = clear frame buffer */
        psurface,                               /* pointer to array of surface pointers */
        2,                                      /* number of buffers = 2 */
        640,480,                                /* width and height of surface */
        KM_DSPBPP_RGB565,                       /* bits per pixel */
        0x100000,                               /* allocate amount of VRAM for texture = 4MB */
        &VertexBufferDesc,                      /* pointer to vertex buffer descriptor */
        0,                                      /* pointer to vertex buffer - ** malloc now on application side */
		2*VBUFFER_SIZE,							/* size in DWORDS of vertex buffer - must be multiple of 32 */
        {50.f,0.f,50.f,0.f,0.f},                /* percentage of vbuf to use for each type of vertex */
        0,0,0,0,0,0,0,                          /* reserved */
        KM_VERTEXBUFMODEL_NORMAL                /* latency model = 3VB */
	};

/****************************************************************************/
/**	Check KAMUI function status *********************************************/
/****************************************************************************/
void	Check_Status(KMSTATUS status, char * func)
{
}

/****************************************************************************/
/**	Initialize Vertex Context ***********************************************/
/****************************************************************************/
void	InitVertexContext(PKMVERTEXCONTEXT pVertexContext)
{
	/* 頂点CONTEXTの生成 */
	pVertexContext->RenderState	= KM_DEPTHMODE  		| KM_CULLINGMODE				/* ISP/TSP IW */
								| KM_SCREENCOORDINATION	| KM_SHADINGMODE
								| KM_MODIFIER 			| KM_ZWRITEDISABLE				/* TSP CW */
								| KM_SRCBLENDINGMODE	| KM_DSTBLENDINGMODE
								| KM_SRCSELECT			| KM_DSTSELECT
								| KM_FOGMODE			| KM_USESPECULAR
								| KM_USEALPHA			| KM_IGNORETEXTUREALPHA
								| KM_FLIPUV 			| KM_CLAMPUV
								| KM_FILTERMODE			| KM_SUPERSAMPLE
								| KM_MIPMAPDADJUST 		| KM_TEXTURESHADINGMODE
								| KM_PARAMTYPE 			| KM_LISTTYPE 					/* Param CW */
								| KM_COLORTYPE			| KM_USESPECULAR
								| KM_UVFORMAT;

	/* for ParameterControlWord  */
	pVertexContext->ParamType			= KM_POLYGON;
	pVertexContext->ListType			= KM_OPAQUE_POLYGON;
	pVertexContext->ColorType			= KM_FLOATINGCOLOR;
	pVertexContext->bUseSpecular		= FALSE;
	pVertexContext->UVFormat			= KM_32BITUV;

	/* for ISP/TSP InstructionWord  */
	pVertexContext->DepthMode			= KM_GREATER;
	pVertexContext->CullingMode			= KM_NOCULLING;
	pVertexContext->ScreenCoordination	= KM_SCREEN;
	pVertexContext->ShadingMode			= KM_NOTEXTUREGOURAUD;
	pVertexContext->SelectModifier		= KM_NOMODIFIER;
	pVertexContext->bZWriteDisable		= FALSE;			/* ARC1にはない */

	/* for TSP ControlWord  */
	pVertexContext->SRCBlendingMode		= KM_ONE;
	pVertexContext->DSTBlendingMode		= KM_ZERO;
	pVertexContext->bSRCSel				= FALSE;			/* ARC1にはない */
	pVertexContext->bDSTSel				= FALSE;			/* ARC1にはない */
	pVertexContext->FogMode				= KM_NOFOG;			/* 11はリザーブ */
	pVertexContext->bUseSpecular		= FALSE;
	pVertexContext->bUseAlpha			= FALSE;
	pVertexContext->FlipUV				= KM_NOFLIP;
	pVertexContext->ClampUV				= KM_NOCLAMP;
	pVertexContext->FilterMode			= KM_POINT_SAMPLE;
	pVertexContext->bSuperSample		= FALSE;
	pVertexContext->MipMapAdjust		= 0x00000004;		/* D=1.00 */
	pVertexContext->TextureShadingMode	= KM_MODULATE;

	/* for Texture ControlBit */

	/* No effect on ARC1 */
	pVertexContext->bColorClamp		= FALSE;
	pVertexContext->PaletteBank		= 0;

	/* for GlobalColorData */
	pVertexContext->fFaceColorAlpha		= 1.0f;		/* Face Color Alpha */
	pVertexContext->fFaceColorRed		= 1.0f;		/* Face Color Red */
	pVertexContext->fFaceColorGreen		= 1.0f;		/* Face Color Green */
	pVertexContext->fFaceColorBlue		= 1.0f;		/* Face Color Blue */
	pVertexContext->fOffsetColorAlpha	= 1.0f;		/* Specular Color Alpha */
	pVertexContext->fOffsetColorRed		= 1.0f;		/* Specular Color Red */
	pVertexContext->fOffsetColorGreen	= 1.0f;		/* Specular Color Green */
	pVertexContext->fOffsetColorBlue	= 1.0f;		/* Specular Color Blue */

	kmProcessVertexRenderState(pVertexContext);
}

/****************************************************************************/

#if GET_AVGE
int counted,total,count1;
#endif

void renderVideo(void)
{
	status = kmSetVertexRenderState(&VertexContext01);
	Check_Status(status, "kmSetVertexRenderState");

	kmxxGetCurrentPtr(&VertexBufferDesc);
	status = kmxxStartVertexStrip(&VertexBufferDesc);
	Check_Status(status, "kmStartVertexStrip");

	/*----------------------------------------------------------------------------------- */

	kmxxSetVertex_5(V[0].ParamControlWord, 
		V[0].fX, V[0].fY, V[0].u.fZ, V[0].fU, V[0].fV, 
		V[0].fBaseAlpha, V[0].fBaseRed, V[0].fBaseGreen, V[0].fBaseBlue, 
		V[0].fOffsetAlpha, V[0].fOffsetRed, V[0].fOffsetGreen, V[0].fOffsetBlue
		);

	kmxxSetVertex_5(V[1].ParamControlWord, 
		V[1].fX, V[1].fY, V[1].u.fZ, V[1].fU, V[1].fV, 
		V[1].fBaseAlpha, V[1].fBaseRed, V[1].fBaseGreen, V[1].fBaseBlue, 
		V[1].fOffsetAlpha, V[1].fOffsetRed, V[1].fOffsetGreen, V[1].fOffsetBlue
		);

	kmxxSetVertex_5(V[2].ParamControlWord, 
		V[2].fX, V[2].fY, V[2].u.fZ, V[2].fU, V[2].fV, 
		V[2].fBaseAlpha, V[2].fBaseRed, V[2].fBaseGreen, V[2].fBaseBlue, 
		V[2].fOffsetAlpha, V[2].fOffsetRed, V[2].fOffsetGreen, V[2].fOffsetBlue
		);

	kmxxSetVertex_5(V[3].ParamControlWord, 
		V[3].fX, V[3].fY, V[3].u.fZ, V[3].fU, V[3].fV, 
		V[3].fBaseAlpha, V[3].fBaseRed, V[3].fBaseGreen, V[3].fBaseBlue, 
		V[3].fOffsetAlpha, V[3].fOffsetRed, V[3].fOffsetGreen, V[3].fOffsetBlue
		);

	kmxxReleaseCurrentPtr(&VertexBufferDesc);

	Check_Status(status, "kmSetVertex(#4)");

	status = kmSetStrideWidth(nStrideWidth);
}
static PLAYER_STATUS_CODE tp_afterDecompress(MovieHandle movie)
{
	PKMDWORD			pTexture01;				/* Pointer to texture */

#if GET_AVGE
	total += syTmrDiffCount(count1, syTmrGetCount());
#endif

	/* flush the decompressed frame from the SH4 cache */
	{
		unsigned long entry;

		for(entry = 0; entry < 512; entry++){
		  *((volatile unsigned long *)(0xF4000000 | (entry << 5))) = 0x00000000; 
		  /* OC address array write */
		}
	}

	/* how to download a frame to the display... */
	/* 
		since the internal format of the xImage matches the 
		UYVY format of the texture, the application transfers it 
		directly to the powerVR
	*/
	
	{
		int x,y,w,h;

		DXL_GetXImageXYWH(movie->xImage, &x, &y, &w, &h);

		status = kmLoadTexturePart(&vidTexSurfaceDesc1,	/* PKMSURFACEDESC pSurfaceDesc */
								DXL_GetXImageFrameBuffer(movie->xImage),			/* PKMDWORD pTexture */
								0, /* offset */
								(w*h)<<1 /* size of part */
								);
	}

	return TP_OK;
}

static PLAYER_STATUS_CODE tp_beforeDecompress(MovieHandle movie)
{
#if GET_AVGE
	counted++;
	count1 = syTmrGetCount();
#endif
	return TP_OK;
}

static PLAYER_STATUS_CODE tp_centerScreen(MovieHandle movie) 
{
	/* called when screen geometry changes */
	int x, y, w, h, tw, th;
	float	x1, y1, x2, y2;

	total = counted = 0;

	DXL_GetXImageXYWH(movie->xImage, &x, &y, &w, &h);

	th = (h < 256) ? 256 : (h < 512) ? 512 : 1024;
	tw = (w < 256) ? 256 : (w < 512) ? 512 : 1024;

	/* Free texture Surface (assuming that one already exists) */
	status = kmFreeTexture(&vidTexSurfaceDesc1);
	Check_Status(status, "kmFreeTexture");

	status = kmCreateTextureSurface(
		&vidTexSurfaceDesc1,		/* OUT	PKMSURFACEDESC	pSurfaceDesc */
		tw,					/*	IN	KMINT32			nWidth  */
		th,					/*	IN	KMINT32			nHeight  */
		nTextureType			/*	IN	KMTEXTURETYPE	nTextureType */
	);

	Check_Status(status, "kmCreateTextureSurface");

	/* Set texture surface */
	VertexContext01.pTextureSurfaceDesc	= &vidTexSurfaceDesc1;

	/* Process & Set */
	status = kmProcessVertexRenderState(&VertexContext01);
	Check_Status(status, "kmProcessVertexRenderState");

	/* this sets the geometry for the textured polygon */

	x1 = ((w*640)/w);
	y1 = (480-((h*640)/w))/2.0;
	y2 = ((h*640)/w) + y1;

	V[0].fY	= V[2].fY	= y1;
	V[0].fX	= V[1].fX	= 00;

	V[1].fY	= V[3].fY	= y2;
	V[2].fX	= V[3].fX	= x1;

	V[0].fV = V[2].fV = 0.f;
	V[0].fU = V[1].fU = 0.f;

	V[2].fU = V[3].fU = (float)w/(float)tw;
	V[1].fV = V[3].fV = (float)h/(float)th;

	VertexContext01.pTextureSurfaceDesc	= &vidTexSurfaceDesc1;

	/*----------------------------------------------------------------------------------- */
	/* Start Triangle strip */
	status = kmSetVertexRenderState(&VertexContext01);
	status = kmStartVertexStrip(&VertexBufferDesc);

	/*----------------------------------------------------------------------------------- */
	/* set vertex data */
	status = kmSetVertex(	&VertexBufferDesc,		/* pBufferDesc */
							&V[0],					/* pVertex */
							KM_VERTEXTYPE_05,		/* VertexType */
							sizeof(KMVERTEX_05)		/* StructSize */
							);

	status = kmSetVertex(	&VertexBufferDesc,		/* pBufferDesc */
							&V[1],					/* pVertex */
							KM_VERTEXTYPE_05,		/* VertexType */
							sizeof(KMVERTEX_05)		/* StructSize */
							);

	status = kmSetVertex(	&VertexBufferDesc,		/* pBufferDesc */
							&V[2],					/* pVertex */
							KM_VERTEXTYPE_05,		/* VertexType */
							sizeof(KMVERTEX_05)		/* StructSize */
							);

	status = kmSetVertex(	&VertexBufferDesc,		/* pBufferDesc */
							&V[3],					/* pVertex */
							KM_VERTEXTYPE_05,		/* VertexType */
							sizeof(KMVERTEX_05)		/* StructSize */
							);

	/* set stride width */
	nStrideWidth = w;		/* Initialize stride width */
	status = kmSetStrideWidth(nStrideWidth);

	return TP_OK;

}

void *tmppVtx = (void *)0L;

static PLAYER_STATUS_CODE tp_restoreDisplay(MovieHandle movie) 
{
	return TP_OK;
	
	status = kmResetRenderer();

	/* release graphics resources (texture) */

	/* Free vertex buffer */
	status = kmDiscardVertexBuffer(&VertexBufferDesc);
	Check_Status(status, "kmDiscadeVertexBuffer");

	/*----------------------------------------------------------------------------------- */
	/* Free texture Surface */
	status = kmFreeTexture(&vidTexSurfaceDesc1);
	Check_Status(status, "kmFreeTexture");

	/*----------------------------------------------------------------------------------- */

	/* End display */
	status = kmStopDisplayFrameBuffer();
	Check_Status(status, "kmStopDisplayFrameBuffer");

	if (tmppVtx) syFree(tmppVtx);

	return TP_OK;
}

void clearVertex(KMVERTEX_05 *vPtr, int paramControl)
{
	vPtr[0].ParamControlWord	= paramControl;
	vPtr[0].fX					= 0.0f;
	vPtr[0].fY					= 0.0f;
#if defined(_STRICT_UNION_)
	vPtr[0].u.fZ				=  0.00002f;
#else
	vPtr[0].fZ					=  0.5f;
#endif
	vPtr[0].fU					=  0.0f;
	vPtr[0].fV					=  0.0f;
	vPtr[0].fBaseAlpha			=  1.0f;
	vPtr[0].fBaseRed			=  1.0f;
	vPtr[0].fBaseGreen			=  1.0f;
	vPtr[0].fBaseBlue			=  1.0f;
	vPtr[0].fOffsetAlpha		=  1.0f;
	vPtr[0].fOffsetRed			=  0.0f;
	vPtr[0].fOffsetGreen		=  0.0f;
	vPtr[0].fOffsetBlue		=  0.0f;
}

PLAYER_STATUS_CODE tp_setupDisplay(MovieHandle movie)
{
	static int iter = 0;
	
	movie->beforeDecompress = tp_beforeDecompress;
	movie->afterDecompress = tp_afterDecompress;
	movie->restoreDisplay = tp_restoreDisplay;
	movie->centerScreen = tp_centerScreen;

	/* initialize our 4 simple vertices */

	clearVertex(&V[0],KM_VERTEXPARAM_NORMAL);
	clearVertex(&V[1],KM_VERTEXPARAM_NORMAL);
	clearVertex(&V[2],KM_VERTEXPARAM_NORMAL);
	clearVertex(&V[3],KM_VERTEXPARAM_ENDOFSTRIP);

	border.dwPacked	=	0x00000000;
	kmSetBorderColor(border);
    Check_Status(status, "kmSetBorderColor");

    psurface[0]         =   &PrimarySurfaceDesc;
    psurface[1]         =   &BackSurfaceDesc;

	/*-----------------------------------------------------------------------------------*/
	/* Create a texture surface big enough to display 640x480 (or up to 1024x512)  */

	nTextureType = KM_TEXTURE_STRIDE | KM_TEXTURE_YUV422;	/* Set texture type */
	status = kmCreateTextureSurface(
		&vidTexSurfaceDesc1,		/* OUT	PKMSURFACEDESC	pSurfaceDesc */
		1024,					/*	IN	KMINT32			nWidth  */
		512,					/*	IN	KMINT32			nHeight  */
		nTextureType			/*	IN	KMTEXTURETYPE	nTextureType */
	);
	Check_Status(status, "kmCreateTextureSurface");

	/*----------------------------------------------------------------------------------- */
	/* set VERTEXCONTEXT */
	memset( &VertexContext01, 0, sizeof(VertexContext01));	/* Clear Context */
	InitVertexContext( &VertexContext01);

	VertexContext01.RenderState	= 0;
	/* Set parameter type */
	VertexContext01.RenderState	|= KM_PARAMTYPE;
	VertexContext01.ParamType	= KM_POLYGON;
	/* Set list type */
	VertexContext01.RenderState	|= KM_LISTTYPE;
	VertexContext01.ListType	= KM_OPAQUE_POLYGON;
	/* Set color type */
	VertexContext01.RenderState	|= KM_COLORTYPE;
	VertexContext01.ColorType	= KM_FLOATINGCOLOR;

	/* Set shading mode */
	VertexContext01.RenderState	|= KM_SHADINGMODE;
	VertexContext01.ShadingMode	= KM_TEXTUREFLAT;
	
	/* Set texture surface */
	VertexContext01.pTextureSurfaceDesc	= &vidTexSurfaceDesc1;

	VertexContext01.RenderState	|= KM_FILTERMODE;
	VertexContext01.FilterMode	= KM_TRILINEAR_B;

	/* Process & Set */
	status = kmProcessVertexRenderState(&VertexContext01);
	Check_Status(status, "kmProcessVertexRenderState");

	return TP_OK;
}

