//
// Asura_RenderStates.cpp
//
// Created by KJFL - Friday, April 02, 2004
//
// Copyright (C) 2004 Rebellion, All Rights Reserved.
//

#include "Core/Asura.h"

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

// Asura headers
#include "Debugging/Asura_Assert.h"
#include "Rendering/Asura_Render.h"

// PSP headers
#include "Debugging/Asura_PSP_GPIO.h"
#include "Rendering/Asura_PSP_Graphics.h"
#include "Rendering/Asura_PSP_TextureHeader.h"
#include "Rendering/Asura_PSP_TextureManagement.h"
#include "Rendering/Asura_PSP_VRAMManagement.h"

void Asura_Render_States::SetTextureIndex(int t, int i) 
{
	// JG - 09/02/07: In theory, we should be able to deprecate this method, but unfortunately ResetAll and ResetTextureIndexToLast is still being used in a per project case, and is defined in independent
	// code. So I will redirect this call to the right manager. I've fixed all the other ocurrances of Asura_Render_States::RequestTextureIndex in PSP code to use the right manager.
	//Asura_Assert( false, "Asura_Render_States::RequestTextureIndex has been deprecated, please use Asura_PSP_TextureManagement::RequestTextureIndex instead" ); 
	Asura_PSP_TextureManagement::SetTextureIndex( i ); 
}

void Asura_Render_States::SetWireFrameMode(bool b)
{
	Asura_Assert(Asura_Render::IsRendering() || Asura_PSP_Graphics::IsInFrameForAssert(), 
		"calling renderstate function outside of BeginFrame/EndFrame()");

	WireFrameMode=b;

	if (b)
	{

	}
	else
	{

	}
}


void Asura_Render_States::SetDitheringMode(bool b)
{
	Asura_Assert(Asura_Render::IsRendering() || Asura_PSP_Graphics::IsInFrameForAssert(), 
		"calling renderstate function outside of BeginFrame/EndFrame()");

	DitheringMode=b;

}



void Asura_Render_States::SetZBufferEnabled(bool b)
{
	Asura_Assert(Asura_Render::IsRendering() || Asura_PSP_Graphics::IsInFrameForAssert(), 
		"calling renderstate function outside of BeginFrame/EndFrame()");

	ZBufferEnabled=b;

	if (b)
	{
		GU_Enable(SCEGU_DEPTH_TEST);
	}
	else													  
	{
		GU_Disable(SCEGU_DEPTH_TEST);
	}
}

void Asura_Render_States::SetZBufferCompareMode(enum ASURA_ZBUFFERCMP_ID mode)
{
	Asura_Assert(Asura_Render::IsRendering() || Asura_PSP_Graphics::IsInFrameForAssert(), 
		"calling renderstate function outside of BeginFrame/EndFrame()");

	ZBufferCompareMode = mode;

	switch (mode)
	{
		case ASURA_ZBUFFERCMP_LESSEQUAL:
		{
			GU_DepthFunc(SCEGU_LEQUAL);
			break;		
		}
		case ASURA_ZBUFFERCMP_ALWAYS:
		{
			GU_DepthFunc(SCEGU_ALWAYS);
			break;		
		}
		case ASURA_ZBUFFERCMP_EQUALS:
		{
			GU_DepthFunc(SCEGU_EQUAL);
			break;
		}
	}
}

void Asura_Render_States::SetZBufferWriteEnabled(bool b)
{
	Asura_Assert(Asura_Render::IsRendering() || Asura_PSP_Graphics::IsInFrameForAssert(), 
		"calling renderstate function outside of BeginFrame/EndFrame()");

	ZBufferWriteEnabled=b;
	if(b)
	{
		GU_DepthMask(0); // Z-write.
	}
	else
	{
		GU_DepthMask(1); // No z-write.
	}
}

void Asura_Render_States::SetAlphaBlending(bool b)
{
	Asura_Assert(Asura_Render::IsRendering() || Asura_PSP_Graphics::IsInFrameForAssert(), 
		"calling renderstate function outside of BeginFrame/EndFrame()");

	AlphaBlendingEnabled = b;

	if (b)
	{
		GU_Enable(SCEGU_BLEND);
		GU_AlphaFunc(SCEGU_GREATER, 0x04, 0xff);
	}
	else
	{
		GU_Disable(SCEGU_BLEND);
	}
}

void Asura_Render_States::SetTranslucencyMode(enum ASURA_TRANSLUCENCY_MODE mode)
{
	Asura_Assert(Asura_Render::IsRendering() || Asura_PSP_Graphics::IsInFrameForAssert(), 
		"calling renderstate function outside of BeginFrame/EndFrame()");

	TranslucencyMode=mode;

	switch(TranslucencyMode)
	{
	 	case ASURA_TRANSLUCENCY_OFF:
		{
			if (AlphaBlendingEnabled) SetAlphaBlending(false);

			break;
		}
	 	case ASURA_TRANSLUCENCY_NORMAL:
		{
			if (!AlphaBlendingEnabled) SetAlphaBlending(true);
			GU_BlendFunc(SCEGU_ADD, SCEGU_SRC_ALPHA, SCEGU_ONE_MINUS_SRC_ALPHA, 0, 0);
			break;
		}
	 	case ASURA_TRANSLUCENCY_COLOUR:
		{
			if (!AlphaBlendingEnabled) SetAlphaBlending(true);

			break;
		}
		case ASURA_TRANSLUCENCY_DOUBLECOLOUR:
		{
			if (!AlphaBlendingEnabled) SetAlphaBlending(true);
			
			GU_BlendFunc(SCEGU_ADD, SCEGU_DST_COLOR, SCEGU_SRC_COLOR, 0, 0);

			break;
		}
	 	case ASURA_TRANSLUCENCY_INVCOLOUR:
		{
			if (!AlphaBlendingEnabled) SetAlphaBlending(true);

			break;
		}
  		case ASURA_TRANSLUCENCY_GLOWING:
		{
			if (!AlphaBlendingEnabled) SetAlphaBlending(true);
			GU_BlendFunc(SCEGU_ADD, SCEGU_SRC_ALPHA, SCEGU_FIX_VALUE, 0, 0xffffff);

			break;
		}
  		case ASURA_TRANSLUCENCY_DARKENINGCOLOUR:
		{
			if (!AlphaBlendingEnabled) SetAlphaBlending(true);

			break;
		}
		case ASURA_TRANSLUCENCY_JUSTSETZ:
		{
			if (!AlphaBlendingEnabled) SetAlphaBlending(true);

			break;
		}
		case ASURA_TRANSLUCENCY_ALPHACOMPARE:
		{
			if (!AlphaBlendingEnabled) SetAlphaBlending(true);

			break;
		}
		case ASURA_TRANSLUCENCY_UGH:
		{
			if (!AlphaBlendingEnabled) SetAlphaBlending(true);
			break;
		}
		case ASURA_TRANSLUCENCY_MINIMUM:
		{
			if (!AlphaBlendingEnabled) SetAlphaBlending(true);
			GU_BlendFunc(SCEGU_MIN, SCEGU_SRC_COLOR, SCEGU_DST_COLOR, 0, 0);

			break;
		}
		default:
			break;
	}
}

void Asura_Render_States::SetTextureOpMode(enum ASURA_TEXTUREOP_ID mode)
{
	Asura_Assert(Asura_Render::IsRendering() || Asura_PSP_Graphics::IsInFrameForAssert(), 
		"calling renderstate function outside of BeginFrame/EndFrame()");

	TextureOpMode = mode;
/*
	switch(mode)
	{
		default:
		{
			break;
		}
	}*/
}

void Asura_Render_States::SetAlphaTest(bool b)
{
	Asura_Assert(Asura_Render::IsRendering() || Asura_PSP_Graphics::IsInFrameForAssert(), 
		"calling renderstate function outside of BeginFrame/EndFrame()");

	AlphaTest=b;
	if(b)
	{
		GU_Enable(SCEGU_ALPHA_TEST);
	}
	else
	{
		GU_Disable(SCEGU_ALPHA_TEST);
	}
}

void Asura_Render_States::SetDynamicLights(bool b)
{
	Asura_Assert(Asura_Render::IsRendering() || Asura_PSP_Graphics::IsInFrameForAssert(), 
		"calling renderstate function outside of BeginFrame/EndFrame()");

	DynamicLights = b;

	
}

void Asura_Render_States::SetCullMode(enum ASURA_CULLMODE_ID eMode)
{
	Asura_Assert(Asura_Render::IsRendering() || Asura_PSP_Graphics::IsInFrameForAssert(), 
		"calling renderstate function outside of BeginFrame/EndFrame()");

	m_eCullMode = eMode;

	switch(eMode)
	{
		default:
		case ASURA_CULLMODE_NONE:
		{
			GU_Disable(SCEGU_CULL_FACE);
			break;
		}

		case ASURA_CULLMODE_CW:
		{
			GU_Enable(SCEGU_CULL_FACE);
			if (Asura_Render::ShouldRenderMirrored())
			{
				GU_FrontFace(SCEGU_CW);
			}
			else
			{
				GU_FrontFace(SCEGU_CCW);
			}
			break;
		}

		case ASURA_CULLMODE_CCW:
		{
			GU_Enable(SCEGU_CULL_FACE);
			if (Asura_Render::ShouldRenderMirrored())
			{
				GU_FrontFace(SCEGU_CCW);
			}
			else
			{
				GU_FrontFace(SCEGU_CW);
			}

			break;
		}

	}
}

void Asura_Render_States::SetStencilEnabled( bool b) 
{ 
#if 0
	StencilEnabled = b;
#endif
}

