Video: implement custom aspect ratio support (already exposed to Qt).

This also renamed some variables/functions.
This commit is contained in:
Filoppi
2023-12-13 00:27:01 +02:00
parent f96bea95d8
commit b3aa6ad93b
10 changed files with 129 additions and 43 deletions

View File

@ -28,9 +28,10 @@ static constexpr int VIDEO_ENCODER_LCM = 4;
namespace VideoCommon
{
static float AspectToWidescreen(float aspect)
// Stretches the native/internal analog resolution aspect ratio from ~4:3 to ~16:9
static float SourceAspectRatioToWidescreen(float source_aspect)
{
return aspect * ((16.0f / 9.0f) / (4.0f / 3.0f));
return source_aspect * ((16.0f / 9.0f) / (4.0f / 3.0f));
}
static std::tuple<int, int> FindClosestIntegerResolution(float width, float height,
@ -292,15 +293,22 @@ float Presenter::CalculateDrawAspectRatio(bool allow_stretch) const
return (static_cast<float>(m_backbuffer_width) / static_cast<float>(m_backbuffer_height));
auto& vi = Core::System::GetInstance().GetVideoInterface();
const float aspect_ratio = vi.GetAspectRatio();
const float source_aspect_ratio = vi.GetAspectRatio();
if (aspect_mode == AspectMode::AnalogWide ||
// This will scale up the source ~4:3 resolution to its equivalent ~16:9 resolution
if (aspect_mode == AspectMode::ForceWide ||
(aspect_mode == AspectMode::Auto && g_widescreen->IsGameWidescreen()))
{
return AspectToWidescreen(aspect_ratio);
return SourceAspectRatioToWidescreen(source_aspect_ratio);
}
// For the "custom" mode, we force the exact target aspect ratio, without
// acknowleding the difference between the source aspect ratio and 4:3.
else if (aspect_mode == AspectMode::Custom)
{
return g_ActiveConfig.GetCustomAspectRatio();
}
return aspect_ratio;
return source_aspect_ratio;
}
void Presenter::AdjustRectanglesToFitBounds(MathUtil::Rectangle<int>* target_rect,
@ -414,7 +422,7 @@ void Presenter::SetSuggestedWindowSize(int width, int height)
Host_RequestRenderWindowSize(out_width, out_height);
}
// Crop to exactly 16:9 or 4:3 if enabled and not AspectMode::Stretch.
// Crop to exact forced aspect ratios if enabled and not AspectMode::Stretch.
std::tuple<float, float> Presenter::ApplyStandardAspectCrop(float width, float height,
bool allow_stretch) const
{
@ -426,13 +434,28 @@ std::tuple<float, float> Presenter::ApplyStandardAspectCrop(float width, float h
if (!g_ActiveConfig.bCrop || aspect_mode == AspectMode::Stretch)
return {width, height};
// Force 4:3 or 16:9 by cropping the image.
// Force aspect ratios by cropping the image.
const float current_aspect = width / height;
const float expected_aspect =
(aspect_mode == AspectMode::AnalogWide ||
(aspect_mode == AspectMode::Auto && g_widescreen->IsGameWidescreen())) ?
(16.0f / 9.0f) :
(4.0f / 3.0f);
float expected_aspect;
switch (aspect_mode)
{
default:
case AspectMode::Auto:
expected_aspect = g_widescreen->IsGameWidescreen() ? (16.0f / 9.0f) : (4.0f / 3.0f);
break;
case AspectMode::ForceWide:
expected_aspect = 16.0f / 9.0f;
break;
case AspectMode::ForceStandard:
expected_aspect = 4.0f / 3.0f;
break;
// There should be no cropping needed in the custom case,
// as output should always exactly match the target aspect ratio
case AspectMode::Custom:
expected_aspect = g_ActiveConfig.GetCustomAspectRatio();
break;
}
if (current_aspect > expected_aspect)
{
// keep height, crop width
@ -457,11 +480,13 @@ void Presenter::UpdateDrawRectangle()
if (g_ActiveConfig.bWidescreenHack)
{
auto& vi = Core::System::GetInstance().GetVideoInterface();
float source_aspect = vi.GetAspectRatio();
float source_aspect_ratio = vi.GetAspectRatio();
// If the game is meant to be in widescreen (or forced to),
// scale the source aspect ratio to it.
if (g_widescreen->IsGameWidescreen())
source_aspect = AspectToWidescreen(source_aspect);
source_aspect_ratio = SourceAspectRatioToWidescreen(source_aspect_ratio);
const float adjust = source_aspect / draw_aspect_ratio;
const float adjust = source_aspect_ratio / draw_aspect_ratio;
if (adjust > 1)
{
// Vert+

View File

@ -85,6 +85,8 @@ void VideoConfig::Refresh()
bWidescreenHack = Config::Get(Config::GFX_WIDESCREEN_HACK);
aspect_mode = Config::Get(Config::GFX_ASPECT_RATIO);
custom_aspect_width = Config::Get(Config::GFX_CUSTOM_ASPECT_RATIO_WIDTH);
custom_aspect_height = Config::Get(Config::GFX_CUSTOM_ASPECT_RATIO_HEIGHT);
suggested_aspect_mode = Config::Get(Config::GFX_SUGGESTED_ASPECT_RATIO);
widescreen_heuristic_transition_threshold =
Config::Get(Config::GFX_WIDESCREEN_HEURISTIC_TRANSITION_THRESHOLD);

View File

@ -21,10 +21,11 @@ constexpr int EFB_SCALE_AUTO_INTEGRAL = 0;
enum class AspectMode : int
{
Auto,
AnalogWide,
Analog,
Auto, // 4:3 or 16:9
ForceWide, // 16:9
ForceStandard, // 4:3
Stretch,
Custom,
};
enum class StereoMode : int
@ -105,6 +106,8 @@ struct VideoConfig final
bool bVSyncActive = false;
bool bWidescreenHack = false;
AspectMode aspect_mode{};
int custom_aspect_width = 1;
int custom_aspect_height = 1;
AspectMode suggested_aspect_mode{};
u32 widescreen_heuristic_transition_threshold = 0;
float widescreen_heuristic_aspect_ratio_slop = 0.f;
@ -365,6 +368,8 @@ struct VideoConfig final
bool UsingUberShaders() const;
u32 GetShaderCompilerThreads() const;
u32 GetShaderPrecompilerThreads() const;
float GetCustomAspectRatio() const { return (float)custom_aspect_width / custom_aspect_height; }
};
extern VideoConfig g_Config;

View File

@ -36,18 +36,18 @@ void WidescreenManager::Update()
m_is_game_widescreen = Config::Get(Config::SYSCONF_WIDESCREEN);
// suggested_aspect_mode overrides SYSCONF_WIDESCREEN
if (g_ActiveConfig.suggested_aspect_mode == AspectMode::Analog)
if (g_ActiveConfig.suggested_aspect_mode == AspectMode::ForceStandard)
m_is_game_widescreen = false;
else if (g_ActiveConfig.suggested_aspect_mode == AspectMode::AnalogWide)
else if (g_ActiveConfig.suggested_aspect_mode == AspectMode::ForceWide)
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)
if (aspect_mode == AspectMode::ForceStandard)
m_is_game_widescreen = false;
else if (aspect_mode == AspectMode::AnalogWide)
else if (aspect_mode == AspectMode::ForceWide)
m_is_game_widescreen = true;
}
}
@ -64,9 +64,10 @@ void WidescreenManager::UpdateWidescreenHeuristic()
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))
// 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: