diff --git a/idd/LGIdd/CIndirectMonitorContext.cpp b/idd/LGIdd/CIndirectMonitorContext.cpp index 785f7bec..0b384702 100644 --- a/idd/LGIdd/CIndirectMonitorContext.cpp +++ b/idd/LGIdd/CIndirectMonitorContext.cpp @@ -71,7 +71,6 @@ 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 99e1e921..1c7bdf94 100644 --- a/idd/LGIdd/CPipeServer.cpp +++ b/idd/LGIdd/CPipeServer.cpp @@ -114,6 +114,11 @@ void CPipeServer::Thread() DEBUG_TRACE("Client connected"); m_connected = true; + + for (const auto& msg : m_queue) + WriteMsg(msg); + m_queue.clear(); + while (m_running && m_connected) { //TODO: Read messages from the client @@ -129,8 +134,14 @@ void CPipeServer::Thread() DEBUG_TRACE("Pipe thread shutdown"); } -void CPipeServer::WriteMsg(LGPipeMsg & msg) +void CPipeServer::WriteMsg(const LGPipeMsg & msg) { + if (!m_connected) + { + m_queue.push_back(msg); + return; + } + DWORD written; if (!WriteFile(m_pipe.Get(), &msg, sizeof(msg), &written, NULL)) { @@ -151,6 +162,7 @@ void CPipeServer::WriteMsg(LGPipeMsg & msg) void CPipeServer::SetCursorPos(uint32_t x, uint32_t y) { + // do not send cursor messages if we are not connected or they will end up queued if (!m_connected) return; @@ -164,9 +176,6 @@ void CPipeServer::SetCursorPos(uint32_t x, uint32_t y) void CPipeServer::SetDisplayMode(uint32_t width, uint32_t height, uint32_t refresh) { - if (!m_connected) - return; - LGPipeMsg msg; msg.size = sizeof(msg); msg.type = LGPipeMsg::SETDISPLAYMODE; @@ -178,9 +187,6 @@ void CPipeServer::SetDisplayMode(uint32_t width, uint32_t height, uint32_t refre void CPipeServer::SetGPUStatus(bool software) { - if (!m_connected) - return; - LGPipeMsg msg; msg.size = sizeof(msg); msg.type = LGPipeMsg::GPUSTATUS; diff --git a/idd/LGIdd/CPipeServer.h b/idd/LGIdd/CPipeServer.h index 5a8d320a..36755e4a 100644 --- a/idd/LGIdd/CPipeServer.h +++ b/idd/LGIdd/CPipeServer.h @@ -24,6 +24,7 @@ #include #include #include +#include #include "PipeMsg.h" @@ -36,6 +37,7 @@ class CPipeServer private: HandleT m_pipe; HandleT m_thread; + std::vector m_queue; bool m_running = false; bool m_connected = false; @@ -45,7 +47,7 @@ class CPipeServer static DWORD WINAPI _pipeThread(LPVOID lpParam) { ((CPipeServer*)lpParam)->Thread(); return 0; } void Thread(); - void WriteMsg(LGPipeMsg & msg); + void WriteMsg(const LGPipeMsg & msg); public: ~CPipeServer() { DeInit(); } diff --git a/idd/LGIdd/CSwapChainProcessor.cpp b/idd/LGIdd/CSwapChainProcessor.cpp index eccb46ac..0d7f01c2 100644 --- a/idd/LGIdd/CSwapChainProcessor.cpp +++ b/idd/LGIdd/CSwapChainProcessor.cpp @@ -22,6 +22,7 @@ #include #include "CDebug.h" +#include "CPipeServer.h" CSwapChainProcessor::CSwapChainProcessor(IDDCX_MONITOR monitor, CIndirectDeviceContext* devContext, IDDCX_SWAPCHAIN hSwapChain, std::shared_ptr dx11Device, std::shared_ptr dx12Device, HANDLE newFrameEvent) : @@ -130,6 +131,10 @@ void CSwapChainProcessor::SwapChainThreadCore() m_lastShapeId = 0; m_thread[1].Attach(CreateThread(nullptr, 0, _CursorThread, this, 0, nullptr)); + // postpone sending this to ensure we dont spam messages if we end up in a + // restart loop while waiting for a valid configuration + g_pipe.SetGPUStatus(m_dx11Device->IsSoftware()); + UINT lastFrameNumber = 0; for (;;) { diff --git a/idd/LGIddHelper/CNotifyWindow.cpp b/idd/LGIddHelper/CNotifyWindow.cpp index 50c3490a..1a36ae68 100644 --- a/idd/LGIddHelper/CNotifyWindow.cpp +++ b/idd/LGIddHelper/CNotifyWindow.cpp @@ -20,13 +20,13 @@ #include "CNotifyWindow.h" #include "CConfigWindow.h" -#include "Devices.h" #include #include #include -#define WM_NOTIFY_ICON (WM_USER) +#define WM_NOTIFY_ICON (WM_USER) #define WM_CLEAN_UP_CONFIG (WM_USER+1) +#define WM_NO_GPU (WM_USER+2) #define ID_MENU_SHOW_LOG 3000 #define ID_MENU_SHOW_CONFIG 3001 @@ -81,6 +81,10 @@ LRESULT CNotifyWindow::handleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) } return 0; + case WM_NO_GPU: + handleNoGPUNotification(); + return 0; + default: if (s_taskbarCreated && uMsg == s_taskbarCreated) { @@ -162,20 +166,14 @@ void CNotifyWindow::registerIcon() if (!Shell_NotifyIcon(NIM_SETVERSION, &m_iconData)) DEBUG_ERROR_HR(GetLastError(), "Shell_NotifyIcon(NIM_SETVERSION)"); - - bool hasGPU; - if (!checkGPU(hasGPU)) - DEBUG_ERROR("Failed to check if the system has a GPU"); - else if (hasGPU) - DEBUG_INFO("GPU identified"); - else - { - DEBUG_INFO("System has no GPU"); - noGPUNotification(); - } } void CNotifyWindow::noGPUNotification() +{ + PostMessage(m_hwnd, WM_NO_GPU, 0, 0); +} + +void CNotifyWindow::handleNoGPUNotification() { CRegistrySettings settings; LSTATUS error = settings.open(); diff --git a/idd/LGIddHelper/CNotifyWindow.h b/idd/LGIddHelper/CNotifyWindow.h index 3f30c1fd..36e3ba7f 100644 --- a/idd/LGIddHelper/CNotifyWindow.h +++ b/idd/LGIddHelper/CNotifyWindow.h @@ -36,7 +36,7 @@ class CNotifyWindow : public CWindow LRESULT onNotifyIcon(UINT uEvent, WORD wIconId, int x, int y); void registerIcon(); - void noGPUNotification(); + void handleNoGPUNotification(); virtual LRESULT handleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) override; virtual LRESULT onCreate() override; @@ -44,11 +44,26 @@ class CNotifyWindow : public CWindow virtual LRESULT onDestroy() override; virtual LRESULT onFinal() override; -public: CNotifyWindow(); ~CNotifyWindow() override; + +public: + CNotifyWindow(const CNotifyWindow&) = delete; + CNotifyWindow& operator=(const CNotifyWindow&) = delete; + + CNotifyWindow(CNotifyWindow&&) = delete; + CNotifyWindow& operator=(CNotifyWindow&&) = delete; + + static CNotifyWindow& instance() + { + static CNotifyWindow window; + return window; + } + static bool registerClass(); + void noGPUNotification(); + HWND hwndDialog(); void close(); -}; +}; \ No newline at end of file diff --git a/idd/LGIddHelper/CPipeClient.cpp b/idd/LGIddHelper/CPipeClient.cpp index 4a2aa8c6..4bdeab4b 100644 --- a/idd/LGIddHelper/CPipeClient.cpp +++ b/idd/LGIddHelper/CPipeClient.cpp @@ -20,6 +20,7 @@ #include "CPipeClient.h" #include "CDebug.h" +#include "CNotifyWindow.h" #include #include @@ -307,5 +308,6 @@ void CPipeClient::HandleSetDisplayMode(const LGPipeMsg& msg) void CPipeClient::HandleGPUStatus(const LGPipeMsg& msg) { - // TODO: implement me + if (msg.gpuStatus.software) + CNotifyWindow::instance().noGPUNotification(); } diff --git a/idd/LGIddHelper/Devices.cpp b/idd/LGIddHelper/Devices.cpp deleted file mode 100644 index f6c9f39d..00000000 --- a/idd/LGIddHelper/Devices.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/** - * Looking Glass - * Copyright © 2017-2026 The Looking Glass Authors - * https://looking-glass.io - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Devices.h" -#include -#include -#include -#include - -inline static bool wprefix(const wchar_t *pre, const wchar_t *str) -{ - return wcsncmp(pre, str, wcslen(pre)) == 0; -} - -bool checkGPU(bool &found) -{ - found = false; - - HDEVINFO hDevInfo = SetupDiGetClassDevsW(&GUID_DEVCLASS_DISPLAY, NULL, NULL, DIGCF_PRESENT); - if (hDevInfo == INVALID_HANDLE_VALUE) - { - DEBUG_WARN_HR(GetLastError(), L"SetupDiGetClassDevsW"); - return false; - } - - SP_DEVINFO_DATA devInfo = { 0 }; - devInfo.cbSize = sizeof devInfo; - - for (DWORD dwIndex = 0; SetupDiEnumDeviceInfo(hDevInfo, dwIndex, &devInfo); ++dwIndex) - { - DWORD dwSizeRequired; - DWORD dwPropertyType; - SetupDiGetDeviceRegistryPropertyW(hDevInfo, &devInfo, SPDRP_HARDWAREID, &dwPropertyType, NULL, 0, &dwSizeRequired); - - DWORD dwLastError = GetLastError(); - if (dwLastError == ERROR_INVALID_DATA) - continue; - else if (dwLastError != ERROR_INSUFFICIENT_BUFFER) - { - DEBUG_WARN_HR(GetLastError(), L"SetupDiGetDeviceRegistryPropertyW(SPDRP_HARDWAREID) size calculation"); - goto fail; - } - - if (dwPropertyType != REG_MULTI_SZ) - { - DEBUG_WARN(L"SetupDiGetDeviceRegistryPropertyW(SPDRP_HARDWAREID) returned wrong type"); - goto fail; - } - - LPWSTR lpBuffer = (LPWSTR)malloc(dwSizeRequired); - if (!lpBuffer) - { - DEBUG_WARN(L"failed to allocate memory for SetupDiGetDeviceRegistryPropertyW(SPDRP_HARDWAREID)"); - goto fail; - } - - if (!SetupDiGetDeviceRegistryPropertyW(hDevInfo, &devInfo, SPDRP_HARDWAREID, &dwPropertyType, (PBYTE)lpBuffer, dwSizeRequired, NULL)) - { - DEBUG_WARN_HR(GetLastError(), L"SetupDiGetDeviceRegistryPropertyW(SPDRP_HARDWAREID) for real"); - free(lpBuffer); - goto fail; - } - - for (LPWSTR lpHwId = lpBuffer; *lpHwId; lpHwId += wcslen(lpBuffer) + 1) - { - if ( - wprefix(L"PCI\\VEN_10DE&", lpHwId) || // Nvidia - wprefix(L"PCI\\VEN_1002&", lpHwId) || // AMD - wprefix(L"PCI\\VEN_8086&", lpHwId) // Intel - ) - { - found = true; - break; - } - } - - free(lpBuffer); - - if (found) - break; - } - - SetupDiDestroyDeviceInfoList(hDevInfo); - return true; - -fail: - SetupDiDestroyDeviceInfoList(hDevInfo); - return false; -} diff --git a/idd/LGIddHelper/Devices.h b/idd/LGIddHelper/Devices.h deleted file mode 100644 index 2951be2e..00000000 --- a/idd/LGIddHelper/Devices.h +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Looking Glass - * Copyright © 2017-2026 The Looking Glass Authors - * https://looking-glass.io - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#pragma once - -bool checkGPU(bool &found); diff --git a/idd/LGIddHelper/LGIddHelper.vcxproj b/idd/LGIddHelper/LGIddHelper.vcxproj index 3acf84dc..5ac47d2b 100644 --- a/idd/LGIddHelper/LGIddHelper.vcxproj +++ b/idd/LGIddHelper/LGIddHelper.vcxproj @@ -191,7 +191,6 @@ copy /Y "$(ProjectDir)VERSION" "$(SolutionDir)$(Platform)\$(Configuration)\LGIdd - @@ -208,7 +207,6 @@ copy /Y "$(ProjectDir)VERSION" "$(SolutionDir)$(Platform)\$(Configuration)\LGIdd - diff --git a/idd/LGIddHelper/LGIddHelper.vcxproj.filters b/idd/LGIddHelper/LGIddHelper.vcxproj.filters index 97b59054..b78f7721 100644 --- a/idd/LGIddHelper/LGIddHelper.vcxproj.filters +++ b/idd/LGIddHelper/LGIddHelper.vcxproj.filters @@ -60,7 +60,8 @@ Source Files - + + Source Files @@ -113,7 +114,10 @@ Header Files - + + + + Header Files diff --git a/idd/LGIddHelper/main.cpp b/idd/LGIddHelper/main.cpp index 5537b371..536fca55 100644 --- a/idd/LGIddHelper/main.cpp +++ b/idd/LGIddHelper/main.cpp @@ -113,11 +113,13 @@ int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _ return EXIT_FAILURE; } + CNotifyWindow& window = CNotifyWindow::instance(); + + // the pipe must be initialized after the CNotifyWindow + // has been created to avoid a potential race if (!g_pipe.Init()) return EXIT_FAILURE; - CNotifyWindow window; - HANDLE hWait; if (!RegisterWaitForSingleObject(&hWait, hParent.Get(), DestroyNotifyWindow, &window, INFINITE, WT_EXECUTEONLYONCE)) DEBUG_ERROR_HR(GetLastError(), "Failed to RegisterWaitForSingleObject");