188 lines
5.1 KiB
C++
188 lines
5.1 KiB
C++
#include "stdafx.h"
|
|
#include "SwapChain.h"
|
|
#include "IResourceFactory.h"
|
|
#include <exception>
|
|
|
|
|
|
SwapChain::SwapChain(IEngine& argEngine)
|
|
: RenderTargetBase(argEngine)
|
|
, m_SwapChain(NULL)
|
|
, m_VSync(true)
|
|
{
|
|
}
|
|
|
|
|
|
SwapChain::~SwapChain()
|
|
{
|
|
this->Uninitialize();
|
|
m_Engine.get_ResourceFactory().DeleteSwapChain(*const_cast<SwapChain*>(this), true);
|
|
|
|
}
|
|
|
|
void SwapChain::SetWindowParameters(HWND argWindowHandle, uint32 argWidth, uint32 argHeight, uint32 argRefreshRate, DataFormat::Enumeration argFormat, uint32 argMultiSampleCount, uint32 argMultiSampleQuality)
|
|
{
|
|
if (m_SwapChain != NULL)
|
|
this->Uninitialize();
|
|
|
|
// get missing information
|
|
if (argMultiSampleCount == 0)
|
|
argMultiSampleCount = 1;
|
|
if (argWidth == 0 || argHeight == 0)
|
|
{
|
|
RECT windowRect;
|
|
::GetClientRect(argWindowHandle, &windowRect);
|
|
if (argWidth == 0)
|
|
argWidth = windowRect.right - windowRect.left;
|
|
if (argHeight == 0)
|
|
argHeight = windowRect.bottom - windowRect.top;
|
|
}
|
|
if (argRefreshRate == 0)
|
|
argRefreshRate = 60; // 60Hz
|
|
if (argFormat == DataFormat::Unknown)
|
|
argFormat = DataFormat::R8G8B8A8_UnsignedNormalized; // RGBA(X) 8Bit per channel -> 32Bit
|
|
|
|
// build the description
|
|
ZeroMemory(&m_SwapChainDescription, sizeof(m_SwapChainDescription));
|
|
m_SwapChainDescription.BufferCount = 1;
|
|
m_SwapChainDescription.BufferDesc.Width = argWidth;
|
|
m_SwapChainDescription.BufferDesc.Height = argHeight;
|
|
m_SwapChainDescription.BufferDesc.Format = (DXGI_FORMAT)argFormat;
|
|
m_SwapChainDescription.BufferDesc.RefreshRate.Numerator = argRefreshRate;
|
|
m_SwapChainDescription.BufferDesc.RefreshRate.Denominator = 1;
|
|
m_SwapChainDescription.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
|
m_SwapChainDescription.OutputWindow = argWindowHandle;
|
|
m_MultiSampleCount = m_SwapChainDescription.SampleDesc.Count = argMultiSampleCount;
|
|
m_MultiSampleQuality = m_SwapChainDescription.SampleDesc.Quality = argMultiSampleQuality;
|
|
m_SwapChainDescription.Windowed = TRUE;
|
|
|
|
if (S_OK != m_Engine.get_DXGIFactory().CreateSwapChain(&m_Engine.get_DX10Device(), &m_SwapChainDescription, &m_SwapChain))
|
|
{
|
|
throw L"SwapChain: Unable to create swapchain.";
|
|
}
|
|
|
|
this->RetriveData();
|
|
|
|
ViewPort vp;
|
|
vp.m_Width = argWidth;
|
|
vp.m_Height = argHeight;
|
|
this->set_ViewPort(vp);
|
|
}
|
|
|
|
|
|
void SwapChain::Uninitialize()
|
|
{
|
|
RenderTargetBase::Uninitialize();
|
|
|
|
/*if (m_SwapChain != NULL)
|
|
m_SwapChain->Release();*/
|
|
m_SwapChain = NULL;
|
|
}
|
|
|
|
|
|
void SwapChain::Resize(int argWidth, int argHeight)
|
|
{
|
|
if (m_SwapChain == NULL || m_RenderTargetView == NULL)
|
|
{
|
|
throw L"SwapChain: Access forbidden until resource has been initialized.";
|
|
}
|
|
|
|
if (argWidth == 0 || argHeight == 0)
|
|
{
|
|
RECT windowRect;
|
|
::GetClientRect(m_SwapChainDescription.OutputWindow, &windowRect);
|
|
if (argWidth == 0)
|
|
argWidth = windowRect.right - windowRect.left;
|
|
if (argHeight == 0)
|
|
argHeight = windowRect.bottom - windowRect.top;
|
|
}
|
|
|
|
if (m_SwapChainDescription.BufferDesc.Width == argWidth ||
|
|
m_SwapChainDescription.BufferDesc.Height == argHeight)
|
|
return;
|
|
|
|
bool depthStencilBuffer = this->get_HasDepthStencilBuffer();
|
|
|
|
m_Engine.get_DX10Device().ClearState();
|
|
|
|
this->set_HasDepthStencilBuffer(false);
|
|
|
|
if (m_RenderTargetView != NULL)
|
|
m_RenderTargetView->Release();
|
|
m_RenderTargetView = NULL;
|
|
|
|
m_SwapChain->ResizeBuffers(m_SwapChainDescription.BufferCount, argWidth, argHeight, m_SwapChainDescription.BufferDesc.Format, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH);
|
|
m_SwapChainDescription.BufferDesc.Width = argWidth;
|
|
m_SwapChainDescription.BufferDesc.Height = argHeight;
|
|
this->RetriveData();
|
|
this->set_HasDepthStencilBuffer(depthStencilBuffer);
|
|
|
|
ViewPort vp = this->get_ViewPort();
|
|
vp.m_Width = argWidth;
|
|
vp.m_Height = argHeight;
|
|
this->set_ViewPort(vp);
|
|
}
|
|
|
|
|
|
void SwapChain::set_Fullscreen(bool argState)
|
|
{
|
|
if (m_SwapChainDescription.Windowed == FALSE && argState)
|
|
{
|
|
throw L"SwapChain: Fullscreen mode already set.";
|
|
}
|
|
if (m_SwapChainDescription.Windowed == TRUE && !argState)
|
|
{
|
|
throw L"SwapChain: Windowed mode already set.";
|
|
}
|
|
|
|
m_SwapChainDescription.Windowed = argState ? FALSE : TRUE;
|
|
|
|
bool depthStencilBuffer = this->get_HasDepthStencilBuffer();
|
|
|
|
m_Engine.get_DX10Device().ClearState();
|
|
|
|
this->set_HasDepthStencilBuffer(false);
|
|
|
|
if (m_RenderTargetView != NULL)
|
|
m_RenderTargetView->Release();
|
|
m_RenderTargetView = NULL;
|
|
|
|
m_SwapChain->SetFullscreenState(m_SwapChainDescription.Windowed == FALSE, NULL);
|
|
this->RetriveData();
|
|
this->set_HasDepthStencilBuffer(depthStencilBuffer);
|
|
}
|
|
|
|
|
|
|
|
void SwapChain::Present()
|
|
{
|
|
if (m_SwapChain == NULL || m_RenderTargetView == NULL)
|
|
{
|
|
throw L"SwapChain: Access forbidden until resource has been initialized.";
|
|
}
|
|
|
|
m_SwapChain->Present(m_VSync ? 1 : 0, 0); // VSync, Flags
|
|
}
|
|
|
|
|
|
void SwapChain::RetriveData()
|
|
{
|
|
if (m_SwapChain == NULL || m_RenderTargetView != NULL)
|
|
{
|
|
throw L"SwapChain: Access forbidden until resource has been initialized.";
|
|
}
|
|
|
|
ID3D10Texture2D* backBuffer;
|
|
HRESULT result = m_SwapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), (void**)&backBuffer);
|
|
if(FAILED(result))
|
|
{
|
|
throw L"SwapChain: Unable to retrive backbuffer.";
|
|
}
|
|
|
|
result = m_Engine.get_DX10Device().CreateRenderTargetView(backBuffer, NULL, &m_RenderTargetView);
|
|
backBuffer->Release();
|
|
if(FAILED(result))
|
|
{
|
|
throw L"SwapChain: Unable to retrive rendertarget view.";
|
|
}
|
|
}
|