/*
 * Copyright 2019,2020 Sony Corporation
 */

#include "Compositor/StereoTexture.h"

// CopyTexture
#include <CommonRenderResources.h>
#include <GlobalShader.h>
#include <ScreenRendering.h>
#include <ClearQuad.h>

namespace
{
	void CopyTexture(FRHICommandListImmediate& RHICmdList, FRHITexture2D* BackBuffer, FRHITexture2D* SrcTexture, FVector2D WindowSize, uint32 SourceWidth, uint32 SourceHeight)
	{
		const FVector2D ViewportSize = FVector2D(WindowSize.X, WindowSize.Y);

		FRHIRenderPassInfo RPInfoTempRight(BackBuffer, ERenderTargetActions::Load_Store);
		RHICmdList.BeginRenderPass(RPInfoTempRight, TEXT("StereoTexture_CopyTexture"));
		{
			DrawClearQuad(RHICmdList, FLinearColor(0.f, 0.f, 0.f, 1.f));
			RHICmdList.SetViewport(0, 0, 0.f, ViewportSize.X, ViewportSize.Y, 1.f);

			FGraphicsPipelineStateInitializer GraphicsPSOInit;
			RHICmdList.ApplyCachedRenderTargets(GraphicsPSOInit);

			const auto FeatureLevel = GMaxRHIFeatureLevel;
			auto ShaderMap = GetGlobalShaderMap(FeatureLevel);
			TShaderMapRef<FScreenVS> VertexShader(ShaderMap);
			TShaderMapRef<FScreenPS> PixelShader(ShaderMap);

			GraphicsPSOInit.BlendState = TStaticBlendState<>::GetRHI();
			GraphicsPSOInit.RasterizerState = TStaticRasterizerState<>::GetRHI();
			GraphicsPSOInit.DepthStencilState = TStaticDepthStencilState<false, CF_Always>::GetRHI();
			GraphicsPSOInit.PrimitiveType = PT_TriangleList;
			GraphicsPSOInit.BoundShaderState.VertexDeclarationRHI = GFilterVertexDeclaration.VertexDeclarationRHI;
#if ENGINE_MINOR_VERSION<=24
			GraphicsPSOInit.BoundShaderState.VertexShaderRHI = GETSAFERHISHADER_VERTEX(*VertexShader);
			GraphicsPSOInit.BoundShaderState.PixelShaderRHI = GETSAFERHISHADER_PIXEL(*PixelShader);
#else // ENGINE_MINOR_VERSION<=24
			GraphicsPSOInit.BoundShaderState.VertexShaderRHI = VertexShader.GetVertexShader();
			GraphicsPSOInit.BoundShaderState.PixelShaderRHI = PixelShader.GetPixelShader();
#endif // ENGINE_MINOR_VERSION<=24
			SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit);

			PixelShader->SetParameters(RHICmdList, TStaticSamplerState<SF_Bilinear>::GetRHI(), SrcTexture);

			static const FName RendererModuleName("Renderer");
			IRendererModule* RendererModule = FModuleManager::GetModulePtr<IRendererModule>(RendererModuleName);
#if ENGINE_MINOR_VERSION<=24
			RendererModule->DrawRectangle(
				RHICmdList,
				0.f, 0.f,
				ViewportSize.X, ViewportSize.Y,
				0.f, 0.f,
				1.f, 1.f,
				FIntPoint(ViewportSize.X, ViewportSize.Y),
				FIntPoint(1, 1),
				*VertexShader,
				EDRF_Default);
#else // ENGINE_MINOR_VERSION<=24
			RendererModule->DrawRectangle(
				RHICmdList,
				0.f, 0.f,
				ViewportSize.X, ViewportSize.Y,
				0.f, 0.f,
				1.f, 1.f,
				FIntPoint(ViewportSize.X, ViewportSize.Y),
				FIntPoint(1, 1),
				VertexShader,
				EDRF_Default);
#endif // ENGINE_MINOR_VERSION<=24
		}
		RHICmdList.EndRenderPass();
	}
}

namespace sr_display
{
	FStereoTexture::FStereoTexture()
	{
	}

	FStereoTexture::~FStereoTexture()
	{
	}

	void  FStereoTexture::SetLeft(FTexture2DRHIRef Left)
	{
		LeftTexture = Left;
	}

	void  FStereoTexture::SetRight(FTexture2DRHIRef Right)
	{
		RightTexture = Right;
	}

	void FStereoTexture::Overwrite(FTexture2DRHIRef Left, FTexture2DRHIRef Right,
		FRHICommandListImmediate& RHICmdList, uint32 SourceWidth, uint32 SourceHeight) const
	{
		CopyTexture(RHICmdList, Left, LeftTexture, Left->GetSizeXY(), SourceWidth, SourceHeight);
		CopyTexture(RHICmdList, Right, RightTexture, Right->GetSizeXY(), SourceWidth, SourceHeight);
	}

	bool FStereoTexture::IsValid() const
	{
		return LeftTexture.IsValid() && RightTexture.IsValid();
	}

} // namespace sr_display
