From 8612d34283a0a054dd96bbc4cbc8f7e83c84b874 Mon Sep 17 00:00:00 2001 From: teejusb <5017202+teejusb@users.noreply.github.com> Date: Sun, 5 Jun 2022 23:12:06 -0700 Subject: [PATCH] Prevent hanging when going into "Graphics Options" Remove calls to ChangeDisplaySettingsEx(CDS_TEST). This prevents an an alarming system hang on NVIDIA GPUs with DisplayPort displays when using "Graphics Options" in the system menu, and doesn't seem to have any downsides as far as I can tell. Taken from: https://github.com/ClubFantastic/stepmania/commit/46061f818d020138eff80ba5785e0ea88cd68dfd --- src/archutils/Win32/GraphicsWindow.cpp | 70 +++++++++++++++----------- 1 file changed, 41 insertions(+), 29 deletions(-) diff --git a/src/archutils/Win32/GraphicsWindow.cpp b/src/archutils/Win32/GraphicsWindow.cpp index 8838171bec..147dccf2c8 100644 --- a/src/archutils/Win32/GraphicsWindow.cpp +++ b/src/archutils/Win32/GraphicsWindow.cpp @@ -541,47 +541,59 @@ HWND GraphicsWindow::GetHwnd() void GraphicsWindow::GetDisplaySpecs( DisplaySpecs &out ) { - const size_t DM_DRIVER_EXTRA_BYTES = 4096; - const size_t DMSIZE = sizeof( DEVMODE ) + DM_DRIVER_EXTRA_BYTES; - auto reset = [=]( std::unique_ptr &p ) { - ::memset( p.get(), 0, DMSIZE ); - p->dmSize = sizeof( DEVMODE ); - p->dmDriverExtra = static_cast (DM_DRIVER_EXTRA_BYTES); - }; - auto isvalid = []( std::unique_ptr &dm ) { - // Windows 8 and later don't support less than 32bpp, so don't even test - // for them. GetDisplaySpecs only tracks resolution/refresh rate anyway. -Kyz, drewbarbs - return (dm->dmFields & DM_PELSWIDTH) && (dm->dmFields & DM_PELSHEIGHT) && (dm->dmFields & DM_DISPLAYFREQUENCY) - && (dm->dmBitsPerPel >= 32 || !(dm->dmFields & DM_BITSPERPEL)); +auto resetDeviceMode = [=]( DEVMODE& mode ) { + ZeroMemory( &mode, sizeof( DEVMODE ) ); + mode.dmSize = sizeof(DEVMODE); + mode.dmDriverExtra = 0; }; - std::unique_ptr dm( static_cast (operator new(DMSIZE)) ); - reset( dm ); + auto deviceModeIsValid = [=]( const DEVMODE& mode ) { + return (mode.dmFields & DM_PELSWIDTH) && (mode.dmFields & DM_PELSHEIGHT) + && (mode.dmFields & DM_DISPLAYFREQUENCY) + && (mode.dmBitsPerPel >= 32 || !(mode.dmFields & DM_BITSPERPEL)); + }; + + DEVMODE devmode; + resetDeviceMode(devmode); + + std::set displayModes; int i = 0; - std::set modes; - while ( EnumDisplaySettingsEx( nullptr, i++, dm.get(), 0 ) ) + while ( EnumDisplaySettingsEx( nullptr, i++, &devmode, 0 ) ) { - if ( isvalid( dm ) && ChangeDisplaySettingsEx( nullptr, dm.get(), nullptr, CDS_TEST, nullptr ) == DISP_CHANGE_SUCCESSFUL ) + if ( deviceModeIsValid( devmode ) ) { - DisplayMode m = { dm->dmPelsWidth, dm->dmPelsHeight, static_cast (dm->dmDisplayFrequency) }; - modes.insert(m); + DisplayMode m = { devmode.dmPelsWidth, devmode.dmPelsHeight, static_cast (devmode.dmDisplayFrequency) }; + displayModes.insert( m ); } - reset( dm ); + resetDeviceMode( devmode ); } - reset( dm ); - // Get the current display mode - if ( EnumDisplaySettingsEx( nullptr, ENUM_CURRENT_SETTINGS, dm.get(), 0 ) && isvalid( dm ) ) - { - DisplayMode m = { dm->dmPelsWidth, dm->dmPelsHeight, static_cast (dm->dmDisplayFrequency) }; - RectI bounds = { 0, 0, static_cast (m.width), static_cast (m.height) }; - out.insert( DisplaySpec( "", "Fullscreen", modes, m, bounds ) ); + /* + XXXCF: This doesn't appear to actually be necessary, and causes a horrible system lock-up for about 5s. + std::set displayModes; + for ( auto& deviceMode : allDeviceModes) { + Sleep(1); + if (ChangeDisplaySettingsEx(nullptr, &devmode, nullptr, CDS_TEST, nullptr) == DISP_CHANGE_SUCCESSFUL) { + DisplayMode m = { deviceMode.dmPelsWidth, deviceMode.dmPelsHeight, static_cast (deviceMode.dmDisplayFrequency) }; + displayModes.insert(m); + } } - else if ( !modes.empty() ) + */ + + resetDeviceMode(devmode); + + // Get the current display mode + if ( EnumDisplaySettingsEx( nullptr, ENUM_CURRENT_SETTINGS, &devmode, 0 ) && deviceModeIsValid(devmode) ) + { + DisplayMode m = { devmode.dmPelsWidth, devmode.dmPelsHeight, static_cast (devmode.dmDisplayFrequency) }; + RectI bounds = { 0, 0, static_cast (m.width), static_cast (m.height) }; + out.insert( DisplaySpec( "", "Fullscreen", displayModes, m, bounds ) ); + } + else if ( !displayModes.empty() ) { LOG->Warn( "Could not retrieve valid current display mode" ); - out.insert( DisplaySpec( "", "Fullscreen", *modes.begin() ) ); + out.insert( DisplaySpec( "", "Fullscreen", *displayModes.begin() ) ); } else {