mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-19 05:52:11 +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) {
|
HRESULT STDMETHODCALLTYPE DxgiSwapChain::GetContainingOutput(IDXGIOutput** ppOutput) {
|
||||||
InitReturnPtr(ppOutput);
|
InitReturnPtr(ppOutput);
|
||||||
|
|
||||||
if (!IsWindow(m_window))
|
if (!wsi::isWindow(m_window))
|
||||||
return DXGI_ERROR_INVALID_CALL;
|
return DXGI_ERROR_INVALID_CALL;
|
||||||
|
|
||||||
if (m_target != nullptr) {
|
if (m_target != nullptr) {
|
||||||
@ -99,15 +99,7 @@ namespace dxvk {
|
|||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
RECT windowRect = { 0, 0, 0, 0 };
|
return GetOutputFromMonitor(wsi::getWindowMonitor(m_window), ppOutput);
|
||||||
::GetWindowRect(m_window, &windowRect);
|
|
||||||
|
|
||||||
HMONITOR monitor = ::MonitorFromPoint(
|
|
||||||
{ (windowRect.left + windowRect.right) / 2,
|
|
||||||
(windowRect.top + windowRect.bottom) / 2 },
|
|
||||||
MONITOR_DEFAULTTOPRIMARY);
|
|
||||||
|
|
||||||
return GetOutputFromMonitor(monitor, ppOutput);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -256,7 +248,7 @@ namespace dxvk {
|
|||||||
UINT PresentFlags,
|
UINT PresentFlags,
|
||||||
const DXGI_PRESENT_PARAMETERS* pPresentParameters) {
|
const DXGI_PRESENT_PARAMETERS* pPresentParameters) {
|
||||||
|
|
||||||
if (!IsWindow(m_window))
|
if (!wsi::isWindow(m_window))
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
||||||
if (SyncInterval > 4)
|
if (SyncInterval > 4)
|
||||||
@ -283,7 +275,7 @@ namespace dxvk {
|
|||||||
UINT Height,
|
UINT Height,
|
||||||
DXGI_FORMAT NewFormat,
|
DXGI_FORMAT NewFormat,
|
||||||
UINT SwapChainFlags) {
|
UINT SwapChainFlags) {
|
||||||
if (!IsWindow(m_window))
|
if (!wsi::isWindow(m_window))
|
||||||
return DXGI_ERROR_INVALID_CALL;
|
return DXGI_ERROR_INVALID_CALL;
|
||||||
|
|
||||||
constexpr UINT PreserveFlags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
|
constexpr UINT PreserveFlags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
|
||||||
@ -295,7 +287,7 @@ namespace dxvk {
|
|||||||
m_desc.Width = Width;
|
m_desc.Width = Width;
|
||||||
m_desc.Height = Height;
|
m_desc.Height = Height;
|
||||||
|
|
||||||
GetWindowClientSize(m_window,
|
wsi::getWindowSize(m_window,
|
||||||
m_desc.Width ? nullptr : &m_desc.Width,
|
m_desc.Width ? nullptr : &m_desc.Width,
|
||||||
m_desc.Height ? nullptr : &m_desc.Height);
|
m_desc.Height ? nullptr : &m_desc.Height);
|
||||||
|
|
||||||
@ -333,7 +325,7 @@ namespace dxvk {
|
|||||||
if (pNewTargetParameters == nullptr)
|
if (pNewTargetParameters == nullptr)
|
||||||
return DXGI_ERROR_INVALID_CALL;
|
return DXGI_ERROR_INVALID_CALL;
|
||||||
|
|
||||||
if (!IsWindow(m_window))
|
if (!wsi::isWindow(m_window))
|
||||||
return DXGI_ERROR_INVALID_CALL;
|
return DXGI_ERROR_INVALID_CALL;
|
||||||
|
|
||||||
// Update the swap chain description
|
// Update the swap chain description
|
||||||
@ -344,19 +336,10 @@ namespace dxvk {
|
|||||||
m_descFs.Scaling = pNewTargetParameters->Scaling;
|
m_descFs.Scaling = pNewTargetParameters->Scaling;
|
||||||
|
|
||||||
if (m_descFs.Windowed) {
|
if (m_descFs.Windowed) {
|
||||||
// Adjust window position and size
|
wsi::resizeWindow(
|
||||||
RECT newRect = { 0, 0, 0, 0 };
|
m_window, &m_windowState,
|
||||||
RECT oldRect = { 0, 0, 0, 0 };
|
pNewTargetParameters->Width,
|
||||||
|
pNewTargetParameters->Height);
|
||||||
::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);
|
|
||||||
} else {
|
} else {
|
||||||
Com<IDXGIOutput> output;
|
Com<IDXGIOutput> output;
|
||||||
|
|
||||||
@ -370,15 +353,8 @@ namespace dxvk {
|
|||||||
ChangeDisplayMode(output.ptr(), pNewTargetParameters);
|
ChangeDisplayMode(output.ptr(), pNewTargetParameters);
|
||||||
NotifyModeChange(m_monitor, FALSE);
|
NotifyModeChange(m_monitor, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resize and reposition the window to
|
wsi::updateFullscreenWindow(m_monitor, m_window, false);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
@ -555,7 +531,7 @@ namespace dxvk {
|
|||||||
HRESULT DxgiSwapChain::EnterFullscreenMode(IDXGIOutput* pTarget) {
|
HRESULT DxgiSwapChain::EnterFullscreenMode(IDXGIOutput* pTarget) {
|
||||||
Com<IDXGIOutput> output = pTarget;
|
Com<IDXGIOutput> output = pTarget;
|
||||||
|
|
||||||
if (!IsWindow(m_window))
|
if (!wsi::isWindow(m_window))
|
||||||
return DXGI_ERROR_NOT_CURRENTLY_AVAILABLE;
|
return DXGI_ERROR_NOT_CURRENTLY_AVAILABLE;
|
||||||
|
|
||||||
if (output == nullptr) {
|
if (output == nullptr) {
|
||||||
@ -564,11 +540,10 @@ namespace dxvk {
|
|||||||
return E_FAIL;
|
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
|
if (modeSwitch) {
|
||||||
::GetWindowRect(m_window, &m_windowState.rect);
|
|
||||||
|
|
||||||
if (m_desc.Flags & DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH) {
|
|
||||||
DXGI_MODE_DESC displayMode;
|
DXGI_MODE_DESC displayMode;
|
||||||
displayMode.Width = m_desc.Width;
|
displayMode.Width = m_desc.Width;
|
||||||
displayMode.Height = m_desc.Height;
|
displayMode.Height = m_desc.Height;
|
||||||
@ -588,28 +563,14 @@ namespace dxvk {
|
|||||||
// Update swap chain description
|
// Update swap chain description
|
||||||
m_descFs.Windowed = FALSE;
|
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
|
// Move the window so that it covers the entire output
|
||||||
DXGI_OUTPUT_DESC desc;
|
DXGI_OUTPUT_DESC desc;
|
||||||
output->GetDesc(&desc);
|
output->GetDesc(&desc);
|
||||||
|
|
||||||
const RECT rect = desc.DesktopCoordinates;
|
if (!wsi::enterFullscreenMode(desc.Monitor, m_window, &m_windowState, modeSwitch)) {
|
||||||
|
Logger::err("DXGI: EnterFullscreenMode: Failed to enter fullscreen mode");
|
||||||
::SetWindowPos(m_window, HWND_TOPMOST,
|
return DXGI_ERROR_NOT_CURRENTLY_AVAILABLE;
|
||||||
rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
|
}
|
||||||
SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOACTIVATE);
|
|
||||||
|
|
||||||
m_monitor = desc.Monitor;
|
m_monitor = desc.Monitor;
|
||||||
m_target = std::move(output);
|
m_target = std::move(output);
|
||||||
@ -652,27 +613,14 @@ namespace dxvk {
|
|||||||
m_monitor = nullptr;
|
m_monitor = nullptr;
|
||||||
m_target = nullptr;
|
m_target = nullptr;
|
||||||
|
|
||||||
if (!IsWindow(m_window))
|
if (!wsi::isWindow(m_window))
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
||||||
// Only restore the window style if the application hasn't
|
if (!wsi::leaveFullscreenMode(m_window, &m_windowState)) {
|
||||||
// changed them. This is in line with what native DXGI does.
|
Logger::err("DXGI: LeaveFullscreenMode: Failed to exit fullscreen mode");
|
||||||
LONG curStyle = ::GetWindowLongW(m_window, GWL_STYLE) & ~WS_VISIBLE;
|
return DXGI_ERROR_NOT_CURRENTLY_AVAILABLE;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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);
|
NotifyModeChange(monitor, TRUE);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
@ -705,23 +653,17 @@ namespace dxvk {
|
|||||||
"@", preferredMode.RefreshRate.Numerator / preferredMode.RefreshRate.Denominator));
|
"@", preferredMode.RefreshRate.Numerator / preferredMode.RefreshRate.Denominator));
|
||||||
return hr;
|
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)
|
DXGI_MODE_DESC1 selectedMode1;
|
||||||
? S_OK
|
selectedMode1.Width = selectedMode.Width;
|
||||||
: DXGI_ERROR_NOT_CURRENTLY_AVAILABLE;
|
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)
|
if (!hMonitor)
|
||||||
return DXGI_ERROR_INVALID_CALL;
|
return DXGI_ERROR_INVALID_CALL;
|
||||||
|
|
||||||
return RestoreMonitorDisplayMode()
|
return wsi::restoreDisplayMode()
|
||||||
? S_OK
|
? S_OK
|
||||||
: DXGI_ERROR_NOT_CURRENTLY_AVAILABLE;
|
: DXGI_ERROR_NOT_CURRENTLY_AVAILABLE;
|
||||||
}
|
}
|
||||||
@ -787,15 +729,13 @@ namespace dxvk {
|
|||||||
void DxgiSwapChain::NotifyModeChange(
|
void DxgiSwapChain::NotifyModeChange(
|
||||||
HMONITOR hMonitor,
|
HMONITOR hMonitor,
|
||||||
BOOL Windowed) {
|
BOOL Windowed) {
|
||||||
DEVMODEW devMode = { };
|
wsi::WsiMode mode = { };
|
||||||
devMode.dmSize = sizeof(devMode);
|
|
||||||
devMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
|
|
||||||
|
|
||||||
if (GetMonitorDisplayMode(hMonitor, ENUM_CURRENT_SETTINGS, &devMode)) {
|
if (wsi::getCurrentDisplayMode(hMonitor, &mode)) {
|
||||||
DXGI_MODE_DESC displayMode = { };
|
DXGI_MODE_DESC displayMode = { };
|
||||||
displayMode.Width = devMode.dmPelsWidth;
|
displayMode.Width = mode.width;
|
||||||
displayMode.Height = devMode.dmPelsHeight;
|
displayMode.Height = mode.height;
|
||||||
displayMode.RefreshRate = { devMode.dmDisplayFrequency, 1 };
|
displayMode.RefreshRate = { mode.refreshRate.numerator, mode.refreshRate.denominator };
|
||||||
displayMode.Format = m_desc.Format;
|
displayMode.Format = m_desc.Format;
|
||||||
displayMode.ScanlineOrdering = m_descFs.ScanlineOrdering;
|
displayMode.ScanlineOrdering = m_descFs.ScanlineOrdering;
|
||||||
displayMode.Scaling = m_descFs.Scaling;
|
displayMode.Scaling = m_descFs.Scaling;
|
||||||
|
@ -13,6 +13,9 @@
|
|||||||
|
|
||||||
#include "../util/util_time.h"
|
#include "../util/util_time.h"
|
||||||
|
|
||||||
|
#include "../wsi/wsi_window.h"
|
||||||
|
#include "../wsi/wsi_monitor.h"
|
||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
class DxgiDevice;
|
class DxgiDevice;
|
||||||
@ -169,12 +172,6 @@ namespace dxvk {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
struct WindowState {
|
|
||||||
LONG style = 0;
|
|
||||||
LONG exstyle = 0;
|
|
||||||
RECT rect = { 0, 0, 0, 0 };
|
|
||||||
};
|
|
||||||
|
|
||||||
dxvk::recursive_mutex m_lockWindow;
|
dxvk::recursive_mutex m_lockWindow;
|
||||||
dxvk::mutex m_lockBuffer;
|
dxvk::mutex m_lockBuffer;
|
||||||
|
|
||||||
@ -191,7 +188,7 @@ namespace dxvk {
|
|||||||
Com<IDXGIVkSwapChain> m_presenter;
|
Com<IDXGIVkSwapChain> m_presenter;
|
||||||
|
|
||||||
HMONITOR m_monitor;
|
HMONITOR m_monitor;
|
||||||
WindowState m_windowState;
|
wsi::DxvkWindowState m_windowState;
|
||||||
|
|
||||||
HRESULT EnterFullscreenMode(
|
HRESULT EnterFullscreenMode(
|
||||||
IDXGIOutput *pTarget);
|
IDXGIOutput *pTarget);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user