mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-08-22 07:01:30 +00:00
[idd] config: retain four-decimal refresh rates
This commit is contained in:
@@ -51,7 +51,7 @@ struct LGPipeMsg
|
|||||||
enum : uint32_t
|
enum : uint32_t
|
||||||
{
|
{
|
||||||
RECOVERY_ACTIVE = 0x1U,
|
RECOVERY_ACTIVE = 0x1U,
|
||||||
PROTOCOL_VERSION = 2U
|
PROTOCOL_VERSION = 3U
|
||||||
};
|
};
|
||||||
|
|
||||||
union
|
union
|
||||||
@@ -67,7 +67,7 @@ struct LGPipeMsg
|
|||||||
{
|
{
|
||||||
uint32_t width;
|
uint32_t width;
|
||||||
uint32_t height;
|
uint32_t height;
|
||||||
uint32_t refreshMilliHz;
|
uint32_t refresh100uHz;
|
||||||
}
|
}
|
||||||
displayMode;
|
displayMode;
|
||||||
|
|
||||||
|
|||||||
@@ -50,14 +50,14 @@ static bool ToUnsigned(const std::wstring& text, unsigned& value)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LGParseRefreshRate(const std::wstring& text, unsigned& refreshMilliHz)
|
bool LGParseRefreshRate(const std::wstring& text, unsigned& refresh100uHz)
|
||||||
{
|
{
|
||||||
const std::wstring value = Trim(text);
|
const std::wstring value = Trim(text);
|
||||||
const size_t decimal = value.find(L'.');
|
const size_t decimal = value.find(L'.');
|
||||||
if (value.empty() ||
|
if (value.empty() ||
|
||||||
(decimal != std::wstring::npos &&
|
(decimal != std::wstring::npos &&
|
||||||
(value.find(L'.', decimal + 1) != std::wstring::npos ||
|
(value.find(L'.', decimal + 1) != std::wstring::npos ||
|
||||||
decimal == 0 || decimal + 4 < value.size())))
|
decimal == 0 || decimal + 5 < value.size())))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const std::wstring wholeText = value.substr(0, decimal);
|
const std::wstring wholeText = value.substr(0, decimal);
|
||||||
@@ -71,30 +71,34 @@ bool LGParseRefreshRate(const std::wstring& text, unsigned& refreshMilliHz)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (fractionText.size() == 1)
|
if (fractionText.size() == 1)
|
||||||
fraction *= 100;
|
fraction *= 1000;
|
||||||
else if (fractionText.size() == 2)
|
else if (fractionText.size() == 2)
|
||||||
|
fraction *= 100;
|
||||||
|
else if (fractionText.size() == 3)
|
||||||
fraction *= 10;
|
fraction *= 10;
|
||||||
|
|
||||||
const unsigned long long valueMilliHz =
|
const unsigned long long value100uHz =
|
||||||
(unsigned long long)whole * 1000 + fraction;
|
(unsigned long long)whole * LG_REFRESH_RATE_SCALE + fraction;
|
||||||
if (valueMilliHz < 23900 || valueMilliHz > 1000000)
|
if (value100uHz < 239000 || value100uHz > 10000000)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
refreshMilliHz = (unsigned)valueMilliHz;
|
refresh100uHz = (unsigned)value100uHz;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::wstring LGFormatRefreshRate(unsigned refreshMilliHz)
|
std::wstring LGFormatRefreshRate(unsigned refresh100uHz)
|
||||||
{
|
{
|
||||||
std::wstring result = std::to_wstring(refreshMilliHz / 1000);
|
std::wstring result = std::to_wstring(
|
||||||
const unsigned fraction = refreshMilliHz % 1000;
|
refresh100uHz / LG_REFRESH_RATE_SCALE);
|
||||||
|
const unsigned fraction = refresh100uHz % LG_REFRESH_RATE_SCALE;
|
||||||
if (!fraction)
|
if (!fraction)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
const wchar_t text[] =
|
const wchar_t text[] =
|
||||||
{
|
{
|
||||||
L'.',
|
L'.',
|
||||||
(wchar_t)(L'0' + fraction / 100),
|
(wchar_t)(L'0' + fraction / 1000),
|
||||||
|
(wchar_t)(L'0' + fraction / 100 % 10),
|
||||||
(wchar_t)(L'0' + fraction / 10 % 10),
|
(wchar_t)(L'0' + fraction / 10 % 10),
|
||||||
(wchar_t)(L'0' + fraction % 10),
|
(wchar_t)(L'0' + fraction % 10),
|
||||||
L'\0'
|
L'\0'
|
||||||
|
|||||||
@@ -22,5 +22,8 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
bool LGParseRefreshRate(const std::wstring& text, unsigned& refreshMilliHz);
|
// Refresh rates are represented in 100 microhertz units.
|
||||||
std::wstring LGFormatRefreshRate(unsigned refreshMilliHz);
|
static constexpr unsigned LG_REFRESH_RATE_SCALE = 10000;
|
||||||
|
|
||||||
|
bool LGParseRefreshRate(const std::wstring& text, unsigned& refresh100uHz);
|
||||||
|
std::wstring LGFormatRefreshRate(unsigned refresh100uHz);
|
||||||
|
|||||||
@@ -33,14 +33,14 @@ CSettings::CSettings()
|
|||||||
|
|
||||||
CSettings::DisplayModes CSettings::LoadModes()
|
CSettings::DisplayModes CSettings::LoadModes()
|
||||||
{
|
{
|
||||||
const unsigned defaultRefreshMilliHz = GetDefaultRefreshMilliHz();
|
const unsigned defaultRefresh100uHz = GetDefaultRefresh100uHz();
|
||||||
DisplayModes displayModes;
|
DisplayModes displayModes;
|
||||||
|
|
||||||
bool hasPreferred = false;
|
bool hasPreferred = false;
|
||||||
DisplayMode m;
|
DisplayMode m;
|
||||||
if (GetExtraMode(m))
|
if (GetExtraMode(m))
|
||||||
{
|
{
|
||||||
const std::wstring refresh = LGFormatRefreshRate(m.refreshMilliHz);
|
const std::wstring refresh = LGFormatRefreshRate(m.refresh100uHz);
|
||||||
DEBUG_INFO("ExtraMode: %ux%u@%ls%s", m.width, m.height,
|
DEBUG_INFO("ExtraMode: %ux%u@%ls%s", m.width, m.height,
|
||||||
refresh.c_str(), m.preferred ? "*" : "");
|
refresh.c_str(), m.preferred ? "*" : "");
|
||||||
displayModes.push_back(m);
|
displayModes.push_back(m);
|
||||||
@@ -57,7 +57,7 @@ CSettings::DisplayModes CSettings::LoadModes()
|
|||||||
{
|
{
|
||||||
m.width = DefaultDisplayModes[i][0];
|
m.width = DefaultDisplayModes[i][0];
|
||||||
m.height = DefaultDisplayModes[i][1];
|
m.height = DefaultDisplayModes[i][1];
|
||||||
m.refreshMilliHz = defaultRefreshMilliHz;
|
m.refresh100uHz = defaultRefresh100uHz;
|
||||||
m.preferred = !hasPreferred &&
|
m.preferred = !hasPreferred &&
|
||||||
(i == DefaultPreferredDisplayMode);
|
(i == DefaultPreferredDisplayMode);
|
||||||
m.extraMode = false;
|
m.extraMode = false;
|
||||||
@@ -96,7 +96,7 @@ TransportInstances CSettings::LoadTransportInstances() const
|
|||||||
bool CSettings::SetExtraMode(const DisplayMode& mode)
|
bool CSettings::SetExtraMode(const DisplayMode& mode)
|
||||||
{
|
{
|
||||||
WCHAR buf[64];
|
WCHAR buf[64];
|
||||||
const std::wstring refresh = LGFormatRefreshRate(mode.refreshMilliHz);
|
const std::wstring refresh = LGFormatRefreshRate(mode.refresh100uHz);
|
||||||
_snwprintf_s(buf, _countof(buf), _TRUNCATE, L"%ux%u@%ls%s",
|
_snwprintf_s(buf, _countof(buf), _TRUNCATE, L"%ux%u@%ls%s",
|
||||||
mode.width, mode.height, refresh.c_str(),
|
mode.width, mode.height, refresh.c_str(),
|
||||||
mode.preferred ? L"*" : L"");
|
mode.preferred ? L"*" : L"");
|
||||||
@@ -199,13 +199,13 @@ bool CSettings::GetExtraMode(DisplayMode& mode)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned CSettings::GetDefaultRefreshMilliHz() const
|
unsigned CSettings::GetDefaultRefresh100uHz() const
|
||||||
{
|
{
|
||||||
HKEY hKey = nullptr;
|
HKEY hKey = nullptr;
|
||||||
LONG status = RegOpenKeyExW(
|
LONG status = RegOpenKeyExW(
|
||||||
HKEY_LOCAL_MACHINE, RegistryKey(), 0, KEY_QUERY_VALUE, &hKey);
|
HKEY_LOCAL_MACHINE, RegistryKey(), 0, KEY_QUERY_VALUE, &hKey);
|
||||||
if (status != ERROR_SUCCESS)
|
if (status != ERROR_SUCCESS)
|
||||||
return 60000;
|
return 60 * LG_REFRESH_RATE_SCALE;
|
||||||
|
|
||||||
DWORD type = 0;
|
DWORD type = 0;
|
||||||
DWORD size = 0;
|
DWORD size = 0;
|
||||||
@@ -214,17 +214,17 @@ unsigned CSettings::GetDefaultRefreshMilliHz() const
|
|||||||
if (status != ERROR_SUCCESS)
|
if (status != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
RegCloseKey(hKey);
|
RegCloseKey(hKey);
|
||||||
return 60000;
|
return 60 * LG_REFRESH_RATE_SCALE;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned refreshMilliHz = 0;
|
unsigned refresh100uHz = 0;
|
||||||
if (type == REG_DWORD && size == sizeof(DWORD))
|
if (type == REG_DWORD && size == sizeof(DWORD))
|
||||||
{
|
{
|
||||||
DWORD refresh = 0;
|
DWORD refresh = 0;
|
||||||
status = RegQueryValueExW(hKey, L"DefaultRefresh", nullptr, &type,
|
status = RegQueryValueExW(hKey, L"DefaultRefresh", nullptr, &type,
|
||||||
(LPBYTE)&refresh, &size);
|
(LPBYTE)&refresh, &size);
|
||||||
if (status == ERROR_SUCCESS && refresh >= 24 && refresh <= 1000)
|
if (status == ERROR_SUCCESS && refresh >= 24 && refresh <= 1000)
|
||||||
refreshMilliHz = refresh * 1000;
|
refresh100uHz = refresh * LG_REFRESH_RATE_SCALE;
|
||||||
}
|
}
|
||||||
else if ((type == REG_SZ || type == REG_EXPAND_SZ) && size &&
|
else if ((type == REG_SZ || type == REG_EXPAND_SZ) && size &&
|
||||||
size % sizeof(wchar_t) == 0)
|
size % sizeof(wchar_t) == 0)
|
||||||
@@ -233,11 +233,11 @@ unsigned CSettings::GetDefaultRefreshMilliHz() const
|
|||||||
status = RegQueryValueExW(hKey, L"DefaultRefresh", nullptr, &type,
|
status = RegQueryValueExW(hKey, L"DefaultRefresh", nullptr, &type,
|
||||||
(LPBYTE)value.data(), &size);
|
(LPBYTE)value.data(), &size);
|
||||||
if (status == ERROR_SUCCESS)
|
if (status == ERROR_SUCCESS)
|
||||||
LGParseRefreshRate(value.data(), refreshMilliHz);
|
LGParseRefreshRate(value.data(), refresh100uHz);
|
||||||
}
|
}
|
||||||
|
|
||||||
RegCloseKey(hKey);
|
RegCloseKey(hKey);
|
||||||
return refreshMilliHz ? refreshMilliHz : 60000;
|
return refresh100uHz ? refresh100uHz : 60 * LG_REFRESH_RATE_SCALE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CSettings::ReadMultiStringValue(const wchar_t * name,
|
bool CSettings::ReadMultiStringValue(const wchar_t * name,
|
||||||
@@ -331,7 +331,7 @@ bool CSettings::ParseModeString(const std::wstring& in, DisplayMode& out)
|
|||||||
|
|
||||||
if (!toUnsigned(s.substr(0, xPos), out.width) ||
|
if (!toUnsigned(s.substr(0, xPos), out.width) ||
|
||||||
!toUnsigned(s.substr(xPos + 1, atPos - (xPos + 1)), out.height) ||
|
!toUnsigned(s.substr(xPos + 1, atPos - (xPos + 1)), out.height) ||
|
||||||
!LGParseRefreshRate(s.substr(atPos + 1), out.refreshMilliHz))
|
!LGParseRefreshRate(s.substr(atPos + 1), out.refresh100uHz))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// sanity check
|
// sanity check
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ class CSettings
|
|||||||
{
|
{
|
||||||
unsigned width;
|
unsigned width;
|
||||||
unsigned height;
|
unsigned height;
|
||||||
unsigned refreshMilliHz;
|
unsigned refresh100uHz;
|
||||||
bool preferred;
|
bool preferred;
|
||||||
bool extraMode;
|
bool extraMode;
|
||||||
};
|
};
|
||||||
@@ -44,7 +44,7 @@ class CSettings
|
|||||||
TransportInstances LoadTransportInstances() const;
|
TransportInstances LoadTransportInstances() const;
|
||||||
bool SetExtraMode(const DisplayMode & mode);
|
bool SetExtraMode(const DisplayMode & mode);
|
||||||
bool GetExtraMode(DisplayMode & mode);
|
bool GetExtraMode(DisplayMode & mode);
|
||||||
unsigned GetDefaultRefreshMilliHz() const;
|
unsigned GetDefaultRefresh100uHz() const;
|
||||||
|
|
||||||
std::wstring ReadStringValue(const wchar_t* name, const wchar_t* defaultValue = nullptr);
|
std::wstring ReadStringValue(const wchar_t* name, const wchar_t* defaultValue = nullptr);
|
||||||
static bool ReadBoolValue(
|
static bool ReadBoolValue(
|
||||||
|
|||||||
@@ -440,7 +440,7 @@ void CDeviceContext::OnSwapChainReady()
|
|||||||
m_monitorManager.QueueReplug();
|
m_monitorManager.QueueReplug();
|
||||||
else if (action.setMode)
|
else if (action.setMode)
|
||||||
g_pipe.SetDisplayMode(
|
g_pipe.SetDisplayMode(
|
||||||
action.mode.width, action.mode.height, action.mode.refreshMilliHz);
|
action.mode.width, action.mode.height, action.mode.refresh100uHz);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display configuration
|
// Display configuration
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include "CDebug.h"
|
#include "CDebug.h"
|
||||||
#include "CSRWLock.h"
|
#include "CSRWLock.h"
|
||||||
|
#include "RefreshRate.h"
|
||||||
|
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@@ -66,24 +67,26 @@ bool CDisplayConfiguration::LoadModes(const FrameCaps& caps)
|
|||||||
{
|
{
|
||||||
configuredMode.width,
|
configuredMode.width,
|
||||||
configuredMode.height,
|
configuredMode.height,
|
||||||
configuredMode.refreshMilliHz,
|
configuredMode.refresh100uHz,
|
||||||
};
|
};
|
||||||
if (!frameMode.width || !frameMode.height ||
|
if (!frameMode.width || !frameMode.height ||
|
||||||
!frameMode.refreshMilliHz)
|
!frameMode.refresh100uHz)
|
||||||
{
|
{
|
||||||
DEBUG_WARN("Filtering invalid %s mode %ux%u@%.3f",
|
DEBUG_WARN("Filtering invalid %s mode %ux%u@%.4f",
|
||||||
configuredMode.extraMode ? "extra" : "configured",
|
configuredMode.extraMode ? "extra" : "configured",
|
||||||
configuredMode.width, configuredMode.height,
|
configuredMode.width, configuredMode.height,
|
||||||
configuredMode.refreshMilliHz / 1000.0);
|
configuredMode.refresh100uHz /
|
||||||
|
static_cast<double>(LG_REFRESH_RATE_SCALE));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!caps.CanUseMode(frameMode))
|
if (!caps.CanUseMode(frameMode))
|
||||||
{
|
{
|
||||||
DEBUG_WARN(
|
DEBUG_WARN(
|
||||||
"Filtering unsupported %s mode %ux%u@%.3f",
|
"Filtering unsupported %s mode %ux%u@%.4f",
|
||||||
configuredMode.extraMode ? "extra" : "configured",
|
configuredMode.extraMode ? "extra" : "configured",
|
||||||
configuredMode.width, configuredMode.height,
|
configuredMode.width, configuredMode.height,
|
||||||
configuredMode.refreshMilliHz / 1000.0);
|
configuredMode.refresh100uHz /
|
||||||
|
static_cast<double>(LG_REFRESH_RATE_SCALE));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,11 +131,11 @@ bool CDisplayConfiguration::ReloadSettings(
|
|||||||
CSettings::DisplayMode extraMode = {};
|
CSettings::DisplayMode extraMode = {};
|
||||||
if (m_settings.GetExtraMode(extraMode))
|
if (m_settings.GetExtraMode(extraMode))
|
||||||
{
|
{
|
||||||
const unsigned refreshMilliHz =
|
const unsigned refresh100uHz =
|
||||||
m_settings.GetDefaultRefreshMilliHz();
|
m_settings.GetDefaultRefresh100uHz();
|
||||||
if (extraMode.refreshMilliHz != refreshMilliHz)
|
if (extraMode.refresh100uHz != refresh100uHz)
|
||||||
{
|
{
|
||||||
extraMode.refreshMilliHz = refreshMilliHz;
|
extraMode.refresh100uHz = refresh100uHz;
|
||||||
settingsUpdated = m_settings.SetExtraMode(extraMode);
|
settingsUpdated = m_settings.SetExtraMode(extraMode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -155,10 +158,10 @@ CDisplayConfiguration::SetResolution(
|
|||||||
CSettings::DisplayMode mode = {};
|
CSettings::DisplayMode mode = {};
|
||||||
mode.width = width;
|
mode.width = width;
|
||||||
mode.height = height;
|
mode.height = height;
|
||||||
mode.refreshMilliHz = m_settings.GetDefaultRefreshMilliHz();
|
mode.refresh100uHz = m_settings.GetDefaultRefresh100uHz();
|
||||||
mode.preferred = true;
|
mode.preferred = true;
|
||||||
|
|
||||||
if (!mode.width || !mode.height || !mode.refreshMilliHz)
|
if (!mode.width || !mode.height || !mode.refresh100uHz)
|
||||||
{
|
{
|
||||||
DEBUG_WARN("Ignoring invalid resolution request: %ux%u", width, height);
|
DEBUG_WARN("Ignoring invalid resolution request: %ux%u", width, height);
|
||||||
return result;
|
return result;
|
||||||
@@ -168,7 +171,7 @@ CDisplayConfiguration::SetResolution(
|
|||||||
{
|
{
|
||||||
mode.width,
|
mode.width,
|
||||||
mode.height,
|
mode.height,
|
||||||
mode.refreshMilliHz,
|
mode.refresh100uHz,
|
||||||
};
|
};
|
||||||
if (!caps.CanUseMode(frameMode, &result.requiredMiB))
|
if (!caps.CanUseMode(frameMode, &result.requiredMiB))
|
||||||
{
|
{
|
||||||
@@ -289,9 +292,11 @@ static inline void FillSignalInfo(DISPLAYCONFIG_VIDEO_SIGNAL_INFO& signal,
|
|||||||
signal.AdditionalSignalInfo.vSyncFreqDivider = monitorMode ? 0 : 1;
|
signal.AdditionalSignalInfo.vSyncFreqDivider = monitorMode ? 0 : 1;
|
||||||
signal.AdditionalSignalInfo.videoStandard = 255;
|
signal.AdditionalSignalInfo.videoStandard = 255;
|
||||||
|
|
||||||
SetSignalRate(signal.vSyncFreq, mode.refreshMilliHz, 1000);
|
SetSignalRate(signal.vSyncFreq, mode.refresh100uHz,
|
||||||
|
LG_REFRESH_RATE_SCALE);
|
||||||
SetSignalRate(signal.hSyncFreq,
|
SetSignalRate(signal.hSyncFreq,
|
||||||
(UINT64)mode.refreshMilliHz * signal.totalSize.cy, 1000);
|
(UINT64)mode.refresh100uHz * signal.totalSize.cy,
|
||||||
|
LG_REFRESH_RATE_SCALE);
|
||||||
|
|
||||||
signal.scanLineOrdering = DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE;
|
signal.scanLineOrdering = DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE;
|
||||||
signal.pixelRate = timing.pixelClock;
|
signal.pixelRate = timing.pixelClock;
|
||||||
|
|||||||
@@ -20,6 +20,8 @@
|
|||||||
|
|
||||||
#include "display/CEdid.h"
|
#include "display/CEdid.h"
|
||||||
|
|
||||||
|
#include "RefreshRate.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -367,7 +369,7 @@ bool CEdid::GetTiming(Timing& timing, const CSettings::DisplayMode& mode)
|
|||||||
timing.vActive = mode.height;
|
timing.vActive = mode.height;
|
||||||
|
|
||||||
if (timing.hActive == 0 || timing.vActive == 0 ||
|
if (timing.hActive == 0 || timing.vActive == 0 ||
|
||||||
mode.refreshMilliHz == 0)
|
mode.refresh100uHz == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
timing.hBlank = std::max<DWORD>(160,
|
timing.hBlank = std::max<DWORD>(160,
|
||||||
@@ -391,11 +393,12 @@ bool CEdid::GetTiming(Timing& timing, const CSettings::DisplayMode& mode)
|
|||||||
if (timing.vFront + timing.vSync >= timing.vBlank)
|
if (timing.vFront + timing.vSync >= timing.vBlank)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const UINT64 pixelClockMilliHz =
|
const UINT64 pixelClock100uHz =
|
||||||
(UINT64)(timing.hActive + timing.hBlank) *
|
(UINT64)(timing.hActive + timing.hBlank) *
|
||||||
(UINT64)(timing.vActive + timing.vBlank) *
|
(UINT64)(timing.vActive + timing.vBlank) *
|
||||||
(UINT64)mode.refreshMilliHz;
|
(UINT64)mode.refresh100uHz;
|
||||||
timing.pixelClock = (pixelClockMilliHz + 500) / 1000;
|
timing.pixelClock = (pixelClock100uHz + LG_REFRESH_RATE_SCALE / 2) /
|
||||||
|
LG_REFRESH_RATE_SCALE;
|
||||||
return timing.pixelClock != 0;
|
return timing.pixelClock != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -564,14 +564,14 @@ bool CPipeServer::SetCursorPos(int32_t x, int32_t y)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CPipeServer::SetDisplayMode(
|
void CPipeServer::SetDisplayMode(
|
||||||
uint32_t width, uint32_t height, uint32_t refreshMilliHz)
|
uint32_t width, uint32_t height, uint32_t refresh100uHz)
|
||||||
{
|
{
|
||||||
LGPipeMsg msg = {};
|
LGPipeMsg msg = {};
|
||||||
msg.size = sizeof(msg);
|
msg.size = sizeof(msg);
|
||||||
msg.type = LGPipeMsg::SETDISPLAYMODE;
|
msg.type = LGPipeMsg::SETDISPLAYMODE;
|
||||||
msg.displayMode.width = width;
|
msg.displayMode.width = width;
|
||||||
msg.displayMode.height = height;
|
msg.displayMode.height = height;
|
||||||
msg.displayMode.refreshMilliHz = refreshMilliHz;
|
msg.displayMode.refresh100uHz = refresh100uHz;
|
||||||
WriteMsg(msg);
|
WriteMsg(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ class CPipeServer : private IPipeEndpointHandler,
|
|||||||
|
|
||||||
bool SetCursorPos(int32_t x, int32_t y);
|
bool SetCursorPos(int32_t x, int32_t y);
|
||||||
void SetDisplayMode(
|
void SetDisplayMode(
|
||||||
uint32_t width, uint32_t height, uint32_t refreshMilliHz);
|
uint32_t width, uint32_t height, uint32_t refresh100uHz);
|
||||||
void SetGPUStatus(bool software);
|
void SetGPUStatus(bool software);
|
||||||
void ResolutionRejected(uint32_t width, uint32_t height,
|
void ResolutionRejected(uint32_t width, uint32_t height,
|
||||||
uint32_t requiredSizeMiB);
|
uint32_t requiredSizeMiB);
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ struct FrameMode
|
|||||||
{
|
{
|
||||||
uint32_t width = 0;
|
uint32_t width = 0;
|
||||||
uint32_t height = 0;
|
uint32_t height = 0;
|
||||||
uint32_t refreshMilliHz = 0;
|
uint32_t refresh100uHz = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FrameCaps
|
class FrameCaps
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ namespace
|
|||||||
const FrameMode& mode, uint64_t& frameSize)
|
const FrameMode& mode, uint64_t& frameSize)
|
||||||
{
|
{
|
||||||
frameSize = 0;
|
frameSize = 0;
|
||||||
if (!mode.width || !mode.height || !mode.refreshMilliHz)
|
if (!mode.width || !mode.height || !mode.refresh100uHz)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
uint64_t pitch;
|
uint64_t pitch;
|
||||||
|
|||||||
@@ -254,7 +254,7 @@ void CConfigWindow::onModeListSelectChange()
|
|||||||
auto &mode = (*m_modes)[index];
|
auto &mode = (*m_modes)[index];
|
||||||
m_modeWidth->setNumericValue(mode.width);
|
m_modeWidth->setNumericValue(mode.width);
|
||||||
m_modeHeight->setNumericValue(mode.height);
|
m_modeHeight->setNumericValue(mode.height);
|
||||||
m_modeRefresh->setValue(LGFormatRefreshRate(mode.refreshMilliHz));
|
m_modeRefresh->setValue(LGFormatRefreshRate(mode.refresh100uHz));
|
||||||
m_modePreferred->setChecked(mode.preferred);
|
m_modePreferred->setChecked(mode.preferred);
|
||||||
}
|
}
|
||||||
EnableWindow(*m_modeUpdate, TRUE);
|
EnableWindow(*m_modeUpdate, TRUE);
|
||||||
@@ -294,11 +294,11 @@ LRESULT CConfigWindow::onCommand(WORD id, WORD code, HWND hwnd)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned refreshMilliHz;
|
unsigned refresh100uHz;
|
||||||
if (!LGParseRefreshRate(
|
if (!LGParseRefreshRate(
|
||||||
m_modeRefresh->getValue(), refreshMilliHz))
|
m_modeRefresh->getValue(), refresh100uHz))
|
||||||
return 0;
|
return 0;
|
||||||
mode.refreshMilliHz = refreshMilliHz;
|
mode.refresh100uHz = refresh100uHz;
|
||||||
|
|
||||||
m_modeBox->clear();
|
m_modeBox->clear();
|
||||||
m_modeBox->setSel(updateModeList(index));
|
m_modeBox->setSel(updateModeList(index));
|
||||||
@@ -325,10 +325,10 @@ LRESULT CConfigWindow::onCommand(WORD id, WORD code, HWND hwnd)
|
|||||||
}
|
}
|
||||||
else if (m_defRefresh && hwnd == *m_defRefresh && code == EN_CHANGE && m_defaultRefresh)
|
else if (m_defRefresh && hwnd == *m_defRefresh && code == EN_CHANGE && m_defaultRefresh)
|
||||||
{
|
{
|
||||||
unsigned refreshMilliHz;
|
unsigned refresh100uHz;
|
||||||
if (!LGParseRefreshRate(m_defRefresh->getValue(), refreshMilliHz))
|
if (!LGParseRefreshRate(m_defRefresh->getValue(), refresh100uHz))
|
||||||
return 0;
|
return 0;
|
||||||
m_defaultRefresh = refreshMilliHz;
|
m_defaultRefresh = refresh100uHz;
|
||||||
}
|
}
|
||||||
else if (m_prefNoGPU && hwnd == *m_prefNoGPU && code == BN_CLICKED && m_noGPU)
|
else if (m_prefNoGPU && hwnd == *m_prefNoGPU && code == BN_CLICKED && m_noGPU)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include "CSRWLock.h"
|
#include "CSRWLock.h"
|
||||||
#include "CNotifyWindow.h"
|
#include "CNotifyWindow.h"
|
||||||
#include "CRegistrySettings.h"
|
#include "CRegistrySettings.h"
|
||||||
|
#include "RefreshRate.h"
|
||||||
|
|
||||||
#include <setupapi.h>
|
#include <setupapi.h>
|
||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
@@ -1011,7 +1012,8 @@ void CPipeClient::HandleSetDisplayMode(const LGPipeMsg& msg)
|
|||||||
dm.dmPelsWidth = msg.displayMode.width;
|
dm.dmPelsWidth = msg.displayMode.width;
|
||||||
dm.dmPelsHeight = msg.displayMode.height;
|
dm.dmPelsHeight = msg.displayMode.height;
|
||||||
dm.dmDisplayFrequency =
|
dm.dmDisplayFrequency =
|
||||||
(msg.displayMode.refreshMilliHz + 500) / 1000;
|
(msg.displayMode.refresh100uHz + LG_REFRESH_RATE_SCALE / 2) /
|
||||||
|
LG_REFRESH_RATE_SCALE;
|
||||||
dm.dmFields =
|
dm.dmFields =
|
||||||
DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
|
DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
#define LGIDD_REGKEY L"SOFTWARE\\LookingGlass\\IDD"
|
#define LGIDD_REGKEY L"SOFTWARE\\LookingGlass\\IDD"
|
||||||
|
|
||||||
const DWORD DEFAULT_REFRESH = 120000;
|
const DWORD DEFAULT_REFRESH = 120 * LG_REFRESH_RATE_SCALE;
|
||||||
|
|
||||||
CRegistrySettings::CRegistrySettings() : hKey(nullptr) {}
|
CRegistrySettings::CRegistrySettings() : hKey(nullptr) {}
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ static std::basic_string<T> trim(const std::basic_string<T> &s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static std::wregex displayMode(
|
static std::wregex displayMode(
|
||||||
L"(\\d+)x(\\d+)@(\\d+(?:\\.\\d{1,3})?)(\\*)?");
|
L"(\\d+)x(\\d+)@(\\d+(?:\\.\\d{1,4})?)(\\*)?");
|
||||||
|
|
||||||
static std::optional<DisplayMode> parseDisplayMode(const std::wstring &str)
|
static std::optional<DisplayMode> parseDisplayMode(const std::wstring &str)
|
||||||
{
|
{
|
||||||
@@ -78,7 +78,7 @@ static std::optional<DisplayMode> parseDisplayMode(const std::wstring &str)
|
|||||||
DisplayMode mode;
|
DisplayMode mode;
|
||||||
mode.width = std::stoul(match[1]);
|
mode.width = std::stoul(match[1]);
|
||||||
mode.height = std::stoul(match[2]);
|
mode.height = std::stoul(match[2]);
|
||||||
if (!LGParseRefreshRate(match[3], mode.refreshMilliHz))
|
if (!LGParseRefreshRate(match[3], mode.refresh100uHz))
|
||||||
return {};
|
return {};
|
||||||
mode.preferred = match[4] == L"*";
|
mode.preferred = match[4] == L"*";
|
||||||
return mode;
|
return mode;
|
||||||
@@ -87,7 +87,7 @@ static std::optional<DisplayMode> parseDisplayMode(const std::wstring &str)
|
|||||||
std::vector<DisplayMode> CRegistrySettings::getDefaultModes()
|
std::vector<DisplayMode> CRegistrySettings::getDefaultModes()
|
||||||
{
|
{
|
||||||
auto defaultRefresh = getDefaultRefresh();
|
auto defaultRefresh = getDefaultRefresh();
|
||||||
const unsigned refreshMilliHz =
|
const unsigned refresh100uHz =
|
||||||
defaultRefresh ? *defaultRefresh : DEFAULT_REFRESH;
|
defaultRefresh ? *defaultRefresh : DEFAULT_REFRESH;
|
||||||
|
|
||||||
std::vector<DisplayMode> result;
|
std::vector<DisplayMode> result;
|
||||||
@@ -96,7 +96,7 @@ std::vector<DisplayMode> CRegistrySettings::getDefaultModes()
|
|||||||
DisplayMode mode;
|
DisplayMode mode;
|
||||||
mode.width = DefaultDisplayModes[i][0];
|
mode.width = DefaultDisplayModes[i][0];
|
||||||
mode.height = DefaultDisplayModes[i][1];
|
mode.height = DefaultDisplayModes[i][1];
|
||||||
mode.refreshMilliHz = refreshMilliHz;
|
mode.refresh100uHz = refresh100uHz;
|
||||||
mode.preferred = i == DefaultPreferredDisplayMode;
|
mode.preferred = i == DefaultPreferredDisplayMode;
|
||||||
result.emplace_back(mode);
|
result.emplace_back(mode);
|
||||||
}
|
}
|
||||||
@@ -166,7 +166,7 @@ std::wstring DisplayMode::toString()
|
|||||||
serialized.push_back('x');
|
serialized.push_back('x');
|
||||||
serialized.append(std::to_wstring(height));
|
serialized.append(std::to_wstring(height));
|
||||||
serialized.push_back('@');
|
serialized.push_back('@');
|
||||||
serialized.append(LGFormatRefreshRate(refreshMilliHz));
|
serialized.append(LGFormatRefreshRate(refresh100uHz));
|
||||||
if (preferred)
|
if (preferred)
|
||||||
serialized.push_back('*');
|
serialized.push_back('*');
|
||||||
return serialized;
|
return serialized;
|
||||||
@@ -192,7 +192,7 @@ std::optional<DWORD> CRegistrySettings::getDefaultRefresh()
|
|||||||
status = RegQueryValueExW(hKey, L"DefaultRefresh", nullptr, &type,
|
status = RegQueryValueExW(hKey, L"DefaultRefresh", nullptr, &type,
|
||||||
(LPBYTE)&refresh, &size);
|
(LPBYTE)&refresh, &size);
|
||||||
if (status == ERROR_SUCCESS && refresh >= 24 && refresh <= 1000)
|
if (status == ERROR_SUCCESS && refresh >= 24 && refresh <= 1000)
|
||||||
return refresh * 1000;
|
return refresh * LG_REFRESH_RATE_SCALE;
|
||||||
}
|
}
|
||||||
else if ((type == REG_SZ || type == REG_EXPAND_SZ) && size &&
|
else if ((type == REG_SZ || type == REG_EXPAND_SZ) && size &&
|
||||||
size % sizeof(wchar_t) == 0)
|
size % sizeof(wchar_t) == 0)
|
||||||
@@ -202,9 +202,9 @@ std::optional<DWORD> CRegistrySettings::getDefaultRefresh()
|
|||||||
(LPBYTE)value.data(), &size);
|
(LPBYTE)value.data(), &size);
|
||||||
if (status == ERROR_SUCCESS)
|
if (status == ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
unsigned refreshMilliHz;
|
unsigned refresh100uHz;
|
||||||
if (LGParseRefreshRate(value.data(), refreshMilliHz))
|
if (LGParseRefreshRate(value.data(), refresh100uHz))
|
||||||
return refreshMilliHz;
|
return refresh100uHz;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,9 +212,9 @@ std::optional<DWORD> CRegistrySettings::getDefaultRefresh()
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
LSTATUS CRegistrySettings::setDefaultRefresh(DWORD refreshMilliHz)
|
LSTATUS CRegistrySettings::setDefaultRefresh(DWORD refresh100uHz)
|
||||||
{
|
{
|
||||||
const std::wstring value = LGFormatRefreshRate(refreshMilliHz);
|
const std::wstring value = LGFormatRefreshRate(refresh100uHz);
|
||||||
return RegSetValueExW(hKey, L"DefaultRefresh", 0, REG_SZ,
|
return RegSetValueExW(hKey, L"DefaultRefresh", 0, REG_SZ,
|
||||||
(const BYTE *)value.c_str(),
|
(const BYTE *)value.c_str(),
|
||||||
(DWORD)((value.size() + 1) * sizeof(wchar_t)));
|
(DWORD)((value.size() + 1) * sizeof(wchar_t)));
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
struct DisplayMode {
|
struct DisplayMode {
|
||||||
unsigned width;
|
unsigned width;
|
||||||
unsigned height;
|
unsigned height;
|
||||||
unsigned refreshMilliHz;
|
unsigned refresh100uHz;
|
||||||
bool preferred;
|
bool preferred;
|
||||||
|
|
||||||
std::wstring toString();
|
std::wstring toString();
|
||||||
@@ -49,7 +49,7 @@ public:
|
|||||||
LSTATUS setModes(const std::vector<DisplayMode> &modes);
|
LSTATUS setModes(const std::vector<DisplayMode> &modes);
|
||||||
|
|
||||||
std::optional<DWORD> getDefaultRefresh();
|
std::optional<DWORD> getDefaultRefresh();
|
||||||
LSTATUS setDefaultRefresh(DWORD refreshMilliHz);
|
LSTATUS setDefaultRefresh(DWORD refresh100uHz);
|
||||||
|
|
||||||
std::optional<bool> getNoGPU();
|
std::optional<bool> getNoGPU();
|
||||||
LSTATUS setNoGPU(bool noGPU);
|
LSTATUS setNoGPU(bool noGPU);
|
||||||
|
|||||||
Reference in New Issue
Block a user