From 2703efedef62813e1374f873c76f5156062dc771 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sat, 23 Mar 2019 12:05:08 -0700 Subject: [PATCH] Improve performance of looking up static system properties --- app/app.pro | 6 +- app/backend/systemproperties.cpp | 101 +++++++++++++++++++++ app/backend/systemproperties.h | 38 ++++++++ app/gui/PcView.qml | 5 -- app/gui/SettingsView.qml | 20 ++--- app/gui/main.qml | 12 +-- app/main.cpp | 6 ++ app/settings/streamingpreferences.cpp | 123 -------------------------- app/settings/streamingpreferences.h | 14 --- 9 files changed, 164 insertions(+), 161 deletions(-) create mode 100644 app/backend/systemproperties.cpp create mode 100644 app/backend/systemproperties.h diff --git a/app/app.pro b/app/app.pro index 85d231f6..e4fbde20 100644 --- a/app/app.pro +++ b/app/app.pro @@ -137,7 +137,8 @@ SOURCES += \ path.cpp \ settings/mappingmanager.cpp \ gui/sdlgamepadkeynavigation.cpp \ - streaming/video/overlaymanager.cpp + streaming/video/overlaymanager.cpp \ + backend/systemproperties.cpp HEADERS += \ utils.h \ @@ -164,7 +165,8 @@ HEADERS += \ path.h \ settings/mappingmanager.h \ gui/sdlgamepadkeynavigation.h \ - streaming/video/overlaymanager.h + streaming/video/overlaymanager.h \ + backend/systemproperties.h # Platform-specific renderers and decoders ffmpeg { diff --git a/app/backend/systemproperties.cpp b/app/backend/systemproperties.cpp new file mode 100644 index 00000000..7b3d0f3d --- /dev/null +++ b/app/backend/systemproperties.cpp @@ -0,0 +1,101 @@ +#include "systemproperties.h" + +#include "streaming/session.h" +#include "streaming/streamutils.h" + +SystemProperties::SystemProperties() +{ + hasHardwareAcceleration = + Session::isHardwareDecodeAvailable(StreamingPreferences::VDS_AUTO, + VIDEO_FORMAT_H264, + 1920, 1080, 60); + + isRunningWayland = qgetenv("XDG_SESSION_TYPE") == "wayland"; + +#ifdef Q_OS_WIN32 + isWow64 = QSysInfo::currentCpuArchitecture() != QSysInfo::buildCpuArchitecture(); +#else + isWow64 = false; +#endif + +#ifndef STEAM_LINK + hasBrowser = true; +#else + hasBrowser = false; +#endif + + unmappedGamepads = SdlInputHandler::getUnmappedGamepads(); + + // Populate data that requires talking to SDL. We do it all in one shot + // and cache the results to speed up future queries on this data. + querySdlVideoInfo(); + + Q_ASSERT(maximumStreamingFrameRate >= 60); + Q_ASSERT(!monitorDesktopResolutions.isEmpty()); + Q_ASSERT(!monitorNativeResolutions.isEmpty()); +} + +QRect SystemProperties::getDesktopResolution(int displayIndex) +{ + // Returns default constructed QRect if out of bounds + return monitorDesktopResolutions.value(displayIndex); +} + +QRect SystemProperties::getNativeResolution(int displayIndex) +{ + // Returns default constructed QRect if out of bounds + return monitorNativeResolutions.value(displayIndex); +} + +void SystemProperties::querySdlVideoInfo() +{ + monitorDesktopResolutions.clear(); + monitorNativeResolutions.clear(); + + // Never let the maximum drop below 60 FPS + maximumStreamingFrameRate = 60; + + if (SDL_InitSubSystem(SDL_INIT_VIDEO) != 0) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "SDL_InitSubSystem(SDL_INIT_VIDEO) failed: %s", + SDL_GetError()); + return; + } + + SDL_DisplayMode bestMode; + for (int displayIndex = 0; displayIndex < SDL_GetNumVideoDisplays(); displayIndex++) { + SDL_DisplayMode desktopMode; + int err; + + err = SDL_GetDesktopDisplayMode(displayIndex, &desktopMode); + if (err == 0) { + monitorDesktopResolutions.insert(displayIndex, QRect(0, 0, desktopMode.w, desktopMode.h)); + } + else { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "SDL_GetDesktopDisplayMode() failed: %s", + SDL_GetError()); + } + + if (StreamUtils::getRealDesktopMode(displayIndex, &desktopMode)) { + monitorNativeResolutions.insert(displayIndex, QRect(0, 0, desktopMode.w, desktopMode.h)); + + // Start at desktop mode and work our way up + bestMode = desktopMode; + for (int i = 0; i < SDL_GetNumDisplayModes(displayIndex); i++) { + SDL_DisplayMode mode; + if (SDL_GetDisplayMode(displayIndex, i, &mode) == 0) { + if (mode.w == desktopMode.w && mode.h == desktopMode.h) { + if (mode.refresh_rate > bestMode.refresh_rate) { + bestMode = mode; + } + } + } + } + + maximumStreamingFrameRate = qMax(maximumStreamingFrameRate, bestMode.refresh_rate); + } + } + + SDL_QuitSubSystem(SDL_INIT_VIDEO); +} diff --git a/app/backend/systemproperties.h b/app/backend/systemproperties.h new file mode 100644 index 00000000..23ee70a4 --- /dev/null +++ b/app/backend/systemproperties.h @@ -0,0 +1,38 @@ +#pragma once + +#include +#include + +class SystemProperties : public QObject +{ + Q_OBJECT + +public: + SystemProperties(); + + Q_PROPERTY(bool hasHardwareAcceleration MEMBER hasHardwareAcceleration CONSTANT) + Q_PROPERTY(bool isRunningWayland MEMBER isRunningWayland CONSTANT) + Q_PROPERTY(bool isWow64 MEMBER isWow64 CONSTANT) + Q_PROPERTY(bool hasBrowser MEMBER hasBrowser CONSTANT) + Q_PROPERTY(QString unmappedGamepads MEMBER unmappedGamepads NOTIFY unmappedGamepadsChanged) + Q_PROPERTY(int maximumStreamingFrameRate MEMBER maximumStreamingFrameRate CONSTANT) + + Q_INVOKABLE QRect getDesktopResolution(int displayIndex); + Q_INVOKABLE QRect getNativeResolution(int displayIndex); + +signals: + void unmappedGamepadsChanged(); + +private: + void querySdlVideoInfo(); + + bool hasHardwareAcceleration; + bool isRunningWayland; + bool isWow64; + bool hasBrowser; + QString unmappedGamepads; + int maximumStreamingFrameRate; + QList monitorDesktopResolutions; + QList monitorNativeResolutions; +}; + diff --git a/app/gui/PcView.qml b/app/gui/PcView.qml index c55ed75e..3969b5f0 100644 --- a/app/gui/PcView.qml +++ b/app/gui/PcView.qml @@ -7,7 +7,6 @@ import QtQuick.Window 2.2 import ComputerModel 1.0 import ComputerManager 1.0 -import StreamingPreferences 1.0 import SdlGamepadKeyNavigation 1.0 GridView { @@ -24,10 +23,6 @@ GridView { cellWidth: 350; cellHeight: 350; objectName: "Computers" - StreamingPreferences { - id: prefs - } - SdlGamepadKeyNavigation { id: gamepadKeyNav } diff --git a/app/gui/SettingsView.qml b/app/gui/SettingsView.qml index 1bf49cb9..72991607 100644 --- a/app/gui/SettingsView.qml +++ b/app/gui/SettingsView.qml @@ -4,6 +4,7 @@ import QtQuick.Controls 2.2 import StreamingPreferences 1.0 import ComputerManager 1.0 import SdlGamepadKeyNavigation 1.0 +import SystemProperties 1.0 Flickable { id: settingsPage @@ -89,10 +90,10 @@ Flickable { // Some platforms have different desktop resolutions // and native resolutions (like macOS with Retina displays) if (displayResIndex == 0) { - screenRect = prefs.getDesktopResolution(displayIndex) + screenRect = SystemProperties.getDesktopResolution(displayIndex) } else { - screenRect = prefs.getNativeResolution(displayIndex) + screenRect = SystemProperties.getNativeResolution(displayIndex) } if (screenRect.width === 0) { @@ -195,31 +196,28 @@ Flickable { function createModel() { var fpsListModel = Qt.createQmlObject('import QtQuick 2.0; ListModel {}', parent, '') - // Get the max supported FPS on this system - var max_fps = prefs.getMaximumStreamingFrameRate(); - // Default entries fpsListModel.append({"text": "30 FPS", "video_fps": "30"}) fpsListModel.append({"text": "60 FPS", "video_fps": "60"}) // Add unsupported FPS values that come before the display max FPS if (prefs.unsupportedFps) { - if (max_fps > 90) { + if (SystemProperties.maximumStreamingFrameRate > 90) { fpsListModel.append({"text": "90 FPS (Unsupported)", "video_fps": "90"}) } - if (max_fps > 120) { + if (SystemProperties.maximumStreamingFrameRate > 120) { fpsListModel.append({"text": "120 FPS (Unsupported)", "video_fps": "120"}) } } // Use 64 as the cutoff for adding a separate option to // handle wonky displays that report just over 60 Hz. - if (max_fps > 64) { + if (SystemProperties.maximumStreamingFrameRate > 64) { // Mark any FPS value greater than 120 as unsupported if (prefs.unsupportedFps && max_fps > 120) { fpsListModel.append({"text": max_fps+" FPS (Unsupported)", "video_fps": ""+max_fps}) } - else if (max_fps > 120) { + else if (SystemProperties.maximumStreamingFrameRate > 120) { fpsListModel.append({"text": "120 FPS", "video_fps": "120"}) } else { @@ -229,10 +227,10 @@ Flickable { // Add unsupported FPS values that come after the display max FPS if (prefs.unsupportedFps) { - if (max_fps < 90) { + if (SystemProperties.maximumStreamingFrameRate < 90) { fpsListModel.append({"text": "90 FPS (Unsupported)", "video_fps": "90"}) } - if (max_fps < 120) { + if (SystemProperties.maximumStreamingFrameRate < 120) { fpsListModel.append({"text": "120 FPS (Unsupported)", "video_fps": "120"}) } } diff --git a/app/gui/main.qml b/app/gui/main.qml index 7f68b498..83b6c564 100644 --- a/app/gui/main.qml +++ b/app/gui/main.qml @@ -7,6 +7,7 @@ import QtQuick.Window 2.2 import ComputerManager 1.0 import AutoUpdateChecker 1.0 import StreamingPreferences 1.0 +import SystemProperties 1.0 ApplicationWindow { property bool pollingActive: false @@ -137,19 +138,18 @@ ApplicationWindow { // onAfterRendering call and potentially reenter this code. initialized = true; - if (prefs.isRunningWayland()) { + if (SystemProperties.isRunningWayland) { waylandDialog.open() } - else if (prefs.isWow64()) { + else if (SystemProperties.isWow64) { wow64Dialog.open() } - else if (!prefs.hasAnyHardwareAcceleration()) { + else if (!SystemProperties.hasHardwareAcceleration) { noHwDecoderDialog.open() } - var unmappedGamepads = prefs.getUnmappedGamepads() - if (unmappedGamepads) { - unmappedGamepadDialog.unmappedGamepads = unmappedGamepads + if (SystemProperties.unmappedGamepads) { + unmappedGamepadDialog.unmappedGamepads = SystemProperties.unmappedGamepads unmappedGamepadDialog.open() } } diff --git a/app/main.cpp b/app/main.cpp index bb213657..187834bd 100644 --- a/app/main.cpp +++ b/app/main.cpp @@ -30,6 +30,7 @@ #include "gui/computermodel.h" #include "gui/appmodel.h" #include "backend/autoupdatechecker.h" +#include "backend/systemproperties.h" #include "streaming/session.h" #include "settings/streamingpreferences.h" #include "gui/sdlgamepadkeynavigation.h" @@ -361,6 +362,11 @@ int main(int argc, char *argv[]) [](QQmlEngine*, QJSEngine*) -> QObject* { return new AutoUpdateChecker(); }); + qmlRegisterSingletonType("SystemProperties", 1, 0, + "SystemProperties", + [](QQmlEngine*, QJSEngine*) -> QObject* { + return new SystemProperties(); + }); #ifndef Q_OS_WINRT // Use the dense material dark theme by default diff --git a/app/settings/streamingpreferences.cpp b/app/settings/streamingpreferences.cpp index 34f04fc2..afb76b0e 100644 --- a/app/settings/streamingpreferences.cpp +++ b/app/settings/streamingpreferences.cpp @@ -1,6 +1,4 @@ #include "streamingpreferences.h" -#include "streaming/session.h" -#include "streaming/streamutils.h" #include @@ -88,127 +86,6 @@ void StreamingPreferences::save() settings.setValue(SER_WINDOWMODE, static_cast(windowMode)); } -bool StreamingPreferences::hasAnyHardwareAcceleration() -{ - // Always use VDS_AUTO to avoid spamming the user with warnings - // if they've forced software decoding. - return Session::isHardwareDecodeAvailable(VDS_AUTO, - VIDEO_FORMAT_H264, - 1920, 1080, 60); -} - -bool StreamingPreferences::isRunningWayland() -{ - return qgetenv("XDG_SESSION_TYPE") == QByteArray("wayland"); -} - -bool StreamingPreferences::isWow64() -{ -#ifdef Q_OS_WIN32 - return QSysInfo::currentCpuArchitecture() != QSysInfo::buildCpuArchitecture(); -#else - return false; -#endif -} - -QString StreamingPreferences::getUnmappedGamepads() -{ - return SdlInputHandler::getUnmappedGamepads(); -} - -int StreamingPreferences::getMaximumStreamingFrameRate() -{ - // Never let the maximum drop below 60 FPS - int maxFrameRate = 60; - - if (SDL_InitSubSystem(SDL_INIT_VIDEO) != 0) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, - "SDL_InitSubSystem(SDL_INIT_VIDEO) failed: %s", - SDL_GetError()); - return maxFrameRate; - } - - SDL_DisplayMode mode, bestMode, desktopMode; - for (int displayIndex = 0; displayIndex < SDL_GetNumVideoDisplays(); displayIndex++) { - // Get the native desktop resolution - if (StreamUtils::getRealDesktopMode(displayIndex, &desktopMode)) { - - // Start at desktop mode and work our way up - bestMode = desktopMode; - for (int i = 0; i < SDL_GetNumDisplayModes(displayIndex); i++) { - if (SDL_GetDisplayMode(displayIndex, i, &mode) == 0) { - if (mode.w == desktopMode.w && mode.h == desktopMode.h) { - if (mode.refresh_rate > bestMode.refresh_rate) { - bestMode = mode; - } - } - } - } - - maxFrameRate = qMax(maxFrameRate, bestMode.refresh_rate); - } - } - - SDL_QuitSubSystem(SDL_INIT_VIDEO); - - return maxFrameRate; -} - -QRect StreamingPreferences::getDesktopResolution(int displayIndex) -{ - if (SDL_InitSubSystem(SDL_INIT_VIDEO) != 0) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, - "SDL_InitSubSystem(SDL_INIT_VIDEO) failed: %s", - SDL_GetError()); - return QRect(); - } - - if (displayIndex >= SDL_GetNumVideoDisplays()) { - SDL_QuitSubSystem(SDL_INIT_VIDEO); - return QRect(); - } - - SDL_DisplayMode mode; - int err = SDL_GetDesktopDisplayMode(displayIndex, &mode); - SDL_QuitSubSystem(SDL_INIT_VIDEO); - - if (err == 0) { - return QRect(0, 0, mode.w, mode.h); - } - else { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, - "SDL_GetDesktopDisplayMode() failed: %s", - SDL_GetError()); - return QRect(); - } -} - -QRect StreamingPreferences::getNativeResolution(int displayIndex) -{ - if (SDL_InitSubSystem(SDL_INIT_VIDEO) != 0) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, - "SDL_InitSubSystem(SDL_INIT_VIDEO) failed: %s", - SDL_GetError()); - return QRect(); - } - - if (displayIndex >= SDL_GetNumVideoDisplays()) { - SDL_QuitSubSystem(SDL_INIT_VIDEO); - return QRect(); - } - - SDL_DisplayMode mode; - bool success = StreamUtils::getRealDesktopMode(displayIndex, &mode); - SDL_QuitSubSystem(SDL_INIT_VIDEO); - - if (success) { - return QRect(0, 0, mode.w, mode.h); - } - else { - return QRect(); - } -} - int StreamingPreferences::getDefaultBitrate(int width, int height, int fps) { // This table prefers 16:10 resolutions because they are diff --git a/app/settings/streamingpreferences.h b/app/settings/streamingpreferences.h index 3305802a..bfa95e87 100644 --- a/app/settings/streamingpreferences.h +++ b/app/settings/streamingpreferences.h @@ -15,20 +15,6 @@ public: Q_INVOKABLE void save(); - Q_INVOKABLE static bool hasAnyHardwareAcceleration(); - - Q_INVOKABLE static bool isRunningWayland(); - - Q_INVOKABLE static bool isWow64(); - - Q_INVOKABLE static int getMaximumStreamingFrameRate(); - - Q_INVOKABLE QRect getDesktopResolution(int displayIndex); - - Q_INVOKABLE QRect getNativeResolution(int displayIndex); - - Q_INVOKABLE QString getUnmappedGamepads(); - void reload(); enum AudioConfig