mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Added SupportedResolutions setting
This commit is contained in:
parent
ee350c7f08
commit
ffc8e04a35
@ -5,5 +5,6 @@ namespace Config
|
||||
Settings::CpuAffinity cpuAffinity;
|
||||
Settings::DesktopColorDepth desktopColorDepth;
|
||||
Settings::DisplayResolution displayResolution;
|
||||
Settings::SupportedResolutions supportedResolutions;
|
||||
Settings::ThreadPriorityBoost threadPriorityBoost;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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))
|
||||
{
|
||||
}
|
||||
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
@ -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} })
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -5,7 +5,7 @@ namespace Config
|
||||
namespace Settings
|
||||
{
|
||||
DisplayResolution::DisplayResolution()
|
||||
: MappedSetting("DisplayResolution", DESKTOP, { {"app", APP}, {"desktop", DESKTOP} })
|
||||
: MappedSetting("DisplayResolution", "desktop", { {"app", APP}, {"desktop", DESKTOP} })
|
||||
{
|
||||
}
|
||||
|
||||
|
37
DDrawCompat/Config/Settings/SupportedResolutions.cpp
Normal file
37
DDrawCompat/Config/Settings/SupportedResolutions.cpp
Normal 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 };
|
||||
}
|
||||
}
|
29
DDrawCompat/Config/Settings/SupportedResolutions.h
Normal file
29
DDrawCompat/Config/Settings/SupportedResolutions.h
Normal 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;
|
||||
};
|
||||
}
|
||||
}
|
@ -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" })
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -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" />
|
||||
|
@ -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">
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user