mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-18 20:52:10 +01:00
[dxgi] Make swapchain use new wsi interface
This commit is contained in:
parent
e13a9f9cf6
commit
21744198e0
@ -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;
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user