From d68cafa52222e13ffc2ab4f8775c109af71f69f7 Mon Sep 17 00:00:00 2001 From: narzoul Date: Sun, 29 May 2016 20:23:37 +0200 Subject: [PATCH] Avoid redundant display mode changes --- DDrawCompat/CompatDisplayMode.cpp | 61 +++++++++++++++++++++++++++++++ DDrawCompat/CompatDisplayMode.h | 2 + DDrawCompat/DDrawLog.cpp | 17 +++++++++ DDrawCompat/DDrawLog.h | 2 + DDrawCompat/DllMain.cpp | 3 ++ 5 files changed, 85 insertions(+) diff --git a/DDrawCompat/CompatDisplayMode.cpp b/DDrawCompat/CompatDisplayMode.cpp index d8d7fc1..6e5f19a 100644 --- a/DDrawCompat/CompatDisplayMode.cpp +++ b/DDrawCompat/CompatDisplayMode.cpp @@ -10,6 +10,61 @@ namespace HDC g_compatibleDc = nullptr; CompatDisplayMode::DisplayMode g_emulatedDisplayMode = {}; + template + LONG changeDisplaySettingsEx( + ChangeDisplaySettingsExPtr origChangeDisplaySettings, + EnumDisplaySettingsPtr origEnumDisplaySettings, + CStr lpszDeviceName, DevMode* lpDevMode, HWND hwnd, DWORD dwflags, LPVOID lParam) + { + DevMode targetDevMode = {}; + if (lpDevMode) + { + targetDevMode = *lpDevMode; + } + else + { + targetDevMode.dmSize = sizeof(targetDevMode); + origEnumDisplaySettings(lpszDeviceName, ENUM_REGISTRY_SETTINGS, &targetDevMode); + } + + if (targetDevMode.dmPelsWidth) + { + DevMode currentDevMode = {}; + currentDevMode.dmSize = sizeof(currentDevMode); + origEnumDisplaySettings(lpszDeviceName, ENUM_CURRENT_SETTINGS, ¤tDevMode); + + if (targetDevMode.dmPelsWidth == currentDevMode.dmPelsWidth && + targetDevMode.dmPelsHeight == currentDevMode.dmPelsHeight && + targetDevMode.dmBitsPerPel == currentDevMode.dmBitsPerPel && + targetDevMode.dmDisplayFrequency == currentDevMode.dmDisplayFrequency && + targetDevMode.dmDisplayFlags == currentDevMode.dmDisplayFlags) + { + HANDLE dwmDxFullScreenTransitionEvent = OpenEventW( + EVENT_MODIFY_STATE, FALSE, L"DWM_DX_FULLSCREEN_TRANSITION_EVENT"); + SetEvent(dwmDxFullScreenTransitionEvent); + CloseHandle(dwmDxFullScreenTransitionEvent); + return DISP_CHANGE_SUCCESSFUL; + } + } + + return origChangeDisplaySettings(lpszDeviceName, lpDevMode, hwnd, dwflags, lParam); + } + + LONG WINAPI changeDisplaySettingsExA( + LPCSTR lpszDeviceName, DEVMODEA* lpDevMode, HWND hwnd, DWORD dwflags, LPVOID lParam) + { + return changeDisplaySettingsEx(CALL_ORIG_FUNC(ChangeDisplaySettingsExA), + CALL_ORIG_FUNC(EnumDisplaySettingsA), lpszDeviceName, lpDevMode, hwnd, dwflags, lParam); + } + + LONG WINAPI changeDisplaySettingsExW( + LPCWSTR lpszDeviceName, DEVMODEW* lpDevMode, HWND hwnd, DWORD dwflags, LPVOID lParam) + { + return changeDisplaySettingsEx(CALL_ORIG_FUNC(ChangeDisplaySettingsExW), + CALL_ORIG_FUNC(EnumDisplaySettingsW), lpszDeviceName, lpDevMode, hwnd, dwflags, lParam); + } + CompatPtr createCompatibleSurface() { DDSURFACEDESC2 desc = {}; @@ -151,6 +206,12 @@ namespace CompatDisplayMode return dm; } + void installHooks() + { + HOOK_FUNCTION(user32, ChangeDisplaySettingsExA, changeDisplaySettingsExA); + HOOK_FUNCTION(user32, ChangeDisplaySettingsExW, changeDisplaySettingsExW); + } + HRESULT restoreDisplayMode(CompatRef dd) { const HRESULT result = dd->RestoreDisplayMode(&dd); diff --git a/DDrawCompat/CompatDisplayMode.h b/DDrawCompat/CompatDisplayMode.h index 6cbb816..8742054 100644 --- a/DDrawCompat/CompatDisplayMode.h +++ b/DDrawCompat/CompatDisplayMode.h @@ -17,6 +17,8 @@ namespace CompatDisplayMode DWORD flags; }; + void installHooks(); + HBITMAP WINAPI createCompatibleBitmap(HDC hdc, int cx, int cy); HBITMAP WINAPI createDIBitmap(HDC hdc, const BITMAPINFOHEADER* lpbmih, DWORD fdwInit, const void* lpbInit, const BITMAPINFO* lpbmi, UINT fuUsage); diff --git a/DDrawCompat/DDrawLog.cpp b/DDrawCompat/DDrawLog.cpp index 973882c..3a92a29 100644 --- a/DDrawCompat/DDrawLog.cpp +++ b/DDrawCompat/DDrawLog.cpp @@ -14,6 +14,13 @@ namespace empty.dwSize = t.dwSize; return 0 == memcmp(&t, &empty, sizeof(t)); } + + template + std::ostream& streamDevMode(std::ostream& os, const DevMode& dm) + { + return os << "DM(" << dm.dmPelsWidth << ',' << dm.dmPelsHeight << ',' << dm.dmBitsPerPel << + ',' << dm.dmDisplayFrequency << ',' << dm.dmDisplayFlags << ')'; + } } std::ostream& operator<<(std::ostream& os, const char* str) @@ -42,6 +49,16 @@ std::ostream& operator<<(std::ostream& os, const WCHAR* wstr) return os << '"' << static_cast(str) << '"'; } +std::ostream& operator<<(std::ostream& os, const DEVMODEA& dm) +{ + return streamDevMode(os, dm); +} + +std::ostream& operator<<(std::ostream& os, const DEVMODEW& dm) +{ + return streamDevMode(os, dm); +} + std::ostream& operator<<(std::ostream& os, const RECT& rect) { return os << "R(" << rect.left << ',' << rect.top << ',' << rect.right << ',' << rect.bottom << ')'; diff --git a/DDrawCompat/DDrawLog.h b/DDrawCompat/DDrawLog.h index 41aac76..076c714 100644 --- a/DDrawCompat/DDrawLog.h +++ b/DDrawCompat/DDrawLog.h @@ -17,6 +17,8 @@ std::ostream& operator<<(std::ostream& os, const char* str); std::ostream& operator<<(std::ostream& os, const unsigned char* data); std::ostream& operator<<(std::ostream& os, const WCHAR* wstr); +std::ostream& operator<<(std::ostream& os, const DEVMODEA& dm); +std::ostream& operator<<(std::ostream& os, const DEVMODEW& dm); std::ostream& operator<<(std::ostream& os, const RECT& rect); std::ostream& operator<<(std::ostream& os, HDC__& dc); std::ostream& operator<<(std::ostream& os, HWND__& hwnd); diff --git a/DDrawCompat/DllMain.cpp b/DDrawCompat/DllMain.cpp index f1bf171..3eb5287 100644 --- a/DDrawCompat/DllMain.cpp +++ b/DDrawCompat/DllMain.cpp @@ -9,6 +9,7 @@ #include "CompatDirectDraw.h" #include "CompatDirectDrawSurface.h" #include "CompatDirectDrawPalette.h" +#include "CompatDisplayMode.h" #include "CompatFontSmoothing.h" #include "CompatGdi.h" #include "CompatHooks.h" @@ -199,6 +200,8 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID /*lpvReserved*/) SetProcessPriorityBoost(GetCurrentProcess(), disablePriorityBoost); SetProcessAffinityMask(GetCurrentProcess(), 1); SetThemeAppProperties(0); + + CompatDisplayMode::installHooks(); CompatFontSmoothing::g_origSystemSettings = CompatFontSmoothing::getSystemSettings(); CompatHooks::installHooks(); Time::init();