diff options
Diffstat (limited to 'Source/Core/VideoCommon')
| -rw-r--r-- | Source/Core/VideoCommon/Present.cpp | 51 | ||||
| -rw-r--r-- | Source/Core/VideoCommon/Present.h | 3 | ||||
| -rw-r--r-- | Source/Core/VideoCommon/VideoConfig.cpp | 2 | ||||
| -rw-r--r-- | Source/Core/VideoCommon/VideoConfig.h | 13 |
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; |
