#include "platform-dx/device-dx.hpp" #include "platform-dx/dxhelpers.hpp" #include "graphics/adapter.hpp" #include "graphics/swapchain.hpp" #include "platform-dx/implementations.hpp" namespace xna { SwapChain::SwapChain() : GraphicsResource(nullptr) { impl = unew(); } SwapChain::SwapChain(sptr const& device) : GraphicsResource(device) { impl = unew(); } SwapChain::~SwapChain() { impl = nullptr; } static bool internalInit(GraphicsDevice& device, HWND windowHandle, IDXGISwapChain1*& swapChain, DXGI_SWAP_CHAIN_DESC1 const& desc, DXGI_SWAP_CHAIN_FULLSCREEN_DESC const& fdesc) { if (!device._device || !windowHandle) return false; if (swapChain) { swapChain->Release(); swapChain = nullptr; } auto adapter = device.Adapter(); auto dxAdapter = adapter->impl->dxadapter; IDXGIFactory1* dxFactory1 = nullptr; auto hr = dxAdapter->GetParent(IID_IDXGIFactory1, (void**)&dxFactory1); if (FAILED(hr)) return false; IDXGIFactory2* dxFactory2 = nullptr; hr = dxFactory1->QueryInterface(IID_IDXGIFactory2, (void**)&dxFactory2); if (FAILED(hr)) return false; dxFactory2->CreateSwapChainForHwnd( device._device, windowHandle, &desc, &fdesc, nullptr, &swapChain); return true; } bool SwapChain::Initialize(xna_error_ptr_arg) { if (!impl || !m_device || !m_device->_device) { xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); return false; } const auto parameters = m_device->_presentationParameters; impl->dxDescription.Width = static_cast(parameters->BackBufferWidth); impl->dxDescription.Height = static_cast(parameters->BackBufferHeight); impl->dxDescription.Format = DxHelpers::ConvertSurfaceToDXGIFORMAT(parameters->BackBufferFormat); impl->dxDescription.SampleDesc.Count = 1; impl->dxDescription.SampleDesc.Quality = 0; impl->dxDescription.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; impl->dxDescription.BufferCount = 2; impl->dxDescription.SwapEffect = static_cast(parameters->PresentationSwapEffect); impl->dxDescription.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; impl->dxDescription.AlphaMode = DXGI_ALPHA_MODE::DXGI_ALPHA_MODE_UNSPECIFIED; impl->dxFullScreenDescription.RefreshRate.Numerator = 60; impl->dxFullScreenDescription.RefreshRate.Denominator = 1; impl->dxFullScreenDescription.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; impl->dxFullScreenDescription.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; impl->dxFullScreenDescription.Windowed = !parameters->Fullscreen; HWND hwnd = reinterpret_cast(parameters->DeviceWindowHandle); return internalInit(*m_device, hwnd, impl->dxSwapChain, impl->dxDescription, impl->dxFullScreenDescription); } bool SwapChain::GetBackBuffer(Texture2D& texture2D) { if (!impl || !impl->dxSwapChain) return false; const auto hr = impl->dxSwapChain->GetBuffer(0, IID_ID3D11Texture2D, (void**)(&texture2D.impl->dxTexture2D)); return !FAILED(hr); } bool SwapChain::Present(bool vsync) { if (!impl || !impl->dxSwapChain) return false; const auto hr = impl->dxSwapChain->Present(vsync, NULL); return !FAILED(hr); } }