Files
2026-04-18 22:31:51 +02:00

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.";
}
}