From cb70643fa4563052f90a45a30849d0736e23494b Mon Sep 17 00:00:00 2001 From: Quantum Date: Wed, 3 Jun 2026 01:50:15 -0400 Subject: [PATCH 1/4] [idd] helper: load default mode list with default refresh rate After 882d53179287a216dafa1a573a0b6dc32ef05768, the existing code in the helper reads past the end of the array for refresh rate, which is broken. This PR also refactors the default modes into a getDefaultModes method so that it can be used for a reset feature later. --- idd/LGIddHelper/CRegistrySettings.cpp | 32 ++++++++++++++++----------- idd/LGIddHelper/CRegistrySettings.h | 1 + 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/idd/LGIddHelper/CRegistrySettings.cpp b/idd/LGIddHelper/CRegistrySettings.cpp index 8e38ed4d..1cda0708 100644 --- a/idd/LGIddHelper/CRegistrySettings.cpp +++ b/idd/LGIddHelper/CRegistrySettings.cpp @@ -78,6 +78,24 @@ static std::optional parseDisplayMode(const std::wstring &str) return mode; } +std::vector CRegistrySettings::getDefaultModes() +{ + auto defaultRefresh = getDefaultRefresh(); + int refresh = defaultRefresh ? *defaultRefresh : DEFAULT_REFRESH; + + std::vector result; + for (int i = 0; i < ARRAYSIZE(DefaultDisplayModes); ++i) + { + DisplayMode mode; + mode.width = DefaultDisplayModes[i][0]; + mode.height = DefaultDisplayModes[i][1]; + mode.refresh = refresh; + mode.preferred = i == DefaultPreferredDisplayMode; + result.emplace_back(mode); + } + return result; +} + std::optional> CRegistrySettings::getModes() { LSTATUS status; @@ -89,19 +107,7 @@ std::optional> CRegistrySettings::getModes() case ERROR_SUCCESS: break; case ERROR_FILE_NOT_FOUND: - { - std::vector result; - for (int i = 0; i < ARRAYSIZE(DefaultDisplayModes); ++i) - { - DisplayMode mode; - mode.width = DefaultDisplayModes[i][0]; - mode.height = DefaultDisplayModes[i][1]; - mode.refresh = DefaultDisplayModes[i][2]; - mode.preferred = i == DefaultPreferredDisplayMode; - result.emplace_back(mode); - } - return result; - } + return getDefaultModes(); default: DEBUG_ERROR_HR(status, "RegGetValue(Modes) length computation"); return {}; diff --git a/idd/LGIddHelper/CRegistrySettings.h b/idd/LGIddHelper/CRegistrySettings.h index 83af6a50..49801985 100644 --- a/idd/LGIddHelper/CRegistrySettings.h +++ b/idd/LGIddHelper/CRegistrySettings.h @@ -44,6 +44,7 @@ public: LSTATUS open(); bool isOpen() { return !!hKey; } + std::vector getDefaultModes(); std::optional> getModes(); LSTATUS setModes(const std::vector &modes); From 803aea0d21a329659ea83f5f3767d5b36bfb42f9 Mon Sep 17 00:00:00 2001 From: Geoffrey McRae Date: Wed, 3 Jun 2026 17:48:32 +1000 Subject: [PATCH 2/4] [idd] ipc: implement reporting of GPU software status --- idd/LGCommon/PipeMsg.h | 9 ++++++++- idd/LGIdd/CD3D11Device.cpp | 7 +++++++ idd/LGIdd/CD3D11Device.h | 3 +++ idd/LGIdd/CIndirectMonitorContext.cpp | 2 ++ idd/LGIdd/CPipeServer.cpp | 12 ++++++++++++ idd/LGIdd/CPipeServer.h | 1 + idd/LGIddHelper/CPipeClient.cpp | 9 +++++++++ idd/LGIddHelper/CPipeClient.h | 1 + 8 files changed, 43 insertions(+), 1 deletion(-) diff --git a/idd/LGCommon/PipeMsg.h b/idd/LGCommon/PipeMsg.h index cf74d6fe..99595c40 100644 --- a/idd/LGCommon/PipeMsg.h +++ b/idd/LGCommon/PipeMsg.h @@ -30,7 +30,8 @@ struct LGPipeMsg enum { SETCURSORPOS, - SETDISPLAYMODE + SETDISPLAYMODE, + GPUSTATUS } type; union @@ -49,5 +50,11 @@ struct LGPipeMsg uint32_t refresh; } displayMode; + + struct + { + bool software; + } + gpuStatus; }; }; \ No newline at end of file diff --git a/idd/LGIdd/CD3D11Device.cpp b/idd/LGIdd/CD3D11Device.cpp index 33fb26aa..a179845f 100644 --- a/idd/LGIdd/CD3D11Device.cpp +++ b/idd/LGIdd/CD3D11Device.cpp @@ -30,6 +30,13 @@ HRESULT CD3D11Device::Init() hr = m_factory->EnumAdapterByLuid(m_adapterLuid, IID_PPV_ARGS(&m_adapter)); if (FAILED(hr)) return hr; + + DXGI_ADAPTER_DESC1 desc = {}; + hr = m_adapter->GetDesc1(&desc); + if (FAILED(hr)) + return hr; + + m_isSoftware = (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) != 0; // only 11.1 supports DX12 interoperabillity static const D3D_FEATURE_LEVEL featureLevels[] = diff --git a/idd/LGIdd/CD3D11Device.h b/idd/LGIdd/CD3D11Device.h index 7a275c6c..e8020f4f 100644 --- a/idd/LGIdd/CD3D11Device.h +++ b/idd/LGIdd/CD3D11Device.h @@ -36,6 +36,7 @@ private: ComPtr m_adapter; ComPtr m_device; ComPtr m_context; + bool m_isSoftware; public: CD3D11Device(LUID adapterLuid) : @@ -51,4 +52,6 @@ public: ComPtr GetDevice() { return m_device; } ComPtr GetContext() { return m_context; } + + bool IsSoftware() { return m_isSoftware; } }; \ No newline at end of file diff --git a/idd/LGIdd/CIndirectMonitorContext.cpp b/idd/LGIdd/CIndirectMonitorContext.cpp index 864e828c..785f7bec 100644 --- a/idd/LGIdd/CIndirectMonitorContext.cpp +++ b/idd/LGIdd/CIndirectMonitorContext.cpp @@ -21,6 +21,7 @@ #include "CIndirectMonitorContext.h" #include "CPlatformInfo.h" #include "CDebug.h" +#include "CPipeServer.h" CIndirectMonitorContext::CIndirectMonitorContext(_In_ IDDCX_MONITOR monitor, CIndirectDeviceContext * device) : m_monitor(monitor), @@ -70,6 +71,7 @@ reInit: } m_swapChain.reset(new CSwapChainProcessor(m_monitor, m_devContext, swapChain, m_dx11Device, m_dx12Device, newFrameEvent)); + g_pipe.SetGPUStatus(m_dx11Device->IsSoftware()); } void CIndirectMonitorContext::UnassignSwapChain() diff --git a/idd/LGIdd/CPipeServer.cpp b/idd/LGIdd/CPipeServer.cpp index e71ad500..99e1e921 100644 --- a/idd/LGIdd/CPipeServer.cpp +++ b/idd/LGIdd/CPipeServer.cpp @@ -174,4 +174,16 @@ void CPipeServer::SetDisplayMode(uint32_t width, uint32_t height, uint32_t refre msg.displayMode.height = height; msg.displayMode.refresh = refresh; WriteMsg(msg); +} + +void CPipeServer::SetGPUStatus(bool software) +{ + if (!m_connected) + return; + + LGPipeMsg msg; + msg.size = sizeof(msg); + msg.type = LGPipeMsg::GPUSTATUS; + msg.gpuStatus.software = software; + WriteMsg(msg); } \ No newline at end of file diff --git a/idd/LGIdd/CPipeServer.h b/idd/LGIdd/CPipeServer.h index f2fe5a63..5a8d320a 100644 --- a/idd/LGIdd/CPipeServer.h +++ b/idd/LGIdd/CPipeServer.h @@ -55,6 +55,7 @@ class CPipeServer void SetCursorPos(uint32_t x, uint32_t y); void SetDisplayMode(uint32_t width, uint32_t height, uint32_t refresh); + void SetGPUStatus(bool software); }; extern CPipeServer g_pipe; \ No newline at end of file diff --git a/idd/LGIddHelper/CPipeClient.cpp b/idd/LGIddHelper/CPipeClient.cpp index 2108f029..4a2aa8c6 100644 --- a/idd/LGIddHelper/CPipeClient.cpp +++ b/idd/LGIddHelper/CPipeClient.cpp @@ -264,6 +264,10 @@ void CPipeClient::Thread() HandleSetDisplayMode(msg); break; + case LGPipeMsg::GPUSTATUS: + HandleGPUStatus(msg); + break; + default: DEBUG_ERROR("Unknown message type %d", msg.type); break; @@ -300,3 +304,8 @@ void CPipeClient::HandleSetDisplayMode(const LGPipeMsg& msg) if (result != DISP_CHANGE_SUCCESSFUL) DEBUG_ERROR("ChangeDisplaySettingsEx Failed (0x%08x)", result); } + +void CPipeClient::HandleGPUStatus(const LGPipeMsg& msg) +{ + // TODO: implement me +} diff --git a/idd/LGIddHelper/CPipeClient.h b/idd/LGIddHelper/CPipeClient.h index 33f72872..c6e53552 100644 --- a/idd/LGIddHelper/CPipeClient.h +++ b/idd/LGIddHelper/CPipeClient.h @@ -49,6 +49,7 @@ private: void HandleSetCursorPos(const LGPipeMsg& msg); void HandleSetDisplayMode(const LGPipeMsg& msg); + void HandleGPUStatus(const LGPipeMsg& msg); public: ~CPipeClient() { DeInit(); } From 415a946e56dbef48041e1951575bab32adfe4123 Mon Sep 17 00:00:00 2001 From: Quantum Date: Wed, 3 Jun 2026 03:36:15 -0400 Subject: [PATCH 3/4] [idd] helper: avoid potential empty option deference --- idd/LGIddHelper/CConfigWindow.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/idd/LGIddHelper/CConfigWindow.cpp b/idd/LGIddHelper/CConfigWindow.cpp index 398f7e8c..fd8e2fa7 100644 --- a/idd/LGIddHelper/CConfigWindow.cpp +++ b/idd/LGIddHelper/CConfigWindow.cpp @@ -231,11 +231,11 @@ void CConfigWindow::onModeListSelectChange() LRESULT CConfigWindow::onCommand(WORD id, WORD code, HWND hwnd) { - if (hwnd == *m_modeBox && code == LBN_SELCHANGE && m_modes) + if (m_modeBox && hwnd == *m_modeBox && code == LBN_SELCHANGE && m_modes) { onModeListSelectChange(); } - else if (hwnd == *m_modeUpdate && code == BN_CLICKED && m_modes) + else if (m_modeUpdate && hwnd == *m_modeUpdate && code == BN_CLICKED && m_modes) { int sel = m_modeBox->getSel(); if (sel == LB_ERR) @@ -264,7 +264,7 @@ LRESULT CConfigWindow::onCommand(WORD id, WORD code, HWND hwnd) if (result != ERROR_SUCCESS) DEBUG_ERROR_HR((HRESULT) result, "Failed to save modes"); } - else if (hwnd == *m_modeDelete && code == BN_CLICKED && m_modes) + else if (m_modeDelete && hwnd == *m_modeDelete && code == BN_CLICKED && m_modes) { int sel = m_modeBox->getSel(); if (sel == LB_ERR) @@ -281,7 +281,7 @@ LRESULT CConfigWindow::onCommand(WORD id, WORD code, HWND hwnd) updateModeList(); onModeListSelectChange(); } - else if (hwnd == *m_defRefresh && code == EN_CHANGE && m_defaultRefresh) + else if (m_defRefresh && hwnd == *m_defRefresh && code == EN_CHANGE && m_defaultRefresh) { int value; try From 708ed2cbae56808af98a6cc8529e2bbe73741f69 Mon Sep 17 00:00:00 2001 From: Quantum Date: Wed, 3 Jun 2026 01:52:34 -0400 Subject: [PATCH 4/4] [idd] helper: add mode list reset button --- idd/LGIddHelper/CConfigWindow.cpp | 12 +++++++++++- idd/LGIddHelper/CConfigWindow.h | 1 + 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/idd/LGIddHelper/CConfigWindow.cpp b/idd/LGIddHelper/CConfigWindow.cpp index fd8e2fa7..e111f8eb 100644 --- a/idd/LGIddHelper/CConfigWindow.cpp +++ b/idd/LGIddHelper/CConfigWindow.cpp @@ -88,7 +88,7 @@ void CConfigWindow::updateFont() for (HWND child : std::initializer_list({ *m_version, *m_modeGroup, *m_modeBox, *m_widthLabel, *m_heightLabel, *m_refreshLabel, - *m_modeWidth, *m_modeHeight, *m_modeRefresh, *m_modeUpdate, *m_modeDelete, + *m_modeWidth, *m_modeHeight, *m_modeRefresh, *m_modeUpdate, *m_modeDelete, *m_modeReset, *m_autosizeGroup, *m_defRefreshLabel, *m_defRefresh, *m_defRefreshHz, })) SendMessage(child, WM_SETFONT, (WPARAM)m_font.Get(), 1); @@ -154,6 +154,7 @@ LRESULT CConfigWindow::onCreate() m_modeUpdate.reset(new CButton(L"Save", WS_CHILD | WS_VISIBLE | WS_TABSTOP, m_hwnd)); m_modeDelete.reset(new CButton(L"Delete", WS_CHILD | WS_VISIBLE | WS_TABSTOP, m_hwnd)); + m_modeReset.reset(new CButton(L"Reset", WS_CHILD | WS_VISIBLE | WS_TABSTOP, m_hwnd)); EnableWindow(*m_modeUpdate, FALSE); EnableWindow(*m_modeDelete, FALSE); @@ -198,6 +199,7 @@ LRESULT CConfigWindow::onResize(DWORD width, DWORD height) pos.pinBottomLeft(*m_modeRefresh, 75, 48, 50, 20); pos.pinBottomLeft(*m_modeUpdate, 24, 20, 50, 24); pos.pinBottomLeft(*m_modeDelete, 75, 20, 50, 24); + pos.pinBottomLeft(*m_modeReset, 126, 20, 50, 24); pos.pinTopLeft(*m_autosizeGroup, 224, 40, 200, 52); pos.pinTopLeft(*m_defRefreshLabel, 236, 64, 95, 20); @@ -281,6 +283,14 @@ LRESULT CConfigWindow::onCommand(WORD id, WORD code, HWND hwnd) updateModeList(); onModeListSelectChange(); } + else if (m_modeReset && hwnd == *m_modeReset && code == BN_CLICKED && m_modes) + { + *m_modes = m_settings.getDefaultModes(); + m_settings.setModes(*m_modes); + m_modeBox->clear(); + updateModeList(); + onModeListSelectChange(); + } else if (m_defRefresh && hwnd == *m_defRefresh && code == EN_CHANGE && m_defaultRefresh) { int value; diff --git a/idd/LGIddHelper/CConfigWindow.h b/idd/LGIddHelper/CConfigWindow.h index f8fbecf7..8b294e43 100644 --- a/idd/LGIddHelper/CConfigWindow.h +++ b/idd/LGIddHelper/CConfigWindow.h @@ -51,6 +51,7 @@ class CConfigWindow : public CWindow std::unique_ptr m_modeUpdate; std::unique_ptr m_modeDelete; + std::unique_ptr m_modeReset; std::unique_ptr m_autosizeGroup; std::unique_ptr m_defRefreshLabel;