///////////////////////////////////////////////////////////////////////////////
//
// File   : Asura_Platform_Render.cpp
// Author : Andy Tate
// Date   : 24-Jun-2005
//
// Copyright (C) 2005 Rebellion, All Rights Reserved.
//
///////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// Include files...
////////////////////////////////////////////////////////////////////////////////

#include "Core/Asura.h"

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

// Asura independent includes
#include "Core/Asura_TextureManagement.h"
#include "Debugging/Asura_CPUProfile.h"
#if defined(ASURA_USE_PROFILING_SYSTEM)
#include "Debugging/Asura_CPUProfile_Renderer.h"
#endif	// defined(ASURA_USE_PROFILING_SYSTEM)

// Asura PS3 includes
#include "Animation/Asura_Platform_Animation_RenderCache.h"
#include "Rendering/Asura_PS3_CharacterRenderer.h"
#include "Rendering/Asura_PS3_EnvironmentRenderer.h"
#include "Rendering/Asura_PS3_Graphics.h"
#include "Rendering/Asura_PS3_LineRenderer.h"
#include "Rendering/Asura_PS3_ObjectHierarchyRenderer.h"
#include "Rendering/Asura_PS3_QuadOverlayRenderer.h"
#include "Rendering/Asura_PS3_ScratchRenderMemory.h"
#include "FSFX/Asura_PS3_FSFX.h"
#include "Rendering/Asura_PS3_Fog.h"
#include "Rendering/Asura_PS3_FrameBuffer.h"
#include "Rendering/Asura_PS3_DeferredRendering.h"
#include "Rendering/Asura_PS3_SPU_Skinning.h"
#include "Rendering/Asura_PS3_RSXProfiling.h"
#if defined ASURA_USE_HDR
	#include "Rendering/Asura_PS3_HDR.h"
#endif
#ifdef ASURA_EDGE_ANTIALIASING
	#include "Rendering/Asura_PS3_EdgeAntiAliasing.h"
#endif

#ifndef ASURA_PS3_RENDER_INITIALISE_MEMORY
#define ASURA_PS3_RENDER_INITIALISE_MEMORY 64
#endif // #ifndef ASURA_PS3_RENDER_INITIALISE_MEMORY

DEBUGVAR float dbg_fPlayerRenderViewportMinZ = 0.0f;
DEBUGVAR float dbg_fPlayerRenderViewportMaxZ = 0.001f;


////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_Render::Platform_Initialise
// Author       : Andy Tate
// Date         : 24-Jun-2005
//
// Description  : Handles PS3 specific renderer initilisation.
//
// Return value : None.
////////////////////////////////////////////////////////////////////////////////

void Asura_Render::Platform_Initialise (void)
{
	Asura_Render::SetEnableScreenClear(false);

	// Intialise the graphics...
	Asura_PS3_Graphics::Initialise( ASURA_PS3_RENDER_INITIALISE_MEMORY );

	// Init the shader system - has to be before renderers get initialised
	Asura_PS3_GCM_ShadersLibrary::Initialise();

	// Initialise the specific renderers...
	Asura_PS3_EnvironmentRenderer::Initialise();
	Asura_PS3_CharacterRenderer::Initialise();
	Asura_PS3_ObjectHierarchyRenderer::Initialise();

	Asura_PS3_LineRenderer::Initialise();
	Asura_PS3_QuadOverlayRenderer::Initialise();

	Asura_PS3_Fog::Initialise();

#if defined ASURA_USE_HDR
	Asura_PS3_HDR::Initialise();
#endif

	Asura_PS3_SPU_Skinning::Initialise();
	
#ifdef ASURA_EDGE_ANTIALIASING
	Asura_PS3_EdgeAntiAliasing::Initialise();
#endif

	ASURA_CPU_PROFILE__START_LABEL(ASURA_CPU_PROFILE__TOTALFRAME, "total frame");
}

/// End of function 'Asura_Render::Platform_Initialise'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_Render::Platform_EarlyShutdown
// Author       : Andy Tate
// Date         : 24-Jun-2005
//
// Description  : Handles PS3 specific early-shutdown code.
//
// Return value : None.
////////////////////////////////////////////////////////////////////////////////

void Asura_Render::Platform_EarlyShutdown (void)
{
}

/// End of function 'Asura_Render::Platform_EarlyShutdown'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_Render::Platform_LateShutdown
// Author       : Andy Tate
// Date         : 24-Jun-2005
//
// Description  : Handles PS3 specific late-shutdown code.
//
// Return value : None.
////////////////////////////////////////////////////////////////////////////////

void Asura_Render::Platform_LateShutdown (void)
{
	// Shutdown the specific renderers...
	Asura_PS3_ObjectHierarchyRenderer::Shutdown();
	Asura_PS3_SPU_Skinning::Shutdown();
#ifdef ASURA_EDGE_ANTIALIASING
	Asura_PS3_EdgeAntiAliasing::Shutdown();
#endif
	Asura_PS3_CharacterRenderer::Shutdown();
	Asura_PS3_EnvironmentRenderer::Shutdown();

	Asura_PS3_QuadOverlayRenderer::Shutdown();
	Asura_PS3_LineRenderer::Shutdown();

#if defined ASURA_USE_HDR
	Asura_PS3_HDR::Shutdown();
#endif

	Asura_PS3_Fog::Shutdown();

	// shutdown the shader system - has to be after renderers get shutdown
	Asura_PS3_GCM_ShadersLibrary::Shutdown();

	// Shutdown the graphics...
	Asura_PS3_Graphics::Shutdown();
}

/// End of function 'Asura_Render::Platform_LateShutdown'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_Render::Platform_Reset
// Author       : Andy Tate
// Date         : 24-Jun-2005
//
// Description  : Handles the PS3 specific renderer reset.
//
// Return value : 
////////////////////////////////////////////////////////////////////////////////

void Asura_Render::Platform_Reset (void)
{
	// First make sure the RSX finishes the previous frame (otherwise it can reference deallocated memory)
	Asura_PS3_Graphics::Reset();

	// Reset the renderers...
	Asura_PS3_ObjectHierarchyRenderer::Reset();
	Asura_PS3_CharacterRenderer::Reset();
	//Asura_PS3_AABBRenderer::Reset();
	Asura_PS3_EnvironmentRenderer::Reset();
	Asura_PS3_GCM_ShadersLibrary::Reset();
}

/// End of function 'Asura_Render::Platform_Reset'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_Render::Platform_ApplyCameraSettings
// Author       : Andy Tate
// Date         : 24-Jun-2005
//
// Description  : Not sure what this is used for - something to with special
//				  effects rendering (i.e. water/weather).
//
// Return value : None.
////////////////////////////////////////////////////////////////////////////////

void Asura_Render::Platform_ApplyCameraSettings (void)
{
	Asura_PS3_Graphics::ApplyCameraSettings();
}

/// End of function 'Asura_Render::Platform_ApplyCameraSettings'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_Render::Platform_AllowFullScreenRendering
// Author       : Andy Tate
// Date         : 24-Jun-2005
//
// Description  : Not relevant on the PS3.
//
// Return value : None.
////////////////////////////////////////////////////////////////////////////////

void Asura_Render::Platform_AllowFullScreenRendering (void)
{
}

/// End of function 'Asura_Render::Platform_AllowFullScreenRendering'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_Render::Platform_ClearZBuffer
// Author       : Andy Tate
// Date         : 24-Jun-2005
//
// Description  : Clears the current PS3 Z-buffer.
//
// Return value : None.
////////////////////////////////////////////////////////////////////////////////

void Asura_Render::Platform_ClearZBuffer (void)
{
	Asura_PS3_Graphics::ClearZBuffer();
}

/// End of function 'Asura_Render::Platform_ClearZBuffer'. ///

#include "Core/Asura_TextureManagement.h"

void Asura_Render::Platform_BeginFrame (void)
{
	// This is all done in the PS3 graphics code...
	Asura_PS3_Graphics::BeginFrame	();
	Asura_PS3_ScratchRenderMemory::BeginFrame();
	Asura_PS3_SPU_Skinning::BeginFrame();
#ifdef ASURA_EDGE_ANTIALIASING
	Asura_PS3_EdgeAntiAliasing::BeginFrame();
#endif
}

////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_Render::Platform_EndFrame
// Author       : Andy Tate
// Date         : 24-Jun-2005
//
// Description  : Handles the PS3 specific end-of-frame code.
//
// Return value : None.
////////////////////////////////////////////////////////////////////////////////

void Asura_Render::Platform_EndFrame (void)
{
	ASURA_CPU_PROFILE__STOP(ASURA_CPU_PROFILE__TOTALFRAME);

#ifdef ASURA_EDGE_ANTIALIASING
	Asura_PS3_EdgeAntiAliasing::EndFrame();
#endif
	Asura_PS3_SPU_Skinning::EndFrame();

  	// these profile bars are not the most efficient as they use Asura_Overlay_Quad.
#ifdef ASURA_USE_PROFILING_SYSTEM
  	Asura_CPUProfile_Renderer::Render(true);
  	Asura_CPUProfile_Renderer::ClearValues();
#endif

	// should really start total frame marker from after VSync...
	ASURA_CPU_PROFILE__START_LABEL(ASURA_CPU_PROFILE__TOTALFRAME, "total frame");
	Asura_PS3_Graphics::EndFrame();

	Asura_PS3_GCM_ShadersLibrary::EndFrame();
	Asura_PS3_ScratchRenderMemory::EndFrame();
	Asura_Platform_Animation_RenderCache::Cleanup();
}
/// End of function 'Asura_Render::Platform_EndFrame'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_Render::Platform_FlushDisplay
// Author       : Andy Tate
// Date         : 24-Jun-2005
//
// Description  : Handles the flushing of the PS3 display.
//
// Return value : None.
////////////////////////////////////////////////////////////////////////////////

#if defined(ASURA_PS3_FINISH_WHEN_FLUSHRENDER)
static uint32_t s_uGcmFinishReferenceValue=0;
#endif // defined(ASURA_PS3_FINISH_WHEN_FLUSHRENDER)

void Asura_Render::Platform_FlushDisplay (void)
{
	Asura_PS3_QuadOverlayRenderer::Flush();
#if defined(ASURA_PS3_FINISH_WHEN_FLUSHRENDER)
	// DJG - 03/05/2007 - Wait for the RSX to catch up
	cellGcmSetReferenceCommand( Asura_PS3_Graphics::GetGcmCurrentContext(), s_uGcmFinishReferenceValue );
	cellGcmFinish( Asura_PS3_Graphics::GetGcmCurrentContext(), s_uGcmFinishReferenceValue );
	++s_uGcmFinishReferenceValue;
#endif // defined(ASURA_PS3_FINISH_WHEN_FLUSHRENDER)
}

/// End of function 'Asura_Render::Platform_FlushDisplay'. ///



////////////////////////////////////////////////////////////////////////////////
//
// Function    : Asura_Render::Platform_BeginMRT()
//
// Description : Begins MRT usage during the render frame.
//
////////////////////////////////////////////////////////////////////////////////

void Asura_Render::Platform_BeginMRT()
{
}

/// End of function 'Asura_Render::Platform_EndMRT'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_Render::Platform_EndMRT
// Author       : Andrew McDonald
// Date         : 26-Oct-2006
//
// Description  : Ends MRT usage during the render frame.
//
// Return value : None.
////////////////////////////////////////////////////////////////////////////////

void Asura_Render::Platform_EndMRT (void)
{
	Asura_PS3_DeferredRendering::EndMrt();
}

/// End of function 'Asura_Render::Platform_EndMRT'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_Render::Platform_SetVideoMode
// Author       : Andy Tate
// Date         : 24-Jun-2005
//
// Description  : Sets the specified video mode.
//
// Parameters   : The width, height and whether it's full-screen.
//
// Return value : "true" if successfully set, "false" if not.
////////////////////////////////////////////////////////////////////////////////

bool Asura_Render::Platform_SetVideoMode (int width,
										  int height,
										  bool fsaa)
{
	// ART - Is this relevant on the PS3? Maybe it is for HDTV mode?
	return	(true);
}

/// End of function 'Asura_Render::Platform_SetVideoMode'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_Render::Platform_InitialiseSplashScreen
// Author       : Andy Tate
// Date         : 24-Jun-2005
//
// Description  : Splash-screen initialisation code.
//
// Parameters   : The name of the splash-screen file to be loaded.
//
// Return value : None.
////////////////////////////////////////////////////////////////////////////////

void Asura_Render::Platform_InitialiseSplashScreen (const char* szName)
{
}

/// End of function 'Asura_Render::Platform_InitialiseSplashScreen'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_Render::Platform_ShutdownSplashScreen
// Author       : Andy Tate
// Date         : 24-Jun-2005
//
// Description  : Shuts down the previously opened splash-screen.
//
// Return value : None.
////////////////////////////////////////////////////////////////////////////////

void Asura_Render::Platform_ShutdownSplashScreen (void)
{
}

/// End of function 'Asura_Render::Platform_ShutdownSplashScreen'. ///


////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_Render::Platform_SplashScreenRender
// Author       : Andy Tate
// Date         : 24-Jun-2005
//
// Description  : Renders the previously loaded splash-screen.
//
// Return value : None.
////////////////////////////////////////////////////////////////////////////////

void Asura_Render::Platform_SplashScreenRender (void)
{
}

/// End of function 'Asura_Render::Platform_SplashScreenRender'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_Render::Platform_RenderLine
// Author       : Andy Tate
// Date         : 24-Jun-2005
//
// Description  : Renders a line in 3D space.
//
// Parameters   : The start and end positions of the line and it's colour.
//
// Return value : None.
////////////////////////////////////////////////////////////////////////////////

void Asura_Render::Platform_RenderLine (const Asura_Vector_3& xP1,
										const Asura_Vector_3& xP2,
										u_int uColour)
{
	// Render the line in 3D...
	Asura_PS3_LineRenderer::Render3DLine (xP1, xP2, uColour);
}

/// End of function 'Asura_Render::Platform_RenderLine'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_Render::Platform_Render2DLine
// Author       : Andy Tate
// Date         : 24-Jun-2005
//
// Description  : Renders a line in 2D space.
//
// Parameters   : The start and end positions of the line and it's colour.
//
// Return value : None.
////////////////////////////////////////////////////////////////////////////////

void Asura_Render::Platform_Render2DLine (const Asura_Vector_2& xP1,
										  const Asura_Vector_2& xP2,
										  u_int uColour)
{
	// Render the line in 2D...
	Asura_PS3_LineRenderer::Render2DLine(xP1, xP2, uColour);
}

/// End of function 'Asura_Render::Platform_Render2DLine'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_Render::Platform_RenderDynamicShadowsOntoEnvironment
// Author       : Andy Tate
// Date         : 24-Jun-2005
//
// Description  : PS3 specific shadow rendering.
//
// Return value : None.
////////////////////////////////////////////////////////////////////////////////

void Asura_Render::Platform_PrepareToRenderFirstPersonMesh ()
{
    Asura_PS3_Graphics::SetViewProjMatricesAndViewport( dbg_fPlayerRenderViewportMinZ, dbg_fPlayerRenderViewportMaxZ );
	Asura_PS3_Graphics::ApplyCameraSettings();
}

void Asura_Render::Platform_FinishRenderFirstPersonMesh( void )
{
    Asura_PS3_Graphics::SetViewProjMatricesAndViewport( fASURA_PS3_DEFAULT_VIEWPORT_MIN_Z, fASURA_PS3_DEFAULT_VIEWPORT_MAX_Z );
	Asura_PS3_Graphics::ApplyCameraSettings();
}


#if defined ASURA_USE_HDR

void Asura_Render::Platform_ApplyToneMapping()
{
	Asura_PS3_HDR::ApplyToneMapping();
}

#endif // ASURA_USE_HDR

#ifdef ASURA_TARGET_SM3
void Asura_Render::Platform_BeginSkyboxRendering(void)
{
	ASURA_PS3_RSX_PROFILE__BEGIN( ASURA_PS3_RSX_PROFILE__MISC, "Asura_Skybox - objects" );


	Asura_PS3_Graphics::BeginRenderToSkybox();
}

void Asura_Render::Platform_EndSkyboxRendering(void)
{
	ASURA_PS3_RSX_PROFILE__END( ASURA_PS3_RSX_PROFILE__MISC );


	Asura_PS3_Graphics::EndRenderToSkybox();
}
#endif // ASURA_TARGET_SM3

#ifdef ASURA_EDGE_ANTIALIASING
void Asura_Render::Platform_SetCollectAAEdges( bool bCollectEdges )
{
	// doesn't do anything on PS3
}
void Asura_Render::Platform_RenderEdgeAntiAliasing( void )
{
	Asura_PS3_EdgeAntiAliasing::Render();
}
#endif

/// End of file. ///
