mirror of
https://github.com/moonlight-stream/moonlight-qt.git
synced 2026-06-18 14:40:56 +00:00
Add FPS values for all attached displays and support custom FPS values
Fixes #926
This commit is contained in:
@@ -70,7 +70,7 @@ SystemProperties::SystemProperties()
|
|||||||
// and cache the results to speed up future queries on this data.
|
// and cache the results to speed up future queries on this data.
|
||||||
querySdlVideoInfo();
|
querySdlVideoInfo();
|
||||||
|
|
||||||
Q_ASSERT(maximumStreamingFrameRate >= 60);
|
Q_ASSERT(!monitorRefreshRates.isEmpty());
|
||||||
Q_ASSERT(!monitorNativeResolutions.isEmpty());
|
Q_ASSERT(!monitorNativeResolutions.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,6 +80,12 @@ QRect SystemProperties::getNativeResolution(int displayIndex)
|
|||||||
return monitorNativeResolutions.value(displayIndex);
|
return monitorNativeResolutions.value(displayIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int SystemProperties::getRefreshRate(int displayIndex)
|
||||||
|
{
|
||||||
|
// Returns 0 if out of bounds
|
||||||
|
return monitorRefreshRates.value(displayIndex);
|
||||||
|
}
|
||||||
|
|
||||||
class QuerySdlVideoThread : public QThread
|
class QuerySdlVideoThread : public QThread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -188,9 +194,6 @@ void SystemProperties::refreshDisplaysInternal()
|
|||||||
|
|
||||||
monitorNativeResolutions.clear();
|
monitorNativeResolutions.clear();
|
||||||
|
|
||||||
// Never let the maximum drop below 60 FPS
|
|
||||||
maximumStreamingFrameRate = 60;
|
|
||||||
|
|
||||||
SDL_DisplayMode bestMode;
|
SDL_DisplayMode bestMode;
|
||||||
for (int displayIndex = 0; displayIndex < SDL_GetNumVideoDisplays(); displayIndex++) {
|
for (int displayIndex = 0; displayIndex < SDL_GetNumVideoDisplays(); displayIndex++) {
|
||||||
SDL_DisplayMode desktopMode;
|
SDL_DisplayMode desktopMode;
|
||||||
@@ -218,7 +221,17 @@ void SystemProperties::refreshDisplaysInternal()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
maximumStreamingFrameRate = qMax(maximumStreamingFrameRate, bestMode.refresh_rate);
|
// Try to normalize values around our our standard refresh rates.
|
||||||
|
// Some displays/OSes report values that are slightly off.
|
||||||
|
if (bestMode.refresh_rate >= 58 && bestMode.refresh_rate <= 62) {
|
||||||
|
monitorRefreshRates.append(60);
|
||||||
|
}
|
||||||
|
else if (bestMode.refresh_rate >= 28 && bestMode.refresh_rate <= 32) {
|
||||||
|
monitorRefreshRates.append(30);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
monitorRefreshRates.append(bestMode.refresh_rate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,13 +23,13 @@ public:
|
|||||||
Q_PROPERTY(bool hasBrowser MEMBER hasBrowser CONSTANT)
|
Q_PROPERTY(bool hasBrowser MEMBER hasBrowser CONSTANT)
|
||||||
Q_PROPERTY(bool hasDiscordIntegration MEMBER hasDiscordIntegration CONSTANT)
|
Q_PROPERTY(bool hasDiscordIntegration MEMBER hasDiscordIntegration CONSTANT)
|
||||||
Q_PROPERTY(QString unmappedGamepads MEMBER unmappedGamepads NOTIFY unmappedGamepadsChanged)
|
Q_PROPERTY(QString unmappedGamepads MEMBER unmappedGamepads NOTIFY unmappedGamepadsChanged)
|
||||||
Q_PROPERTY(int maximumStreamingFrameRate MEMBER maximumStreamingFrameRate CONSTANT)
|
|
||||||
Q_PROPERTY(QSize maximumResolution MEMBER maximumResolution CONSTANT)
|
Q_PROPERTY(QSize maximumResolution MEMBER maximumResolution CONSTANT)
|
||||||
Q_PROPERTY(QString versionString MEMBER versionString CONSTANT)
|
Q_PROPERTY(QString versionString MEMBER versionString CONSTANT)
|
||||||
Q_PROPERTY(bool supportsHdr MEMBER supportsHdr CONSTANT)
|
Q_PROPERTY(bool supportsHdr MEMBER supportsHdr CONSTANT)
|
||||||
|
|
||||||
Q_INVOKABLE void refreshDisplays();
|
Q_INVOKABLE void refreshDisplays();
|
||||||
Q_INVOKABLE QRect getNativeResolution(int displayIndex);
|
Q_INVOKABLE QRect getNativeResolution(int displayIndex);
|
||||||
|
Q_INVOKABLE int getRefreshRate(int displayIndex);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void unmappedGamepadsChanged();
|
void unmappedGamepadsChanged();
|
||||||
@@ -49,9 +49,9 @@ private:
|
|||||||
bool hasBrowser;
|
bool hasBrowser;
|
||||||
bool hasDiscordIntegration;
|
bool hasDiscordIntegration;
|
||||||
QString unmappedGamepads;
|
QString unmappedGamepads;
|
||||||
int maximumStreamingFrameRate;
|
|
||||||
QSize maximumResolution;
|
QSize maximumResolution;
|
||||||
QList<QRect> monitorNativeResolutions;
|
QList<QRect> monitorNativeResolutions;
|
||||||
|
QList<int> monitorRefreshRates;
|
||||||
QString versionString;
|
QString versionString;
|
||||||
bool supportsHdr;
|
bool supportsHdr;
|
||||||
};
|
};
|
||||||
|
|||||||
+50
-34
@@ -388,48 +388,58 @@ Flickable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AutoResizingComboBox {
|
AutoResizingComboBox {
|
||||||
|
function addRefreshRateOrdered(fpsListModel, refreshRate, description) {
|
||||||
|
var indexToAdd = 0
|
||||||
|
for (var j = 0; j < fpsListModel.count; j++) {
|
||||||
|
var existing_fps = parseInt(fpsListModel.get(j).video_fps);
|
||||||
|
|
||||||
|
if (refreshRate === existing_fps) {
|
||||||
|
// Duplicate entry, skip
|
||||||
|
indexToAdd = -1
|
||||||
|
break
|
||||||
|
}
|
||||||
|
else if (refreshRate > existing_fps) {
|
||||||
|
// Candidate entrypoint after this entry
|
||||||
|
indexToAdd = j + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert this display's resolution if it's not a duplicate
|
||||||
|
if (indexToAdd >= 0) {
|
||||||
|
fpsListModel.insert(indexToAdd,
|
||||||
|
{
|
||||||
|
"text": description,
|
||||||
|
"video_fps": ""+refreshRate
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return indexToAdd
|
||||||
|
}
|
||||||
|
|
||||||
function createModel() {
|
function createModel() {
|
||||||
var fpsListModel = Qt.createQmlObject('import QtQuick 2.0; ListModel {}', parent, '')
|
var fpsListModel = Qt.createQmlObject('import QtQuick 2.0; ListModel {}', parent, '')
|
||||||
|
|
||||||
var max_fps = SystemProperties.maximumStreamingFrameRate
|
|
||||||
|
|
||||||
// Default entries
|
// Default entries
|
||||||
fpsListModel.append({"text": qsTr("%1 FPS").arg("30"), "video_fps": "30"})
|
fpsListModel.append({"text": qsTr("%1 FPS").arg("30"), "video_fps": "30"})
|
||||||
fpsListModel.append({"text": qsTr("%1 FPS").arg("60"), "video_fps": "60"})
|
fpsListModel.append({"text": qsTr("%1 FPS").arg("60"), "video_fps": "60"})
|
||||||
|
|
||||||
// Add unsupported FPS values that come before the display max FPS
|
// Add native refresh rate for all attached displays
|
||||||
if (StreamingPreferences.unsupportedFps) {
|
var done = false
|
||||||
if (max_fps > 90) {
|
for (var displayIndex = 0; !done; displayIndex++) {
|
||||||
fpsListModel.append({"text": qsTr("%1 FPS (Unsupported)").arg("90"), "video_fps": "90"})
|
var refreshRate = SystemProperties.getRefreshRate(displayIndex);
|
||||||
}
|
if (refreshRate === 0) {
|
||||||
if (max_fps > 120) {
|
// Exceeded max count of displays
|
||||||
fpsListModel.append({"text": qsTr("%1 FPS (Unsupported)").arg("120"), "video_fps": "120"})
|
done = true
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addRefreshRateOrdered(fpsListModel, refreshRate, qsTr("%1 FPS").arg(refreshRate))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use 64 as the cutoff for adding a separate option to
|
// Add unsupported FPS values
|
||||||
// handle wonky displays that report just over 60 Hz.
|
|
||||||
if (max_fps > 64) {
|
|
||||||
// Mark any FPS value greater than 120 as unsupported
|
|
||||||
if (StreamingPreferences.unsupportedFps && max_fps > 120) {
|
|
||||||
fpsListModel.append({"text": qsTr("%1 FPS (Unsupported)").arg(max_fps), "video_fps": ""+max_fps})
|
|
||||||
}
|
|
||||||
else if (max_fps > 120) {
|
|
||||||
fpsListModel.append({"text": qsTr("%1 FPS").arg("120"), "video_fps": "120"})
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
fpsListModel.append({"text": qsTr("%1 FPS").arg(max_fps), "video_fps": ""+max_fps})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add unsupported FPS values that come after the display max FPS
|
|
||||||
if (StreamingPreferences.unsupportedFps) {
|
if (StreamingPreferences.unsupportedFps) {
|
||||||
if (max_fps < 90) {
|
addRefreshRateOrdered(fpsListModel, 90, qsTr("%1 FPS (Unsupported)").arg(90))
|
||||||
fpsListModel.append({"text":qsTr("%1 FPS (Unsupported)").arg("90"), "video_fps": "90"})
|
addRefreshRateOrdered(fpsListModel, 120, qsTr("%1 FPS (Unsupported)").arg(120))
|
||||||
}
|
|
||||||
if (max_fps < 120) {
|
|
||||||
fpsListModel.append({"text":qsTr("%1 FPS (Unsupported)").arg("120"), "video_fps": "120"})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return fpsListModel
|
return fpsListModel
|
||||||
@@ -439,16 +449,22 @@ Flickable {
|
|||||||
model = createModel()
|
model = createModel()
|
||||||
|
|
||||||
var saved_fps = StreamingPreferences.fps
|
var saved_fps = StreamingPreferences.fps
|
||||||
currentIndex = 0
|
currentIndex = -1
|
||||||
for (var i = 0; i < model.count; i++) {
|
for (var i = 0; i < model.count; i++) {
|
||||||
var el_fps = parseInt(model.get(i).video_fps);
|
var el_fps = parseInt(model.get(i).video_fps);
|
||||||
|
|
||||||
// Pick the highest value lesser or equal to the saved FPS
|
// Look for a matching frame rate
|
||||||
if (saved_fps >= el_fps) {
|
if (saved_fps === el_fps) {
|
||||||
currentIndex = i
|
currentIndex = i
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we didn't find one, add a custom frame rate for the current value
|
||||||
|
if (currentIndex === -1) {
|
||||||
|
currentIndex = addRefreshRateOrdered(model, saved_fps, qsTr("%1 FPS (Custom)").arg(saved_fps))
|
||||||
|
}
|
||||||
|
|
||||||
// Persist the selected value
|
// Persist the selected value
|
||||||
activated(currentIndex)
|
activated(currentIndex)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user