From 50891ee8c261df8ccd3a6962b6211b8f9d806cda Mon Sep 17 00:00:00 2001 From: amwatson Date: Wed, 24 Jan 2024 17:05:36 -0600 Subject: [PATCH] Set resolution and default background based on HMD type --- src/android/app/src/main/jni/config.cpp | 15 ++++- .../app/src/main/jni/vr/utils/LogUtils.h | 3 +- src/android/app/src/main/jni/vr/vr_main.cpp | 66 ++++++++++--------- .../app/src/main/jni/vr/vr_settings.cpp | 48 +++++++++++++- src/android/app/src/main/jni/vr/vr_settings.h | 25 +++---- 5 files changed, 106 insertions(+), 51 deletions(-) diff --git a/src/android/app/src/main/jni/config.cpp b/src/android/app/src/main/jni/config.cpp index fbb1b2791..d5261fb88 100644 --- a/src/android/app/src/main/jni/config.cpp +++ b/src/android/app/src/main/jni/config.cpp @@ -288,8 +288,19 @@ void Config::ReadValues() { sdl2_config->GetInteger("Camera", "camera_outer_left_flip", 0); // VR - VRSettings::values.vr_environment = VRSettings::values.extra_performance_mode_enabled ? 2 /* void environment */: sdl2_config->GetInteger( - "VR", "vr_environment", 1); + + // Note: hmdType is not read as a preference. It is initialized here so that it can + // be used to determine per-hmd settings in the config + { + const std::string hmdTypeStr = VRSettings::GetHMDTypeStr(); + LOG_INFO(Config, "HMD type: {}", hmdTypeStr.c_str()); + VRSettings::values.hmd_type = VRSettings::HmdTypeFromStr(hmdTypeStr); + } + VRSettings::values.vr_environment = VRSettings::values.extra_performance_mode_enabled ? + static_cast(VRSettings::VREnvironmentType::VOID) : sdl2_config->GetInteger( + "VR", "vr_environment", + static_cast(VRSettings::values.hmd_type == VRSettings::HMDType::QUEST3 ? + VRSettings::VREnvironmentType::PASSTHROUGH : VRSettings::VREnvironmentType::VOID)); VRSettings::values.cpu_level = VRSettings::values.extra_performance_mode_enabled ? XR_HIGHEST_CPU_PERF_LEVEL diff --git a/src/android/app/src/main/jni/vr/utils/LogUtils.h b/src/android/app/src/main/jni/vr/utils/LogUtils.h index a35b0b1ce..d2aaff275 100644 --- a/src/android/app/src/main/jni/vr/utils/LogUtils.h +++ b/src/android/app/src/main/jni/vr/utils/LogUtils.h @@ -15,7 +15,7 @@ License : Licensed under GPLv3 or any later version. #include #include #ifndef LOG_TAG -#define LOG_TAG "Citra::VR" +#define LOG_TAG "Citra::Input" #endif #define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) #define ALOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__) @@ -26,6 +26,7 @@ License : Licensed under GPLv3 or any later version. #else #define ALOGD(...) #endif + #define FAIL(...) \ do { \ __android_log_print(ANDROID_LOG_FATAL, LOG_TAG, __VA_ARGS__); \ diff --git a/src/android/app/src/main/jni/vr/vr_main.cpp b/src/android/app/src/main/jni/vr/vr_main.cpp index f0224cd6c..16ecd69c6 100644 --- a/src/android/app/src/main/jni/vr/vr_main.cpp +++ b/src/android/app/src/main/jni/vr/vr_main.cpp @@ -95,7 +95,7 @@ void ForwardButtonStateIfNeeded(JNIEnv* jni, jobject activityObject, } } -const char* XrSessionStateToString(const XrSessionState state) { +[[maybe_unused]] const char* XrSessionStateToString(const XrSessionState state) { switch (state) { case XR_SESSION_STATE_UNKNOWN: return "XR_SESSION_STATE_UNKNOWN"; @@ -122,34 +122,19 @@ const char* XrSessionStateToString(const XrSessionState state) { } } -enum class HMDType { UNKNOWN = 0, QUEST1, QUEST2, QUEST3, QUESTPRO }; - -HMDType StringToHmdType(const std::string& hmdType) { - if (hmdType == "Quest") { - return HMDType::QUEST1; - } else if (hmdType == "Quest" || hmdType == "Quest 2" || hmdType == "Miramar") { - return HMDType::QUEST2; - } else if (hmdType == "Quest 3") { - return HMDType::QUEST3; - } else if (hmdType == "Quest Pro") { - return HMDType::QUESTPRO; - } - return HMDType::UNKNOWN; -} - -uint32_t GetDefaultGameResolutionFactorForHmd(const HMDType& hmdType) { +uint32_t GetDefaultGameResolutionFactorForHmd(const VRSettings::HMDType& hmdType) { static constexpr uint32_t kDefaultResolutionFactor = 2; switch (hmdType) { - case HMDType::QUEST3: + case VRSettings::HMDType::QUEST3: return 3; - case HMDType::UNKNOWN: + case VRSettings::HMDType::UNKNOWN: ALOGW("Warning: Unknown HMD type, using default scale factor of %d", kDefaultResolutionFactor); - case HMDType::QUEST1: + case VRSettings::HMDType::QUEST1: ALOGW("Warning: Unsupported HMD type, using default scale factor of %d", kDefaultResolutionFactor); - case HMDType::QUEST2: - case HMDType::QUESTPRO: + case VRSettings::HMDType::QUEST2: + case VRSettings::HMDType::QUESTPRO: return kDefaultResolutionFactor; } } @@ -201,19 +186,25 @@ public: mInputStateStatic = std::make_unique(OpenXr::GetInstance(), gOpenXr->session_); - assert(VRSettings::values.vr_environment > 0 && VRSettings::values.vr_environment <= 2); + ////////////////////////////////////////////////// + // Create the layers + ////////////////////////////////////////////////// + + // Create the background layer. + assert(VRSettings::values.vr_environment == + static_cast(VRSettings::VREnvironmentType::VOID) || + VRSettings::values.vr_environment == + static_cast(VRSettings::VREnvironmentType::PASSTHROUGH)); // If user set "Void" in settings, don't render passthrough - if (VRSettings::values.vr_environment != 2) { + if (VRSettings::values.vr_environment != + static_cast(VRSettings::VREnvironmentType::VOID)) { mPassthroughLayer = std::make_unique(gOpenXr->session_); } - mCursorLayer = std::make_unique(gOpenXr->session_); - { - const std::string hmdTypeStr = - SyspropUtils::GetSysPropAsString("ro.product.model", "unknown"); - const HMDType hmdType = StringToHmdType(hmdTypeStr); - ALOGI("HMD type: %s (%d)", hmdTypeStr.c_str(), hmdType); - const uint32_t defaultResolutionFactor = GetDefaultGameResolutionFactorForHmd(hmdType); + // Create the game surface layer. + { + const uint32_t defaultResolutionFactor = + GetDefaultGameResolutionFactorForHmd(VRSettings::values.hmd_type); const uint32_t resolutionFactorFromPreferences = VRSettings::values.resolution_factor; const uint32_t resolutionFactor = resolutionFactorFromPreferences > 0 ? resolutionFactorFromPreferences @@ -226,12 +217,19 @@ public: XrVector3f{0, 0, -2.0f}, jni, mActivityObject, gOpenXr->session_, resolutionFactor); } + // Create the cursor layer. + mCursorLayer = std::make_unique(gOpenXr->session_); + #if defined(UI_LAYER) mErrorMessageLayer = std::make_unique("org/citra/citra_emu/vr/ErrorMessageLayer", XrVector3f{0, 0, -0.7}, jni, mActivityObject, gOpenXr->session_); #endif + ////////////////////////////////////////////////// + // Intialize JNI methods + ////////////////////////////////////////////////// + mForwardVRInputMethodID = jni->GetMethodID(jni->GetObjectClass(mActivityObject), "forwardVRInput", "(IZ)V"); if (mForwardVRInputMethodID == nullptr) { @@ -264,6 +262,10 @@ public: FAIL("could not get openSettingsMenuMethodID"); } + ////////////////////////////////////////////////// + // Frame loop + ////////////////////////////////////////////////// + while (!mIsStopRequested) { Frame(jni); } @@ -806,7 +808,7 @@ private: __func__); break; case XR_TYPE_EVENT_DATA_PERF_SETTINGS_EXT: { - const XrEventDataPerfSettingsEXT* pfs = + [[maybe_unused]] const XrEventDataPerfSettingsEXT* pfs = (XrEventDataPerfSettingsEXT*)(baseEventHeader); ALOGV("%s(): Received " "XR_TYPE_EVENT_DATA_PERF_SETTINGS_EXT event: type %d " diff --git a/src/android/app/src/main/jni/vr/vr_settings.cpp b/src/android/app/src/main/jni/vr/vr_settings.cpp index 93948f716..4682f3b4e 100644 --- a/src/android/app/src/main/jni/vr/vr_settings.cpp +++ b/src/android/app/src/main/jni/vr/vr_settings.cpp @@ -1,8 +1,54 @@ +/******************************************************************************* + +Filename : vr_settings.cpp +Content : VR-specific settings initialized in config.cpp + +Authors : Amanda M. Watson +License : Licensed under GPLv3 or any later version. + Refer to the license.txt file included. + +*******************************************************************************/ #include "vr_settings.h" -namespace VRSettings { +#include "utils/LogUtils.h" +#include "utils/SyspropUtils.h" +#include + +namespace VRSettings { Values values = {}; +HMDType HmdTypeFromStr(const std::string& hmdType) { + if (hmdType == "Quest") { + return HMDType::QUEST1; + } else if (hmdType == "Quest" || hmdType == "Quest 2" || hmdType == "Miramar") { + return HMDType::QUEST2; + } else if (hmdType == "Quest 3") { + return HMDType::QUEST3; + } else if (hmdType == "Quest Pro") { + return HMDType::QUESTPRO; + } + return HMDType::UNKNOWN; } + +std::string GetHMDTypeStr() { + return SyspropUtils::GetSysPropAsString("ro.product.model", "Unknown"); +} + +XrPerfSettingsLevelEXT CPUPrefToPerfSettingsLevel(const int32_t cpu_level_pref) { + switch (cpu_level_pref) { + case 1: + return XR_PERF_SETTINGS_LEVEL_POWER_SAVINGS_EXT; + case 2: + return XR_PERF_SETTINGS_LEVEL_SUSTAINED_LOW_EXT; + case 3: + return XR_PERF_SETTINGS_LEVEL_SUSTAINED_HIGH_EXT; + case 4: + return XR_PERF_SETTINGS_LEVEL_BOOST_EXT; + default: + FAIL("Invalid CPU level preference %d", cpu_level_pref); + } +} + +} // namespace VRSettings diff --git a/src/android/app/src/main/jni/vr/vr_settings.h b/src/android/app/src/main/jni/vr/vr_settings.h index f65468105..5ff2004fb 100644 --- a/src/android/app/src/main/jni/vr/vr_settings.h +++ b/src/android/app/src/main/jni/vr/vr_settings.h @@ -15,7 +15,6 @@ License : Licensed under GPLv3 or any later version. #pragma once #include "OpenXR.h" -#include "utils/LogUtils.h" #include @@ -25,26 +24,22 @@ License : Licensed under GPLv3 or any later version. namespace VRSettings { -static inline XrPerfSettingsLevelEXT CPUPrefToPerfSettingsLevel(const int32_t cpu_level_pref) { - switch (cpu_level_pref) { - case 1: - return XR_PERF_SETTINGS_LEVEL_POWER_SAVINGS_EXT; - case 2: - return XR_PERF_SETTINGS_LEVEL_SUSTAINED_LOW_EXT; - case 3: - return XR_PERF_SETTINGS_LEVEL_SUSTAINED_HIGH_EXT; - case 4: - return XR_PERF_SETTINGS_LEVEL_BOOST_EXT; - default: - FAIL("Invalid CPU level preference %d", cpu_level_pref); - } -} +enum class HMDType { UNKNOWN = 0, QUEST1, QUEST2, QUEST3, QUESTPRO }; +enum class VREnvironmentType { PASSTHROUGH = 1, VOID = 2 }; + +// Given a CPU level preference, return the corresponding OpenXR performance level +XrPerfSettingsLevelEXT CPUPrefToPerfSettingsLevel(const int32_t cpu_level_pref); +// Return the HMD type as a string (queried from ro.product.model) +std::string GetHMDTypeStr(); +// Given a string from GetHMDTypeStr(), return the corresponding HMDType +HMDType HmdTypeFromStr(const std::string& hmdType); struct Values { bool extra_performance_mode_enabled = false; int32_t vr_environment = 0; XrPerfSettingsLevelEXT cpu_level = XR_HIGHEST_CPU_PERF_LEVEL; uint32_t resolution_factor = 0; + HMDType hmd_type = HMDType::UNKNOWN; } extern values; } // namespace VRSettings