[dxgi] Make swapchain use new wsi interface

This commit is contained in:
Joshua Ashton 2022-08-09 13:25:12 +01:00 committed by Philip Rebohle
parent e13a9f9cf6
commit 21744198e0
2 changed files with 45 additions and 108 deletions

View File

@ -91,7 +91,7 @@ namespace dxvk {
HRESULT STDMETHODCALLTYPE DxgiSwapChain::GetContainingOutput(IDXGIOutput** ppOutput) {
InitReturnPtr(ppOutput);
if (!IsWindow(m_window))
if (!wsi::isWindow(m_window))
return DXGI_ERROR_INVALID_CALL;
if (m_target != nullptr) {
@ -99,15 +99,7 @@ namespace dxvk {
return S_OK;
}
RECT windowRect = { 0, 0, 0, 0 };
::GetWindowRect(m_window, &windowRect);
HMONITOR monitor = ::MonitorFromPoint(
{ (windowRect.left + windowRect.right) / 2,
(windowRect.top + windowRect.bottom) / 2 },
MONITOR_DEFAULTTOPRIMARY);
return GetOutputFromMonitor(monitor, ppOutput);
return GetOutputFromMonitor(wsi::getWindowMonitor(m_window), ppOutput);
}
@ -256,7 +248,7 @@ namespace dxvk {
UINT PresentFlags,
const DXGI_PRESENT_PARAMETERS* pPresentParameters) {
if (!IsWindow(m_window))
if (!wsi::isWindow(m_window))
return S_OK;
if (SyncInterval > 4)
@ -283,7 +275,7 @@ namespace dxvk {
UINT Height,
DXGI_FORMAT NewFormat,
UINT SwapChainFlags) {
if (!IsWindow(m_window))
if (!wsi::isWindow(m_window))
return DXGI_ERROR_INVALID_CALL;
constexpr UINT PreserveFlags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
@ -295,7 +287,7 @@ namespace dxvk {
m_desc.Width = Width;
m_desc.Height = Height;
GetWindowClientSize(m_window,
wsi::getWindowSize(m_window,
m_desc.Width ? nullptr : &m_desc.Width,
m_desc.Height ? nullptr : &m_desc.Height);
@ -333,7 +325,7 @@ namespace dxvk {
if (pNewTargetParameters == nullptr)
return DXGI_ERROR_INVALID_CALL;
if (!IsWindow(m_window))
if (!wsi::isWindow(m_window))
return DXGI_ERROR_INVALID_CALL;
// Update the swap chain description
@ -344,19 +336,10 @@ namespace dxvk {
m_descFs.Scaling = pNewTargetParameters->Scaling;
if (m_descFs.Windowed) {
// Adjust window position and size
RECT newRect = { 0, 0, 0, 0 };
RECT oldRect = { 0, 0, 0, 0 };
::GetWindowRect(m_window, &oldRect);
::SetRect(&newRect, 0, 0, pNewTargetParameters->Width, pNewTargetParameters->Height);
::AdjustWindowRectEx(&newRect,
::GetWindowLongW(m_window, GWL_STYLE), FALSE,
::GetWindowLongW(m_window, GWL_EXSTYLE));
::SetRect(&newRect, 0, 0, newRect.right - newRect.left, newRect.bottom - newRect.top);
::OffsetRect(&newRect, oldRect.left, oldRect.top);
::MoveWindow(m_window, newRect.left, newRect.top,
newRect.right - newRect.left, newRect.bottom - newRect.top, TRUE);
wsi::resizeWindow(
m_window, &m_windowState,
pNewTargetParameters->Width,
pNewTargetParameters->Height);
} else {
Com<IDXGIOutput> output;
@ -370,15 +353,8 @@ namespace dxvk {
ChangeDisplayMode(output.ptr(), pNewTargetParameters);
NotifyModeChange(m_monitor, FALSE);
}
// Resize and reposition the window to
DXGI_OUTPUT_DESC desc;
output->GetDesc(&desc);
RECT newRect = desc.DesktopCoordinates;
::MoveWindow(m_window, newRect.left, newRect.top,
newRect.right - newRect.left, newRect.bottom - newRect.top, TRUE);
wsi::updateFullscreenWindow(m_monitor, m_window, false);
}
return S_OK;
@ -555,7 +531,7 @@ namespace dxvk {
HRESULT DxgiSwapChain::EnterFullscreenMode(IDXGIOutput* pTarget) {
Com<IDXGIOutput> output = pTarget;
if (!IsWindow(m_window))
if (!wsi::isWindow(m_window))
return DXGI_ERROR_NOT_CURRENTLY_AVAILABLE;
if (output == nullptr) {
@ -564,11 +540,10 @@ namespace dxvk {
return E_FAIL;
}
}
const bool modeSwitch = m_desc.Flags & DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
// Find a display mode that matches what we need
::GetWindowRect(m_window, &m_windowState.rect);
if (m_desc.Flags & DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH) {
if (modeSwitch) {
DXGI_MODE_DESC displayMode;
displayMode.Width = m_desc.Width;
displayMode.Height = m_desc.Height;
@ -588,28 +563,14 @@ namespace dxvk {
// Update swap chain description
m_descFs.Windowed = FALSE;
// Change the window flags to remove the decoration etc.
LONG style = ::GetWindowLongW(m_window, GWL_STYLE);
LONG exstyle = ::GetWindowLongW(m_window, GWL_EXSTYLE);
m_windowState.style = style;
m_windowState.exstyle = exstyle;
style &= ~WS_OVERLAPPEDWINDOW;
exstyle &= ~WS_EX_OVERLAPPEDWINDOW;
::SetWindowLongW(m_window, GWL_STYLE, style);
::SetWindowLongW(m_window, 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_window, HWND_TOPMOST,
rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOACTIVATE);
if (!wsi::enterFullscreenMode(desc.Monitor, m_window, &m_windowState, modeSwitch)) {
Logger::err("DXGI: EnterFullscreenMode: Failed to enter fullscreen mode");
return DXGI_ERROR_NOT_CURRENTLY_AVAILABLE;
}
m_monitor = desc.Monitor;
m_target = std::move(output);
@ -652,27 +613,14 @@ namespace dxvk {
m_monitor = nullptr;
m_target = nullptr;
if (!IsWindow(m_window))
if (!wsi::isWindow(m_window))
return S_OK;
// Only restore the window style if the application hasn't
// changed them. This is in line with what native DXGI does.
LONG curStyle = ::GetWindowLongW(m_window, GWL_STYLE) & ~WS_VISIBLE;
LONG curExstyle = ::GetWindowLongW(m_window, GWL_EXSTYLE) & ~WS_EX_TOPMOST;
if (curStyle == (m_windowState.style & ~(WS_VISIBLE | WS_OVERLAPPEDWINDOW))
&& curExstyle == (m_windowState.exstyle & ~(WS_EX_TOPMOST | WS_EX_OVERLAPPEDWINDOW))) {
::SetWindowLongW(m_window, GWL_STYLE, m_windowState.style);
::SetWindowLongW(m_window, GWL_EXSTYLE, m_windowState.exstyle);
if (!wsi::leaveFullscreenMode(m_window, &m_windowState)) {
Logger::err("DXGI: LeaveFullscreenMode: Failed to exit fullscreen mode");
return DXGI_ERROR_NOT_CURRENTLY_AVAILABLE;
}
// Restore window position and apply the style
const RECT rect = m_windowState.rect;
::SetWindowPos(m_window, (m_windowState.exstyle & WS_EX_TOPMOST) ? HWND_TOPMOST : HWND_NOTOPMOST,
rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
SWP_FRAMECHANGED | SWP_NOACTIVATE);
NotifyModeChange(monitor, TRUE);
return S_OK;
}
@ -705,23 +653,17 @@ namespace dxvk {
"@", preferredMode.RefreshRate.Numerator / preferredMode.RefreshRate.Denominator));
return hr;
}
DEVMODEW devMode = { };
devMode.dmSize = sizeof(devMode);
devMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
devMode.dmPelsWidth = selectedMode.Width;
devMode.dmPelsHeight = selectedMode.Height;
devMode.dmBitsPerPel = GetMonitorFormatBpp(selectedMode.Format);
if (selectedMode.RefreshRate.Numerator != 0) {
devMode.dmFields |= DM_DISPLAYFREQUENCY;
devMode.dmDisplayFrequency = selectedMode.RefreshRate.Numerator
/ selectedMode.RefreshRate.Denominator;
}
return SetMonitorDisplayMode(outputDesc.Monitor, &devMode)
? S_OK
: DXGI_ERROR_NOT_CURRENTLY_AVAILABLE;
DXGI_MODE_DESC1 selectedMode1;
selectedMode1.Width = selectedMode.Width;
selectedMode1.Height = selectedMode.Height;
selectedMode1.RefreshRate = selectedMode.RefreshRate;
selectedMode1.Format = selectedMode.Format;
selectedMode1.ScanlineOrdering = selectedMode.ScanlineOrdering;
selectedMode1.Scaling = selectedMode.Scaling;
selectedMode1.Stereo = false;
return wsi::setWindowMode(outputDesc.Monitor, m_window, ConvertDisplayMode(selectedMode1));
}
@ -729,7 +671,7 @@ namespace dxvk {
if (!hMonitor)
return DXGI_ERROR_INVALID_CALL;
return RestoreMonitorDisplayMode()
return wsi::restoreDisplayMode()
? S_OK
: DXGI_ERROR_NOT_CURRENTLY_AVAILABLE;
}
@ -787,15 +729,13 @@ namespace dxvk {
void DxgiSwapChain::NotifyModeChange(
HMONITOR hMonitor,
BOOL Windowed) {
DEVMODEW devMode = { };
devMode.dmSize = sizeof(devMode);
devMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
wsi::WsiMode mode = { };
if (GetMonitorDisplayMode(hMonitor, ENUM_CURRENT_SETTINGS, &devMode)) {
if (wsi::getCurrentDisplayMode(hMonitor, &mode)) {
DXGI_MODE_DESC displayMode = { };
displayMode.Width = devMode.dmPelsWidth;
displayMode.Height = devMode.dmPelsHeight;
displayMode.RefreshRate = { devMode.dmDisplayFrequency, 1 };
displayMode.Width = mode.width;
displayMode.Height = mode.height;
displayMode.RefreshRate = { mode.refreshRate.numerator, mode.refreshRate.denominator };
displayMode.Format = m_desc.Format;
displayMode.ScanlineOrdering = m_descFs.ScanlineOrdering;
displayMode.Scaling = m_descFs.Scaling;

View File

@ -13,6 +13,9 @@
#include "../util/util_time.h"
#include "../wsi/wsi_window.h"
#include "../wsi/wsi_monitor.h"
namespace dxvk {
class DxgiDevice;
@ -169,12 +172,6 @@ namespace dxvk {
private:
struct WindowState {
LONG style = 0;
LONG exstyle = 0;
RECT rect = { 0, 0, 0, 0 };
};
dxvk::recursive_mutex m_lockWindow;
dxvk::mutex m_lockBuffer;
@ -191,7 +188,7 @@ namespace dxvk {
Com<IDXGIVkSwapChain> m_presenter;
HMONITOR m_monitor;
WindowState m_windowState;
wsi::DxvkWindowState m_windowState;
HRESULT EnterFullscreenMode(
IDXGIOutput *pTarget);