diff --git a/Source/Core/Core/BootManager.cpp b/Source/Core/Core/BootManager.cpp index 0b7b0b9064..a1ebc7ff4f 100644 --- a/Source/Core/Core/BootManager.cpp +++ b/Source/Core/Core/BootManager.cpp @@ -290,13 +290,11 @@ bool BootCore(const std::string& _rFilename) } } - Core::g_aspect_wide = StartUp.bWii; - // Wii settings if (StartUp.bWii) { IniFile::Section* wii_section = game_ini.GetOrCreateSection("Wii"); - wii_section->Get("Widescreen", &Core::g_aspect_wide, !!StartUp.m_wii_aspect_ratio); + wii_section->Get("Widescreen", &StartUp.m_wii_aspect_ratio, !!StartUp.m_wii_aspect_ratio); wii_section->Get("Language", &StartUp.m_wii_language, StartUp.m_wii_language); int source; diff --git a/Source/Core/Core/Core.cpp b/Source/Core/Core/Core.cpp index ee9a396eae..d886c3bbdd 100644 --- a/Source/Core/Core/Core.cpp +++ b/Source/Core/Core/Core.cpp @@ -81,9 +81,6 @@ namespace Core { -// TODO: ugly, remove -bool g_aspect_wide; - static bool s_wants_determinism; // Declarations and definitions diff --git a/Source/Core/Core/Core.h b/Source/Core/Core/Core.h index 291105c9ab..89bdedb25c 100644 --- a/Source/Core/Core/Core.h +++ b/Source/Core/Core/Core.h @@ -18,9 +18,6 @@ namespace Core { -// TODO: ugly, remove -extern bool g_aspect_wide; - bool GetIsThrottlerTempDisabled(); void SetIsThrottlerTempDisabled(bool disable); diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp index 6af408d9a3..b389756b5b 100644 --- a/Source/Core/VideoCommon/RenderBase.cpp +++ b/Source/Core/VideoCommon/RenderBase.cpp @@ -55,6 +55,8 @@ #include "VideoCommon/Statistics.h" #include "VideoCommon/TextureCacheBase.h" #include "VideoCommon/TextureDecoder.h" +#include "VideoCommon/VertexManagerBase.h" +#include "VideoCommon/VertexShaderManager.h" #include "VideoCommon/VideoConfig.h" #include "VideoCommon/XFMemory.h" @@ -89,6 +91,11 @@ Renderer::Renderer(int backbuffer_width, int backbuffer_height) OSDChoice = 0; OSDTime = 0; + + if (SConfig::GetInstance().bWii) + { + m_aspect_wide = SConfig::GetInstance().m_wii_aspect_ratio != 0; + } } Renderer::~Renderer() @@ -457,7 +464,7 @@ float Renderer::CalculateDrawAspectRatio(int target_width, int target_height) co // The rendering window aspect ratio as a proportion of the 4:3 or 16:9 ratio if (g_ActiveConfig.iAspectRatio == ASPECT_ANALOG_WIDE || - (g_ActiveConfig.iAspectRatio != ASPECT_ANALOG && Core::g_aspect_wide)) + (g_ActiveConfig.iAspectRatio != ASPECT_ANALOG && m_aspect_wide)) { return (static_cast(target_width) / static_cast(target_height)) / AspectToWidescreen(VideoInterface::GetAspectRatio()); @@ -532,7 +539,7 @@ void Renderer::UpdateDrawRectangle() if (g_ActiveConfig.bWidescreenHack) { float source_aspect = VideoInterface::GetAspectRatio(); - if (Core::g_aspect_wide) + if (m_aspect_wide) source_aspect = AspectToWidescreen(source_aspect); float target_aspect; @@ -652,11 +659,10 @@ void Renderer::SetWindowSize(int width, int height) { // Force 4:3 or 16:9 by cropping the image. float current_aspect = scaled_width / scaled_height; - float expected_aspect = - (g_ActiveConfig.iAspectRatio == ASPECT_ANALOG_WIDE || - (g_ActiveConfig.iAspectRatio != ASPECT_ANALOG && Core::g_aspect_wide)) ? - (16.0f / 9.0f) : - (4.0f / 3.0f); + float expected_aspect = (g_ActiveConfig.iAspectRatio == ASPECT_ANALOG_WIDE || + (g_ActiveConfig.iAspectRatio != ASPECT_ANALOG && m_aspect_wide)) ? + (16.0f / 9.0f) : + (4.0f / 3.0f); if (current_aspect > expected_aspect) { // keep height, crop width @@ -722,6 +728,22 @@ void Renderer::RecordVideoMemory() void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const EFBRectangle& rc, u64 ticks, float Gamma) { + // Heuristic to detect if a GameCube game is in 16:9 anamorphic widescreen mode. + if (!SConfig::GetInstance().bWii) + { + size_t flush_count_4_3, flush_count_anamorphic; + std::tie(flush_count_4_3, flush_count_anamorphic) = + g_vertex_manager->ResetFlushAspectRatioCount(); + size_t flush_total = flush_count_4_3 + flush_count_anamorphic; + + // 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. + if (m_aspect_wide) + m_aspect_wide = !(flush_count_4_3 > 0.75 * flush_total); + else + m_aspect_wide = flush_count_anamorphic > 0.75 * flush_total; + } + // TODO: merge more generic parts into VideoCommon SwapImpl(xfbAddr, fbWidth, fbStride, fbHeight, rc, ticks, Gamma); diff --git a/Source/Core/VideoCommon/RenderBase.h b/Source/Core/VideoCommon/RenderBase.h index 4882b8853d..027d7dd793 100644 --- a/Source/Core/VideoCommon/RenderBase.h +++ b/Source/Core/VideoCommon/RenderBase.h @@ -159,6 +159,7 @@ protected: Common::Event m_screenshot_completed; std::mutex m_screenshot_lock; std::string m_screenshot_name; + bool m_aspect_wide = false; // The framebuffer size int m_target_width = 0; diff --git a/Source/Core/VideoCommon/VertexManagerBase.cpp b/Source/Core/VideoCommon/VertexManagerBase.cpp index 2fd3affcaf..b08f311c0a 100644 --- a/Source/Core/VideoCommon/VertexManagerBase.cpp +++ b/Source/Core/VideoCommon/VertexManagerBase.cpp @@ -4,12 +4,14 @@ #include "VideoCommon/VertexManagerBase.h" +#include #include #include "Common/BitSet.h" #include "Common/ChunkFile.h" #include "Common/CommonTypes.h" #include "Common/Logging/Log.h" +#include "Core/ConfigManager.h" #include "VideoCommon/BPMemory.h" #include "VideoCommon/DataReader.h" @@ -41,6 +43,23 @@ static const PrimitiveType primitive_from_gx[8] = { PRIMITIVE_POINTS, // GX_DRAW_POINTS }; +// Due to the BT.601 standard which the GameCube is based on being a compromise +// between PAL and NTSC, neither standard gets square pixels. They are each off +// by ~9% in opposite directions. +// Just in case any game decides to take this into account, we do both these +// tests with a large amount of slop. +static bool AspectIs4_3(float width, float height) +{ + float aspect = fabsf(width / height); + return fabsf(aspect - 4.0f / 3.0f) < 4.0f / 3.0f * 0.11; // within 11% of 4:3 +} + +static bool AspectIs16_9(float width, float height) +{ + float aspect = fabsf(width / height); + return fabsf(aspect - 16.0f / 9.0f) < 16.0f / 9.0f * 0.11; // within 11% of 16:9 +} + VertexManagerBase::VertexManagerBase() { } @@ -157,6 +176,14 @@ u32 VertexManagerBase::GetRemainingIndices(int primitive) } } +std::pair VertexManagerBase::ResetFlushAspectRatioCount() +{ + std::pair val = std::make_pair(m_flush_count_4_3, m_flush_count_anamorphic); + m_flush_count_4_3 = 0; + m_flush_count_anamorphic = 0; + return val; +} + void VertexManagerBase::Flush() { if (m_is_flushed) @@ -237,6 +264,24 @@ void VertexManagerBase::Flush() // set global vertex constants VertexShaderManager::SetConstants(); + // Track some stats used elsewhere by the anamorphic widescreen heuristic. + if (!SConfig::GetInstance().bWii) + { + float* rawProjection = xfmem.projection.rawProjection; + bool viewport_is_4_3 = AspectIs4_3(xfmem.viewport.wd, xfmem.viewport.ht); + if (AspectIs16_9(rawProjection[2], rawProjection[0]) && viewport_is_4_3) + { + // Projection is 16:9 and viewport is 4:3, we are rendering an anamorphic + // widescreen picture. + m_flush_count_anamorphic++; + } + else if (AspectIs4_3(rawProjection[2], rawProjection[0]) && viewport_is_4_3) + { + // Projection and viewports are both 4:3, we are rendering a normal image. + m_flush_count_4_3++; + } + } + // Calculate ZSlope for zfreeze if (!bpmem.genMode.zfreeze) { diff --git a/Source/Core/VideoCommon/VertexManagerBase.h b/Source/Core/VideoCommon/VertexManagerBase.h index 20ebd9307d..dae639a47d 100644 --- a/Source/Core/VideoCommon/VertexManagerBase.h +++ b/Source/Core/VideoCommon/VertexManagerBase.h @@ -61,6 +61,8 @@ public: void DoState(PointerWrap& p); + std::pair ResetFlushAspectRatioCount(); + protected: virtual void vDoState(PointerWrap& p) {} PrimitiveType m_current_primitive_type = PrimitiveType::PRIMITIVE_POINTS; @@ -81,6 +83,8 @@ protected: private: bool m_is_flushed = true; + size_t m_flush_count_4_3 = 0; + size_t m_flush_count_anamorphic = 0; virtual void vFlush() = 0; diff --git a/Source/Core/VideoCommon/VertexShaderGen.cpp b/Source/Core/VideoCommon/VertexShaderGen.cpp index b590303679..9fe4bfcada 100644 --- a/Source/Core/VideoCommon/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/VertexShaderGen.cpp @@ -2,7 +2,6 @@ // Licensed under GPLv2+ // Refer to the license.txt file included. -#include #include #include "Common/Assert.h" diff --git a/Source/Core/VideoCommon/VertexShaderManager.cpp b/Source/Core/VideoCommon/VertexShaderManager.cpp index 76a91e0f05..8818c7f387 100644 --- a/Source/Core/VideoCommon/VertexShaderManager.cpp +++ b/Source/Core/VideoCommon/VertexShaderManager.cpp @@ -92,23 +92,6 @@ static float PHackValue(std::string sValue) return f; } -// Due to the BT.601 standard which the GameCube is based on being a compromise -// between PAL and NTSC, neither standard gets square pixels. They are each off -// by ~9% in opposite directions. -// Just in case any game decides to take this into account, we do both these -// tests with a large amount of slop. -static bool AspectIs4_3(float width, float height) -{ - float aspect = fabsf(width / height); - return fabsf(aspect - 4.0f / 3.0f) < 4.0f / 3.0f * 0.11; // within 11% of 4:3 -} - -static bool AspectIs16_9(float width, float height) -{ - float aspect = fabsf(width / height); - return fabsf(aspect - 16.0f / 9.0f) < 16.0f / 9.0f * 0.11; // within 11% of 16:9 -} - void UpdateProjectionHack(int iPhackvalue[], std::string sPhackvalue[]) { float fhackvalue1 = 0, fhackvalue2 = 0; @@ -470,18 +453,6 @@ void VertexShaderManager::SetConstants() g_fProjectionMatrix[14] = -1.0f; g_fProjectionMatrix[15] = 0.0f; - // Heuristic to detect if a GameCube game is in 16:9 anamorphic widescreen mode. - if (!SConfig::GetInstance().bWii) - { - bool viewport_is_4_3 = AspectIs4_3(xfmem.viewport.wd, xfmem.viewport.ht); - if (AspectIs16_9(rawProjection[2], rawProjection[0]) && viewport_is_4_3) - Core::g_aspect_wide = true; // Projection is 16:9 and viewport is 4:3, we are rendering - // an anamorphic widescreen picture - else if (AspectIs4_3(rawProjection[2], rawProjection[0]) && viewport_is_4_3) - Core::g_aspect_wide = - false; // Project and viewports are both 4:3, we are rendering a normal image. - } - SETSTAT_FT(stats.gproj_0, g_fProjectionMatrix[0]); SETSTAT_FT(stats.gproj_1, g_fProjectionMatrix[1]); SETSTAT_FT(stats.gproj_2, g_fProjectionMatrix[2]);