#include "stdafx.h" #include "SwapChain.h" #include "IResourceFactory.h" #include SwapChain::SwapChain(IEngine& argEngine) : RenderTargetBase(argEngine) , m_SwapChain(NULL) , m_VSync(true) { } SwapChain::~SwapChain() { this->Uninitialize(); m_Engine.get_ResourceFactory().DeleteSwapChain(*const_cast(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."; } }