From 21744198e0427824a1e120fdfed57b16d3b2bf1f Mon Sep 17 00:00:00 2001 From: Joshua Ashton Date: Tue, 9 Aug 2022 13:25:12 +0100 Subject: [PATCH] [dxgi] Make swapchain use new wsi interface --- src/dxgi/dxgi_swapchain.cpp | 142 +++++++++++------------------------- src/dxgi/dxgi_swapchain.h | 11 +-- 2 files changed, 45 insertions(+), 108 deletions(-) diff --git a/src/dxgi/dxgi_swapchain.cpp b/src/dxgi/dxgi_swapchain.cpp index 09ebd6972..399a99616 100644 --- a/src/dxgi/dxgi_swapchain.cpp +++ b/src/dxgi/dxgi_swapchain.cpp @@ -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 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 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; diff --git a/src/dxgi/dxgi_swapchain.h b/src/dxgi/dxgi_swapchain.h index 62adf0e8a..31e49b941 100644 --- a/src/dxgi/dxgi_swapchain.h +++ b/src/dxgi/dxgi_swapchain.h @@ -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 m_presenter; HMONITOR m_monitor; - WindowState m_windowState; + wsi::DxvkWindowState m_windowState; HRESULT EnterFullscreenMode( IDXGIOutput *pTarget);