diff options
| author | Admiral H. Curtiss <pikachu025@gmail.com> | 2024-02-20 21:36:43 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-02-20 21:36:43 +0100 |
| commit | 5090a028e6e4125b780bcb1c76dcd8fe956a0b97 (patch) | |
| tree | 10a0a98a20543b8bc91ef09a0cb18939266abe43 /Source/Core | |
| parent | 4b56ce3988c9b0143671a4a2883eedd6e0937d19 (diff) | |
| parent | 48fbbdba7ca8b84bc6e8a5c2cd4f7b6a38422bca (diff) | |
Merge pull request #12435 from Filoppi/fix-aspect-ratio-stuck
Fix aspect ratio heuristics getting stuck to a state
Diffstat (limited to 'Source/Core')
| -rw-r--r-- | Source/Core/VideoCommon/Widescreen.cpp | 134 | ||||
| -rw-r--r-- | Source/Core/VideoCommon/Widescreen.h | 12 |
2 files changed, 100 insertions, 46 deletions
diff --git a/Source/Core/VideoCommon/Widescreen.cpp b/Source/Core/VideoCommon/Widescreen.cpp index 6cc12c7fc1..d35ba758ec 100644 --- a/Source/Core/VideoCommon/Widescreen.cpp +++ b/Source/Core/VideoCommon/Widescreen.cpp @@ -4,6 +4,7 @@ #include "VideoCommon/Widescreen.h" #include "Common/ChunkFile.h" +#include "Common/Logging/Log.h" #include "Core/Config/SYSCONFSettings.h" #include "Core/System.h" @@ -13,12 +14,34 @@ std::unique_ptr<WidescreenManager> g_widescreen; WidescreenManager::WidescreenManager() { - Update(); + std::optional<bool> is_game_widescreen = GetWidescreenOverride(); + if (is_game_widescreen.has_value()) + m_is_game_widescreen = is_game_widescreen.value(); + + // Throw a warning as unsupported aspect ratio modes have no specific behavior to them + const bool is_valid_suggested_aspect_mode = + g_ActiveConfig.suggested_aspect_mode == AspectMode::Auto || + g_ActiveConfig.suggested_aspect_mode == AspectMode::ForceStandard || + g_ActiveConfig.suggested_aspect_mode == AspectMode::ForceWide; + if (!is_valid_suggested_aspect_mode) + { + WARN_LOG_FMT(VIDEO, + "Invalid suggested aspect ratio mode: only Auto, 4:3 and 16:9 are supported"); + } m_config_changed = ConfigChangedEvent::Register( [this](u32 bits) { if (bits & (CONFIG_CHANGE_BIT_ASPECT_RATIO)) - Update(); + { + std::optional<bool> is_game_widescreen = GetWidescreenOverride(); + // If the widescreen flag isn't being overridden by any settings, + // reset it to default if heuristic aren't running or to the last + // heuristic value if they were running. + if (!is_game_widescreen.has_value()) + is_game_widescreen = (m_heuristic_state == HeuristicState::Active_Found_Anamorphic); + if (is_game_widescreen.has_value()) + m_is_game_widescreen = is_game_widescreen.value(); + } }, "Widescreen"); @@ -31,80 +54,100 @@ WidescreenManager::WidescreenManager() } } -void WidescreenManager::Update() +std::optional<bool> WidescreenManager::GetWidescreenOverride() const { + std::optional<bool> is_game_widescreen; + auto& system = Core::System::GetInstance(); if (system.IsWii()) - m_is_game_widescreen = Config::Get(Config::SYSCONF_WIDESCREEN); + is_game_widescreen = Config::Get(Config::SYSCONF_WIDESCREEN); // suggested_aspect_mode overrides SYSCONF_WIDESCREEN if (g_ActiveConfig.suggested_aspect_mode == AspectMode::ForceStandard) - m_is_game_widescreen = false; + is_game_widescreen = false; else if (g_ActiveConfig.suggested_aspect_mode == AspectMode::ForceWide) - m_is_game_widescreen = true; + is_game_widescreen = true; // If widescreen hack is disabled override game's AR if UI is set to 4:3 or 16:9. if (!g_ActiveConfig.bWidescreenHack) { const auto aspect_mode = g_ActiveConfig.aspect_mode; if (aspect_mode == AspectMode::ForceStandard) - m_is_game_widescreen = false; + is_game_widescreen = false; else if (aspect_mode == AspectMode::ForceWide) - m_is_game_widescreen = true; + is_game_widescreen = true; } + + return is_game_widescreen; } // Heuristic to detect if a GameCube game is in 16:9 anamorphic widescreen mode. // Cheats that change the game aspect ratio to natively unsupported ones won't be recognized here. void WidescreenManager::UpdateWidescreenHeuristic() { + // Reset to baseline state before the update const auto flush_statistics = g_vertex_manager->ResetFlushAspectRatioCount(); + const bool was_orthographically_anamorphic = m_was_orthographically_anamorphic; + m_heuristic_state = HeuristicState::Inactive; + m_was_orthographically_anamorphic = false; // If suggested_aspect_mode (GameINI) is configured don't use heuristic. + // We also don't need to check "GetWidescreenOverride()" in this case as + // nothing would have changed there. if (g_ActiveConfig.suggested_aspect_mode != AspectMode::Auto) return; - Update(); - - // If widescreen hack isn't active and aspect_mode (user setting) - // is set to a forced aspect ratio, don't use heuristic. - if (!g_ActiveConfig.bWidescreenHack && (g_ActiveConfig.aspect_mode == AspectMode::ForceStandard || - g_ActiveConfig.aspect_mode == AspectMode::ForceWide)) - return; - - // Modify the threshold based on which aspect ratio we're already using: - // If the game's in 4:3, it probably won't switch to anamorphic, and vice-versa. - const u32 transition_threshold = g_ActiveConfig.widescreen_heuristic_transition_threshold; - - const auto looks_normal = [transition_threshold](auto& counts) { - return counts.normal_vertex_count > counts.anamorphic_vertex_count * transition_threshold; - }; - const auto looks_anamorphic = [transition_threshold](auto& counts) { - return counts.anamorphic_vertex_count > counts.normal_vertex_count * transition_threshold; - }; - - const auto& persp = flush_statistics.perspective; - const auto& ortho = flush_statistics.orthographic; + std::optional<bool> is_game_widescreen = GetWidescreenOverride(); - const auto ortho_looks_anamorphic = looks_anamorphic(ortho); - - if (looks_anamorphic(persp) || ortho_looks_anamorphic) - { - // If either perspective or orthographic projections look anamorphic, it's a safe bet. - m_is_game_widescreen = true; - } - else if (looks_normal(persp) || (m_was_orthographically_anamorphic && looks_normal(ortho))) + // If widescreen hack isn't active and aspect_mode (UI) is 4:3 or 16:9 don't use heuristic. + if (g_ActiveConfig.bWidescreenHack || (g_ActiveConfig.aspect_mode != AspectMode::ForceStandard && + g_ActiveConfig.aspect_mode != AspectMode::ForceWide)) { - // Many widescreen games (or AR/GeckoCodes) use anamorphic perspective projections - // with NON-anamorphic orthographic projections. - // This can cause incorrect changes to 4:3 when perspective projections are temporarily not - // shown. e.g. Animal Crossing's inventory menu. - // Unless we were in a situation which was orthographically anamorphic - // we won't consider orthographic data for changes from 16:9 to 4:3. - m_is_game_widescreen = false; + // Modify the threshold based on which aspect ratio we're already using: + // If the game's in 4:3, it probably won't switch to anamorphic, and vice-versa. + const u32 transition_threshold = g_ActiveConfig.widescreen_heuristic_transition_threshold; + + const auto looks_normal = [transition_threshold](auto& counts) { + return counts.normal_vertex_count > counts.anamorphic_vertex_count * transition_threshold; + }; + const auto looks_anamorphic = [transition_threshold](auto& counts) { + return counts.anamorphic_vertex_count > counts.normal_vertex_count * transition_threshold; + }; + + const auto& persp = flush_statistics.perspective; + const auto& ortho = flush_statistics.orthographic; + + const auto ortho_looks_anamorphic = looks_anamorphic(ortho); + const auto persp_looks_normal = looks_normal(persp); + + if (looks_anamorphic(persp) || ortho_looks_anamorphic) + { + // If either perspective or orthographic projections look anamorphic, it's a safe bet. + is_game_widescreen = true; + m_heuristic_state = HeuristicState::Active_Found_Anamorphic; + } + else if (persp_looks_normal || looks_normal(ortho)) + { + // Many widescreen games (or AR/GeckoCodes) use anamorphic perspective projections + // with NON-anamorphic orthographic projections. + // This can cause incorrect changes to 4:3 when perspective projections are temporarily not + // shown. e.g. Animal Crossing's inventory menu. + // Unless we were in a situation which was orthographically anamorphic + // we won't consider orthographic data for changes from 16:9 to 4:3. + if (persp_looks_normal || was_orthographically_anamorphic) + is_game_widescreen = false; + m_heuristic_state = HeuristicState::Active_Found_Normal; + } + else + { + m_heuristic_state = HeuristicState::Active_NotFound; + } + + m_was_orthographically_anamorphic = ortho_looks_anamorphic; } - m_was_orthographically_anamorphic = ortho_looks_anamorphic; + if (is_game_widescreen.has_value()) + m_is_game_widescreen = is_game_widescreen.value(); } void WidescreenManager::DoState(PointerWrap& p) @@ -114,5 +157,6 @@ void WidescreenManager::DoState(PointerWrap& p) if (p.IsReadMode()) { m_was_orthographically_anamorphic = false; + m_heuristic_state = HeuristicState::Inactive; } } diff --git a/Source/Core/VideoCommon/Widescreen.h b/Source/Core/VideoCommon/Widescreen.h index 586aa48e84..f58ff7880c 100644 --- a/Source/Core/VideoCommon/Widescreen.h +++ b/Source/Core/VideoCommon/Widescreen.h @@ -24,11 +24,21 @@ public: void DoState(PointerWrap& p); private: - void Update(); + enum class HeuristicState + { + Inactive, + Active_NotFound, + Active_Found_Normal, + Active_Found_Anamorphic, + }; + + // Returns whether the widescreen state wants to change, and its target value + std::optional<bool> GetWidescreenOverride() const; void UpdateWidescreenHeuristic(); bool m_is_game_widescreen = false; bool m_was_orthographically_anamorphic = false; + HeuristicState m_heuristic_state = HeuristicState::Inactive; Common::EventHook m_update_widescreen; Common::EventHook m_config_changed; |
