mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-08-22 15:11:31 +00:00
[idd] helper: preserve mode apply transaction
This commit is contained in:
@@ -196,58 +196,12 @@ namespace
|
|||||||
return lgIndex != SIZE_MAX;
|
return lgIndex != SIZE_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GetLGDisplayState(DisplayState& state)
|
|
||||||
{
|
|
||||||
DISPLAY_DEVICE device = {};
|
|
||||||
device.cb = sizeof(device);
|
|
||||||
for (DWORD i = 0; EnumDisplayDevices(NULL, i, &device, 0); ++i)
|
|
||||||
{
|
|
||||||
if ((device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) &&
|
|
||||||
!(device.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) &&
|
|
||||||
IsLGDisplay(device))
|
|
||||||
{
|
|
||||||
state = {};
|
|
||||||
state.device = device;
|
|
||||||
state.mode.dmSize = sizeof(state.mode);
|
|
||||||
state.isLG = true;
|
|
||||||
return EnumDisplaySettingsEx(device.DeviceName, ENUM_CURRENT_SETTINGS,
|
|
||||||
&state.mode, 0) != FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
device = {};
|
|
||||||
device.cb = sizeof(device);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t DisplayModeRefresh(const LGPipeMsg& msg)
|
uint32_t DisplayModeRefresh(const LGPipeMsg& msg)
|
||||||
{
|
{
|
||||||
return (msg.displayMode.refresh100uHz + LG_REFRESH_RATE_SCALE / 2) /
|
return (msg.displayMode.refresh100uHz + LG_REFRESH_RATE_SCALE / 2) /
|
||||||
LG_REFRESH_RATE_SCALE;
|
LG_REFRESH_RATE_SCALE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FindDisplayMode(const DisplayState& display, const LGPipeMsg& msg,
|
|
||||||
DEVMODE& mode)
|
|
||||||
{
|
|
||||||
const uint32_t refresh = DisplayModeRefresh(msg);
|
|
||||||
for (DWORD i = 0; ; ++i)
|
|
||||||
{
|
|
||||||
DEVMODE candidate = {};
|
|
||||||
candidate.dmSize = sizeof(candidate);
|
|
||||||
if (!EnumDisplaySettingsEx(display.device.DeviceName, i, &candidate, 0))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (candidate.dmPelsWidth == msg.displayMode.width &&
|
|
||||||
candidate.dmPelsHeight == msg.displayMode.height &&
|
|
||||||
candidate.dmDisplayFrequency == refresh)
|
|
||||||
{
|
|
||||||
mode = candidate;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HasActiveDisplay(bool lg)
|
bool HasActiveDisplay(bool lg)
|
||||||
{
|
{
|
||||||
DISPLAY_DEVICE device = {};
|
DISPLAY_DEVICE device = {};
|
||||||
@@ -613,38 +567,28 @@ bool CPipeClient::ApplyDisplayMode(const LGPipeMsg& msg, LONG& result)
|
|||||||
{
|
{
|
||||||
CSRWExclusiveLock lock(m_displayLock);
|
CSRWExclusiveLock lock(m_displayLock);
|
||||||
|
|
||||||
DisplayState display = {};
|
std::vector<DisplayState> displays;
|
||||||
if (!GetLGDisplayState(display))
|
size_t lgIndex;
|
||||||
|
if (!GetDisplayStates(displays, lgIndex))
|
||||||
{
|
{
|
||||||
result = DISP_CHANGE_FAILED;
|
result = DISP_CHANGE_FAILED;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEVMODE mode = {};
|
// Preserve the original mode-application transaction: Windows accepts the
|
||||||
if (!FindDisplayMode(display, msg, mode))
|
// requested values before EnumDisplaySettingsEx necessarily lists the new
|
||||||
{
|
// mode after a monitor replug.
|
||||||
result = DISP_CHANGE_BADMODE;
|
DEVMODE mode = displays[lgIndex].mode;
|
||||||
return false;
|
mode.dmPelsWidth = msg.displayMode.width;
|
||||||
}
|
mode.dmPelsHeight = msg.displayMode.height;
|
||||||
|
mode.dmDisplayFrequency = DisplayModeRefresh(msg);
|
||||||
mode.dmFields =
|
mode.dmFields =
|
||||||
DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
|
DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
|
||||||
result = ChangeDisplaySettingsEx(display.device.DeviceName,
|
result = ChangeDisplaySettingsEx(displays[lgIndex].device.DeviceName,
|
||||||
&mode, NULL, CDS_UPDATEREGISTRY, NULL);
|
&mode, NULL, CDS_UPDATEREGISTRY, NULL);
|
||||||
return result == DISP_CHANGE_SUCCESSFUL;
|
return result == DISP_CHANGE_SUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CPipeClient::VerifyDisplayMode(const LGPipeMsg& msg)
|
|
||||||
{
|
|
||||||
CSRWExclusiveLock lock(m_displayLock);
|
|
||||||
|
|
||||||
DisplayState display = {};
|
|
||||||
return GetLGDisplayState(display) &&
|
|
||||||
display.mode.dmPelsWidth == msg.displayMode.width &&
|
|
||||||
display.mode.dmPelsHeight == msg.displayMode.height &&
|
|
||||||
display.mode.dmDisplayFrequency == DisplayModeRefresh(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CPipeClient::DisplayModeThread()
|
void CPipeClient::DisplayModeThread()
|
||||||
{
|
{
|
||||||
const HANDLE handles[] = { m_displayModeStop, m_displayModeWake };
|
const HANDLE handles[] = { m_displayModeStop, m_displayModeWake };
|
||||||
@@ -683,7 +627,10 @@ void CPipeClient::DisplayModeThread()
|
|||||||
LONG result = DISP_CHANGE_FAILED;
|
LONG result = DISP_CHANGE_FAILED;
|
||||||
if (ApplyDisplayMode(msg, result))
|
if (ApplyDisplayMode(msg, result))
|
||||||
{
|
{
|
||||||
if (EnsureOnlyDisplay() && VerifyDisplayMode(msg))
|
// A requested resolution replug is also a topology transition. Keep
|
||||||
|
// the original apply-then-enforce ordering so LG remains the only
|
||||||
|
// active (and therefore primary) display on this path.
|
||||||
|
if (EnsureOnlyDisplay())
|
||||||
{
|
{
|
||||||
CSRWExclusiveLock lock(m_displayModeLock);
|
CSRWExclusiveLock lock(m_displayModeLock);
|
||||||
if (serial == m_displayModeSerial)
|
if (serial == m_displayModeSerial)
|
||||||
@@ -1225,9 +1172,9 @@ void CPipeClient::HandleSetCursorPos(const LGPipeMsg& msg)
|
|||||||
|
|
||||||
void CPipeClient::HandleSetDisplayMode(const LGPipeMsg& msg)
|
void CPipeClient::HandleSetDisplayMode(const LGPipeMsg& msg)
|
||||||
{
|
{
|
||||||
// The IDD reaches swap-chain readiness before Win32 has necessarily
|
// The IDD reaches swap-chain readiness while the replugged monitor can
|
||||||
// enumerated the replugged monitor's complete mode list. Latch the latest
|
// still be settling. Latch the latest request and retry the original
|
||||||
// request and let the worker apply it once that list is ready.
|
// apply-then-enforce transaction outside the pipe callback.
|
||||||
{
|
{
|
||||||
CSRWExclusiveLock lock(m_displayModeLock);
|
CSRWExclusiveLock lock(m_displayModeLock);
|
||||||
m_displayMode = msg;
|
m_displayMode = msg;
|
||||||
|
|||||||
@@ -64,7 +64,6 @@ private:
|
|||||||
bool StartDisplayModeThread();
|
bool StartDisplayModeThread();
|
||||||
void StopDisplayModeThread();
|
void StopDisplayModeThread();
|
||||||
bool ApplyDisplayMode(const LGPipeMsg& msg, LONG& result);
|
bool ApplyDisplayMode(const LGPipeMsg& msg, LONG& result);
|
||||||
bool VerifyDisplayMode(const LGPipeMsg& msg);
|
|
||||||
|
|
||||||
bool EnsureOnlyDisplayLocked();
|
bool EnsureOnlyDisplayLocked();
|
||||||
uint32_t RestoreSavedTopologyLocked() const;
|
uint32_t RestoreSavedTopologyLocked() const;
|
||||||
|
|||||||
Reference in New Issue
Block a user