//
// Asura_PS3_QuadOverlayRenderer.cpp
//
// Created by KJFL - 03 August 2005
//
// Copyright (C) 2005 Rebellion, All Rights Reserved.
//

#include "Core/Asura.h"

// This file's header.
#include "Rendering/Asura_PS3_QuadOverlayRenderer.h"

// Asura independent
#include "Core/Asura_Maths.h"
#include "Rendering/Asura_Render.h"
#include "Rendering/Asura_Viewport.h"

// Asura PS3
#include "Rendering/Shaders/Asura_PS3_GCM_Shader.h"
#include "Rendering/Asura_PS3_Graphics.h"
#include "Rendering/Asura_PS3_FrameBuffer.h"
#include "Rendering/Asura_PS3_GCM_IndexBuffer.h"
#include "Rendering/Asura_PS3_RenderingOptions.h"
#include "Rendering/Asura_PS3_RSXProfiling.h"
#include "Rendering/Asura_PS3_TextureManagement.h"
#include "Rendering/Asura_PS3_RenderingStates.h"

//Shaders definition
#include "Rendering/ShadersDefinition/VD/OverlayQuad_VD.h"
#include "Rendering/ShadersDefinition/VP/OverlayQuad_VP.h"
#include "Rendering/ShadersDefinition/FP/OverlayQuad_FP.h"

// I N T E R N A L   C L A S S E S ///////////////////////////////////////////
struct Asura_PS3_QuadOverlay_Vertex
{
	float m_fX, m_fY;
	float m_fU, m_fV;
	u_int m_uColour;
};

// C O N S T A N T S /////////////////////////////////////////////////////////
#define ASURA_PS3_MAXIMUM_BATCH_SIZE		8192
Asura_PS3_GCM_VertexBuffer		Asura_PS3_QuadOverlayRenderer::s_xVertexBuffer[ ASURA_QUAD_BUFFERS ];
#ifdef ASURA_PS3_USE_GAMMA_CORRECTION
float							Asura_PS3_QuadOverlayRenderer::m_fGamma = 1.0f;
#endif

// Vertex declarations...

static Asura_PS3_GCM_VertexShader*			g_pxVertexShader							= NULL;

static Asura_PS3_FragmentShader*			g_pxFragmentShader							= NULL;
static Asura_PS3_FragmentShader*			g_pxFragmentShaderFudgedGamma				= NULL;
static Asura_PS3_FragmentShader*			g_pxFragmentShaderHDR						= NULL;
static Asura_PS3_QuadOverlay_Handles*		g_pxQuadHandles								= NULL;
static Asura_PS3_QuadOverlay_FudgedGamma_Handles*		g_pxQuadFGHandles				= NULL;
static Asura_PS3_QuadOverlay_HDR_Handles*	g_pxQuadHandlesHDR							= NULL;
#ifdef ASURA_PS3_USE_GAMMA_CORRECTION
static Asura_PS3_FragmentShader*			g_pxFragmentShaderGamma						= NULL;
static Asura_PS3_QuadOverlay_Gamma_Handles*	g_pxQuadHandlesGamma						= NULL;
#endif

static int									g_iCurrentVertex							= 0;
static int									g_iStartFromVertex							= 0;
static int									g_iLastTexture								= ASURA_TEXTURE_INVALID;
static ASURA_TRANSLUCENCY_MODE				g_eLastTranslucency							= ASURA_TRANSLUCENCY_NOT_SET;
static int									g_iCurrentRenderBuffer						= 0;
static Asura_Overlay_Quad					g_xQuad;


//int g_iFudgedShader;
//int g_iFudgedSRGB;

Asura_PS3_FragmentShader *GetOverlayQuadShader()
{
//	if (g_iFudgedShader == 0)
	{
		return Asura_PS3_DeferredRendering::IsRenderingToFrontBuffer() ? g_pxFragmentShader : g_pxFragmentShaderFudgedGamma;
	} 
// 	else if (g_iFudgedShader == 1) 
// 	{
// 		return g_pxFragmentShader;
// 	} 
// 	else 
// 	{
// 		return g_pxFragmentShaderFudgedGamma;
// 	}
}
bool GetWantedSRGBFlag()
{
// 	if (g_iFudgedSRGB == 0)
// 	{
// 		return Asura_PS3_DeferredRendering::IsRenderingToFrontBuffer();
// 	} 
// 	else if (g_iFudgedSRGB == 1) 
// 	{
// 		return true;
// 	} 
// 	else 
// 	{
		return false;
//	}
}


void Asura_PS3_QuadOverlayRenderer::Initialise( void )
{
	// Load the shaders...
	g_pxVertexShader		= new Asura_PS3_VP_QuadOverlay();
	g_pxQuadHandles			= new Asura_PS3_QuadOverlay_Handles();
	g_pxQuadHandlesHDR		= new Asura_PS3_QuadOverlay_HDR_Handles();
	g_pxQuadFGHandles		= new Asura_PS3_QuadOverlay_FudgedGamma_Handles();
	g_pxFragmentShader		= new Asura_PS3_FragmentShader( (unsigned char *)&_binary_PS3_Overlay_Quad_FP_bin_start, (unsigned char *)&_binary_PS3_Overlay_Quad_FP_bin_end, g_pxQuadHandles );
	g_pxFragmentShaderFudgedGamma		= new Asura_PS3_FragmentShader( (unsigned char *)&_binary_PS3_Overlay_Quad_FudgedGamma_FP_bin_start, (unsigned char *)&_binary_PS3_Overlay_Quad_FudgedGamma_FP_bin_end, g_pxQuadFGHandles );
	g_pxFragmentShaderHDR	= new Asura_PS3_FragmentShader( (unsigned char *)&_binary_PS3_Overlay_Quad_HDR_FP_bin_start, (unsigned char *)&_binary_PS3_Overlay_Quad_HDR_FP_bin_end, g_pxQuadHandlesHDR );
#ifdef ASURA_PS3_USE_GAMMA_CORRECTION
	g_pxQuadHandlesGamma		= new Asura_PS3_QuadOverlay_Gamma_Handles();
	g_pxFragmentShaderGamma		= new Asura_PS3_FragmentShader( (unsigned char *)&_binary_PS3_Overlay_Quad_Gamma_FP_bin_start, (unsigned char *)&_binary_PS3_Overlay_Quad_Gamma_FP_bin_end, g_pxQuadHandlesGamma );
#endif
	g_pxVertexShader->InitVertexBufferDeclaration( g_axVertexDeclaration, VD_ELEMENTS );

	for( int i = 0; i < ASURA_QUAD_BUFFERS; ++i )
	{
		s_xVertexBuffer[ i ].Initialise( QUAD_OVERLAY_VERTEX_SIZE, ASURA_PS3_MAXIMUM_BATCH_SIZE, CELL_GCM_LOCATION_LOCAL );
	}

	g_xQuad.SetRectUV( 0.0f, 0.0f, 1.0f, 1.0f );
	g_xQuad.SetRectXY( 0.0f, 0.0f, Asura_PS3_Graphics::GetScreenWidth(), Asura_PS3_Graphics::GetScreenHeight() );
	g_xQuad.TextureIndex = ASURA_TEXTURE_NONE;
	g_xQuad.TranslucencyMode = ASURA_TRANSLUCENCY_OFF;
	g_xQuad.Colour = 0xFFFFFFFF;
}

void Asura_PS3_QuadOverlayRenderer::RenderHDR( void )
{
	ASURA_PS3_RSX_PROFILE__BEGIN( ASURA_PS3_RSX_PROFILE__MISC, "Asura_PS3_QuadOverlayRenderer::RenderHDR" );

	bool bOldSRGB = Asura_PS3_RenderingStates::GetSRGBWriteEnabled();
	Asura_PS3_RenderingStates::SetSRGBWriteEnabled( false );

	g_pxFragmentShaderHDR->SetTexture( FP_Sampler, Asura_PS3_DeferredRendering::GetDeferredFrameBuffer()->GetRTAsTexture( ASURA_DEFERRED_RENDER_TARGET_CURRENT_FRONT_BUFFER ), true );

	Asura_PS3_RenderingStates::RequestTranslucencyMode( ASURA_TRANSLUCENCY_OFF );
	Asura_PS3_RenderingStates::RequestZBufferEnabled( false );
	Asura_PS3_RenderingStates::RequestZBufferWriteEnabled( false );
	Asura_PS3_RenderingStates::RequestCullMode( ASURA_CULLMODE_CCW );

	Asura_PS3_QuadOverlay_Vertex pxBuffer[ 4 ];
	const u_int uNumberOfVerts = 4;
	float fOneOverScreenWidth, fOneOverScreenHeight;

	fOneOverScreenWidth	= 1.0f / static_cast< float >( Asura_Viewport::GetWidth() );
	fOneOverScreenHeight = 1.0f / static_cast< float >( Asura_Viewport::GetHeight() );

	for( u_int u = 0; u < uNumberOfVerts; ++u )
	{
		pxBuffer[u].m_fX = 2.0f * g_xQuad.X[u] * fOneOverScreenWidth - 1.0f;
		pxBuffer[u].m_fY = 2.0f * g_xQuad.Y[u] * fOneOverScreenHeight - 1.0f;
		pxBuffer[u].m_fU = g_xQuad.U[u];
		pxBuffer[u].m_fV = g_xQuad.V[u];
		pxBuffer[u].m_uColour = g_xQuad.Colour;
	}

	g_pxVertexShader->Bind();
	g_pxFragmentShaderHDR->Bind();
	s_xVertexBuffer[ g_iCurrentRenderBuffer ].Bind( g_axVertexDeclaration, VD_ELEMENTS );
	s_xVertexBuffer[ g_iCurrentRenderBuffer ].RenderQuadsInline( 4, pxBuffer );
	Asura_PS3_RenderingStates::SetSRGBWriteEnabled( bOldSRGB );
	Asura_PS3_Graphics::Flush();
	ASURA_PS3_RSX_PROFILE__END( ASURA_PS3_RSX_PROFILE__MISC );

}

void Asura_PS3_QuadOverlayRenderer::RenderCurrentRenderTarget(const Asura_Overlay_Quad& xQuad, Asura_PS3_FragmentShader* pxReplacementFShader, bool bUseViewportSize, u_int uiWidth, u_int uiHeight )
{
	Asura_PS3_FragmentShader* pxFShader = (pxReplacementFShader) ? pxReplacementFShader : GetOverlayQuadShader();

	Flush();
	ASURA_PS3_RSX_PROFILE__BEGIN( ASURA_PS3_RSX_PROFILE__MISC, "Asura_PS3_QuadOverlayRenderer::RenderCurrentRenderTarget" );

	bool bOldSRGBWrite = Asura_PS3_RenderingStates::GetSRGBWriteEnabled();
	Asura_PS3_RenderingStates::SetSRGBWriteEnabled( false );

	if (!pxReplacementFShader)
	{
		pxFShader->SetTexture( FP_Sampler, xQuad.TextureIndex );
	}

	Asura_PS3_RenderingStates::RequestTranslucencyMode( xQuad.TranslucencyMode );
	Asura_PS3_RenderingStates::RequestZBufferEnabled( false );
	Asura_PS3_RenderingStates::RequestZBufferWriteEnabled( false );
	Asura_PS3_RenderingStates::RequestCullMode( ASURA_CULLMODE_CCW );

	Asura_PS3_QuadOverlay_Vertex pxBuffer[ 4 ];
	const u_int uNumberOfVerts = 4;
	float fOneOverScreenWidth, fOneOverScreenHeight;

	if( bUseViewportSize )
	{
		fOneOverScreenWidth	= 1.0f / static_cast< float >( Asura_Viewport::GetWidth() );
		fOneOverScreenHeight = 1.0f / static_cast< float >( Asura_Viewport::GetHeight() );
	}
	else
	{
		fOneOverScreenWidth	= 1.0f / (float)uiWidth;
		fOneOverScreenHeight = 1.0f / (float)uiHeight;
	}


	for( u_int u = 0; u < uNumberOfVerts; ++u )
	{
		pxBuffer[u].m_fX = 2.0f * xQuad.X[u] * fOneOverScreenWidth - 1.0f;
		pxBuffer[u].m_fY = 2.0f * xQuad.Y[u] * fOneOverScreenHeight - 1.0f;
		pxBuffer[u].m_fU = xQuad.U[u];
		pxBuffer[u].m_fV = xQuad.V[u];
		pxBuffer[u].m_uColour = xQuad.m_bGouraudShaded ? xQuad.GouraudColour[u] : xQuad.Colour;
	}

	g_pxVertexShader->Bind();
	pxFShader->Bind();

	s_xVertexBuffer[ g_iCurrentRenderBuffer ].Bind( g_axVertexDeclaration, VD_ELEMENTS );
	s_xVertexBuffer[ g_iCurrentRenderBuffer ].RenderQuadsInline( 4, pxBuffer );
	Asura_PS3_RenderingStates::SetSRGBWriteEnabled( bOldSRGBWrite );
	Asura_PS3_Graphics::Flush();
	ASURA_PS3_RSX_PROFILE__END( ASURA_PS3_RSX_PROFILE__MISC );

}

void Asura_PS3_QuadOverlayRenderer::RenderEx( const Asura_Overlay_Quad& xQuad, Asura_PS3_Texture *pxTexture, bool bUseViewportSize, u_int uiWidth, u_int uiHeight, bool bPointSample )
{
	Flush();
	Asura_PS3_FragmentShader *pxShader = GetOverlayQuadShader();
	if( !pxShader ) return;
	ASURA_PS3_RSX_PROFILE__BEGIN( ASURA_PS3_RSX_PROFILE__MISC, "Asura_PS3_QuadOverlayRenderer::RenderEx" );

	bool bOldSRGBWrite = Asura_PS3_RenderingStates::GetSRGBWriteEnabled();

//BW do no override this state, let caller handle it
//	Asura_PS3_RenderingStates::SetSRGBWriteEnabled( false );
	pxShader->SetTexture( FP_Sampler, pxTexture, true );
	
	if ( bPointSample )
	{
		Asura_PS3_RenderingStates::SetTextureFilter( FP_Sampler, CELL_GCM_TEXTURE_NEAREST, CELL_GCM_TEXTURE_NEAREST, ASURA_PS3_DEFAULT_CONVOLUTION_FILTER );
	}

	Asura_PS3_RenderingStates::RequestTranslucencyMode( xQuad.TranslucencyMode );
	Asura_PS3_RenderingStates::RequestZBufferEnabled( false );
	Asura_PS3_RenderingStates::RequestZBufferWriteEnabled( false );
	Asura_PS3_RenderingStates::RequestCullMode( ASURA_CULLMODE_CCW );

	Asura_PS3_QuadOverlay_Vertex pxBuffer[ 4 ];
	const u_int uNumberOfVerts = 4;
	float fOneOverScreenWidth, fOneOverScreenHeight;

	if( bUseViewportSize )
	{
		fOneOverScreenWidth	= 1.0f / static_cast< float >( Asura_Viewport::GetWidth() );
		fOneOverScreenHeight = 1.0f / static_cast< float >( Asura_Viewport::GetHeight() );
	}
	else
	{
		fOneOverScreenWidth	= 1.0f / (float)uiWidth;
		fOneOverScreenHeight = 1.0f / (float)uiHeight;
	}


	for( u_int u = 0; u < uNumberOfVerts; ++u )
	{
		pxBuffer[u].m_fX = 2.0f * xQuad.X[u] * fOneOverScreenWidth - 1.0f;
		pxBuffer[u].m_fY = 2.0f * xQuad.Y[u] * fOneOverScreenHeight - 1.0f;
		pxBuffer[u].m_fU = xQuad.U[u];
		pxBuffer[u].m_fV = xQuad.V[u];
		pxBuffer[u].m_uColour = xQuad.m_bGouraudShaded ? xQuad.GouraudColour[u] : xQuad.Colour;
	}

	g_pxVertexShader->Bind();
	pxShader->Bind();
	s_xVertexBuffer[ g_iCurrentRenderBuffer ].Bind( g_axVertexDeclaration, VD_ELEMENTS );
	s_xVertexBuffer[ g_iCurrentRenderBuffer ].RenderQuadsInline( 4, pxBuffer );
	Asura_PS3_Graphics::Flush();
	Asura_PS3_RenderingStates::SetSRGBWriteEnabled( bOldSRGBWrite );
	ASURA_PS3_RSX_PROFILE__END( ASURA_PS3_RSX_PROFILE__MISC );

}
#ifdef ASURA_PS3_USE_GAMMA_CORRECTION

void Asura_PS3_QuadOverlayRenderer::RenderGamma( const Asura_Overlay_Quad& xQuad, Asura_PS3_Texture *pxTexture, bool bUseViewportSize, u_int uiWidth, u_int uiHeight )
{
	if( !g_pxFragmentShaderGamma ) return;
	ASURA_PS3_RSX_PROFILE__BEGIN( ASURA_PS3_RSX_PROFILE__MISC, "Asura_PS3_QuadOverlayRenderer::RenderGamma" );

	bool bOldSRGBWrite = Asura_PS3_RenderingStates::GetSRGBWriteEnabled();
	Asura_PS3_RenderingStates::SetSRGBWriteEnabled( false );
	g_pxFragmentShaderGamma->SetTexture( FP_Sampler, pxTexture, true );

	Asura_PS3_RenderingStates::RequestTranslucencyMode( ASURA_TRANSLUCENCY_OFF );
	Asura_PS3_RenderingStates::RequestZBufferEnabled( false );
	Asura_PS3_RenderingStates::RequestZBufferWriteEnabled( false );
	Asura_PS3_RenderingStates::RequestCullMode( ASURA_CULLMODE_CCW );

	Asura_PS3_QuadOverlay_Vertex pxBuffer[ 4 ];
	const u_int uNumberOfVerts = 4;
	float fOneOverScreenWidth, fOneOverScreenHeight;

	if( bUseViewportSize )
	{
		fOneOverScreenWidth	= 1.0f / static_cast< float >( Asura_Viewport::GetWidth() );
		fOneOverScreenHeight = 1.0f / static_cast< float >( Asura_Viewport::GetHeight() );
	}
	else
	{
		fOneOverScreenWidth	= 1.0f / (float)uiWidth;
		fOneOverScreenHeight = 1.0f / (float)uiHeight;
	}


	for( u_int u = 0; u < uNumberOfVerts; ++u )
	{
		pxBuffer[u].m_fX = 2.0f * xQuad.X[u] * fOneOverScreenWidth - 1.0f;
		pxBuffer[u].m_fY = 2.0f * xQuad.Y[u] * fOneOverScreenHeight - 1.0f;
		pxBuffer[u].m_fU = xQuad.U[u];
		pxBuffer[u].m_fV = xQuad.V[u];
		pxBuffer[u].m_uColour = xQuad.m_bGouraudShaded ? xQuad.GouraudColour[u] : xQuad.Colour;
	}

	g_pxVertexShader->Bind();
	g_pxFragmentShaderGamma->SetFloats	( FPQO_GAMMA, 1, &m_fGamma );
	g_pxFragmentShaderGamma->Bind();
	s_xVertexBuffer[ g_iCurrentRenderBuffer ].Bind( g_axVertexDeclaration, VD_ELEMENTS );
	s_xVertexBuffer[ g_iCurrentRenderBuffer ].RenderQuadsInline( 4, pxBuffer );
	Asura_PS3_Graphics::Flush();
	Asura_PS3_RenderingStates::SetSRGBWriteEnabled( bOldSRGBWrite );
	ASURA_PS3_RSX_PROFILE__END( ASURA_PS3_RSX_PROFILE__MISC );

}
#endif

void Asura_PS3_QuadOverlayRenderer::RenderEx( const Asura_Overlay_Quad* xQuad )
{
	Flush();
	ASURA_PS3_RSX_PROFILE__BEGIN( ASURA_PS3_RSX_PROFILE__MISC, "Asura_PS3_QuadOverlayRenderer::RenderEx" );

	bool bOldSRGBWrite = Asura_PS3_RenderingStates::GetSRGBWriteEnabled();
	Asura_PS3_RenderingStates::SetSRGBWriteEnabled(GetWantedSRGBFlag() );
	Asura_PS3_QuadOverlay_Vertex pxBuffer[ 4 ];
	const u_int uNumberOfVerts = 4;
	float fOneOverScreenWidth, fOneOverScreenHeight;

	fOneOverScreenWidth	= 1.0f / static_cast< float >( Asura_Viewport::GetWidth() );
	fOneOverScreenHeight = 1.0f / static_cast< float >( Asura_Viewport::GetHeight() );

	for( u_int u = 0; u < uNumberOfVerts; ++u )
	{
		pxBuffer[u].m_fX = 2.0f * xQuad->X[u] * fOneOverScreenWidth - 1.0f;
		pxBuffer[u].m_fY = 2.0f * xQuad->Y[u] * fOneOverScreenHeight - 1.0f;
		pxBuffer[u].m_fU = xQuad->U[u];
		pxBuffer[u].m_fV = xQuad->V[u];
		pxBuffer[u].m_uColour = xQuad->m_bGouraudShaded ? xQuad->GouraudColour[u] : xQuad->Colour;
	}

	g_pxVertexShader->Bind();
	s_xVertexBuffer[ g_iCurrentRenderBuffer ].Bind( g_axVertexDeclaration, VD_ELEMENTS );
	s_xVertexBuffer[ g_iCurrentRenderBuffer ].RenderQuadsInline( 4, pxBuffer );
	Asura_PS3_Graphics::Flush();
	Asura_PS3_RenderingStates::SetSRGBWriteEnabled( bOldSRGBWrite );
	ASURA_PS3_RSX_PROFILE__END( ASURA_PS3_RSX_PROFILE__MISC );

}

void Asura_PS3_QuadOverlayRenderer::Render( const Asura_Overlay_Quad& xQuad, Asura_PS3_Texture *pxTexture, Asura_PS3_FragmentShader* pxShader, bool bNormalizedCoordinates, bool bUseViewportSize, u_int uiWidth, u_int uiHeight )
{
	Flush();
	ASURA_PS3_RSX_PROFILE__BEGIN( ASURA_PS3_RSX_PROFILE__MISC, "Asura_PS3_QuadOverlayRenderer::Render" );

	bool bOldSRGBWrite = Asura_PS3_RenderingStates::GetSRGBWriteEnabled();
	Asura_PS3_RenderingStates::SetSRGBWriteEnabled( GetWantedSRGBFlag() );
	pxShader->SetTexture( FP_Sampler, pxTexture, bNormalizedCoordinates );

	Asura_PS3_RenderingStates::RequestTranslucencyMode( xQuad.TranslucencyMode );
	Asura_PS3_RenderingStates::RequestZBufferEnabled( false );
	Asura_PS3_RenderingStates::RequestZBufferWriteEnabled( false );
	Asura_PS3_RenderingStates::RequestCullMode( ASURA_CULLMODE_CCW );

	g_pxVertexShader->Bind();

	Asura_PS3_QuadOverlay_Vertex pxBuffer[ 4 ];
	const u_int uNumberOfVerts = 4;
	float fOneOverScreenWidth, fOneOverScreenHeight;

	fOneOverScreenWidth	= 1.0f / static_cast< float >( Asura_Viewport::GetWidth() );
	fOneOverScreenHeight = 1.0f / static_cast< float >( Asura_Viewport::GetHeight() );

	for( u_int u = 0; u < uNumberOfVerts; ++u )
	{
		pxBuffer[ u ].m_fX = 2.0f * xQuad.X[u] * fOneOverScreenWidth - 1.0f;
		pxBuffer[ u ].m_fY = 2.0f * xQuad.Y[u] * fOneOverScreenHeight - 1.0f;
		pxBuffer[ u ].m_fU = xQuad.U[u];
		pxBuffer[ u ].m_fV = xQuad.V[u];
		pxBuffer[ u ].m_uColour = xQuad.m_bGouraudShaded ? xQuad.GouraudColour[ u ] : xQuad.Colour;
	}

	g_pxVertexShader->Bind();
	pxShader->Bind();
	s_xVertexBuffer[ g_iCurrentRenderBuffer ].Bind( g_axVertexDeclaration, VD_ELEMENTS );
	s_xVertexBuffer[ g_iCurrentRenderBuffer ].RenderQuadsInline( 4, pxBuffer );
	Asura_PS3_RenderingStates::SetSRGBWriteEnabled( bOldSRGBWrite );
	ASURA_PS3_RSX_PROFILE__END( ASURA_PS3_RSX_PROFILE__MISC );

}

void Asura_PS3_QuadOverlayRenderer::Shutdown( void )
{
	for( int i = 0; i < ASURA_QUAD_BUFFERS; ++i )
	{
		s_xVertexBuffer[ i ].Destroy();
	}

	delete g_pxVertexShader;
	g_pxVertexShader = NULL;
	delete g_pxFragmentShader;
	delete g_pxFragmentShaderFudgedGamma;
	delete g_pxQuadHandles;
	delete g_pxQuadFGHandles;

	g_pxFragmentShader = NULL;
	g_pxFragmentShaderFudgedGamma = NULL;
	g_pxQuadHandles = NULL;
	g_pxQuadFGHandles = NULL;
}

void Asura_PS3_QuadOverlayRenderer::Render (const Asura_Overlay_Quad& xQuad)
{
	if( !Asura_PS3_RenderingOptions::GetOption( Asura_PS3_RenderingOptions::OPTION_DRAW_OVERLAYS ) | !g_pxVertexShader ) return;

	if( g_iCurrentVertex + 4 >= ASURA_PS3_MAXIMUM_BATCH_SIZE || g_iLastTexture != xQuad.TextureIndex || g_eLastTranslucency != xQuad.TranslucencyMode )
	{
		Flush();
		g_iLastTexture		= xQuad.TextureIndex;
		g_eLastTranslucency	= xQuad.TranslucencyMode;
	}

	Asura_PS3_QuadOverlay_Vertex*	pxBuffer;
	const float fOneOverScreenWidth	= 1.0f / static_cast< float >( Asura_Viewport::GetWidth() );
	const float fOneOverScreenHeight = 1.0f / static_cast< float >( Asura_Viewport::GetHeight() );

	Asura_Assert( g_iCurrentVertex < ASURA_PS3_MAXIMUM_BATCH_SIZE, "array bounds exceeded");
	pxBuffer = static_cast<Asura_PS3_QuadOverlay_Vertex*>( s_xVertexBuffer[ g_iCurrentRenderBuffer ].LockForWriting() );

	for( u_int u = 0; u < 4; ++u )
	{
		pxBuffer[ g_iCurrentVertex ].m_fX = 2.0f * xQuad.X[u] * fOneOverScreenWidth - 1.0f;
		pxBuffer[ g_iCurrentVertex ].m_fY = 2.0f * xQuad.Y[u] * fOneOverScreenHeight - 1.0f;
		pxBuffer[ g_iCurrentVertex ].m_fU = xQuad.U[u];
		pxBuffer[ g_iCurrentVertex ].m_fV = xQuad.V[u];
		pxBuffer[ g_iCurrentVertex ].m_uColour = xQuad.m_bGouraudShaded ? xQuad.GouraudColour[ u ] : xQuad.Colour;
		++g_iCurrentVertex;
	}
}

void Asura_PS3_QuadOverlayRenderer::Flush( void )
{
	int iVertexToRender = g_iCurrentVertex - g_iStartFromVertex;
	if( iVertexToRender > 0 )
	{
		Asura_PS3_FragmentShader *pxShader = GetOverlayQuadShader();
		if( !pxShader ) return;

		ASURA_PS3_RSX_PROFILE__BEGIN( ASURA_PS3_RSX_PROFILE__2D, "Asura_PS3_QuadOverlayRenderer::Flush" );

		bool bOldSRGBWrite = Asura_PS3_RenderingStates::GetSRGBWriteEnabled();
		Asura_PS3_RenderingStates::SetSRGBWriteEnabled(  GetWantedSRGBFlag() );
		Asura_PS3_DeferredRendering::BindAsSingleRT();


		Asura_PS3_RenderingStates::RequestTranslucencyMode( g_eLastTranslucency );
		Asura_PS3_RenderingStates::RequestZBufferEnabled( false );
		Asura_PS3_RenderingStates::RequestZBufferWriteEnabled( false );
		Asura_PS3_RenderingStates::RequestCullMode( ASURA_CULLMODE_CCW );

		g_pxVertexShader->Bind();

		pxShader->SetTexture( FP_Sampler, g_iLastTexture );
		pxShader->Bind();

		s_xVertexBuffer[ g_iCurrentRenderBuffer ].BindFromVertex( g_axVertexDeclaration, VD_ELEMENTS, g_iStartFromVertex );
		s_xVertexBuffer[ g_iCurrentRenderBuffer ].RenderQuads( iVertexToRender );

        ASURA_PS3_RSX_PROFILE__END( ASURA_PS3_RSX_PROFILE__2D );

		Asura_PS3_Graphics::Flush();
		g_iCurrentVertex += (400+sizeof(Asura_PS3_QuadOverlay_Vertex)-1)/sizeof(Asura_PS3_QuadOverlay_Vertex); //fix for the 400 bytes overfetch
		Asura_PS3_RenderingStates::SetSRGBWriteEnabled( bOldSRGBWrite );
	}
	if( g_iCurrentVertex + 4 >= ASURA_PS3_MAXIMUM_BATCH_SIZE )
	{
		++g_iCurrentRenderBuffer;
		g_iCurrentRenderBuffer	= ( g_iCurrentRenderBuffer ) % ASURA_QUAD_BUFFERS;
		g_iCurrentVertex		= 0;
	}

	g_iStartFromVertex		= g_iCurrentVertex;
	g_iLastTexture			= ASURA_TEXTURE_INVALID;
	g_eLastTranslucency		= ASURA_TRANSLUCENCY_NOT_SET;
}

void Asura_PS3_QuadOverlayRenderer::EndFrame( void )
{
	++g_iCurrentRenderBuffer;
	g_iCurrentRenderBuffer	= ( g_iCurrentRenderBuffer ) % ASURA_QUAD_BUFFERS;
	g_iCurrentVertex		= 0;
	g_iStartFromVertex		= 0;
	g_iLastTexture			= ASURA_TEXTURE_INVALID;
	g_eLastTranslucency		= ASURA_TRANSLUCENCY_NOT_SET;
}

/// End of file. ///
