mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-11 19:24:11 +01:00
4e22e4bc3a
Cleans up constructor and moves a bunch of common code to the new CreateDxvkSwapChainForHwnd function, which can be called from both d3d11 and dxgi. Also fixes potential issues with the current implementation of the IWineDXGISwapChainFactory interface.
307 lines
8.9 KiB
C++
307 lines
8.9 KiB
C++
#include "dxgi_factory.h"
|
|
#include "dxgi_swapchain.h"
|
|
|
|
namespace dxvk {
|
|
|
|
DxgiFactory::DxgiFactory(UINT Flags)
|
|
: m_instance(new DxvkInstance()),
|
|
m_options (m_instance->config()),
|
|
m_flags (Flags) {
|
|
for (uint32_t i = 0; m_instance->enumAdapters(i) != nullptr; i++)
|
|
m_instance->enumAdapters(i)->logAdapterInfo();
|
|
}
|
|
|
|
|
|
DxgiFactory::~DxgiFactory() {
|
|
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE DxgiFactory::QueryInterface(REFIID riid, void** ppvObject) {
|
|
*ppvObject = nullptr;
|
|
|
|
if (riid == __uuidof(IUnknown)
|
|
|| riid == __uuidof(IDXGIObject)
|
|
|| riid == __uuidof(IDXGIFactory)
|
|
|| riid == __uuidof(IDXGIFactory1)
|
|
|| riid == __uuidof(IDXGIFactory2)
|
|
|| riid == __uuidof(IDXGIFactory3)
|
|
|| riid == __uuidof(IDXGIFactory4)) {
|
|
*ppvObject = ref(this);
|
|
return S_OK;
|
|
}
|
|
|
|
Logger::warn("DxgiFactory::QueryInterface: Unknown interface query");
|
|
Logger::warn(str::format(riid));
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE DxgiFactory::GetParent(REFIID riid, void** ppParent) {
|
|
InitReturnPtr(ppParent);
|
|
|
|
Logger::warn("DxgiFactory::GetParent: Unknown interface query");
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
|
|
BOOL STDMETHODCALLTYPE DxgiFactory::IsWindowedStereoEnabled() {
|
|
// We don't support Stereo 3D at the moment
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE DxgiFactory::CreateSoftwareAdapter(
|
|
HMODULE Module,
|
|
IDXGIAdapter** ppAdapter) {
|
|
InitReturnPtr(ppAdapter);
|
|
|
|
if (ppAdapter == nullptr)
|
|
return DXGI_ERROR_INVALID_CALL;
|
|
|
|
Logger::err("DXGI: CreateSoftwareAdapter: Software adapters not supported");
|
|
return DXGI_ERROR_UNSUPPORTED;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE DxgiFactory::CreateSwapChain(
|
|
IUnknown* pDevice,
|
|
DXGI_SWAP_CHAIN_DESC* pDesc,
|
|
IDXGISwapChain** ppSwapChain) {
|
|
if (ppSwapChain == nullptr || pDesc == nullptr || pDevice == nullptr)
|
|
return DXGI_ERROR_INVALID_CALL;
|
|
|
|
DXGI_SWAP_CHAIN_DESC1 desc;
|
|
desc.Width = pDesc->BufferDesc.Width;
|
|
desc.Height = pDesc->BufferDesc.Height;
|
|
desc.Format = pDesc->BufferDesc.Format;
|
|
desc.Stereo = FALSE;
|
|
desc.SampleDesc = pDesc->SampleDesc;
|
|
desc.BufferUsage = pDesc->BufferUsage;
|
|
desc.BufferCount = pDesc->BufferCount;
|
|
desc.Scaling = DXGI_SCALING_STRETCH;
|
|
desc.SwapEffect = pDesc->SwapEffect;
|
|
desc.AlphaMode = DXGI_ALPHA_MODE_IGNORE;
|
|
desc.Flags = pDesc->Flags;
|
|
|
|
DXGI_SWAP_CHAIN_FULLSCREEN_DESC descFs;
|
|
descFs.RefreshRate = pDesc->BufferDesc.RefreshRate;
|
|
descFs.ScanlineOrdering = pDesc->BufferDesc.ScanlineOrdering;
|
|
descFs.Scaling = pDesc->BufferDesc.Scaling;
|
|
descFs.Windowed = pDesc->Windowed;
|
|
|
|
IDXGISwapChain1* swapChain = nullptr;
|
|
HRESULT hr = CreateSwapChainForHwnd(
|
|
pDevice, pDesc->OutputWindow,
|
|
&desc, &descFs, nullptr,
|
|
&swapChain);
|
|
|
|
*ppSwapChain = swapChain;
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE DxgiFactory::CreateSwapChainForHwnd(
|
|
IUnknown* pDevice,
|
|
HWND hWnd,
|
|
const DXGI_SWAP_CHAIN_DESC1* pDesc,
|
|
const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc,
|
|
IDXGIOutput* pRestrictToOutput,
|
|
IDXGISwapChain1** ppSwapChain) {
|
|
InitReturnPtr(ppSwapChain);
|
|
|
|
if (!ppSwapChain || !pDesc || !hWnd || !pDevice)
|
|
return DXGI_ERROR_INVALID_CALL;
|
|
|
|
Com<IDXGIVkPresentDevice> dxvkDevice;
|
|
|
|
if (SUCCEEDED(pDevice->QueryInterface(
|
|
__uuidof(IDXGIVkPresentDevice),
|
|
reinterpret_cast<void**>(&dxvkDevice)))) {
|
|
return CreateDxvkSwapChainForHwnd(
|
|
this, dxvkDevice.ptr(), hWnd, pDesc,
|
|
pFullscreenDesc, pRestrictToOutput,
|
|
ppSwapChain);
|
|
}
|
|
|
|
Logger::err("DXGI: CreateSwapChainForHwnd: Unsupported device type");
|
|
return DXGI_ERROR_UNSUPPORTED;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE DxgiFactory::CreateSwapChainForCoreWindow(
|
|
IUnknown* pDevice,
|
|
IUnknown* pWindow,
|
|
const DXGI_SWAP_CHAIN_DESC1* pDesc,
|
|
IDXGIOutput* pRestrictToOutput,
|
|
IDXGISwapChain1** ppSwapChain) {
|
|
InitReturnPtr(ppSwapChain);
|
|
|
|
Logger::err("DxgiFactory::CreateSwapChainForCoreWindow: Not implemented");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE DxgiFactory::CreateSwapChainForComposition(
|
|
IUnknown* pDevice,
|
|
const DXGI_SWAP_CHAIN_DESC1* pDesc,
|
|
IDXGIOutput* pRestrictToOutput,
|
|
IDXGISwapChain1** ppSwapChain) {
|
|
InitReturnPtr(ppSwapChain);
|
|
|
|
Logger::err("DxgiFactory::CreateSwapChainForComposition: Not implemented");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE DxgiFactory::EnumAdapters(
|
|
UINT Adapter,
|
|
IDXGIAdapter** ppAdapter) {
|
|
InitReturnPtr(ppAdapter);
|
|
|
|
if (ppAdapter == nullptr)
|
|
return DXGI_ERROR_INVALID_CALL;
|
|
|
|
IDXGIAdapter1* handle = nullptr;
|
|
HRESULT hr = this->EnumAdapters1(Adapter, &handle);
|
|
*ppAdapter = handle;
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE DxgiFactory::EnumAdapters1(
|
|
UINT Adapter,
|
|
IDXGIAdapter1** ppAdapter) {
|
|
InitReturnPtr(ppAdapter);
|
|
|
|
if (ppAdapter == nullptr)
|
|
return DXGI_ERROR_INVALID_CALL;
|
|
|
|
Rc<DxvkAdapter> dxvkAdapter
|
|
= m_instance->enumAdapters(Adapter);
|
|
|
|
if (dxvkAdapter == nullptr)
|
|
return DXGI_ERROR_NOT_FOUND;
|
|
|
|
*ppAdapter = ref(new DxgiAdapter(this, dxvkAdapter));
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE DxgiFactory::EnumAdapterByLuid(
|
|
LUID AdapterLuid,
|
|
REFIID riid,
|
|
void** ppvAdapter) {
|
|
InitReturnPtr(ppvAdapter);
|
|
uint32_t adapterId = 0;
|
|
|
|
while (true) {
|
|
Com<IDXGIAdapter> adapter;
|
|
HRESULT hr = EnumAdapters(adapterId++, &adapter);
|
|
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
DXGI_ADAPTER_DESC desc;
|
|
adapter->GetDesc(&desc);
|
|
|
|
if (!std::memcmp(&AdapterLuid, &desc.AdapterLuid, sizeof(LUID)))
|
|
return adapter->QueryInterface(riid, ppvAdapter);
|
|
}
|
|
|
|
// This should be unreachable
|
|
return DXGI_ERROR_NOT_FOUND;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE DxgiFactory::EnumWarpAdapter(
|
|
REFIID riid,
|
|
void** ppvAdapter) {
|
|
InitReturnPtr(ppvAdapter);
|
|
|
|
Logger::err("DxgiFactory::EnumWarpAdapter: Not implemented");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE DxgiFactory::GetWindowAssociation(HWND *pWindowHandle) {
|
|
if (pWindowHandle == nullptr)
|
|
return DXGI_ERROR_INVALID_CALL;
|
|
|
|
*pWindowHandle = m_associatedWindow;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE DxgiFactory::GetSharedResourceAdapterLuid(
|
|
HANDLE hResource,
|
|
LUID* pLuid) {
|
|
Logger::err("DxgiFactory::GetSharedResourceAdapterLuid: Not implemented");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE DxgiFactory::MakeWindowAssociation(HWND WindowHandle, UINT Flags) {
|
|
Logger::warn("DXGI: MakeWindowAssociation: Ignoring flags");
|
|
m_associatedWindow = WindowHandle;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
BOOL STDMETHODCALLTYPE DxgiFactory::IsCurrent() {
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE DxgiFactory::RegisterOcclusionStatusWindow(
|
|
HWND WindowHandle,
|
|
UINT wMsg,
|
|
DWORD* pdwCookie) {
|
|
Logger::err("DxgiFactory::RegisterOcclusionStatusWindow: Not implemented");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE DxgiFactory::RegisterStereoStatusEvent(
|
|
HANDLE hEvent,
|
|
DWORD* pdwCookie) {
|
|
Logger::err("DxgiFactory::RegisterStereoStatusEvent: Not implemented");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE DxgiFactory::RegisterStereoStatusWindow(
|
|
HWND WindowHandle,
|
|
UINT wMsg,
|
|
DWORD* pdwCookie) {
|
|
Logger::err("DxgiFactory::RegisterStereoStatusWindow: Not implemented");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE DxgiFactory::RegisterOcclusionStatusEvent(
|
|
HANDLE hEvent,
|
|
DWORD* pdwCookie) {
|
|
Logger::err("DxgiFactory::RegisterOcclusionStatusEvent: Not implemented");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
void STDMETHODCALLTYPE DxgiFactory::UnregisterStereoStatus(
|
|
DWORD dwCookie) {
|
|
Logger::err("DxgiFactory::UnregisterStereoStatus: Not implemented");
|
|
}
|
|
|
|
|
|
void STDMETHODCALLTYPE DxgiFactory::UnregisterOcclusionStatus(
|
|
DWORD dwCookie) {
|
|
Logger::err("DxgiFactory::UnregisterOcclusionStatus: Not implemented");
|
|
}
|
|
|
|
|
|
UINT STDMETHODCALLTYPE DxgiFactory::GetCreationFlags() {
|
|
return m_flags;
|
|
}
|
|
|
|
}
|