Move WidescreenHeuristic to it's own class
It's about the only thing left in renderer
This commit is contained in:
parent
31cfe8250d
commit
9b5397abdb
|
@ -717,6 +717,7 @@
|
||||||
<ClInclude Include="VideoCommon\VideoConfig.h" />
|
<ClInclude Include="VideoCommon\VideoConfig.h" />
|
||||||
<ClInclude Include="VideoCommon\VideoEvents.h" />
|
<ClInclude Include="VideoCommon\VideoEvents.h" />
|
||||||
<ClInclude Include="VideoCommon\VideoState.h" />
|
<ClInclude Include="VideoCommon\VideoState.h" />
|
||||||
|
<ClInclude Include="VideoCommon\Widescreen.h" />
|
||||||
<ClInclude Include="VideoCommon\XFMemory.h" />
|
<ClInclude Include="VideoCommon\XFMemory.h" />
|
||||||
<ClInclude Include="VideoCommon\XFStructs.h" />
|
<ClInclude Include="VideoCommon\XFStructs.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -1306,6 +1307,7 @@
|
||||||
<ClCompile Include="VideoCommon\VideoBackendBase.cpp" />
|
<ClCompile Include="VideoCommon\VideoBackendBase.cpp" />
|
||||||
<ClCompile Include="VideoCommon\VideoConfig.cpp" />
|
<ClCompile Include="VideoCommon\VideoConfig.cpp" />
|
||||||
<ClCompile Include="VideoCommon\VideoState.cpp" />
|
<ClCompile Include="VideoCommon\VideoState.cpp" />
|
||||||
|
<ClCompile Include="VideoCommon\Widescreen.cpp" />
|
||||||
<ClCompile Include="VideoCommon\XFMemory.cpp" />
|
<ClCompile Include="VideoCommon\XFMemory.cpp" />
|
||||||
<ClCompile Include="VideoCommon\XFStructs.cpp" />
|
<ClCompile Include="VideoCommon\XFStructs.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -169,6 +169,8 @@ add_library(videocommon
|
||||||
VideoConfig.h
|
VideoConfig.h
|
||||||
VideoState.cpp
|
VideoState.cpp
|
||||||
VideoState.h
|
VideoState.h
|
||||||
|
Widescreen.cpp
|
||||||
|
Widescreen.h
|
||||||
XFMemory.cpp
|
XFMemory.cpp
|
||||||
XFMemory.h
|
XFMemory.h
|
||||||
XFStructs.cpp
|
XFStructs.cpp
|
||||||
|
|
|
@ -14,11 +14,11 @@
|
||||||
#include "VideoCommon/FrameDumper.h"
|
#include "VideoCommon/FrameDumper.h"
|
||||||
#include "VideoCommon/OnScreenUI.h"
|
#include "VideoCommon/OnScreenUI.h"
|
||||||
#include "VideoCommon/PostProcessing.h"
|
#include "VideoCommon/PostProcessing.h"
|
||||||
#include "VideoCommon/RenderBase.h"
|
|
||||||
#include "VideoCommon/Statistics.h"
|
#include "VideoCommon/Statistics.h"
|
||||||
#include "VideoCommon/VertexManagerBase.h"
|
#include "VideoCommon/VertexManagerBase.h"
|
||||||
#include "VideoCommon/VideoConfig.h"
|
#include "VideoCommon/VideoConfig.h"
|
||||||
#include "VideoCommon/VideoEvents.h"
|
#include "VideoCommon/VideoEvents.h"
|
||||||
|
#include "VideoCommon/Widescreen.h"
|
||||||
|
|
||||||
std::unique_ptr<VideoCommon::Presenter> g_presenter;
|
std::unique_ptr<VideoCommon::Presenter> g_presenter;
|
||||||
|
|
||||||
|
@ -246,7 +246,7 @@ float Presenter::CalculateDrawAspectRatio() const
|
||||||
const float aspect_ratio = VideoInterface::GetAspectRatio();
|
const float aspect_ratio = VideoInterface::GetAspectRatio();
|
||||||
|
|
||||||
if (aspect_mode == AspectMode::AnalogWide ||
|
if (aspect_mode == AspectMode::AnalogWide ||
|
||||||
(aspect_mode == AspectMode::Auto && g_renderer->IsGameWidescreen()))
|
(aspect_mode == AspectMode::Auto && g_widescreen->IsGameWidescreen()))
|
||||||
{
|
{
|
||||||
return AspectToWidescreen(aspect_ratio);
|
return AspectToWidescreen(aspect_ratio);
|
||||||
}
|
}
|
||||||
|
@ -346,7 +346,7 @@ std::tuple<float, float> Presenter::ApplyStandardAspectCrop(float width, float h
|
||||||
const float current_aspect = width / height;
|
const float current_aspect = width / height;
|
||||||
const float expected_aspect =
|
const float expected_aspect =
|
||||||
(aspect_mode == AspectMode::AnalogWide ||
|
(aspect_mode == AspectMode::AnalogWide ||
|
||||||
(aspect_mode == AspectMode::Auto && g_renderer->IsGameWidescreen())) ?
|
(aspect_mode == AspectMode::Auto && g_widescreen->IsGameWidescreen())) ?
|
||||||
(16.0f / 9.0f) :
|
(16.0f / 9.0f) :
|
||||||
(4.0f / 3.0f);
|
(4.0f / 3.0f);
|
||||||
if (current_aspect > expected_aspect)
|
if (current_aspect > expected_aspect)
|
||||||
|
@ -373,7 +373,7 @@ void Presenter::UpdateDrawRectangle()
|
||||||
if (g_ActiveConfig.bWidescreenHack)
|
if (g_ActiveConfig.bWidescreenHack)
|
||||||
{
|
{
|
||||||
float source_aspect = VideoInterface::GetAspectRatio();
|
float source_aspect = VideoInterface::GetAspectRatio();
|
||||||
if (g_renderer && g_renderer->IsGameWidescreen())
|
if (g_widescreen->IsGameWidescreen())
|
||||||
source_aspect = AspectToWidescreen(source_aspect);
|
source_aspect = AspectToWidescreen(source_aspect);
|
||||||
|
|
||||||
const float adjust = source_aspect / draw_aspect_ratio;
|
const float adjust = source_aspect / draw_aspect_ratio;
|
||||||
|
|
|
@ -26,19 +26,14 @@
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
#include "Common/MsgHandler.h"
|
#include "Common/MsgHandler.h"
|
||||||
|
|
||||||
#include "Core/Config/SYSCONFSettings.h"
|
|
||||||
#include "Core/ConfigManager.h"
|
#include "Core/ConfigManager.h"
|
||||||
#include "Core/System.h"
|
#include "Core/System.h"
|
||||||
|
|
||||||
#include "VideoCommon/AbstractGfx.h"
|
|
||||||
#include "VideoCommon/BPFunctions.h"
|
#include "VideoCommon/BPFunctions.h"
|
||||||
#include "VideoCommon/BPMemory.h"
|
#include "VideoCommon/BPMemory.h"
|
||||||
#include "VideoCommon/BoundingBox.h"
|
|
||||||
#include "VideoCommon/FrameDumper.h"
|
|
||||||
#include "VideoCommon/FramebufferManager.h"
|
#include "VideoCommon/FramebufferManager.h"
|
||||||
#include "VideoCommon/PixelEngine.h"
|
#include "VideoCommon/PixelEngine.h"
|
||||||
#include "VideoCommon/Present.h"
|
#include "VideoCommon/Present.h"
|
||||||
#include "VideoCommon/VertexManagerBase.h"
|
|
||||||
#include "VideoCommon/VideoBackendBase.h"
|
#include "VideoCommon/VideoBackendBase.h"
|
||||||
#include "VideoCommon/VideoCommon.h"
|
#include "VideoCommon/VideoCommon.h"
|
||||||
#include "VideoCommon/VideoConfig.h"
|
#include "VideoCommon/VideoConfig.h"
|
||||||
|
@ -48,15 +43,6 @@ std::unique_ptr<Renderer> g_renderer;
|
||||||
|
|
||||||
Renderer::Renderer() : m_prev_efb_format{PixelFormat::INVALID_FMT}
|
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;
|
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()
|
bool Renderer::UseVertexDepthRange()
|
||||||
{
|
{
|
||||||
// We can't compute the depth range in the vertex shader if we don't support depth clamp.
|
// 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)
|
void Renderer::DoState(PointerWrap& p)
|
||||||
{
|
{
|
||||||
p.Do(m_is_game_widescreen);
|
p.Do(m_prev_efb_format);
|
||||||
|
|
||||||
if (p.IsReadMode())
|
|
||||||
{
|
|
||||||
m_was_orthographically_anamorphic = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,28 +37,14 @@ public:
|
||||||
virtual u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data);
|
virtual u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data);
|
||||||
virtual void PokeEFB(EFBAccessType type, const EfbPokeData* points, size_t num_points);
|
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; }
|
PixelFormat GetPrevPixelFormat() const { return m_prev_efb_format; }
|
||||||
void StorePixelFormat(PixelFormat new_format) { m_prev_efb_format = new_format; }
|
void StorePixelFormat(PixelFormat new_format) { m_prev_efb_format = new_format; }
|
||||||
|
|
||||||
static bool UseVertexDepthRange();
|
static bool UseVertexDepthRange();
|
||||||
void DoState(PointerWrap& p);
|
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:
|
private:
|
||||||
PixelFormat m_prev_efb_format;
|
PixelFormat m_prev_efb_format;
|
||||||
|
|
||||||
EventHook m_update_widescreen_handle;
|
|
||||||
EventHook m_config_changed_handle;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern std::unique_ptr<Renderer> g_renderer;
|
extern std::unique_ptr<Renderer> g_renderer;
|
||||||
|
|
|
@ -64,6 +64,7 @@
|
||||||
#include "VideoCommon/VideoCommon.h"
|
#include "VideoCommon/VideoCommon.h"
|
||||||
#include "VideoCommon/VideoConfig.h"
|
#include "VideoCommon/VideoConfig.h"
|
||||||
#include "VideoCommon/VideoState.h"
|
#include "VideoCommon/VideoState.h"
|
||||||
|
#include "VideoCommon/Widescreen.h"
|
||||||
|
|
||||||
VideoBackendBase* g_video_backend = nullptr;
|
VideoBackendBase* g_video_backend = nullptr;
|
||||||
|
|
||||||
|
@ -359,6 +360,7 @@ bool VideoBackendBase::InitializeShared(std::unique_ptr<AbstractGfx> gfx,
|
||||||
g_framebuffer_manager = std::make_unique<FramebufferManager>();
|
g_framebuffer_manager = std::make_unique<FramebufferManager>();
|
||||||
g_shader_cache = std::make_unique<VideoCommon::ShaderCache>();
|
g_shader_cache = std::make_unique<VideoCommon::ShaderCache>();
|
||||||
g_graphics_mod_manager = std::make_unique<GraphicsModManager>();
|
g_graphics_mod_manager = std::make_unique<GraphicsModManager>();
|
||||||
|
g_widescreen = std::make_unique<WidescreenManager>();
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = Core::System::GetInstance();
|
||||||
auto& command_processor = system.GetCommandProcessor();
|
auto& command_processor = system.GetCommandProcessor();
|
||||||
|
@ -407,6 +409,7 @@ void VideoBackendBase::ShutdownShared()
|
||||||
g_shader_cache.reset();
|
g_shader_cache.reset();
|
||||||
g_vertex_manager.reset();
|
g_vertex_manager.reset();
|
||||||
g_renderer.reset();
|
g_renderer.reset();
|
||||||
|
g_widescreen.reset();
|
||||||
g_presenter.reset();
|
g_presenter.reset();
|
||||||
g_gfx.reset();
|
g_gfx.reset();
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "VideoCommon/VertexLoaderManager.h"
|
#include "VideoCommon/VertexLoaderManager.h"
|
||||||
#include "VideoCommon/VertexManagerBase.h"
|
#include "VideoCommon/VertexManagerBase.h"
|
||||||
#include "VideoCommon/VertexShaderManager.h"
|
#include "VideoCommon/VertexShaderManager.h"
|
||||||
|
#include "VideoCommon/Widescreen.h"
|
||||||
#include "VideoCommon/XFMemory.h"
|
#include "VideoCommon/XFMemory.h"
|
||||||
|
|
||||||
void VideoCommon_DoState(PointerWrap& p)
|
void VideoCommon_DoState(PointerWrap& p)
|
||||||
|
@ -105,6 +106,9 @@ void VideoCommon_DoState(PointerWrap& p)
|
||||||
g_bounding_box->DoState(p);
|
g_bounding_box->DoState(p);
|
||||||
p.DoMarker("Bounding Box");
|
p.DoMarker("Bounding Box");
|
||||||
|
|
||||||
|
g_widescreen->DoState(p);
|
||||||
|
p.DoMarker("Widescreen");
|
||||||
|
|
||||||
// Refresh state.
|
// Refresh state.
|
||||||
if (p.IsReadMode())
|
if (p.IsReadMode())
|
||||||
{
|
{
|
||||||
|
|
|
@ -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<WidescreenManager> 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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
// Copyright 2023 Dolphin Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
|
||||||
|
#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<WidescreenManager> g_widescreen;
|
Loading…
Reference in New Issue