1
0
mirror of https://github.com/narzoul/DDrawCompat synced 2024-12-30 08:55:36 +01:00

Added SupportedResolutions setting

This commit is contained in:
narzoul 2021-06-30 23:42:27 +02:00
parent ee350c7f08
commit ffc8e04a35
17 changed files with 263 additions and 124 deletions

View File

@ -5,5 +5,6 @@ namespace Config
Settings::CpuAffinity cpuAffinity;
Settings::DesktopColorDepth desktopColorDepth;
Settings::DisplayResolution displayResolution;
Settings::SupportedResolutions supportedResolutions;
Settings::ThreadPriorityBoost threadPriorityBoost;
}

View File

@ -3,6 +3,7 @@
#include <Config/Settings/CpuAffinity.h>
#include <Config/Settings/DesktopColorDepth.h>
#include <Config/Settings/DisplayResolution.h>
#include <Config/Settings/SupportedResolutions.h>
#include <Config/Settings/ThreadPriorityBoost.h>
namespace Config
@ -14,5 +15,6 @@ namespace Config
extern Settings::CpuAffinity cpuAffinity;
extern Settings::DesktopColorDepth desktopColorDepth;
extern Settings::DisplayResolution displayResolution;
extern Settings::SupportedResolutions supportedResolutions;
extern Settings::ThreadPriorityBoost threadPriorityBoost;
}

View File

@ -21,7 +21,7 @@ namespace
namespace Config
{
EnumSetting::EnumSetting(const std::string& name, unsigned default, const std::vector<std::string>& enumNames)
EnumSetting::EnumSetting(const std::string& name, const std::string& default, const std::vector<std::string>& enumNames)
: MappedSetting(name, default, createMapping(enumNames))
{
}

View File

@ -9,6 +9,6 @@ namespace Config
class EnumSetting : public MappedSetting<unsigned>
{
protected:
EnumSetting(const std::string& name, unsigned default, const std::vector<std::string>& enumNames);
EnumSetting(const std::string& name, const std::string& default, const std::vector<std::string>& enumNames);
};
}

View File

@ -4,16 +4,10 @@
namespace Config
{
ListSetting::ListSetting(const std::string& name, const std::string& default)
: Setting(name)
, m_default(default)
: Setting(name, default)
{
}
void ListSetting::resetValue()
{
setValue(m_default);
}
void ListSetting::setValue(const std::string& value)
{
std::vector<std::string> values;

View File

@ -11,11 +11,7 @@ namespace Config
protected:
ListSetting(const std::string& name, const std::string& default);
void resetValue() override;
void setValue(const std::string& value) override;
virtual void setValues(const std::vector<std::string>& values) = 0;
private:
std::string m_default;
};
}

View File

@ -14,10 +14,9 @@ namespace Config
Value get() const { return m_value; }
protected:
MappedSetting(const std::string& name, Value default, const std::map<std::string, Value>& valueMapping)
: Setting(name)
, m_default(default)
, m_value(default)
MappedSetting(const std::string& name, const std::string& default, const std::map<std::string, Value>& valueMapping)
: Setting(name, default)
, m_value{}
, m_valueMapping(valueMapping)
{
}
@ -34,11 +33,6 @@ namespace Config
throw ParsingError("MappedSetting::getValueStr(): value not found in mapping");
}
void resetValue() override
{
m_value = m_default;
}
void setValue(const std::string& value) override
{
auto it = m_valueMapping.find(value);
@ -49,7 +43,6 @@ namespace Config
m_value = it->second;
}
Value m_default;
Value m_value;
const std::map<std::string, Value> m_valueMapping;
};

View File

@ -3,28 +3,21 @@
namespace Config
{
Setting::Setting(const std::string& name)
Setting::Setting(const std::string& name, const std::string& default)
: m_name(name)
, m_default(default)
{
Parser::registerSetting(*this);
}
void Setting::reset()
{
resetValue();
m_source = "default";
set("default", "default");
}
void Setting::set(const std::string& value, const std::string& source)
{
if ("default" == value)
{
resetValue();
}
else
{
setValue(value);
}
setValue("default" == value ? m_default : value);
m_source = source;
}
}

View File

@ -7,7 +7,7 @@ namespace Config
class Setting
{
public:
Setting(const std::string& name);
Setting(const std::string& name, const std::string& default);
Setting(const Setting&) = delete;
Setting(Setting&&) = delete;
@ -23,11 +23,11 @@ namespace Config
protected:
virtual std::string getValueStr() const = 0;
virtual void resetValue() = 0;
virtual void setValue(const std::string& value) = 0;
private:
std::string m_name;
std::string m_default;
std::string m_source;
};
}

View File

@ -12,7 +12,7 @@ namespace Config
static const UINT INITIAL = 0;
DesktopColorDepth()
: MappedSetting("DesktopColorDepth", INITIAL, { {"initial", INITIAL}, {"8", 8}, {"16", 16}, {"32", 32} })
: MappedSetting("DesktopColorDepth", "initial", { {"initial", INITIAL}, {"8", 8}, {"16", 16}, {"32", 32} })
{
}
};

View File

@ -5,7 +5,7 @@ namespace Config
namespace Settings
{
DisplayResolution::DisplayResolution()
: MappedSetting("DisplayResolution", DESKTOP, { {"app", APP}, {"desktop", DESKTOP} })
: MappedSetting("DisplayResolution", "desktop", { {"app", APP}, {"desktop", DESKTOP} })
{
}

View File

@ -0,0 +1,37 @@
#include <Common/Comparison.h>
#include <Config/Parser.h>
#include <Config/Settings/SupportedResolutions.h>
namespace Config
{
namespace Settings
{
SupportedResolutions::SupportedResolutions()
: ListSetting("SupportedResolutions", "native, 640x480, 800x600, 1024x768")
{
}
std::string SupportedResolutions::getValueStr() const
{
std::string result;
for (const auto& res : m_resolutions)
{
result += ", ";
result += NATIVE == res ? "native" : std::to_string(res.cx) + 'x' + std::to_string(res.cy);
}
return result.substr(2);
}
void SupportedResolutions::setValues(const std::vector<std::string>& values)
{
std::set<SIZE> result;
for (const auto& v : values)
{
result.insert("native" == v ? NATIVE : Parser::parseResolution(v));
}
m_resolutions = result;
}
const SIZE SupportedResolutions::NATIVE = { 0, 0 };
}
}

View File

@ -0,0 +1,29 @@
#pragma once
#include <set>
#include <Windows.h>
#include <Config/ListSetting.h>
namespace Config
{
namespace Settings
{
class SupportedResolutions : public ListSetting
{
public:
static const SIZE NATIVE;
SupportedResolutions();
std::set<SIZE> get() const { return m_resolutions; }
private:
std::string getValueStr() const override;
void setValues(const std::vector<std::string>& values) override;
std::set<SIZE> m_resolutions;
};
}
}

View File

@ -12,7 +12,7 @@ namespace Config
enum Value { OFF, ON, MAIN, APP };
ThreadPriorityBoost()
: EnumSetting("ThreadPriorityBoost", OFF, { "off", "on", "main", "app" })
: EnumSetting("ThreadPriorityBoost", "off", { "off", "on", "main", "app" })
{
}
};

View File

@ -216,6 +216,7 @@
<ClInclude Include="Config\Settings\CpuAffinity.h" />
<ClInclude Include="Config\Settings\DesktopColorDepth.h" />
<ClInclude Include="Config\Settings\DisplayResolution.h" />
<ClInclude Include="Config\Settings\SupportedResolutions.h" />
<ClInclude Include="Config\Settings\ThreadPriorityBoost.h" />
<ClInclude Include="D3dDdi\Adapter.h" />
<ClInclude Include="D3dDdi\AdapterCallbacks.h" />
@ -320,6 +321,7 @@
<ClCompile Include="Config\Setting.cpp" />
<ClCompile Include="Config\Settings\CpuAffinity.cpp" />
<ClCompile Include="Config\Settings\DisplayResolution.cpp" />
<ClCompile Include="Config\Settings\SupportedResolutions.cpp" />
<ClCompile Include="D3dDdi\Adapter.cpp" />
<ClCompile Include="D3dDdi\AdapterCallbacks.cpp" />
<ClCompile Include="D3dDdi\AdapterFuncs.cpp" />

View File

@ -441,6 +441,9 @@
<ClInclude Include="Config\Settings\DesktopColorDepth.h">
<Filter>Header Files\Config\Settings</Filter>
</ClInclude>
<ClInclude Include="Config\Settings\SupportedResolutions.h">
<Filter>Header Files\Config\Settings</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Gdi\Gdi.cpp">
@ -692,6 +695,9 @@
<ClCompile Include="Gdi\Cursor.cpp">
<Filter>Source Files\Gdi</Filter>
</ClCompile>
<ClCompile Include="Config\Settings\SupportedResolutions.cpp">
<Filter>Source Files\Config\Settings</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="DDrawCompat.rc">

View File

@ -1,3 +1,4 @@
#include <map>
#include <set>
#include <string>
#include <vector>
@ -22,6 +23,11 @@ namespace
using Win32::DisplayMode::DisplayMode;
using Win32::DisplayMode::EmulatedDisplayMode;
template <typename Char> struct DevModeType;
template <> struct DevModeType<CHAR> { typedef DEVMODEA Type; };
template <> struct DevModeType<WCHAR> { typedef DEVMODEW Type; };
template <typename Char> using DevMode = typename DevModeType<Char>::Type;
template <typename Char>
struct EnumParams
{
@ -53,8 +59,8 @@ namespace
BOOL WINAPI dwm8And16BitIsShimAppliedCallOut();
BOOL WINAPI seComHookInterface(CLSID* clsid, GUID* iid, DWORD unk1, DWORD unk2);
template <typename DevMode, typename EnumDisplaySettingsExFunc, typename Char>
SIZE getConfiguredResolution(EnumDisplaySettingsExFunc origEnumDisplaySettingsEx, const Char* deviceName);
template <typename Char>
SIZE getConfiguredResolution(const Char* deviceName);
template <typename Char>
std::wstring getDeviceName(const Char* deviceName);
@ -62,9 +68,19 @@ namespace
HMONITOR getMonitorFromDc(HDC dc);
MONITORINFO getMonitorInfo(const std::wstring& deviceName);
template <typename DevMode, typename EnumDisplaySettingsExFunc, typename Char>
std::vector<DisplayMode> getSupportedDisplayModes(
EnumDisplaySettingsExFunc origEnumDisplaySettingsEx, const Char* deviceName, DWORD flags);
template <typename Char>
std::map<SIZE, std::set<DWORD>> getSupportedDisplayModeMap(const Char* deviceName, DWORD flags);
template <typename Char>
std::vector<DisplayMode> getSupportedDisplayModes(const Char* deviceName, DWORD flags);
SIZE makeSize(DWORD width, DWORD height);
LONG origChangeDisplaySettingsEx(LPCSTR lpszDeviceName, DEVMODEA* lpDevMode, HWND hwnd, DWORD dwflags, LPVOID lParam);
LONG origChangeDisplaySettingsEx(LPCWSTR lpszDeviceName, DEVMODEW* lpDevMode, HWND hwnd, DWORD dwflags, LPVOID lParam);
BOOL origEnumDisplaySettingsEx(LPCSTR lpszDeviceName, DWORD iModeNum, DEVMODEA* lpDevMode, DWORD dwFlags);
BOOL origEnumDisplaySettingsEx(LPCWSTR lpszDeviceName, DWORD iModeNum, DEVMODEW* lpDevMode, DWORD dwFlags);
void setDwmDxFullscreenTransitionEvent();
void adjustMonitorInfo(MONITORINFO& mi)
{
@ -80,27 +96,65 @@ namespace
}
}
template <typename CStr, typename DevMode, typename ChangeDisplaySettingsExFunc, typename EnumDisplaySettingsExFunc>
LONG changeDisplaySettingsEx(
ChangeDisplaySettingsExFunc origChangeDisplaySettingsEx,
EnumDisplaySettingsExFunc origEnumDisplaySettingsEx,
CStr lpszDeviceName, DevMode* lpDevMode, HWND hwnd, DWORD dwflags, LPVOID lParam)
template <typename Char>
LONG changeDisplaySettingsEx(const Char* lpszDeviceName, typename DevMode<Char>* lpDevMode, HWND hwnd, DWORD dwflags, LPVOID lParam)
{
DDraw::ScopedThreadLock lock;
DevMode targetDevMode = {};
DevMode<Char> targetDevMode = {};
SIZE emulatedResolution = {};
if (lpDevMode)
{
DevMode<Char> currDevMode = {};
currDevMode.dmSize = sizeof(currDevMode);
enumDisplaySettingsEx(lpszDeviceName, ENUM_CURRENT_SETTINGS, &currDevMode, 0);
targetDevMode = *lpDevMode;
targetDevMode.dmFields |= DM_BITSPERPEL;
targetDevMode.dmBitsPerPel = 32;
SIZE resolutionOverride = getConfiguredResolution<DevMode>(origEnumDisplaySettingsEx, lpszDeviceName);
if (!(targetDevMode.dmFields & DM_PELSWIDTH))
{
targetDevMode.dmFields |= DM_PELSWIDTH;
targetDevMode.dmPelsWidth = currDevMode.dmPelsWidth;
}
if (!(targetDevMode.dmFields & DM_PELSHEIGHT))
{
targetDevMode.dmFields |= DM_PELSHEIGHT;
targetDevMode.dmPelsHeight = currDevMode.dmPelsHeight;
}
emulatedResolution = makeSize(targetDevMode.dmPelsWidth, targetDevMode.dmPelsHeight);
auto supportedDisplayModeMap(getSupportedDisplayModeMap(lpszDeviceName, 0));
if (supportedDisplayModeMap.find(emulatedResolution) == supportedDisplayModeMap.end())
{
if (!(dwflags & CDS_TEST))
{
setDwmDxFullscreenTransitionEvent();
}
return DISP_CHANGE_BADMODE;
}
SIZE resolutionOverride = getConfiguredResolution(lpszDeviceName);
if (0 != resolutionOverride.cx)
{
targetDevMode.dmPelsWidth = resolutionOverride.cx;
targetDevMode.dmPelsHeight = resolutionOverride.cy;
DevMode<Char> dm = {};
dm.dmSize = sizeof(dm);
dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
dm.dmPelsWidth = resolutionOverride.cx;
dm.dmPelsHeight = resolutionOverride.cy;
LONG result = origChangeDisplaySettingsEx(lpszDeviceName, &dm, nullptr, CDS_TEST, nullptr);
if (DISP_CHANGE_SUCCESSFUL == result)
{
targetDevMode.dmPelsWidth = resolutionOverride.cx;
targetDevMode.dmPelsHeight = resolutionOverride.cy;
}
else
{
LOG_ONCE("Failed to apply setting: DisplayResolution = " << dm.dmPelsWidth << 'x' << dm.dmPelsHeight);
}
}
}
DevMode prevDevMode = {};
DevMode<Char> prevDevMode = {};
if (!(dwflags & CDS_TEST))
{
prevDevMode.dmSize = sizeof(prevDevMode);
@ -111,14 +165,6 @@ namespace
if (lpDevMode)
{
result = origChangeDisplaySettingsEx(lpszDeviceName, &targetDevMode, hwnd, dwflags, lParam);
if (DISP_CHANGE_SUCCESSFUL != result &&
(lpDevMode->dmPelsWidth != targetDevMode.dmPelsWidth || lpDevMode->dmPelsHeight != targetDevMode.dmPelsHeight))
{
LOG_ONCE("Failed to apply setting: DisplayResolution = " << targetDevMode.dmPelsWidth << 'x' << targetDevMode.dmPelsHeight);
targetDevMode.dmPelsWidth = lpDevMode->dmPelsWidth;
targetDevMode.dmPelsHeight = lpDevMode->dmPelsHeight;
result = origChangeDisplaySettingsEx(lpszDeviceName, &targetDevMode, hwnd, dwflags, lParam);
}
}
else
{
@ -130,16 +176,13 @@ namespace
return result;
}
DevMode currDevMode = {};
DevMode<Char> currDevMode = {};
currDevMode.dmSize = sizeof(currDevMode);
origEnumDisplaySettingsEx(lpszDeviceName, ENUM_CURRENT_SETTINGS, &currDevMode, 0);
if (0 == memcmp(&currDevMode, &prevDevMode, sizeof(currDevMode)))
{
HANDLE dwmDxFullScreenTransitionEvent = OpenEventW(
EVENT_MODIFY_STATE, FALSE, L"DWM_DX_FULLSCREEN_TRANSITION_EVENT");
SetEvent(dwmDxFullScreenTransitionEvent);
CloseHandle(dwmDxFullScreenTransitionEvent);
setDwmDxFullscreenTransitionEvent();
}
if (DISP_CHANGE_SUCCESSFUL != result)
@ -152,9 +195,12 @@ namespace
++g_displaySettingsUniquenessBias;
if (lpDevMode)
{
g_emulatedDisplayMode.width = lpDevMode->dmPelsWidth;
g_emulatedDisplayMode.height = lpDevMode->dmPelsHeight;
g_emulatedDisplayMode.bpp = lpDevMode->dmBitsPerPel;
g_emulatedDisplayMode.width = emulatedResolution.cx;
g_emulatedDisplayMode.height = emulatedResolution.cy;
if (lpDevMode->dmFields & DM_BITSPERPEL)
{
g_emulatedDisplayMode.bpp = lpDevMode->dmBitsPerPel;
}
g_emulatedDisplayMode.refreshRate = currDevMode.dmDisplayFrequency;
g_emulatedDisplayMode.deviceName = getDeviceName(lpszDeviceName);
@ -171,11 +217,10 @@ namespace
}
}
auto& dm = lpDevMode ? *lpDevMode : currDevMode;
LPARAM resolution = (dm.dmPelsHeight << 16) | dm.dmPelsWidth;
EnumWindows(sendDisplayChange, resolution);
SIZE res = lpDevMode ? emulatedResolution : makeSize(currDevMode.dmPelsWidth, currDevMode.dmPelsHeight);
EnumWindows(sendDisplayChange, (res.cy << 16) | res.cx);
SetCursorPos(currDevMode.dmPosition.x + dm.dmPelsWidth / 2, currDevMode.dmPosition.y + dm.dmPelsHeight / 2);
SetCursorPos(currDevMode.dmPosition.x + res.cx / 2, currDevMode.dmPosition.y + res.cy / 2);
Gdi::VirtualScreen::update();
return result;
@ -185,20 +230,14 @@ namespace
LPCSTR lpszDeviceName, DEVMODEA* lpDevMode, HWND hwnd, DWORD dwflags, LPVOID lParam)
{
LOG_FUNC("ChangeDisplaySettingsExA", lpszDeviceName, lpDevMode, hwnd, dwflags, lParam);
return LOG_RESULT(changeDisplaySettingsEx(
CALL_ORIG_FUNC(ChangeDisplaySettingsExA),
CALL_ORIG_FUNC(EnumDisplaySettingsExA),
lpszDeviceName, lpDevMode, hwnd, dwflags, lParam));
return LOG_RESULT(changeDisplaySettingsEx(lpszDeviceName, lpDevMode, hwnd, dwflags, lParam));
}
LONG WINAPI changeDisplaySettingsExW(
LPCWSTR lpszDeviceName, DEVMODEW* lpDevMode, HWND hwnd, DWORD dwflags, LPVOID lParam)
{
LOG_FUNC("ChangeDisplaySettingsExW", lpszDeviceName, lpDevMode, hwnd, dwflags, lParam);
return LOG_RESULT(changeDisplaySettingsEx(
CALL_ORIG_FUNC(ChangeDisplaySettingsExW),
CALL_ORIG_FUNC(EnumDisplaySettingsExW),
lpszDeviceName, lpDevMode, hwnd, dwflags, lParam));
return LOG_RESULT(changeDisplaySettingsEx(lpszDeviceName, lpDevMode, hwnd, dwflags, lParam));
}
void disableDwm8And16BitMitigation()
@ -223,9 +262,8 @@ namespace
return LOG_RESULT(FALSE);
}
template <typename Char, typename DevMode, typename EnumDisplaySettingsExFunc>
BOOL enumDisplaySettingsEx(EnumDisplaySettingsExFunc origEnumDisplaySettingsEx,
const Char* lpszDeviceName, DWORD iModeNum, DevMode* lpDevMode, DWORD dwFlags)
template <typename Char>
BOOL enumDisplaySettingsEx(const Char* lpszDeviceName, DWORD iModeNum, DevMode<Char>* lpDevMode, DWORD dwFlags)
{
if (ENUM_REGISTRY_SETTINGS == iModeNum || !lpDevMode)
{
@ -259,7 +297,7 @@ namespace
if (0 == iModeNum || displayModes.empty() || currentEnumParams != lastEnumParams)
{
displayModes = getSupportedDisplayModes<DevMode>(origEnumDisplaySettingsEx, lpszDeviceName, dwFlags);
displayModes = getSupportedDisplayModes(lpszDeviceName, dwFlags);
lastEnumParams = currentEnumParams;
}
@ -291,16 +329,14 @@ namespace
LPCSTR lpszDeviceName, DWORD iModeNum, DEVMODEA* lpDevMode, DWORD dwFlags)
{
LOG_FUNC("EnumDisplaySettingsExA", lpszDeviceName, iModeNum, lpDevMode, dwFlags);
return LOG_RESULT(enumDisplaySettingsEx(CALL_ORIG_FUNC(EnumDisplaySettingsExA),
lpszDeviceName, iModeNum, lpDevMode, dwFlags));
return LOG_RESULT(enumDisplaySettingsEx(lpszDeviceName, iModeNum, lpDevMode, dwFlags));
}
BOOL WINAPI enumDisplaySettingsExW(
LPCWSTR lpszDeviceName, DWORD iModeNum, DEVMODEW* lpDevMode, DWORD dwFlags)
{
LOG_FUNC("EnumDisplaySettingsExW", lpszDeviceName, iModeNum, lpDevMode, dwFlags);
return LOG_RESULT(enumDisplaySettingsEx(CALL_ORIG_FUNC(EnumDisplaySettingsExW),
lpszDeviceName, iModeNum, lpDevMode, dwFlags));
return LOG_RESULT(enumDisplaySettingsEx(lpszDeviceName, iModeNum, lpDevMode, dwFlags));
}
ULONG WINAPI gdiEntry13()
@ -309,13 +345,13 @@ namespace
return CALL_ORIG_FUNC(GdiEntry13)() + g_displaySettingsUniquenessBias;
}
template <typename DevMode, typename EnumDisplaySettingsExFunc, typename Char>
SIZE getConfiguredResolution(EnumDisplaySettingsExFunc origEnumDisplaySettingsEx, const Char* deviceName)
template <typename Char>
SIZE getConfiguredResolution(const Char* deviceName)
{
auto resolution = Config::displayResolution.get();
if (Config::Settings::DisplayResolution::DESKTOP == resolution)
{
DevMode dm = {};
DevMode<Char> dm = {};
dm.dmSize = sizeof(dm);
if (origEnumDisplaySettingsEx(deviceName, ENUM_REGISTRY_SETTINGS, &dm, 0))
{
@ -497,61 +533,75 @@ namespace
return LOG_RESULT(result);
}
template <typename DevMode, typename EnumDisplaySettingsExFunc, typename Char>
std::vector<DisplayMode> getSupportedDisplayModes(
EnumDisplaySettingsExFunc origEnumDisplaySettingsEx, const Char* deviceName, DWORD flags)
template <typename Char>
std::map<SIZE, std::set<DWORD>> getSupportedDisplayModeMap(const Char* deviceName, DWORD flags)
{
std::set<DisplayMode> displayModes;
DWORD modeNum = 0;
DevMode dm = {};
dm.dmSize = sizeof(dm);
std::map<SIZE, std::set<DWORD>> nativeDisplayModeMap;
DWORD modeNum = 0;
DevMode<Char> dm = {};
dm.dmSize = sizeof(dm);
while (origEnumDisplaySettingsEx(deviceName, modeNum, &dm, flags))
{
if (32 == dm.dmBitsPerPel)
{
displayModes.insert({ dm.dmPelsWidth, dm.dmPelsHeight, dm.dmBitsPerPel, dm.dmDisplayFrequency });
nativeDisplayModeMap[makeSize(dm.dmPelsWidth, dm.dmPelsHeight)].insert(dm.dmDisplayFrequency);
}
++modeNum;
}
auto resolutionOverride = getConfiguredResolution<DevMode>(origEnumDisplaySettingsEx, deviceName);
if (0 == resolutionOverride.cx)
const auto& supportedResolutions = Config::supportedResolutions.get();
std::map<SIZE, std::set<DWORD>> displayModeMap;
if (supportedResolutions.find(Config::Settings::SupportedResolutions::NATIVE) != supportedResolutions.end())
{
return { displayModes.begin(), displayModes.end() };
displayModeMap = nativeDisplayModeMap;
}
std::set<DWORD> supportedRefreshRates;
for (const auto& mode : displayModes)
const auto resolutionOverride = getConfiguredResolution(deviceName);
const auto it = nativeDisplayModeMap.find({ resolutionOverride.cx, resolutionOverride.cy });
if (it != nativeDisplayModeMap.end())
{
if (static_cast<LONG>(mode.width) == resolutionOverride.cx &&
static_cast<LONG>(mode.height) == resolutionOverride.cy)
for (auto& v : displayModeMap)
{
supportedRefreshRates.insert(mode.refreshRate);
v.second = it->second;
}
}
if (supportedRefreshRates.empty())
for (auto& v : supportedResolutions)
{
return { displayModes.begin(), displayModes.end() };
}
std::vector<DisplayMode> customDisplayModes;
DWORD prevWidth = 0;
DWORD prevHeight = 0;
for (const auto& mode : displayModes)
{
if (mode.width != prevWidth || mode.height != prevHeight)
if (v != Config::Settings::SupportedResolutions::NATIVE)
{
for (auto refreshRate : supportedRefreshRates)
if (it != nativeDisplayModeMap.end())
{
customDisplayModes.push_back({ mode.width, mode.height, mode.bpp, refreshRate });
displayModeMap[{ v.cx, v.cy }] = it->second;
}
else
{
auto iter = nativeDisplayModeMap.find({ v.cx, v.cy });
if (iter != nativeDisplayModeMap.end())
{
displayModeMap.insert(*iter);
}
}
prevWidth = mode.width;
prevHeight = mode.height;
}
}
return customDisplayModes;
return displayModeMap;
}
template <typename Char>
std::vector<DisplayMode> getSupportedDisplayModes(const Char* deviceName, DWORD flags)
{
auto displayModeMap(getSupportedDisplayModeMap(deviceName, flags));
std::vector<DisplayMode> displayModeVector;
for (const auto& v : displayModeMap)
{
for (const auto& r : v.second)
{
displayModeVector.push_back({ static_cast<DWORD>(v.first.cx), static_cast<DWORD>(v.first.cy), 32, r });
}
}
return displayModeVector;
}
BOOL CALLBACK initMonitor(HMONITOR hMonitor, HDC /*hdcMonitor*/, LPRECT /*lprcMonitor*/, LPARAM /*dwData*/)
@ -577,6 +627,31 @@ namespace
return TRUE;
}
SIZE makeSize(DWORD width, DWORD height)
{
return { static_cast<LONG>(width), static_cast<LONG>(height) };
}
LONG origChangeDisplaySettingsEx(LPCSTR lpszDeviceName, DEVMODEA* lpDevMode, HWND hwnd, DWORD dwflags, LPVOID lParam)
{
return CALL_ORIG_FUNC(ChangeDisplaySettingsExA)(lpszDeviceName, lpDevMode, hwnd, dwflags, lParam);
}
LONG origChangeDisplaySettingsEx(LPCWSTR lpszDeviceName, DEVMODEW* lpDevMode, HWND hwnd, DWORD dwflags, LPVOID lParam)
{
return CALL_ORIG_FUNC(ChangeDisplaySettingsExW)(lpszDeviceName, lpDevMode, hwnd, dwflags, lParam);
}
BOOL origEnumDisplaySettingsEx(LPCSTR lpszDeviceName, DWORD iModeNum, DEVMODEA* lpDevMode, DWORD dwFlags)
{
return CALL_ORIG_FUNC(EnumDisplaySettingsExA)(lpszDeviceName, iModeNum, lpDevMode, dwFlags);
}
BOOL origEnumDisplaySettingsEx(LPCWSTR lpszDeviceName, DWORD iModeNum, DEVMODEW* lpDevMode, DWORD dwFlags)
{
return CALL_ORIG_FUNC(EnumDisplaySettingsExW)(lpszDeviceName, iModeNum, lpDevMode, dwFlags);
}
BOOL WINAPI seComHookInterface(CLSID* clsid, GUID* iid, DWORD unk1, DWORD unk2)
{
LOG_FUNC("SE_COM_HookInterface", clsid, iid, unk1, unk2);
@ -597,6 +672,17 @@ namespace
}
return TRUE;
}
void setDwmDxFullscreenTransitionEvent()
{
HANDLE dwmDxFullscreenTransitionEvent = OpenEventW(
EVENT_MODIFY_STATE, FALSE, L"DWM_DX_FULLSCREEN_TRANSITION_EVENT");
if (dwmDxFullscreenTransitionEvent)
{
SetEvent(dwmDxFullscreenTransitionEvent);
CloseHandle(dwmDxFullscreenTransitionEvent);
}
}
}
namespace Win32