summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Core/VideoCommon')
-rw-r--r--Source/Core/VideoCommon/Present.cpp51
-rw-r--r--Source/Core/VideoCommon/Present.h3
-rw-r--r--Source/Core/VideoCommon/VideoConfig.cpp2
-rw-r--r--Source/Core/VideoCommon/VideoConfig.h13
4 files changed, 57 insertions, 12 deletions
diff --git a/Source/Core/VideoCommon/Present.cpp b/Source/Core/VideoCommon/Present.cpp
index d338821dd8..3a026bedd5 100644
--- a/Source/Core/VideoCommon/Present.cpp
+++ b/Source/Core/VideoCommon/Present.cpp
@@ -212,23 +212,49 @@ void Presenter::ProcessFrameDumping(u64 ticks) const
if (g_frame_dumper->IsFrameDumping() && m_xfb_entry)
{
MathUtil::Rectangle<int> target_rect;
- if (!g_ActiveConfig.bInternalResolutionFrameDumps && !g_gfx->IsHeadless())
- target_rect = GetTargetRectangle();
- else
+ switch (g_ActiveConfig.frame_dumps_resolution_type)
+ {
+ default:
+ case FrameDumpResolutionType::WINDOW_RESOLUTION:
+ {
+ if (!g_gfx->IsHeadless())
+ {
+ target_rect = GetTargetRectangle();
+ break;
+ }
+ [[fallthrough]];
+ }
+ case FrameDumpResolutionType::XFB_ASPECT_RATIO_CORRECTED_RESOLUTION:
+ {
+ target_rect = m_xfb_rect;
+ const bool allow_stretch = false;
+ auto [float_width, float_height] =
+ ScaleToDisplayAspectRatio(m_xfb_rect.GetWidth(), m_xfb_rect.GetHeight(), allow_stretch);
+ const float draw_aspect_ratio = CalculateDrawAspectRatio(allow_stretch);
+ auto [int_width, int_height] =
+ FindClosestIntegerResolution(float_width, float_height, draw_aspect_ratio);
+ target_rect = MathUtil::Rectangle<int>(0, 0, int_width, int_height);
+ break;
+ }
+ case FrameDumpResolutionType::XFB_RAW_RESOLUTION:
+ {
target_rect = m_xfb_rect;
+ break;
+ }
+ }
int width = target_rect.GetWidth();
int height = target_rect.GetHeight();
- // Ensure divisibility by "VIDEO_ENCODER_LCM" to make it compatible with all the video
- // encoders. Note that this is theoretically only necessary when recording videos and not
+ // Ensure divisibility by "VIDEO_ENCODER_LCM" and a min of 1 to make it compatible with all the
+ // video encoders. Note that this is theoretically only necessary when recording videos and not
// screenshots.
// We always scale positively to make sure the least amount of information is lost.
//
// TODO: this should be added as black padding on the edges by the frame dumper.
- if ((width % VIDEO_ENCODER_LCM) != 0)
+ if ((width % VIDEO_ENCODER_LCM) != 0 || width == 0)
width += VIDEO_ENCODER_LCM - (width % VIDEO_ENCODER_LCM);
- if ((height % VIDEO_ENCODER_LCM) != 0)
+ if ((height % VIDEO_ENCODER_LCM) != 0 || height == 0)
height += VIDEO_ENCODER_LCM - (height % VIDEO_ENCODER_LCM);
// Remove any black borders, there would be no point in including them in the recording
@@ -237,6 +263,8 @@ void Presenter::ProcessFrameDumping(u64 ticks) const
target_rect.right = width;
target_rect.bottom = height;
+ // TODO: any scaling done by this won't be gamma corrected,
+ // we should either apply post processing as well, or port its gamma correction code
g_frame_dumper->DumpCurrentFrame(m_xfb_entry->texture.get(), m_xfb_rect, target_rect, ticks,
m_frame_count);
}
@@ -360,7 +388,8 @@ float Presenter::CalculateDrawAspectRatio(bool allow_stretch) const
if (aspect_mode == AspectMode::Stretch)
return (static_cast<float>(m_backbuffer_width) / static_cast<float>(m_backbuffer_height));
- auto& vi = Core::System::GetInstance().GetVideoInterface();
+ // The actual aspect ratio of the XFB texture is irrelevant, the VI one is the one that matters
+ const auto& vi = Core::System::GetInstance().GetVideoInterface();
const float source_aspect_ratio = vi.GetAspectRatio();
// This will scale up the source ~4:3 resolution to its equivalent ~16:9 resolution
@@ -551,7 +580,7 @@ void Presenter::UpdateDrawRectangle()
// Don't know if there is a better place for this code so there isn't a 1 frame delay
if (g_ActiveConfig.bWidescreenHack)
{
- auto& vi = Core::System::GetInstance().GetVideoInterface();
+ const auto& vi = Core::System::GetInstance().GetVideoInterface();
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.
@@ -595,9 +624,10 @@ void Presenter::UpdateDrawRectangle()
// Crop the picture to a standard aspect ratio. (if enabled)
auto [crop_width, crop_height] = ApplyStandardAspectCrop(draw_width, draw_height);
+ const float crop_aspect_ratio = crop_width / crop_height;
// scale the picture to fit the rendering window
- if (win_aspect_ratio >= crop_width / crop_height)
+ if (win_aspect_ratio >= crop_aspect_ratio)
{
// the window is flatter than the picture
draw_width *= win_height / crop_height;
@@ -668,6 +698,7 @@ std::tuple<float, float> Presenter::ScaleToDisplayAspectRatio(const int width, c
std::tuple<int, int> Presenter::CalculateOutputDimensions(int width, int height,
bool allow_stretch) const
{
+ // Protect against zero width and height, a minimum of 1 will do
width = std::max(width, 1);
height = std::max(height, 1);
diff --git a/Source/Core/VideoCommon/Present.h b/Source/Core/VideoCommon/Present.h
index 9723e1aa19..3f8f43a687 100644
--- a/Source/Core/VideoCommon/Present.h
+++ b/Source/Core/VideoCommon/Present.h
@@ -107,10 +107,13 @@ private:
void OnBackBufferSizeChanged();
+ // Scales a raw XFB resolution to the target (display) aspect ratio,
+ // also accounting for crop and other minor adjustments
std::tuple<int, int> CalculateOutputDimensions(int width, int height,
bool allow_stretch = true) const;
std::tuple<float, float> ApplyStandardAspectCrop(float width, float height,
bool allow_stretch = true) const;
+ // Scales a raw XFB resolution to the target (display) aspect ratio
std::tuple<float, float> ScaleToDisplayAspectRatio(int width, int height,
bool allow_stretch = true) const;
diff --git a/Source/Core/VideoCommon/VideoConfig.cpp b/Source/Core/VideoCommon/VideoConfig.cpp
index e11776d356..0266cb9c19 100644
--- a/Source/Core/VideoCommon/VideoConfig.cpp
+++ b/Source/Core/VideoCommon/VideoConfig.cpp
@@ -128,7 +128,7 @@ void VideoConfig::Refresh()
sDumpEncoder = Config::Get(Config::GFX_DUMP_ENCODER);
sDumpPath = Config::Get(Config::GFX_DUMP_PATH);
iBitrateKbps = Config::Get(Config::GFX_BITRATE_KBPS);
- bInternalResolutionFrameDumps = Config::Get(Config::GFX_INTERNAL_RESOLUTION_FRAME_DUMPS);
+ frame_dumps_resolution_type = Config::Get(Config::GFX_FRAME_DUMPS_RESOLUTION_TYPE);
bEnableGPUTextureDecoding = Config::Get(Config::GFX_ENABLE_GPU_TEXTURE_DECODING);
bPreferVSForLinePointExpansion = Config::Get(Config::GFX_PREFER_VS_FOR_LINE_POINT_EXPANSION);
bEnablePixelLighting = Config::Get(Config::GFX_ENABLE_PIXEL_LIGHTING);
diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h
index d7ab34f142..baf8fb4e8b 100644
--- a/Source/Core/VideoCommon/VideoConfig.h
+++ b/Source/Core/VideoCommon/VideoConfig.h
@@ -80,6 +80,16 @@ enum class TriState : int
Auto
};
+enum class FrameDumpResolutionType : int
+{
+ // Window resolution (not including potential back buffer black borders)
+ WINDOW_RESOLUTION,
+ // The aspect ratio corrected XFB resolution (XFB pixels might not have been square)
+ XFB_ASPECT_RATIO_CORRECTED_RESOLUTION,
+ // The raw unscaled XFB resolution (based on "internal resolution" scale)
+ XFB_RAW_RESOLUTION,
+};
+
// Bitmask containing information about which configuration has changed for the backend.
enum ConfigChangeBits : u32
{
@@ -189,7 +199,8 @@ struct VideoConfig final
std::string sDumpEncoder;
std::string sDumpFormat;
std::string sDumpPath;
- bool bInternalResolutionFrameDumps = false;
+ FrameDumpResolutionType frame_dumps_resolution_type =
+ FrameDumpResolutionType::XFB_ASPECT_RATIO_CORRECTED_RESOLUTION;
bool bBorderlessFullscreen = false;
bool bEnableGPUTextureDecoding = false;
bool bPreferVSForLinePointExpansion = false;