diff --git a/DDrawCompat/Config/Config.cpp b/DDrawCompat/Config/Config.cpp index 984bc90..21d0c98 100644 --- a/DDrawCompat/Config/Config.cpp +++ b/DDrawCompat/Config/Config.cpp @@ -13,6 +13,7 @@ namespace Config Settings::DisplayFilter displayFilter; Settings::DisplayRefreshRate displayRefreshRate; Settings::DisplayResolution displayResolution; + Settings::DpiAwareness dpiAwareness; Settings::ForceD3D9On12 forceD3D9On12; Settings::FullscreenMode fullscreenMode; Settings::LogLevel logLevel; diff --git a/DDrawCompat/Config/Config.h b/DDrawCompat/Config/Config.h index f985a08..abd7802 100644 --- a/DDrawCompat/Config/Config.h +++ b/DDrawCompat/Config/Config.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -39,6 +40,7 @@ namespace Config extern Settings::DisplayFilter displayFilter; extern Settings::DisplayRefreshRate displayRefreshRate; extern Settings::DisplayResolution displayResolution; + extern Settings::DpiAwareness dpiAwareness; extern Settings::ForceD3D9On12 forceD3D9On12; extern Settings::FullscreenMode fullscreenMode; extern Settings::LogLevel logLevel; diff --git a/DDrawCompat/Config/MappedSetting.h b/DDrawCompat/Config/MappedSetting.h index 6f3e8f0..7808293 100644 --- a/DDrawCompat/Config/MappedSetting.h +++ b/DDrawCompat/Config/MappedSetting.h @@ -50,6 +50,18 @@ namespace Config throw ParsingError("MappedSetting::getValueStr(): value not found in mapping"); } + std::string convertToString(Value value) + { + for (const auto& pair : m_valueMapping) + { + if (pair.second == value) + { + return pair.first; + } + } + return {}; + } + protected: MappedSetting(const std::string& name, const std::string& default, const std::vector>& valueMapping) diff --git a/DDrawCompat/Config/Settings/DpiAwareness.h b/DDrawCompat/Config/Settings/DpiAwareness.h new file mode 100644 index 0000000..ddb448d --- /dev/null +++ b/DDrawCompat/Config/Settings/DpiAwareness.h @@ -0,0 +1,25 @@ +#pragma once + +#include + +namespace Config +{ + namespace Settings + { + class DpiAwareness : public MappedSetting + { + public: + DpiAwareness() + : MappedSetting("DpiAwareness", "permonitor", { + {"app", nullptr}, + {"unaware", DPI_AWARENESS_CONTEXT_UNAWARE}, + {"system", DPI_AWARENESS_CONTEXT_SYSTEM_AWARE}, + {"permonitor", DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE}, + {"permonitorv2", DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2}, + {"gdiscaled", DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED} + }) + { + } + }; + } +} diff --git a/DDrawCompat/D3dDdi/Resource.cpp b/DDrawCompat/D3dDdi/Resource.cpp index 9d1e62d..6075fb0 100644 --- a/DDrawCompat/D3dDdi/Resource.cpp +++ b/DDrawCompat/D3dDdi/Resource.cpp @@ -528,6 +528,7 @@ namespace D3dDdi void Resource::createGdiLockResource() { + LOG_FUNC("Resource::createGdiLockResource"); auto gdiSurfaceDesc(Gdi::VirtualScreen::getSurfaceDesc(DDraw::PrimarySurface::getMonitorRect())); if (!gdiSurfaceDesc.lpSurface) { diff --git a/DDrawCompat/DDraw/Surfaces/PrimarySurface.cpp b/DDrawCompat/DDraw/Surfaces/PrimarySurface.cpp index dcb0852..4b4729d 100644 --- a/DDrawCompat/DDraw/Surfaces/PrimarySurface.cpp +++ b/DDrawCompat/DDraw/Surfaces/PrimarySurface.cpp @@ -222,18 +222,6 @@ namespace DDraw g_primarySurface = m_surface; g_gdiResourceHandle = DirectDrawSurface::getRuntimeResourceHandle(*g_primarySurface); - DDSURFACEDESC2 desc = {}; - desc.dwSize = sizeof(desc); - m_surface->GetSurfaceDesc(m_surface, &desc); - if (desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) - { - DDSURFACEDESC2 gdiDesc = Gdi::VirtualScreen::getSurfaceDesc(g_monitorRect); - desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_LPSURFACE; - desc.lPitch = gdiDesc.lPitch; - desc.lpSurface = gdiDesc.lpSurface; - m_surface->SetSurfaceDesc(m_surface, &desc, 0); - } - updateFrontResource(); D3dDdi::Device::setGdiResourceHandle(g_frontResource); diff --git a/DDrawCompat/DDrawCompat.vcxproj b/DDrawCompat/DDrawCompat.vcxproj index b3e2854..29d54df 100644 --- a/DDrawCompat/DDrawCompat.vcxproj +++ b/DDrawCompat/DDrawCompat.vcxproj @@ -169,6 +169,7 @@ + diff --git a/DDrawCompat/DDrawCompat.vcxproj.filters b/DDrawCompat/DDrawCompat.vcxproj.filters index c3578b5..1c4d807 100644 --- a/DDrawCompat/DDrawCompat.vcxproj.filters +++ b/DDrawCompat/DDrawCompat.vcxproj.filters @@ -573,6 +573,9 @@ Header Files\Config\Settings + + Header Files\Config\Settings + diff --git a/DDrawCompat/Dll/DllMain.cpp b/DDrawCompat/Dll/DllMain.cpp index e9876de..17b6aa9 100644 --- a/DDrawCompat/Dll/DllMain.cpp +++ b/DDrawCompat/Dll/DllMain.cpp @@ -131,6 +131,12 @@ namespace (!Compat::isEqual(currentDllPath, dciman32DllPath) && GetModuleHandleW(dciman32DllPath.c_str())); } + void logDpiAwareness(bool isSuccessful, DPI_AWARENESS_CONTEXT dpiAwareness, const char* funcName) + { + LOG_INFO << (isSuccessful ? "DPI awareness was successfully changed" : "Failed to change process DPI awareness") + << " to \"" << Config::dpiAwareness.convertToString(dpiAwareness) << "\" via " << funcName; + } + void onDirectDrawCreate(GUID* lpGUID, LPDIRECTDRAW* lplpDD, IUnknown* /*pUnkOuter*/) { return DDraw::DirectDraw::onCreate(lpGUID, *CompatPtr::from(*lplpDD)); @@ -148,17 +154,67 @@ namespace void setDpiAwareness() { - HMODULE shcore = LoadLibrary("shcore"); - if (shcore) + auto dpiAwareness = Config::dpiAwareness.get(); + if (!dpiAwareness) { - auto setProcessDpiAwareness = reinterpret_cast( - Compat::getProcAddress(shcore, "SetProcessDpiAwareness")); - if (setProcessDpiAwareness && SUCCEEDED(setProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE))) - { - return; - } + return; } - SetProcessDPIAware(); + + HMODULE user32 = LoadLibrary("user32"); + auto isValidDpiAwarenessContext = reinterpret_cast( + Compat::getProcAddress(user32, "IsValidDpiAwarenessContext")); + auto setProcessDpiAwarenessContext = reinterpret_cast( + Compat::getProcAddress(user32, "SetProcessDpiAwarenessContext")); + if (isValidDpiAwarenessContext && setProcessDpiAwarenessContext) + { + if (DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 == dpiAwareness && + !isValidDpiAwarenessContext(dpiAwareness)) + { + dpiAwareness = DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE; + } + + if (DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED == dpiAwareness && + !isValidDpiAwarenessContext(dpiAwareness)) + { + dpiAwareness = DPI_AWARENESS_CONTEXT_UNAWARE; + } + + logDpiAwareness(setProcessDpiAwarenessContext(dpiAwareness), dpiAwareness, "SetProcessDpiAwarenessContext"); + return; + } + + auto setProcessDpiAwareness = reinterpret_cast( + Compat::getProcAddress(LoadLibrary("shcore"), "SetProcessDpiAwareness")); + if (setProcessDpiAwareness) + { + HRESULT result = S_OK; + if (DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE == dpiAwareness || + DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 == dpiAwareness) + { + dpiAwareness = DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE; + result = setProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE); + } + else if (DPI_AWARENESS_CONTEXT_SYSTEM_AWARE == dpiAwareness) + { + result = setProcessDpiAwareness(PROCESS_SYSTEM_DPI_AWARE); + } + else + { + dpiAwareness = DPI_AWARENESS_CONTEXT_UNAWARE; + result = setProcessDpiAwareness(PROCESS_DPI_UNAWARE); + } + + logDpiAwareness(SUCCEEDED(result), dpiAwareness, "SetProcessDpiAwareness"); + return; + } + + if (DPI_AWARENESS_CONTEXT_UNAWARE == dpiAwareness || + DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED == dpiAwareness) + { + LOG_INFO << "DPI awareness was not changed"; + } + + logDpiAwareness(SetProcessDPIAware(), DPI_AWARENESS_CONTEXT_SYSTEM_AWARE, "SetProcessDPIAware"); } } diff --git a/DDrawCompat/Gdi/VirtualScreen.cpp b/DDrawCompat/Gdi/VirtualScreen.cpp index 0916005..1f5ca5b 100644 --- a/DDrawCompat/Gdi/VirtualScreen.cpp +++ b/DDrawCompat/Gdi/VirtualScreen.cpp @@ -38,10 +38,25 @@ namespace std::map g_dcs; BOOL CALLBACK addMonitorRectToRegion( - HMONITOR /*hMonitor*/, HDC /*hdcMonitor*/, LPRECT lprcMonitor, LPARAM dwData) + HMONITOR hMonitor, HDC /*hdcMonitor*/, LPRECT lprcMonitor, LPARAM dwData) { + MONITORINFOEX mi = {}; + mi.cbSize = sizeof(mi); + CALL_ORIG_FUNC(GetMonitorInfoA)(hMonitor, &mi); + + DEVMODE dm = {}; + dm.dmSize = sizeof(dm); + CALL_ORIG_FUNC(EnumDisplaySettingsExA)(mi.szDevice, ENUM_CURRENT_SETTINGS, &dm, 0); + + RECT rect = *lprcMonitor; + if (0 != dm.dmPelsWidth && 0 != dm.dmPelsHeight) + { + rect.right = rect.left + dm.dmPelsWidth; + rect.bottom = rect.top + dm.dmPelsHeight; + } + Gdi::Region& virtualScreenRegion = *reinterpret_cast(dwData); - Gdi::Region monitorRegion(*lprcMonitor); + Gdi::Region monitorRegion(rect); virtualScreenRegion |= monitorRegion; return TRUE; }