//////////////////////////////////////////////////////////////////////////////
//
// Asura_PS2_Profiling.h
//
// By: Morgan Parry
//
//////////////////////////////////////////////////////////////////////////////

// B E G I N   F I L E   W R A P P E R ///////////////////////////////////////

#ifdef ASURA_USE_PRAGMA_ONCE
    #pragma once
#endif

#ifndef ___ASURA_PS2_PROFILING_H___
#define ___ASURA_PS2_PROFILING_H___ 1

#include "Debugging/Asura_CPUProfile.h"
// D E F I N E S /////////////////////////////////////////////////////////////

#if !defined(ASURA_PS2_SONY_SUBMISSION) && (_DEBUG || !defined(ASURA_PS2_CDEMUL))
	#define ASURA_PS2_ENABLE_PROFILING (1)
#else
	#define ASURA_PS2_ENABLE_PROFILING (0)
#endif

#if ASURA_PS2_ENABLE_PROFILING
#ifndef ASURA_PS2_SN_PROFILER
	#define	ASURA_PS2_SN_PROFILER	    (1)
#endif // #ifndef ASURA_PS2_SN_PROFILER
	#define ASURA_PS2_DRAW_PROFILE_BARS (1)
#else
	#define	ASURA_PS2_SN_PROFILER	    (0)
	#define ASURA_PS2_DRAW_PROFILE_BARS (0)
#endif

// D E F I N E   B A S E D   I N C L U D E S /////////////////////////////////
#if ASURA_PS2_SN_PROFILER
	#include <eetypes.h>                        // For u_long128.
#endif

// O P T I O N   B A S E D   D E F I N E S //////////////////////////////

#if ASURA_PS2_DRAW_PROFILE_BARS
    #define	ASURA_PS2_PROFILE__ADD_VIF_START(u)		Asura_PS2_ProfilingSystem::AddVIFStart( u );
    #define	ASURA_PS2_PROFILE__ADD_VIF_END(u)		Asura_PS2_ProfilingSystem::AddVIFEnd( u );
	#define	ASURA_PS2_PROFILE__ADD_EE_START(u)		Asura_PS2_ProfilingSystem::AddEEStart( u );
	#define	ASURA_PS2_PROFILE__ADD_EE_END(u)		Asura_PS2_ProfilingSystem::AddEEEnd( u );
	#define	ASURA_PS2_PROFILE__REGISTER_LABEL(u,sz) Asura_PS2_ProfilingSystem::RegisterLabel(u, sz);
	#define	ASURA_PS2_PROFILE__RENDER				Asura_PS2_ProfilingSystem::Render();
#else
	#define	ASURA_PS2_PROFILE__ADD_VIF_START(u)		{;}
	#define	ASURA_PS2_PROFILE__ADD_VIF_END(u)		{;}
	#define	ASURA_PS2_PROFILE__ADD_EE_START(u)		{;}
	#define	ASURA_PS2_PROFILE__ADD_EE_END(u)		{;}
	#define	ASURA_PS2_PROFILE__REGISTER_LABEL(u,sz)	{;}
	#define	ASURA_PS2_PROFILE__RENDER				{;}
#endif

// Any other code using the MARK VIF1 register needs to avoid setting either
// of these bits, since we use them here to identify start and stop markers.
#define ASURA_PS2_PROFILE__START_MARK_MASK (0x8000)
#define ASURA_PS2_PROFILE__STOP_MARK_MASK  (0x4000)

#define ASURA_PS2_PROFILE__TOTAL_FRAME_MARKER	0      // white
#define ASURA_PS2_PROFILE__FRACTALSKY_MARKER	1      // blue
#define ASURA_PS2_PROFILE__SKYBOX_MARKER		2      // green
#define ASURA_PS2_PROFILE__ENVIRONMENT_MARKER	3      // red
#define ASURA_PS2_PROFILE__OBJECT_MARKER		4      // cyan
#define ASURA_PS2_PROFILE__HIERARCHY_MARKER		5      // yellow
#define ASURA_PS2_PROFILE__SKINNED_MARKER		6      // magenta
#define ASURA_PS2_PROFILE__PARTICLE_MARKER		7      // black
#define ASURA_PS2_PROFILE__CORONA_MARKER		8      // lime green
#define ASURA_PS2_PROFILE__PROJ_SHADOW_MARKER   9	   // orange
#define ASURA_PS2_PROFILE__WATER_MARKER		    10	   // soft-blue
#define ASURA_PS2_PROFILE__CARPET_MARKER		ASURA_CPU_PROFILE__CARPET_RENDER
#define ASURA_PS2_PROFILE__BOTANICALS_MARKER	ASURA_CPU_PROFILE__BOTANICALS_RENDER  // purple
#define ASURA_PS2_PROFILE__USER_MARKER_5		13     // bright blue
#define ASURA_PS2_PROFILE__USER_MARKER_4		14	   // bright pink
#define ASURA_PS2_PROFILE__USER_MARKER_3		15     // greeny blue
#define ASURA_PS2_PROFILE__USER_MARKER_2		16     // back to white
#define ASURA_PS2_PROFILE__USER_MARKER_1		17     // blue
#define ASURA_PS2_PROFILE__MARKER_QTY			ASURA_CPU_PROFILE__MAX_TIMERS
// C L A S S E S /////////////////////////////////////////////////////////////

class Asura_PS2_ProfilingSystem
{

public:

	// M E T H O D S /////////////////////////////////////////////////////

	static bool Initialise( bool bUseSNProfiler );
	static void Update();
	static void Shutdown();

#if ASURA_PS2_DRAW_PROFILE_BARS
    static void AddVIFStart( u_int uMarkerID );	// Starting point for profiling renderer[uMark]
    static void AddVIFEnd( u_int uMarkerID );	// Finishing point for profiling renderer[uMark]
    static void	AddEEStart( u_int uMarkerID );	// Records the start time of an EE marker
    static void	AddEEEnd( u_int uMarkerID );	// Records the end time of an EE marker
	static void RegisterLabel(u_int uMarkerID, const char* szLabel); // Records the start time of a labelled marker
	static void Render();						// Render timing results
#endif

private:
	// Private methods //////
#if ASURA_PS2_DRAW_PROFILE_BARS
	static int VIF1_InteruptHandler( int channel );
#endif

	// Private Members /////
#if ASURA_PS2_SN_PROFILER
    enum { NUM_SN_PROFILING_DATA_QWORDS = 2048 };
	static u_long128 s_auSNProfilingData[NUM_SN_PROFILING_DATA_QWORDS];
	static bool		 s_bEnableSNProfiling;
	static bool		 s_bSNProfilerEnabled;
#endif

};

// E N D   F I L E   W R A P P E R ///////////////////////////////////////////

#endif // #ifndef ___ASURA_PS2_PROFILING_H___
