
#include "DXSwapChain.h"

#include "DeviceStateManager.h"
#include "DXViewPort.h"

DXSwapChain::DXSwapChain(DeviceStateManager* const device, const STSelMode& mode, const HWND hwnd)
{
	m_SwapChain = NULL;
	m_Wnd = hwnd;
	m_Device = device;

	m_DepthStencilRestore = NULL;
	m_RenderTargetRestore = NULL;
	m_DepthStencil = NULL;

	m_pViewPort = new DXViewPort(device);
		
	Reset(mode);
}

DXSwapChain::~DXSwapChain(void)
{
	Invalidate();
}

void DXSwapChain::Present(void)
{
	if(m_SwapChain)
		m_SwapChain->Present( NULL, NULL, NULL, NULL, NULL );
}

void DXSwapChain::BeginScene(void)
{
	if(m_SwapChain)
	{
		m_Device->GetDevice()->GetRenderTarget(0, &m_RenderTargetRestore);
		m_Device->GetDevice()->GetDepthStencilSurface(&m_DepthStencilRestore);
		
		LPDIRECT3DSURFACE9 bb;
		m_SwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &bb);
		m_Device->GetDevice()->SetRenderTarget(0, bb);
		m_Device->GetDevice()->SetDepthStencilSurface(m_DepthStencil);

		bb->Release();
	}
}

void DXSwapChain::EndScene(void)
{
	if(m_RenderTargetRestore)
	{
		m_Device->GetDevice()->SetRenderTarget(0, m_RenderTargetRestore);
		m_RenderTargetRestore->Release();
		m_RenderTargetRestore = NULL;
	}

	if(m_DepthStencilRestore)
	{
		m_Device->GetDevice()->SetDepthStencilSurface(m_DepthStencilRestore);
		m_DepthStencilRestore->Release();
		m_DepthStencilRestore = NULL;
	}
}

void DXSwapChain::Reset(const STSelMode& mode)
{
	Invalidate();

	memcpy(&m_Mode,&mode,sizeof(STSelMode));
	m_Mode.InitPresentParam(m_PresentParam, m_Wnd);

	if(m_Mode.Width > 0 && m_Mode.Height > 0)
	{
		wlog("SwapChainReset: ID=%d", (unsigned)this);

		m_pViewPort->SetRegion(1, 1, m_Mode.Width, m_Mode.Height, 0 ,1);

		Restore();
	}
}

void DXSwapChain::DoRestore(void)
{
	if(!m_SwapChain)
		m_Device->GetDevice()->CreateAdditionalSwapChain(&m_PresentParam, &m_SwapChain);

	if(!m_DepthStencil && m_PresentParam.EnableAutoDepthStencil)
	{
		HRESULT hr = m_Device->GetDevice()->CreateDepthStencilSurface(m_PresentParam.BackBufferWidth, m_PresentParam.BackBufferHeight, m_PresentParam.AutoDepthStencilFormat, m_PresentParam.MultiSampleType, m_PresentParam.MultiSampleQuality, 0, &m_DepthStencil, NULL);
		if (FAILED(hr))
		{
			wlog("CreateDepthStencilSurface failed @SWAPCHAIN: %r",hr);
		}
	}
}

void DXSwapChain::DoInvalidate(void)
{
	SAFERELEASE(m_SwapChain);
	SAFERELEASE(m_DepthStencil);
}

void DXSwapChain::Release(void)
{
	m_Device->ReleaseSwapChain(this);
}