diff --git a/Source/Core/DolphinLib.props b/Source/Core/DolphinLib.props
index 470d303e21..780f8da7b9 100644
--- a/Source/Core/DolphinLib.props
+++ b/Source/Core/DolphinLib.props
@@ -717,6 +717,7 @@
+
@@ -1306,6 +1307,7 @@
+
diff --git a/Source/Core/VideoCommon/CMakeLists.txt b/Source/Core/VideoCommon/CMakeLists.txt
index 5428facc55..632120ee09 100644
--- a/Source/Core/VideoCommon/CMakeLists.txt
+++ b/Source/Core/VideoCommon/CMakeLists.txt
@@ -169,6 +169,8 @@ add_library(videocommon
VideoConfig.h
VideoState.cpp
VideoState.h
+ Widescreen.cpp
+ Widescreen.h
XFMemory.cpp
XFMemory.h
XFStructs.cpp
diff --git a/Source/Core/VideoCommon/Present.cpp b/Source/Core/VideoCommon/Present.cpp
index d5fa440417..0e7f6b96d9 100644
--- a/Source/Core/VideoCommon/Present.cpp
+++ b/Source/Core/VideoCommon/Present.cpp
@@ -14,11 +14,11 @@
#include "VideoCommon/FrameDumper.h"
#include "VideoCommon/OnScreenUI.h"
#include "VideoCommon/PostProcessing.h"
-#include "VideoCommon/RenderBase.h"
#include "VideoCommon/Statistics.h"
#include "VideoCommon/VertexManagerBase.h"
#include "VideoCommon/VideoConfig.h"
#include "VideoCommon/VideoEvents.h"
+#include "VideoCommon/Widescreen.h"
std::unique_ptr g_presenter;
@@ -246,7 +246,7 @@ float Presenter::CalculateDrawAspectRatio() const
const float aspect_ratio = VideoInterface::GetAspectRatio();
if (aspect_mode == AspectMode::AnalogWide ||
- (aspect_mode == AspectMode::Auto && g_renderer->IsGameWidescreen()))
+ (aspect_mode == AspectMode::Auto && g_widescreen->IsGameWidescreen()))
{
return AspectToWidescreen(aspect_ratio);
}
@@ -346,7 +346,7 @@ std::tuple Presenter::ApplyStandardAspectCrop(float width, float h
const float current_aspect = width / height;
const float expected_aspect =
(aspect_mode == AspectMode::AnalogWide ||
- (aspect_mode == AspectMode::Auto && g_renderer->IsGameWidescreen())) ?
+ (aspect_mode == AspectMode::Auto && g_widescreen->IsGameWidescreen())) ?
(16.0f / 9.0f) :
(4.0f / 3.0f);
if (current_aspect > expected_aspect)
@@ -373,7 +373,7 @@ void Presenter::UpdateDrawRectangle()
if (g_ActiveConfig.bWidescreenHack)
{
float source_aspect = VideoInterface::GetAspectRatio();
- if (g_renderer && g_renderer->IsGameWidescreen())
+ if (g_widescreen->IsGameWidescreen())
source_aspect = AspectToWidescreen(source_aspect);
const float adjust = source_aspect / draw_aspect_ratio;
diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp
index d324dacac6..e597ee1e82 100644
--- a/Source/Core/VideoCommon/RenderBase.cpp
+++ b/Source/Core/VideoCommon/RenderBase.cpp
@@ -26,19 +26,14 @@
#include "Common/Logging/Log.h"
#include "Common/MsgHandler.h"
-#include "Core/Config/SYSCONFSettings.h"
#include "Core/ConfigManager.h"
#include "Core/System.h"
-#include "VideoCommon/AbstractGfx.h"
#include "VideoCommon/BPFunctions.h"
#include "VideoCommon/BPMemory.h"
-#include "VideoCommon/BoundingBox.h"
-#include "VideoCommon/FrameDumper.h"
#include "VideoCommon/FramebufferManager.h"
#include "VideoCommon/PixelEngine.h"
#include "VideoCommon/Present.h"
-#include "VideoCommon/VertexManagerBase.h"
#include "VideoCommon/VideoBackendBase.h"
#include "VideoCommon/VideoCommon.h"
#include "VideoCommon/VideoConfig.h"
@@ -48,15 +43,6 @@ std::unique_ptr g_renderer;
Renderer::Renderer() : m_prev_efb_format{PixelFormat::INVALID_FMT}
{
- UpdateWidescreen();
-
- m_config_changed_handle =
- ConfigChangedEvent::Register([this](u32 bits) { OnConfigChanged(bits); }, "Renderer");
-
- // VertexManager doesn't maintain statistics in Wii mode.
- if (!SConfig::GetInstance().bWii)
- m_update_widescreen_handle =
- AfterFrameEvent::Register([this] { UpdateWidescreenHeuristic(); }, "WideScreen Heuristic");
}
Renderer::~Renderer() = default;
@@ -166,85 +152,6 @@ void Renderer::PokeEFB(EFBAccessType type, const EfbPokeData* points, size_t num
}
}
-void Renderer::UpdateWidescreen()
-{
- if (SConfig::GetInstance().bWii)
- m_is_game_widescreen = Config::Get(Config::SYSCONF_WIDESCREEN);
-
- // suggested_aspect_mode overrides SYSCONF_WIDESCREEN
- if (g_ActiveConfig.suggested_aspect_mode == AspectMode::Analog)
- m_is_game_widescreen = false;
- else if (g_ActiveConfig.suggested_aspect_mode == AspectMode::AnalogWide)
- m_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::Analog)
- m_is_game_widescreen = false;
- else if (aspect_mode == AspectMode::AnalogWide)
- m_is_game_widescreen = true;
- }
-}
-
-// Heuristic to detect if a GameCube game is in 16:9 anamorphic widescreen mode.
-void Renderer::UpdateWidescreenHeuristic()
-{
- const auto flush_statistics = g_vertex_manager->ResetFlushAspectRatioCount();
-
- // If suggested_aspect_mode (GameINI) is configured don't use heuristic.
- if (g_ActiveConfig.suggested_aspect_mode != AspectMode::Auto)
- return;
-
- UpdateWidescreen();
-
- // 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::Analog ||
- g_ActiveConfig.aspect_mode == AspectMode::AnalogWide))
- 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.
- static constexpr u32 TRANSITION_THRESHOLD = 3;
-
- const auto looks_normal = [](auto& counts) {
- return counts.normal_vertex_count > counts.anamorphic_vertex_count * TRANSITION_THRESHOLD;
- };
- const auto looks_anamorphic = [](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);
-
- 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)))
- {
- // 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;
- }
-
- m_was_orthographically_anamorphic = ortho_looks_anamorphic;
-}
-
-void Renderer::OnConfigChanged(u32 bits)
-{
- if (bits & CONFIG_CHANGE_BIT_ASPECT_RATIO)
- UpdateWidescreen();
-}
-
bool Renderer::UseVertexDepthRange()
{
// We can't compute the depth range in the vertex shader if we don't support depth clamp.
@@ -266,10 +173,5 @@ bool Renderer::UseVertexDepthRange()
void Renderer::DoState(PointerWrap& p)
{
- p.Do(m_is_game_widescreen);
-
- if (p.IsReadMode())
- {
- m_was_orthographically_anamorphic = false;
- }
+ p.Do(m_prev_efb_format);
}
diff --git a/Source/Core/VideoCommon/RenderBase.h b/Source/Core/VideoCommon/RenderBase.h
index afdfffccb9..e2ff0d0a06 100644
--- a/Source/Core/VideoCommon/RenderBase.h
+++ b/Source/Core/VideoCommon/RenderBase.h
@@ -37,28 +37,14 @@ public:
virtual u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data);
virtual void PokeEFB(EFBAccessType type, const EfbPokeData* points, size_t num_points);
- bool IsGameWidescreen() const { return m_is_game_widescreen; }
-
PixelFormat GetPrevPixelFormat() const { return m_prev_efb_format; }
void StorePixelFormat(PixelFormat new_format) { m_prev_efb_format = new_format; }
static bool UseVertexDepthRange();
void DoState(PointerWrap& p);
- void OnConfigChanged(u32 bits);
-
-protected:
- void UpdateWidescreen();
- void UpdateWidescreenHeuristic();
-
- bool m_is_game_widescreen = false;
- bool m_was_orthographically_anamorphic = false;
-
private:
PixelFormat m_prev_efb_format;
-
- EventHook m_update_widescreen_handle;
- EventHook m_config_changed_handle;
};
extern std::unique_ptr g_renderer;
diff --git a/Source/Core/VideoCommon/VideoBackendBase.cpp b/Source/Core/VideoCommon/VideoBackendBase.cpp
index 3eeceb3c5e..95b58322d2 100644
--- a/Source/Core/VideoCommon/VideoBackendBase.cpp
+++ b/Source/Core/VideoCommon/VideoBackendBase.cpp
@@ -64,6 +64,7 @@
#include "VideoCommon/VideoCommon.h"
#include "VideoCommon/VideoConfig.h"
#include "VideoCommon/VideoState.h"
+#include "VideoCommon/Widescreen.h"
VideoBackendBase* g_video_backend = nullptr;
@@ -359,6 +360,7 @@ bool VideoBackendBase::InitializeShared(std::unique_ptr gfx,
g_framebuffer_manager = std::make_unique();
g_shader_cache = std::make_unique();
g_graphics_mod_manager = std::make_unique();
+ g_widescreen = std::make_unique();
auto& system = Core::System::GetInstance();
auto& command_processor = system.GetCommandProcessor();
@@ -407,6 +409,7 @@ void VideoBackendBase::ShutdownShared()
g_shader_cache.reset();
g_vertex_manager.reset();
g_renderer.reset();
+ g_widescreen.reset();
g_presenter.reset();
g_gfx.reset();
diff --git a/Source/Core/VideoCommon/VideoState.cpp b/Source/Core/VideoCommon/VideoState.cpp
index 5aae09e354..45b06e4973 100644
--- a/Source/Core/VideoCommon/VideoState.cpp
+++ b/Source/Core/VideoCommon/VideoState.cpp
@@ -26,6 +26,7 @@
#include "VideoCommon/VertexLoaderManager.h"
#include "VideoCommon/VertexManagerBase.h"
#include "VideoCommon/VertexShaderManager.h"
+#include "VideoCommon/Widescreen.h"
#include "VideoCommon/XFMemory.h"
void VideoCommon_DoState(PointerWrap& p)
@@ -105,6 +106,9 @@ void VideoCommon_DoState(PointerWrap& p)
g_bounding_box->DoState(p);
p.DoMarker("Bounding Box");
+ g_widescreen->DoState(p);
+ p.DoMarker("Widescreen");
+
// Refresh state.
if (p.IsReadMode())
{
diff --git a/Source/Core/VideoCommon/Widescreen.cpp b/Source/Core/VideoCommon/Widescreen.cpp
new file mode 100644
index 0000000000..ac8fa2fcfd
--- /dev/null
+++ b/Source/Core/VideoCommon/Widescreen.cpp
@@ -0,0 +1,113 @@
+// Copyright 2023 Dolphin Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "VideoCommon/Widescreen.h"
+
+#include "Common/ChunkFile.h"
+#include "Core/Config/SYSCONFSettings.h"
+#include "Core/ConfigManager.h"
+
+#include "VideoCommon/VertexManagerBase.h"
+
+std::unique_ptr g_widescreen;
+
+WidescreenManager::WidescreenManager()
+{
+ Update();
+
+ m_config_changed = ConfigChangedEvent::Register([this](u32 bits) {
+ if (bits & (CONFIG_CHANGE_BIT_ASPECT_RATIO))
+ Update();
+ }, "Widescreen");
+
+ // VertexManager doesn't maintain statistics in Wii mode.
+ if (!SConfig::GetInstance().bWii)
+ {
+ m_update_widescreen =
+ AfterFrameEvent::Register([this] { UpdateWidescreenHeuristic(); }, "WideScreen Heuristic");
+ }
+}
+
+
+void WidescreenManager::Update()
+{
+ if (SConfig::GetInstance().bWii)
+ m_is_game_widescreen = Config::Get(Config::SYSCONF_WIDESCREEN);
+
+ // suggested_aspect_mode overrides SYSCONF_WIDESCREEN
+ if (g_ActiveConfig.suggested_aspect_mode == AspectMode::Analog)
+ m_is_game_widescreen = false;
+ else if (g_ActiveConfig.suggested_aspect_mode == AspectMode::AnalogWide)
+ m_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::Analog)
+ m_is_game_widescreen = false;
+ else if (aspect_mode == AspectMode::AnalogWide)
+ m_is_game_widescreen = true;
+ }
+}
+
+// Heuristic to detect if a GameCube game is in 16:9 anamorphic widescreen mode.
+void WidescreenManager::UpdateWidescreenHeuristic()
+{
+ const auto flush_statistics = g_vertex_manager->ResetFlushAspectRatioCount();
+
+ // If suggested_aspect_mode (GameINI) is configured don't use heuristic.
+ if (g_ActiveConfig.suggested_aspect_mode != AspectMode::Auto)
+ return;
+
+ Update();
+
+ // 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::Analog ||
+ g_ActiveConfig.aspect_mode == AspectMode::AnalogWide))
+ 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.
+ static constexpr u32 TRANSITION_THRESHOLD = 3;
+
+ const auto looks_normal = [](auto& counts) {
+ return counts.normal_vertex_count > counts.anamorphic_vertex_count * TRANSITION_THRESHOLD;
+ };
+ const auto looks_anamorphic = [](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);
+
+ 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)))
+ {
+ // 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;
+ }
+
+ m_was_orthographically_anamorphic = ortho_looks_anamorphic;
+}
+
+void WidescreenManager::DoState(PointerWrap& p)
+{
+ p.Do(m_is_game_widescreen);
+
+ if (p.IsReadMode())
+ {
+ m_was_orthographically_anamorphic = false;
+ }
+}
\ No newline at end of file
diff --git a/Source/Core/VideoCommon/Widescreen.h b/Source/Core/VideoCommon/Widescreen.h
new file mode 100644
index 0000000000..437149cb54
--- /dev/null
+++ b/Source/Core/VideoCommon/Widescreen.h
@@ -0,0 +1,34 @@
+// Copyright 2023 Dolphin Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include
+
+
+#include "VideoCommon/VideoConfig.h"
+#include "VideoCommon/VideoEvents.h"
+
+class PointerWrap;
+
+// This class is responsible for tracking the game's aspect ratio.
+class WidescreenManager
+{
+public:
+ WidescreenManager();
+
+ bool IsGameWidescreen() const { return m_is_game_widescreen; }
+
+ void DoState(PointerWrap& p);
+private:
+ void Update();
+ void UpdateWidescreenHeuristic();
+
+ bool m_is_game_widescreen = false;
+ bool m_was_orthographically_anamorphic = false;
+
+ EventHook m_update_widescreen;
+ EventHook m_config_changed;
+};
+
+extern std::unique_ptr g_widescreen;
\ No newline at end of file