Merge pull request #5008 from ligfx/aspectheuristic
VideoCommon: rework anamorphic widescreen heuristic
This commit is contained in:
commit
e6476b805e
|
@ -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;
|
||||
|
|
|
@ -81,9 +81,6 @@
|
|||
|
||||
namespace Core
|
||||
{
|
||||
// TODO: ugly, remove
|
||||
bool g_aspect_wide;
|
||||
|
||||
static bool s_wants_determinism;
|
||||
|
||||
// Declarations and definitions
|
||||
|
|
|
@ -18,9 +18,6 @@
|
|||
|
||||
namespace Core
|
||||
{
|
||||
// TODO: ugly, remove
|
||||
extern bool g_aspect_wide;
|
||||
|
||||
bool GetIsThrottlerTempDisabled();
|
||||
void SetIsThrottlerTempDisabled(bool disable);
|
||||
|
||||
|
|
|
@ -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<float>(target_width) / static_cast<float>(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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -4,12 +4,14 @@
|
|||
|
||||
#include "VideoCommon/VertexManagerBase.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <memory>
|
||||
|
||||
#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<size_t, size_t> VertexManagerBase::ResetFlushAspectRatioCount()
|
||||
{
|
||||
std::pair<size_t, size_t> 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)
|
||||
{
|
||||
|
|
|
@ -61,6 +61,8 @@ public:
|
|||
|
||||
void DoState(PointerWrap& p);
|
||||
|
||||
std::pair<size_t, size_t> 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;
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
|
||||
#include "Common/Assert.h"
|
||||
|
|
|
@ -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]);
|
||||
|
|
Loading…
Reference in New Issue