From 87db473122af1b0bdc612c240ec74116ed71eb0f Mon Sep 17 00:00:00 2001 From: Geoffrey McRae Date: Sat, 18 Jul 2026 04:36:42 +1000 Subject: [PATCH] [idd] apply resolution after the final replug Preserve the requested display mode across intermediate swap chains when rapid resolution changes cause replugs to be coalesced. Apply and clear the mode only once the final replacement swap chain is ready. --- idd/LGIdd/CIndirectDeviceContext.cpp | 27 ++++++++++++++------------- idd/LGIdd/CIndirectDeviceContext.h | 1 - idd/LGIdd/Device.cpp | 1 - 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/idd/LGIdd/CIndirectDeviceContext.cpp b/idd/LGIdd/CIndirectDeviceContext.cpp index 80aa7bb3..8865fa39 100644 --- a/idd/LGIdd/CIndirectDeviceContext.cpp +++ b/idd/LGIdd/CIndirectDeviceContext.cpp @@ -412,18 +412,6 @@ void CIndirectDeviceContext::OnMonitorDestroyed(IDDCX_MONITOR monitor) ReleaseSRWLockExclusive(&m_stateLock); } -void CIndirectDeviceContext::OnAssignSwapChain() -{ - AcquireSRWLockExclusive(&m_stateLock); - bool doSetMode = m_doSetMode; - CSettings::DisplayMode mode = m_setMode; - m_doSetMode = false; - ReleaseSRWLockExclusive(&m_stateLock); - - if (doSetMode) - g_pipe.SetDisplayMode(mode.width, mode.height, mode.refresh); -} - void CIndirectDeviceContext::OnSwapChainAssigned() { AcquireSRWLockExclusive(&m_stateLock); @@ -452,7 +440,9 @@ void CIndirectDeviceContext::OnSwapChainReleased() void CIndirectDeviceContext::OnSwapChainReady() { - bool replug = false; + bool replug = false; + bool doSetMode = false; + CSettings::DisplayMode mode = {}; AcquireSRWLockExclusive(&m_stateLock); m_swapChainReady = true; @@ -471,6 +461,15 @@ void CIndirectDeviceContext::OnSwapChainReady() m_replugPending = false; replug = true; } + + // Do not consume the requested mode on an intermediate replacement swap + // chain. The last coalesced replug must be the one that applies it. + if (!replug && m_doSetMode) + { + mode = m_setMode; + m_doSetMode = false; + doSetMode = true; + } ReleaseSRWLockExclusive(&m_stateLock); // Do not expose the context to pipe reload requests until the initial swap @@ -479,6 +478,8 @@ void CIndirectDeviceContext::OnSwapChainReady() if (replug) InterlockedExchange(&m_replugQueued, 1); + else if (doSetMode) + g_pipe.SetDisplayMode(mode.width, mode.height, mode.refresh); } static inline void FillSignalInfo(DISPLAYCONFIG_VIDEO_SIGNAL_INFO & mode, DWORD width, DWORD height, DWORD vsync, bool monitorMode) diff --git a/idd/LGIdd/CIndirectDeviceContext.h b/idd/LGIdd/CIndirectDeviceContext.h index d8b0918b..61767a67 100644 --- a/idd/LGIdd/CIndirectDeviceContext.h +++ b/idd/LGIdd/CIndirectDeviceContext.h @@ -187,7 +187,6 @@ public: void ReplugMonitor(); void OnMonitorDestroyed(IDDCX_MONITOR monitor); - void OnAssignSwapChain(); void OnSwapChainAssigned(); void OnSwapChainReleased(); void OnSwapChainReady(); diff --git a/idd/LGIdd/Device.cpp b/idd/LGIdd/Device.cpp index e996a009..10763c07 100644 --- a/idd/LGIdd/Device.cpp +++ b/idd/LGIdd/Device.cpp @@ -192,7 +192,6 @@ NTSTATUS LGIddMonitorAssignSwapChain(IDDCX_MONITOR monitor, const IDARG_IN_SETSW auto * wrapper = WdfObjectGet_CIndirectMonitorContextWrapper(monitor); wrapper->context->AssignSwapChain( inArgs->hSwapChain, inArgs->RenderAdapterLuid, inArgs->hNextSurfaceAvailable); - wrapper->context->GetDeviceContext()->OnAssignSwapChain(); return STATUS_SUCCESS; }