Merge pull request #2765 from mirrorbender/master

Aspect Ratio/VI Scaling FIx
This commit is contained in:
Scott Mansell 2015-08-01 12:45:38 +12:00
commit fc4ba3adee
8 changed files with 124 additions and 38 deletions

View file

@ -436,6 +436,57 @@ u32 GetXFBAddressBottom()
return m_XFBInfoBottom.FBB; return m_XFBInfoBottom.FBB;
} }
float GetAspectRatio(bool wide)
{
u32 multiplier = static_cast<u32>(m_PictureConfiguration.STD / m_PictureConfiguration.WPL);
int height = (multiplier * m_VerticalTimingRegister.ACV);
int width = ((2 * m_HTiming0.HLW) - (m_HTiming0.HLW - m_HTiming1.HBS640)
- m_HTiming1.HBE640);
float pixelAR;
if (m_DisplayControlRegister.FMT == 1)
{
//PAL active frame is 702*576
//In square pixels, 1024*576 is 16:9, and 768*576 is 4:3
//Therefore a 16:9 TV would have a "pixel" aspect ratio of 1024/702
//Similarly a 4:3 TV would have a ratio of 768/702
if (wide)
{
pixelAR = 1024.0f / 702.0f;
}
else
{
pixelAR = 768.0f / 702.0f;
}
}
else
{
//NTSC active frame is 710.85*486
//In square pixels, 864*486 is 16:9, and 648*486 is 4:3
//Therefore a 16:9 TV would have a "pixel" aspect ratio of 864/710.85
//Similarly a 4:3 TV would have a ratio of 648/710.85
if (wide)
{
pixelAR = 864.0f / 710.85f;
}
else
{
pixelAR = 648.0f / 710.85f;
}
}
if (width == 0 || height == 0)
{
if (wide)
{
return 16.0f / 9.0f;
}
else
{
return 4.0f / 3.0f;
}
}
return ((float)width / (float)height) * pixelAR;
}
void UpdateParameters() void UpdateParameters()
{ {
fields = m_DisplayControlRegister.NIN ? 2 : 1; fields = m_DisplayControlRegister.NIN ? 2 : 1;

View file

@ -353,4 +353,7 @@ union UVIHorizontalStepping
unsigned int GetTicksPerLine(); unsigned int GetTicksPerLine();
unsigned int GetTicksPerFrame(); unsigned int GetTicksPerFrame();
//For VI Scaling and Aspect Ratio Correction
float GetAspectRatio(bool);
} }

View file

@ -101,7 +101,7 @@ static wxString keep_window_on_top_desc = wxTRANSLATE("Keep the game window on t
static wxString hide_mouse_cursor_desc = wxTRANSLATE("Hides the mouse cursor if it's on top of the emulation window.\n\nIf unsure, leave this unchecked."); static wxString hide_mouse_cursor_desc = wxTRANSLATE("Hides the mouse cursor if it's on top of the emulation window.\n\nIf unsure, leave this unchecked.");
static wxString render_to_main_win_desc = wxTRANSLATE("Enable this if you want to use the main Dolphin window for rendering rather than a separate render window.\n\nIf unsure, leave this unchecked."); static wxString render_to_main_win_desc = wxTRANSLATE("Enable this if you want to use the main Dolphin window for rendering rather than a separate render window.\n\nIf unsure, leave this unchecked.");
static wxString prog_scan_desc = wxTRANSLATE("Enables progressive scan if supported by the emulated software.\nMost games don't care about this.\n\nIf unsure, leave this unchecked."); static wxString prog_scan_desc = wxTRANSLATE("Enables progressive scan if supported by the emulated software.\nMost games don't care about this.\n\nIf unsure, leave this unchecked.");
static wxString ar_desc = wxTRANSLATE("Select what aspect ratio to use when rendering:\nAuto: Use the native aspect ratio\nForce 16:9: Stretch the picture to an aspect ratio of 16:9.\nForce 4:3: Stretch the picture to an aspect ratio of 4:3.\nStretch to Window: Stretch the picture to the window size.\n\nIf unsure, select Auto."); static wxString ar_desc = wxTRANSLATE("Select what aspect ratio to use when rendering:\nAuto: Use the native aspect ratio\nForce 16:9: Mimic an analog TV with a widescreen aspect ratio.\nForce 4:3: Mimic a standard 4:3 analog TV.\nStretch to Window: Stretch the picture to the window size.\n\nIf unsure, select Auto.");
static wxString ws_hack_desc = wxTRANSLATE("Forces the game to output graphics for any aspect ratio.\nUse with \"Aspect Ratio\" set to \"Force 16:9\" to force 4:3-only games to run at 16:9.\nRarely produces good results and often partially breaks graphics and game UIs.\nUnnecessary (and detrimental) if using any AR/Gecko-code widescreen patches.\n\nIf unsure, leave this unchecked."); static wxString ws_hack_desc = wxTRANSLATE("Forces the game to output graphics for any aspect ratio.\nUse with \"Aspect Ratio\" set to \"Force 16:9\" to force 4:3-only games to run at 16:9.\nRarely produces good results and often partially breaks graphics and game UIs.\nUnnecessary (and detrimental) if using any AR/Gecko-code widescreen patches.\n\nIf unsure, leave this unchecked.");
static wxString vsync_desc = wxTRANSLATE("Wait for vertical blanks in order to reduce tearing.\nDecreases performance if emulation speed is below 100%.\n\nIf unsure, leave this unchecked."); static wxString vsync_desc = wxTRANSLATE("Wait for vertical blanks in order to reduce tearing.\nDecreases performance if emulation speed is below 100%.\n\nIf unsure, leave this unchecked.");
static wxString af_desc = wxTRANSLATE("Enable anisotropic filtering.\nEnhances visual quality of textures that are at oblique viewing angles.\nMight cause issues in a small number of games.\nOn Direct3D, setting this above 1x will also have the same effect as enabling \"Force Texture Filtering\".\n\nIf unsure, select 1x."); static wxString af_desc = wxTRANSLATE("Enable anisotropic filtering.\nEnhances visual quality of textures that are at oblique viewing angles.\nMight cause issues in a small number of games.\nOn Direct3D, setting this above 1x will also have the same effect as enabling \"Force Texture Filtering\".\n\nIf unsure, select 1x.");
@ -136,7 +136,7 @@ static wxString dump_efb_desc = wxTRANSLATE("Dump the contents of EFB copies to
static wxString use_ffv1_desc = wxTRANSLATE("Encode frame dumps using the FFV1 codec.\n\nIf unsure, leave this unchecked."); static wxString use_ffv1_desc = wxTRANSLATE("Encode frame dumps using the FFV1 codec.\n\nIf unsure, leave this unchecked.");
#endif #endif
static wxString free_look_desc = wxTRANSLATE("This feature allows you to change the game's camera.\nMove the mouse while holding the right mouse button to pan and while holding the middle button to move.\nHold SHIFT and press one of the WASD keys to move the camera by a certain step distance (SHIFT+2 to move faster and SHIFT+1 to move slower). Press SHIFT+R to reset the camera and SHIFT+F to reset the speed.\n\nIf unsure, leave this unchecked."); static wxString free_look_desc = wxTRANSLATE("This feature allows you to change the game's camera.\nMove the mouse while holding the right mouse button to pan and while holding the middle button to move.\nHold SHIFT and press one of the WASD keys to move the camera by a certain step distance (SHIFT+2 to move faster and SHIFT+1 to move slower). Press SHIFT+R to reset the camera and SHIFT+F to reset the speed.\n\nIf unsure, leave this unchecked.");
static wxString crop_desc = wxTRANSLATE("Crop the picture from 4:3 to 5:4 or from 16:9 to 16:10.\n\nIf unsure, leave this unchecked."); static wxString crop_desc = wxTRANSLATE("Crop the picture from its native aspect ratio to 4:3 or 16:9.\n\nIf unsure, leave this unchecked.");
static wxString ppshader_desc = wxTRANSLATE("Apply a post-processing effect after finishing a frame.\n\nIf unsure, select (off)."); static wxString ppshader_desc = wxTRANSLATE("Apply a post-processing effect after finishing a frame.\n\nIf unsure, select (off).");
static wxString cache_efb_copies_desc = wxTRANSLATE("Slightly speeds up EFB to RAM copies by sacrificing emulation accuracy.\nIf you're experiencing any issues, try raising texture cache accuracy or disable this option.\n\nIf unsure, leave this unchecked."); static wxString cache_efb_copies_desc = wxTRANSLATE("Slightly speeds up EFB to RAM copies by sacrificing emulation accuracy.\nIf you're experiencing any issues, try raising texture cache accuracy or disable this option.\n\nIf unsure, leave this unchecked.");
static wxString stereo_3d_desc = wxTRANSLATE("Selects the stereoscopic 3D mode. Stereoscopy allows you to get a better feeling of depth if you have the necessary hardware.\nSide-by-Side and Top-and-Bottom are used by most 3D TVs.\nAnaglyph is used for Red-Cyan colored glasses.\nHeavily decreases emulation speed and sometimes causes issues.\n\nIf unsure, select Off."); static wxString stereo_3d_desc = wxTRANSLATE("Selects the stereoscopic 3D mode. Stereoscopy allows you to get a better feeling of depth if you have the necessary hardware.\nSide-by-Side and Top-and-Bottom are used by most 3D TVs.\nAnaglyph is used for Red-Cyan colored glasses.\nHeavily decreases emulation speed and sometimes causes issues.\n\nIf unsure, select Off.");

View file

@ -56,6 +56,14 @@ FramebufferManager::FramebufferManager()
{ {
m_target_width = Renderer::GetTargetWidth(); m_target_width = Renderer::GetTargetWidth();
m_target_height = Renderer::GetTargetHeight(); m_target_height = Renderer::GetTargetHeight();
if (m_target_height < 1)
{
m_target_height = 1;
}
if (m_target_width < 1)
{
m_target_width = 1;
}
DXGI_SAMPLE_DESC sample_desc = D3D::GetAAMode(g_ActiveConfig.iMultisampleMode); DXGI_SAMPLE_DESC sample_desc = D3D::GetAAMode(g_ActiveConfig.iMultisampleMode);
ID3D11Texture2D* buf; ID3D11Texture2D* buf;

View file

@ -929,7 +929,8 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co
} }
// Resize the back buffers NOW to avoid flickering // Resize the back buffers NOW to avoid flickering
if (xfbchanged || if (CalculateTargetSize(s_backbuffer_width, s_backbuffer_height) ||
xfbchanged ||
windowResized || windowResized ||
fullscreen_changed || fullscreen_changed ||
s_last_efb_scale != g_ActiveConfig.iEFBScale || s_last_efb_scale != g_ActiveConfig.iEFBScale ||
@ -969,7 +970,6 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co
s_last_efb_scale = g_ActiveConfig.iEFBScale; s_last_efb_scale = g_ActiveConfig.iEFBScale;
s_last_stereo_mode = g_ActiveConfig.iStereoMode > 0; s_last_stereo_mode = g_ActiveConfig.iStereoMode > 0;
CalculateTargetSize(s_backbuffer_width, s_backbuffer_height);
PixelShaderManager::SetEfbScaleChanged(); PixelShaderManager::SetEfbScaleChanged();

View file

@ -1654,14 +1654,18 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co
s_backbuffer_height = H; s_backbuffer_height = H;
s_last_efb_scale = g_ActiveConfig.iEFBScale; s_last_efb_scale = g_ActiveConfig.iEFBScale;
} }
bool TargetSizeChanged = false;
if (xfbchanged || WindowResized || (s_last_multisample_mode != g_ActiveConfig.iMultisampleMode) || (s_last_stereo_mode != (g_ActiveConfig.iStereoMode > 0))) if (CalculateTargetSize(s_backbuffer_width, s_backbuffer_height))
{
TargetSizeChanged = true;
}
if (TargetSizeChanged || xfbchanged || WindowResized || (s_last_multisample_mode != g_ActiveConfig.iMultisampleMode) || (s_last_stereo_mode != (g_ActiveConfig.iStereoMode > 0)))
{ {
s_last_xfb_mode = g_ActiveConfig.bUseRealXFB; s_last_xfb_mode = g_ActiveConfig.bUseRealXFB;
UpdateDrawRectangle(s_backbuffer_width, s_backbuffer_height); UpdateDrawRectangle(s_backbuffer_width, s_backbuffer_height);
if (CalculateTargetSize(s_backbuffer_width, s_backbuffer_height) || s_last_multisample_mode != g_ActiveConfig.iMultisampleMode || s_last_stereo_mode != (g_ActiveConfig.iStereoMode > 0)) if (TargetSizeChanged || s_last_multisample_mode != g_ActiveConfig.iMultisampleMode || s_last_stereo_mode != (g_ActiveConfig.iStereoMode > 0))
{ {
s_last_stereo_mode = g_ActiveConfig.iStereoMode > 0; s_last_stereo_mode = g_ActiveConfig.iStereoMode > 0;
s_last_multisample_mode = g_ActiveConfig.iMultisampleMode; s_last_multisample_mode = g_ActiveConfig.iMultisampleMode;

View file

@ -28,6 +28,8 @@
#include "Core/Movie.h" #include "Core/Movie.h"
#include "Core/FifoPlayer/FifoRecorder.h" #include "Core/FifoPlayer/FifoRecorder.h"
#include "Core/HW/VideoInterface.h"
#include "VideoCommon/AVIDump.h" #include "VideoCommon/AVIDump.h"
#include "VideoCommon/BPMemory.h" #include "VideoCommon/BPMemory.h"
#include "VideoCommon/CommandProcessor.h" #include "VideoCommon/CommandProcessor.h"
@ -360,15 +362,14 @@ void Renderer::DrawDebugText()
case ASPECT_AUTO: case ASPECT_AUTO:
ar_text = "Auto"; ar_text = "Auto";
break; break;
case ASPECT_FORCE_16_9:
ar_text = "16:9";
break;
case ASPECT_FORCE_4_3:
ar_text = "4:3";
break;
case ASPECT_STRETCH: case ASPECT_STRETCH:
ar_text = "Stretch"; ar_text = "Stretch";
break; break;
case ASPECT_ANALOG:
ar_text = "Force 4:3";
break;
case ASPECT_ANALOG_WIDE:
ar_text = "Force 16:9";
} }
const char* const efbcopy_text = g_ActiveConfig.bSkipEFBCopyToRam ? "to Texture" : "to RAM"; const char* const efbcopy_text = g_ActiveConfig.bSkipEFBCopyToRam ? "to Texture" : "to RAM";
@ -425,31 +426,27 @@ void Renderer::UpdateDrawRectangle(int backbuffer_width, int backbuffer_height)
const float WinWidth = FloatGLWidth; const float WinWidth = FloatGLWidth;
const float WinHeight = FloatGLHeight; const float WinHeight = FloatGLHeight;
// Handle aspect ratio.
// Default to auto.
bool use16_9 = g_aspect_wide;
// Update aspect ratio hack values // Update aspect ratio hack values
// Won't take effect until next frame // Won't take effect until next frame
// Don't know if there is a better place for this code so there isn't a 1 frame delay // Don't know if there is a better place for this code so there isn't a 1 frame delay
if (g_ActiveConfig.bWidescreenHack) if (g_ActiveConfig.bWidescreenHack)
{ {
float source_aspect = use16_9 ? (16.0f / 9.0f) : (4.0f / 3.0f); float source_aspect = VideoInterface::GetAspectRatio(g_aspect_wide);
float target_aspect; float target_aspect;
switch (g_ActiveConfig.iAspectRatio) switch (g_ActiveConfig.iAspectRatio)
{ {
case ASPECT_FORCE_16_9:
target_aspect = 16.0f / 9.0f;
break;
case ASPECT_FORCE_4_3:
target_aspect = 4.0f / 3.0f;
break;
case ASPECT_STRETCH: case ASPECT_STRETCH:
target_aspect = WinWidth / WinHeight; target_aspect = WinWidth / WinHeight;
break; break;
case ASPECT_ANALOG:
target_aspect = VideoInterface::GetAspectRatio(false);
break;
case ASPECT_ANALOG_WIDE:
target_aspect = VideoInterface::GetAspectRatio(true);
break;
default: default:
// ASPECT_AUTO == no hacking // ASPECT_AUTO
target_aspect = source_aspect; target_aspect = source_aspect;
break; break;
} }
@ -476,16 +473,24 @@ void Renderer::UpdateDrawRectangle(int backbuffer_width, int backbuffer_height)
} }
// Check for force-settings and override. // Check for force-settings and override.
if (g_ActiveConfig.iAspectRatio == ASPECT_FORCE_16_9)
use16_9 = true; // The rendering window aspect ratio as a proportion of the 4:3 or 16:9 ratio
else if (g_ActiveConfig.iAspectRatio == ASPECT_FORCE_4_3) float Ratio;
use16_9 = false; switch (g_ActiveConfig.iAspectRatio)
{
case ASPECT_ANALOG_WIDE:
Ratio = (WinWidth / WinHeight) / VideoInterface::GetAspectRatio(true);
break;
case ASPECT_ANALOG:
Ratio = (WinWidth / WinHeight) / VideoInterface::GetAspectRatio(false);
break;
default:
Ratio = (WinWidth / WinHeight) / VideoInterface::GetAspectRatio(g_aspect_wide);
break;
}
if (g_ActiveConfig.iAspectRatio != ASPECT_STRETCH) if (g_ActiveConfig.iAspectRatio != ASPECT_STRETCH)
{ {
// The rendering window aspect ratio as a proportion of the 4:3 or 16:9 ratio
float Ratio = (WinWidth / WinHeight) / (!use16_9 ? (4.0f / 3.0f) : (16.0f / 9.0f));
// Check if height or width is the limiting factor. If ratio > 1 the picture is too wide and have to limit the width.
if (Ratio > 1.0f) if (Ratio > 1.0f)
{ {
// Scale down and center in the X direction. // Scale down and center in the X direction.
@ -502,12 +507,27 @@ void Renderer::UpdateDrawRectangle(int backbuffer_width, int backbuffer_height)
} }
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// Crop the picture from 4:3 to 5:4 or from 16:9 to 16:10. // Crop the picture from Analog to 4:3 or from Analog (Wide) to 16:9.
// Output: FloatGLWidth, FloatGLHeight, FloatXOffset, FloatYOffset // Output: FloatGLWidth, FloatGLHeight, FloatXOffset, FloatYOffset
// ------------------ // ------------------
if (g_ActiveConfig.iAspectRatio != ASPECT_STRETCH && g_ActiveConfig.bCrop) if (g_ActiveConfig.iAspectRatio != ASPECT_STRETCH && g_ActiveConfig.bCrop)
{ {
float Ratio = !use16_9 ? ((4.0f / 3.0f) / (5.0f / 4.0f)) : (((16.0f / 9.0f) / (16.0f / 10.0f))); switch (g_ActiveConfig.iAspectRatio)
{
case ASPECT_ANALOG_WIDE:
Ratio = (16.0f / 9.0f) / VideoInterface::GetAspectRatio(true);
break;
case ASPECT_ANALOG:
Ratio = (4.0f / 3.0f) / VideoInterface::GetAspectRatio(false);
break;
default:
Ratio = (!g_aspect_wide ? (4.0f / 3.0f) : (16.0f / 9.0f)) / VideoInterface::GetAspectRatio(g_aspect_wide);
break;
}
if (Ratio <= 1.0f)
{
Ratio = 1.0f / Ratio;
}
// The width and height we will add (calculate this before FloatGLWidth and FloatGLHeight is adjusted) // The width and height we will add (calculate this before FloatGLWidth and FloatGLHeight is adjusted)
float IncreasedWidth = (Ratio - 1.0f) * FloatGLWidth; float IncreasedWidth = (Ratio - 1.0f) * FloatGLWidth;
float IncreasedHeight = (Ratio - 1.0f) * FloatGLHeight; float IncreasedHeight = (Ratio - 1.0f) * FloatGLHeight;

View file

@ -25,10 +25,10 @@
enum AspectMode enum AspectMode
{ {
ASPECT_AUTO = 0, ASPECT_AUTO = 0,
ASPECT_FORCE_16_9 = 1, ASPECT_ANALOG_WIDE = 1,
ASPECT_FORCE_4_3 = 2, ASPECT_ANALOG = 2,
ASPECT_STRETCH = 3, ASPECT_STRETCH = 3,
}; };
enum EFBScale enum EFBScale