From adc22a5e201ba92919447051f048048aa04297cd Mon Sep 17 00:00:00 2001 From: Stenzek Date: Thu, 10 Nov 2016 22:36:11 +1000 Subject: [PATCH] VideoCommon: Add method for calculating full-scale framedump rectangles --- Source/Core/VideoCommon/RenderBase.cpp | 83 ++++++++++++++++++++++---- Source/Core/VideoCommon/RenderBase.h | 2 + 2 files changed, 74 insertions(+), 11 deletions(-) diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp index bc03ebaa6a..113358d35f 100644 --- a/Source/Core/VideoCommon/RenderBase.cpp +++ b/Source/Core/VideoCommon/RenderBase.cpp @@ -18,6 +18,7 @@ #include #include +#include "Common/Assert.h" #include "Common/CommonTypes.h" #include "Common/Event.h" #include "Common/FileUtil.h" @@ -449,6 +450,76 @@ void Renderer::DrawDebugText() g_renderer->RenderText(final_yellow, 20, 20, 0xFFFFFF00); } +float Renderer::CalculateDrawAspectRatio(int target_width, int target_height) +{ + // The dimensions are the sizes that are used to create the EFB/backbuffer textures, so + // they should always be greater than zero. + _assert_(target_width > 0 && target_height > 0); + if (g_ActiveConfig.iAspectRatio == ASPECT_STRETCH) + { + // If stretch is enabled, we prefer the aspect ratio of the window. + return (static_cast(target_width) / static_cast(target_height)) / + (static_cast(s_backbuffer_width) / static_cast(s_backbuffer_height)); + } + + // 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)) + { + return (static_cast(target_width) / static_cast(target_height)) / + AspectToWidescreen(VideoInterface::GetAspectRatio()); + } + else + { + return (static_cast(target_width) / static_cast(target_height)) / + VideoInterface::GetAspectRatio(); + } +} + +TargetRectangle Renderer::CalculateFrameDumpDrawRectangle() +{ + // No point including any borders in the frame dump image, since they'd have to be cropped anyway. + TargetRectangle rc; + rc.left = 0; + rc.top = 0; + + // If full-resolution frame dumping is disabled, just use the window draw rectangle. + // Also do this if RealXFB is enabled, since the image has been downscaled for the XFB copy + // anyway, and there's no point writing an upscaled frame with no filtering. + if (!g_ActiveConfig.bInternalResolutionFrameDumps || g_ActiveConfig.RealXFBEnabled()) + { + // But still remove the borders, since the caller expects this. + rc.right = target_rc.GetWidth(); + rc.bottom = target_rc.GetHeight(); + return rc; + } + + // Grab the dimensions of the EFB textures, we scale either of these depending on the ratio. + unsigned int efb_width, efb_height; + g_framebuffer_manager->GetTargetSize(&efb_width, &efb_height); + + // Scale either the width or height depending the content aspect ratio. + // This way we preserve as much resolution as possible when scaling. + float ratio = CalculateDrawAspectRatio(efb_width, efb_height); + float draw_width, draw_height; + if (ratio >= 1.0f) + { + // Preserve horizontal resolution, scale vertically. + draw_width = static_cast(efb_width); + draw_height = static_cast(efb_height) * ratio; + } + else + { + // Preserve vertical resolution, scale horizontally. + draw_width = static_cast(efb_width) / ratio; + draw_height = static_cast(efb_height); + } + + rc.right = static_cast(std::ceil(draw_width)); + rc.bottom = static_cast(std::ceil(draw_height)); + return rc; +} + void Renderer::UpdateDrawRectangle() { float FloatGLWidth = static_cast(s_backbuffer_width); @@ -511,17 +582,7 @@ void Renderer::UpdateDrawRectangle() // Check for force-settings and override. // The rendering window aspect ratio as a proportion of the 4:3 or 16:9 ratio - float Ratio; - if (g_ActiveConfig.iAspectRatio == ASPECT_ANALOG_WIDE || - (g_ActiveConfig.iAspectRatio != ASPECT_ANALOG && Core::g_aspect_wide)) - { - Ratio = (WinWidth / WinHeight) / AspectToWidescreen(VideoInterface::GetAspectRatio()); - } - else - { - Ratio = (WinWidth / WinHeight) / VideoInterface::GetAspectRatio(); - } - + float Ratio = CalculateDrawAspectRatio(s_backbuffer_width, s_backbuffer_height); if (g_ActiveConfig.iAspectRatio != ASPECT_STRETCH) { if (Ratio > 1.0f) diff --git a/Source/Core/VideoCommon/RenderBase.h b/Source/Core/VideoCommon/RenderBase.h index dccc5c1b72..f33ce4395a 100644 --- a/Source/Core/VideoCommon/RenderBase.h +++ b/Source/Core/VideoCommon/RenderBase.h @@ -93,6 +93,8 @@ public: virtual TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc) = 0; static const TargetRectangle& GetTargetRectangle() { return target_rc; } + static float CalculateDrawAspectRatio(int target_width, int target_height); + static TargetRectangle CalculateFrameDumpDrawRectangle(); static void UpdateDrawRectangle(); // Use this to convert a single target rectangle to two stereo rectangles