summaryrefslogtreecommitdiff
path: root/indra/llwindow/llwindowwin32.cpp
diff options
context:
space:
mode:
authorJonathan "Geenz" Goodman <geenz@geenzo.com>2026-08-12 16:09:42 -0400
committerJonathan "Geenz" Goodman <geenz@geenzo.com>2026-08-12 16:09:42 -0400
commit480af3ea32856007b166a06ca4932078c9f557c6 (patch)
tree010a3b43a75dae55d6a66d3cdece6277dc97a1d8 /indra/llwindow/llwindowwin32.cpp
parent8cabc33e960ca93fdc1a32c77cf611269d95d51b (diff)
parent932e8ac318eb2e29ea519249348315b50c7d1d58 (diff)
Merge branch 'release/26.3' into geenz/linux-to-develop
Diffstat (limited to 'indra/llwindow/llwindowwin32.cpp')
-rw-r--r--indra/llwindow/llwindowwin32.cpp72
1 files changed, 68 insertions, 4 deletions
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index e947948c57..3fccc1fbff 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -466,6 +466,16 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool
}
});
}
+
+ // For mainWindowProc, it should not unpause watchdog if it was paused
+ void pingWindowTimeout(std::string_view state)
+ {
+ if (mWindowTimeout && mWindowTimeout->started())
+ {
+ mWindowTimeout->setTimeout(WINDOW_TIMEOUT_SEC);
+ mWindowTimeout->ping(state);
+ }
+ }
private:
// These timeout related functions are strictly for the thread.
void resumeTimeout(std::string_view state)
@@ -2430,18 +2440,45 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
case WM_DEVICECHANGE:
{
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_DEVICECHANGE");
+ window_imp->mWindowThread->pingWindowTimeout("WM_DEVICECHANGE");
+
+ // Log detailed device change information
+ std::string change_type = "UNKNOWN";
+ switch (w_param)
+ {
+ case DBT_DEVICEARRIVAL: change_type = "DBT_DEVICEARRIVAL"; break;
+ case DBT_DEVICEREMOVECOMPLETE: change_type = "DBT_DEVICEREMOVECOMPLETE"; break;
+ case DBT_DEVNODES_CHANGED: change_type = "DBT_DEVNODES_CHANGED"; break;
+ case DBT_DEVICEQUERYREMOVE: change_type = "DBT_DEVICEQUERYREMOVE"; break;
+ case DBT_DEVICEQUERYREMOVEFAILED: change_type = "DBT_DEVICEQUERYREMOVEFAILED"; break;
+ case DBT_DEVICEREMOVEPENDING: change_type = "DBT_DEVICEREMOVEPENDING"; break;
+ case DBT_CONFIGCHANGED: change_type = "DBT_CONFIGCHANGED"; break;
+ }
+
if (w_param == DBT_DEVNODES_CHANGED || w_param == DBT_DEVICEARRIVAL)
{
- WINDOW_IMP_POST(window_imp->mCallbacks->handleDeviceChange(window_imp));
+ WINDOW_IMP_POST(window_imp->mCallbacks->handleDeviceChange(window_imp, change_type));
return 1;
}
+ else if (l_param)
+ {
+ const auto* hdr = reinterpret_cast<const DEV_BROADCAST_HDR*>(l_param);
+ if (hdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
+ {
+ // Might need to register for monitor device notifications
+ // to get this message when monitor is suspended or resumed.
+ // TODO: log monitor suspending and resuming.
+ LL_INFOS("Window") << "DEVICEINTERFACE: " << change_type << LL_ENDL;
+ }
+ }
break;
}
case WM_PAINT:
{
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_PAINT");
+ window_imp->mWindowThread->pingWindowTimeout("WM_PAINT");
GetUpdateRect(window_imp->mWindowHandle, &update_rect, FALSE);
update_width = update_rect.right - update_rect.left + 1;
update_height = update_rect.bottom - update_rect.top + 1;
@@ -2586,6 +2623,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
case WM_CLOSE:
{
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_CLOSE");
+ window_imp->mWindowThread->pingWindowTimeout("WM_CLOSE");
window_imp->mCallbacks->handlePreCloseRequest(); // mark app as potentially closing
if (!window_imp->mReceivedSCClose)
@@ -2654,6 +2692,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
// Comes after WM_QUERYENDSESSION
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_ENDSESSION");
LL_INFOS("Window") << "Received WM_ENDSESSION with wParam: " << (U32)w_param << " lParam: " << (U32)l_param << LL_ENDL;
+ window_imp->mWindowThread->pingWindowTimeout("WM_ENDSESSION");
unsigned int end_session_flags = (U32)l_param;
if (w_param == TRUE // if true, session is ending
@@ -2722,6 +2761,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
return TRUE;
default:
+ LL_INFOS("Window") << "Received WM_POWERBROADCAST with wParam: 0x" << std::hex << (uintptr_t)w_param << " lParam: 0x" << (uintptr_t)l_param << std::dec << LL_ENDL;
break;
}
break;
@@ -3377,6 +3417,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
case WM_DPICHANGED:
{
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_DPICHANGED");
+ window_imp->mWindowThread->pingWindowTimeout("WM_DPICHANGED");
LPRECT lprc_new_scale;
F32 new_scale = F32(LOWORD(w_param)) / F32(USER_DEFAULT_SCREEN_DPI);
lprc_new_scale = (LPRECT)l_param;
@@ -3398,6 +3439,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
case WM_DISPLAYCHANGE:
{
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_DISPLAYCHANGE");
+ window_imp->mWindowThread->pingWindowTimeout("WM_DISPLAYCHANGE");
window_imp->post([=]() {
window_imp->mCallbacks->handleDisplayChanged();
// Note: WM_DISPLAYCHANGE was passing to WM_SETFOCUS
@@ -3446,6 +3488,9 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
case WM_SETTINGCHANGE:
{
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_SETTINGCHANGE");
+ // Can be called on OS user switching
+ LL_INFOS("Window") << "WM_SETTINGCHANGE, with wParam: 0x" << std::hex << (uintptr_t)w_param << " lParam: 0x" << (uintptr_t)l_param << std::dec << LL_ENDL;
+ window_imp->mWindowThread->pingWindowTimeout("WM_SETTINGCHANGE");
if (w_param == SPI_SETMOUSEVANISH)
{
if (!SystemParametersInfo(SPI_GETMOUSEVANISH, 0, &window_imp->mMouseVanish, 0))
@@ -4980,6 +5025,16 @@ void LLWindowWin32::requestHighPerformanceGPU() const
<< ", Vendor: 0x" << std::hex << desc.VendorId << std::dec
<< ", Flags: " << desc.Flags << LL_ENDL;
}
+ // Skip Microsoft Basic Render Driver, it's a placeholder for missing drivers
+ else if (description.find("Microsoft Basic Render Driver") != std::string::npos)
+ {
+ // User is likely missing drivers, so log a warning.
+ // Don't consider this adapter as a valid selection.
+ LL_WARNS("Window") << "Adapter " << adapterIndex << ": " << description
+ << ", Dedicated VRAM: " << (desc.DedicatedVideoMemory / 1024 / 1024) << " MB"
+ << ", Vendor: 0x" << std::hex << desc.VendorId << std::dec
+ << ", Flags: " << desc.Flags << LL_ENDL;
+ }
else
{
LL_INFOS("Window") << "Adapter " << adapterIndex << ": " << description
@@ -5292,6 +5347,13 @@ inline LLWindowWin32::LLWindowWin32Thread::LLWindowWin32Thread()
: LL::ThreadPool("Window Thread", 1, MAX_QUEUE_SIZE, false)
{
LL::ThreadPool::start();
+
+ // Set thread name for the window thread
+ // This will make it distinguishable in Visual Studio debugger
+ post([this]()
+ {
+ SetThreadDescription(GetCurrentThread(), L"LLWindowWin32 Thread");
+ });
}
/**
@@ -5473,7 +5535,7 @@ void LLWindowWin32::LLWindowWin32Thread::run()
}
// Normally won't exist yet, but in case of re-init, make sure it's cleaned up
- resumeTimeout("WindowThread");
+ resumeTimeout("Window:WindowThread");
while (! getQueue().done())
{
@@ -5484,23 +5546,25 @@ void LLWindowWin32::LLWindowWin32Thread::run()
if (mWindowHandleThrd != 0)
{
- pingTimeout("messages");
MSG msg;
BOOL status;
if (mhDCThrd == 0)
{
+ pingTimeout("Window:PeekMessage");
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("w32t - PeekMessage");
logger.onChange("PeekMessage(", std::hex, mWindowHandleThrd, ")");
status = PeekMessage(&msg, mWindowHandleThrd, 0, 0, PM_REMOVE);
}
else
{
+ pingTimeout("Window:GetMessage");
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("w32t - GetMessage");
logger.always("GetMessage(", std::hex, mWindowHandleThrd, ")");
status = GetMessage(&msg, NULL, 0, 0);
}
if (status > 0)
{
+ pingTimeout("Window:TranslateMessage");
logger.always("got MSG (", std::hex, msg.hwnd, ", ", msg.message,
", ", msg.wParam, ")");
TranslateMessage(&msg);
@@ -5512,7 +5576,7 @@ void LLWindowWin32::LLWindowWin32Thread::run()
{
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("w32t - Function Queue");
- pingTimeout("queue");
+ pingTimeout("Window:Queue");
logger.onChange("runPending()");
//process any pending functions
getQueue().runPending();