mirror of
https://github.com/EduApps-CDG/OpenDX
synced 2024-12-30 09:45:37 +01:00
[dxgi] Initial fullscreen support
The implementation is highly experimental and may cause issues. Tested with DXUT-based Microsoft SDK samples and Nier:Automata.
This commit is contained in:
parent
745ded47e0
commit
10269876e3
@ -153,6 +153,26 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HRESULT DxgiAdapter::GetOutputFromMonitor(
|
||||||
|
HMONITOR Monitor,
|
||||||
|
IDXGIOutput** ppOutput) {
|
||||||
|
Com<IDXGIOutput> output;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; SUCCEEDED(EnumOutputs(i, &output)); i++) {
|
||||||
|
DXGI_OUTPUT_DESC outputDesc;
|
||||||
|
output->GetDesc(&outputDesc);
|
||||||
|
|
||||||
|
if (outputDesc.Monitor == Monitor) {
|
||||||
|
*ppOutput = output.ref();
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No such output found
|
||||||
|
return DXGI_ERROR_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxgiAdapter::AddColorFormat(
|
void DxgiAdapter::AddColorFormat(
|
||||||
DXGI_FORMAT srcFormat,
|
DXGI_FORMAT srcFormat,
|
||||||
VkFormat dstFormat) {
|
VkFormat dstFormat) {
|
||||||
|
@ -51,6 +51,10 @@ namespace dxvk {
|
|||||||
DxgiFormatInfo STDMETHODCALLTYPE LookupFormat(
|
DxgiFormatInfo STDMETHODCALLTYPE LookupFormat(
|
||||||
DXGI_FORMAT format, DxgiFormatMode mode) final;
|
DXGI_FORMAT format, DxgiFormatMode mode) final;
|
||||||
|
|
||||||
|
HRESULT GetOutputFromMonitor(
|
||||||
|
HMONITOR Monitor,
|
||||||
|
IDXGIOutput** ppOutput);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
using FormatMap = std::unordered_map<DXGI_FORMAT, DxgiFormatInfo>;
|
using FormatMap = std::unordered_map<DXGI_FORMAT, DxgiFormatInfo>;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include "dxgi_device.h"
|
||||||
#include "dxgi_factory.h"
|
#include "dxgi_factory.h"
|
||||||
#include "dxgi_swapchain.h"
|
#include "dxgi_swapchain.h"
|
||||||
|
|
||||||
@ -18,17 +19,18 @@ namespace dxvk {
|
|||||||
|
|
||||||
// Retrieve the adapter, which is going
|
// Retrieve the adapter, which is going
|
||||||
// to be used to enumerate displays.
|
// to be used to enumerate displays.
|
||||||
|
Com<IDXGIDevice> device;
|
||||||
Com<IDXGIAdapter> adapter;
|
Com<IDXGIAdapter> adapter;
|
||||||
|
|
||||||
if (FAILED(pDevice->QueryInterface(__uuidof(IDXGIDevicePrivate),
|
if (FAILED(pDevice->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&device))))
|
||||||
reinterpret_cast<void**>(&m_device))))
|
|
||||||
throw DxvkError("DxgiSwapChain::DxgiSwapChain: Invalid device");
|
throw DxvkError("DxgiSwapChain::DxgiSwapChain: Invalid device");
|
||||||
|
|
||||||
if (FAILED(m_device->GetAdapter(&adapter))
|
if (FAILED(device->GetAdapter(&adapter)))
|
||||||
|| FAILED(adapter->QueryInterface(__uuidof(IDXGIAdapterPrivate),
|
|
||||||
reinterpret_cast<void**>(&m_adapter))))
|
|
||||||
throw DxvkError("DxgiSwapChain::DxgiSwapChain: Failed to retrieve adapter");
|
throw DxvkError("DxgiSwapChain::DxgiSwapChain: Failed to retrieve adapter");
|
||||||
|
|
||||||
|
m_device = static_cast<DxgiDevice*>(device.ptr());
|
||||||
|
m_adapter = static_cast<DxgiAdapter*>(adapter.ptr());
|
||||||
|
|
||||||
// Initialize frame statistics
|
// Initialize frame statistics
|
||||||
m_stats.PresentCount = 0;
|
m_stats.PresentCount = 0;
|
||||||
m_stats.PresentRefreshCount = 0;
|
m_stats.PresentRefreshCount = 0;
|
||||||
@ -44,8 +46,8 @@ namespace dxvk {
|
|||||||
if (m_desc.BufferDesc.Height == 0) m_desc.BufferDesc.Height = windowSize.height;
|
if (m_desc.BufferDesc.Height == 0) m_desc.BufferDesc.Height = windowSize.height;
|
||||||
|
|
||||||
// Set initial window mode and fullscreen state
|
// Set initial window mode and fullscreen state
|
||||||
// if (FAILED(this->SetFullscreenState(!pDesc->Windowed, nullptr)))
|
if (!pDesc->Windowed && FAILED(EnterFullscreenMode(nullptr)))
|
||||||
// throw DxvkError("DxgiSwapChain: Failed to set initial fullscreen state");
|
throw DxvkError("DxgiSwapChain: Failed to set initial fullscreen state");
|
||||||
|
|
||||||
if (FAILED(CreatePresenter()) || FAILED(CreateBackBuffer()))
|
if (FAILED(CreatePresenter()) || FAILED(CreateBackBuffer()))
|
||||||
throw DxvkError("DxgiSwapChain: Failed to create presenter or back buffer");
|
throw DxvkError("DxgiSwapChain: Failed to create presenter or back buffer");
|
||||||
@ -91,11 +93,18 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE DxgiSwapChain::GetContainingOutput(IDXGIOutput** ppOutput) {
|
HRESULT STDMETHODCALLTYPE DxgiSwapChain::GetContainingOutput(IDXGIOutput** ppOutput) {
|
||||||
if (ppOutput != nullptr)
|
if (ppOutput == nullptr)
|
||||||
return DXGI_ERROR_INVALID_CALL;
|
return DXGI_ERROR_INVALID_CALL;
|
||||||
|
|
||||||
Logger::err("DxgiSwapChain::GetContainingOutput: Not implemented");
|
RECT windowRect = { 0, 0, 0, 0 };
|
||||||
return E_NOTIMPL;
|
::GetWindowRect(m_desc.OutputWindow, &windowRect);
|
||||||
|
|
||||||
|
HMONITOR monitor = ::MonitorFromPoint(
|
||||||
|
{ (windowRect.left + windowRect.right) / 2,
|
||||||
|
(windowRect.top + windowRect.bottom) / 2 },
|
||||||
|
MONITOR_DEFAULTTOPRIMARY);
|
||||||
|
|
||||||
|
return m_adapter->GetOutputFromMonitor(monitor, ppOutput);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -232,8 +241,15 @@ namespace dxvk {
|
|||||||
IDXGIOutput* pTarget) {
|
IDXGIOutput* pTarget) {
|
||||||
std::lock_guard<std::mutex> lock(m_mutex);
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
|
|
||||||
Logger::err("DxgiSwapChain::SetFullscreenState: Not implemented");
|
if (Fullscreen)
|
||||||
return E_NOTIMPL;
|
Logger::warn("DxgiSwapChain: Display mode changes not implemented");
|
||||||
|
|
||||||
|
if (m_desc.Windowed && Fullscreen)
|
||||||
|
return this->EnterFullscreenMode(pTarget);
|
||||||
|
else if (!m_desc.Windowed && !Fullscreen)
|
||||||
|
return this->LeaveFullscreenMode();
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -284,6 +300,66 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HRESULT DxgiSwapChain::EnterFullscreenMode(IDXGIOutput *pTarget) {
|
||||||
|
Com<IDXGIOutput> output = pTarget;
|
||||||
|
|
||||||
|
if (output == nullptr) {
|
||||||
|
if (FAILED(GetContainingOutput(&output))) {
|
||||||
|
Logger::err("DxgiSwapChain: Failed to enter fullscreen mode: Cannot query containing output");
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change the window flags to remove the decoration etc.
|
||||||
|
LONG style = ::GetWindowLongW(m_desc.OutputWindow, GWL_STYLE);
|
||||||
|
LONG exstyle = ::GetWindowLongW(m_desc.OutputWindow, GWL_EXSTYLE);
|
||||||
|
|
||||||
|
m_windowState.style = style;
|
||||||
|
m_windowState.exstyle = exstyle;
|
||||||
|
::GetWindowRect(m_desc.OutputWindow, &m_windowState.rect);
|
||||||
|
|
||||||
|
style |= WS_POPUP | WS_SYSMENU;
|
||||||
|
style &= ~(WS_CAPTION | WS_THICKFRAME);
|
||||||
|
|
||||||
|
exstyle &= ~(WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE);
|
||||||
|
|
||||||
|
::SetWindowLongW(m_desc.OutputWindow, GWL_STYLE, style);
|
||||||
|
::SetWindowLongW(m_desc.OutputWindow, GWL_EXSTYLE, exstyle);
|
||||||
|
|
||||||
|
// Move the window so that it covers the entire output
|
||||||
|
DXGI_OUTPUT_DESC desc;
|
||||||
|
output->GetDesc(&desc);
|
||||||
|
|
||||||
|
const RECT rect = desc.DesktopCoordinates;
|
||||||
|
|
||||||
|
::SetWindowPos(m_desc.OutputWindow, HWND_TOPMOST,
|
||||||
|
rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
|
||||||
|
SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOACTIVATE);
|
||||||
|
|
||||||
|
// Update swap chain description
|
||||||
|
m_desc.Windowed = FALSE;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HRESULT DxgiSwapChain::LeaveFullscreenMode() {
|
||||||
|
// FIXME wine only restores window flags if the application
|
||||||
|
// has not modified them in the meantime. Some applications
|
||||||
|
// may rely on that behaviour.
|
||||||
|
const RECT rect = m_windowState.rect;
|
||||||
|
|
||||||
|
::SetWindowLongW(m_desc.OutputWindow, GWL_STYLE, m_windowState.style);
|
||||||
|
::SetWindowLongW(m_desc.OutputWindow, GWL_EXSTYLE, m_windowState.exstyle);
|
||||||
|
|
||||||
|
::SetWindowPos(m_desc.OutputWindow, 0,
|
||||||
|
rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
|
||||||
|
SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOACTIVATE);
|
||||||
|
|
||||||
|
m_desc.Windowed = TRUE;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
HRESULT DxgiSwapChain::GetSampleCount(UINT Count, VkSampleCountFlagBits* pCount) const {
|
HRESULT DxgiSwapChain::GetSampleCount(UINT Count, VkSampleCountFlagBits* pCount) const {
|
||||||
switch (Count) {
|
switch (Count) {
|
||||||
case 1: *pCount = VK_SAMPLE_COUNT_1_BIT; return S_OK;
|
case 1: *pCount = VK_SAMPLE_COUNT_1_BIT; return S_OK;
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
|
class DxgiDevice;
|
||||||
class DxgiFactory;
|
class DxgiFactory;
|
||||||
|
|
||||||
class DxgiSwapChain : public DxgiObject<IDXGISwapChain> {
|
class DxgiSwapChain : public DxgiObject<IDXGISwapChain> {
|
||||||
@ -81,11 +82,17 @@ namespace dxvk {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
struct WindowState {
|
||||||
|
uint32_t style = 0;
|
||||||
|
uint32_t exstyle = 0;
|
||||||
|
RECT rect = { 0, 0, 0, 0 };
|
||||||
|
};
|
||||||
|
|
||||||
std::mutex m_mutex;
|
std::mutex m_mutex;
|
||||||
|
|
||||||
Com<DxgiFactory> m_factory;
|
Com<DxgiFactory> m_factory;
|
||||||
Com<IDXGIAdapterPrivate> m_adapter;
|
Com<DxgiAdapter> m_adapter;
|
||||||
Com<IDXGIDevicePrivate> m_device;
|
Com<DxgiDevice> m_device;
|
||||||
Com<IDXGIPresentDevicePrivate> m_presentDevice;
|
Com<IDXGIPresentDevicePrivate> m_presentDevice;
|
||||||
|
|
||||||
DXGI_SWAP_CHAIN_DESC m_desc;
|
DXGI_SWAP_CHAIN_DESC m_desc;
|
||||||
@ -94,15 +101,22 @@ namespace dxvk {
|
|||||||
Rc<DxgiPresenter> m_presenter;
|
Rc<DxgiPresenter> m_presenter;
|
||||||
Com<IDXGIPresentBackBuffer> m_backBuffer;
|
Com<IDXGIPresentBackBuffer> m_backBuffer;
|
||||||
|
|
||||||
|
WindowState m_windowState;
|
||||||
|
|
||||||
HRESULT CreatePresenter();
|
HRESULT CreatePresenter();
|
||||||
HRESULT CreateBackBuffer();
|
HRESULT CreateBackBuffer();
|
||||||
|
|
||||||
VkExtent2D GetWindowSize() const;
|
VkExtent2D GetWindowSize() const;
|
||||||
|
|
||||||
|
HRESULT EnterFullscreenMode(
|
||||||
|
IDXGIOutput *pTarget);
|
||||||
|
|
||||||
|
HRESULT LeaveFullscreenMode();
|
||||||
|
|
||||||
HRESULT GetSampleCount(
|
HRESULT GetSampleCount(
|
||||||
UINT Count,
|
UINT Count,
|
||||||
VkSampleCountFlagBits* pCount) const;
|
VkSampleCountFlagBits* pCount) const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user