diff --git a/Source/Core/VideoCommon/Src/FramebufferManagerBase.cpp b/Source/Core/VideoCommon/Src/FramebufferManagerBase.cpp index 090c1c7872..c883714daf 100644 --- a/Source/Core/VideoCommon/Src/FramebufferManagerBase.cpp +++ b/Source/Core/VideoCommon/Src/FramebufferManagerBase.cpp @@ -10,8 +10,8 @@ XFBSourceBase *FramebufferManagerBase::m_realXFBSource; // Only used in Real XFB FramebufferManagerBase::VirtualXFBListType FramebufferManagerBase::m_virtualXFBList; // Only used in Virtual XFB mode const XFBSourceBase* FramebufferManagerBase::m_overlappingXFBArray[MAX_VIRTUAL_XFB]; -unsigned int FramebufferManagerBase::s_last_xfb_width; -unsigned int FramebufferManagerBase::s_last_xfb_height; +unsigned int FramebufferManagerBase::s_last_xfb_width = 1; +unsigned int FramebufferManagerBase::s_last_xfb_height = 1; FramebufferManagerBase::FramebufferManagerBase() { @@ -230,30 +230,30 @@ void FramebufferManagerBase::ReplaceVirtualXFB() } } -unsigned int FramebufferManagerBase::ScaleToVirtualXfbWidth(unsigned int width, unsigned int backbuffer_width) +int FramebufferManagerBase::ScaleToVirtualXfbWidth(int x, unsigned int backbuffer_width) { if (g_ActiveConfig.RealXFBEnabled()) - return width; + return x; if (g_ActiveConfig.b3DVision) { // This works, yet the version in the else doesn't. No idea why. - return width * backbuffer_width / FramebufferManagerBase::LastXfbWidth(); + return x * (int)backbuffer_width / (int)FramebufferManagerBase::LastXfbWidth(); } else - return width * Renderer::GetTargetRectangle().GetWidth() / FramebufferManagerBase::LastXfbWidth(); + return x * (int)Renderer::GetTargetRectangle().GetWidth() / (int)FramebufferManagerBase::LastXfbWidth(); } -unsigned int FramebufferManagerBase::ScaleToVirtualXfbHeight(unsigned int height, unsigned int backbuffer_height) +int FramebufferManagerBase::ScaleToVirtualXfbHeight(int y, unsigned int backbuffer_height) { if (g_ActiveConfig.RealXFBEnabled()) - return height; + return y; if (g_ActiveConfig.b3DVision) { // This works, yet the version in the else doesn't. No idea why. - return height * backbuffer_height / FramebufferManagerBase::LastXfbHeight(); + return y * (int)backbuffer_height / (int)FramebufferManagerBase::LastXfbHeight(); } else - return height * Renderer::GetTargetRectangle().GetHeight() / FramebufferManagerBase::LastXfbHeight(); + return y * (int)Renderer::GetTargetRectangle().GetHeight() / (int)FramebufferManagerBase::LastXfbHeight(); } diff --git a/Source/Core/VideoCommon/Src/FramebufferManagerBase.h b/Source/Core/VideoCommon/Src/FramebufferManagerBase.h index d915130ac4..e529bb1a39 100644 --- a/Source/Core/VideoCommon/Src/FramebufferManagerBase.h +++ b/Source/Core/VideoCommon/Src/FramebufferManagerBase.h @@ -55,8 +55,8 @@ public: static unsigned int LastXfbWidth() { return s_last_xfb_width; } static unsigned int LastXfbHeight() { return s_last_xfb_height; } - static unsigned int ScaleToVirtualXfbWidth(unsigned int width, unsigned int backbuffer_width); - static unsigned int ScaleToVirtualXfbHeight(unsigned int height, unsigned int backbuffer_height); + static int ScaleToVirtualXfbWidth(int x, unsigned int backbuffer_width); + static int ScaleToVirtualXfbHeight(int y, unsigned int backbuffer_height); protected: struct VirtualXFB diff --git a/Source/Core/VideoCommon/Src/RenderBase.cpp b/Source/Core/VideoCommon/Src/RenderBase.cpp index 8bb6ab6750..f83ce29e49 100644 --- a/Source/Core/VideoCommon/Src/RenderBase.cpp +++ b/Source/Core/VideoCommon/Src/RenderBase.cpp @@ -76,6 +76,11 @@ bool Renderer::XFBWrited; bool Renderer::s_EnableDLCachingAfterRecording; unsigned int Renderer::prev_efb_format = (unsigned int)-1; +unsigned int Renderer::efb_scale_numeratorX = 1; +unsigned int Renderer::efb_scale_numeratorY = 1; +unsigned int Renderer::efb_scale_denominatorX = 1; +unsigned int Renderer::efb_scale_denominatorY = 1; +unsigned int Renderer::ssaa_multiplier = 1; Renderer::Renderer() : frame_data(NULL), bLastFrameDumped(false) @@ -93,6 +98,8 @@ Renderer::~Renderer() // invalidate previous efb format prev_efb_format = (unsigned int)-1; + efb_scale_numeratorX = efb_scale_numeratorY = efb_scale_denominatorX = efb_scale_denominatorY = ssaa_multiplier = 1; + #if defined _WIN32 || defined HAVE_LIBAV if (g_ActiveConfig.bDumpFrames && bLastFrameDumped && bAVIDumping) AVIDump::Stop(); @@ -129,41 +136,86 @@ void Renderer::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRect } } -void Renderer::CalculateTargetScale(int x, int y, int &scaledX, int &scaledY) +int Renderer::EFBToScaledX(int x) { switch (g_ActiveConfig.iEFBScale) { - case 3: // 1.5x - scaledX = (x / 2) * 3; - scaledY = (y / 2) * 3; - break; - case 4: // 2x - scaledX = x * 2; - scaledY = y * 2; - break; - case 5: // 2.5x - scaledX = (x / 2) * 5; - scaledY = (y / 2) * 5; - break; - case 6: // 3x - scaledX = x * 3; - scaledY = y * 3; - break; - case 7: // 4x - scaledX = x * 4; - scaledY = y * 4; - break; + case 0: // fractional + return (int)ssaa_multiplier * FramebufferManagerBase::ScaleToVirtualXfbWidth(x, s_backbuffer_width); + default: - scaledX = x; - scaledY = y; - break; + return x * (int)ssaa_multiplier * (int)efb_scale_numeratorX / (int)efb_scale_denominatorX; }; } +int Renderer::EFBToScaledY(int y) +{ + switch (g_ActiveConfig.iEFBScale) + { + case 0: // fractional + return (int)ssaa_multiplier * FramebufferManagerBase::ScaleToVirtualXfbHeight(y, s_backbuffer_height); + + default: + return y * (int)ssaa_multiplier * (int)efb_scale_numeratorY / (int)efb_scale_denominatorY; + }; +} + +void Renderer::CalculateTargetScale(int x, int y, int &scaledX, int &scaledY) +{ + if (g_ActiveConfig.iEFBScale == 0 || g_ActiveConfig.iEFBScale == 1) + { + scaledX = x; + scaledY = y; + } + else + { + scaledX = x * (int)efb_scale_numeratorX / (int)efb_scale_denominatorX; + scaledY = y * (int)efb_scale_numeratorY / (int)efb_scale_denominatorY; + } +} + // return true if target size changed bool Renderer::CalculateTargetSize(unsigned int framebuffer_width, unsigned int framebuffer_height, int multiplier) { int newEFBWidth, newEFBHeight; + + // TODO: Ugly. Clean up + switch (s_LastEFBScale) + { + case 2: // 1x + efb_scale_numeratorX = efb_scale_numeratorY = 1; + efb_scale_denominatorX = efb_scale_denominatorY = 1; + break; + + case 3: // 1.5x + efb_scale_numeratorX = efb_scale_numeratorY = 3; + efb_scale_denominatorX = efb_scale_denominatorY = 2; + break; + + case 4: // 2x + efb_scale_numeratorX = efb_scale_numeratorY = 2; + efb_scale_denominatorX = efb_scale_denominatorY = 1; + break; + + case 5: // 2.5x + efb_scale_numeratorX = efb_scale_numeratorY = 5; + efb_scale_denominatorX = efb_scale_denominatorY = 2; + break; + + case 6: // 3x + efb_scale_numeratorX = efb_scale_numeratorY = 3; + efb_scale_denominatorX = efb_scale_denominatorY = 1; + break; + + case 7: // 4x + efb_scale_numeratorX = efb_scale_numeratorY = 4; + efb_scale_denominatorX = efb_scale_denominatorY = 1; + break; + + default: // fractional & integral handled later + break; + } + switch (s_LastEFBScale) { case 0: // fractional @@ -171,13 +223,18 @@ bool Renderer::CalculateTargetSize(unsigned int framebuffer_width, unsigned int newEFBWidth = FramebufferManagerBase::ScaleToVirtualXfbWidth(EFB_WIDTH, framebuffer_width); newEFBHeight = FramebufferManagerBase::ScaleToVirtualXfbHeight(EFB_HEIGHT, framebuffer_height); - if (s_LastEFBScale) + if (s_LastEFBScale == 1) { newEFBWidth = ((newEFBWidth-1) / EFB_WIDTH + 1) * EFB_WIDTH; newEFBHeight = ((newEFBHeight-1) / EFB_HEIGHT + 1) * EFB_HEIGHT; } + efb_scale_numeratorX = newEFBWidth; + efb_scale_denominatorX = EFB_WIDTH; + efb_scale_numeratorY = newEFBHeight; + efb_scale_denominatorY = EFB_HEIGHT; break; + default: CalculateTargetScale(EFB_WIDTH, EFB_HEIGHT, newEFBWidth, newEFBHeight); break; @@ -185,6 +242,7 @@ bool Renderer::CalculateTargetSize(unsigned int framebuffer_width, unsigned int newEFBWidth *= multiplier; newEFBHeight *= multiplier; + ssaa_multiplier = multiplier; if (newEFBWidth != s_target_width || newEFBHeight != s_target_height) { diff --git a/Source/Core/VideoCommon/Src/RenderBase.h b/Source/Core/VideoCommon/Src/RenderBase.h index 534aa732fe..4da80c9752 100644 --- a/Source/Core/VideoCommon/Src/RenderBase.h +++ b/Source/Core/VideoCommon/Src/RenderBase.h @@ -86,8 +86,8 @@ public: // Use this to upscale native EFB coordinates to IDEAL internal resolution - static unsigned int EFBToScaledX(int x) { return x * GetTargetWidth() / EFB_WIDTH; } - static unsigned int EFBToScaledY(int y) { return y * GetTargetHeight() / EFB_HEIGHT; } + static int EFBToScaledX(int x); + static int EFBToScaledY(int y); // Floating point versions of the above - only use them if really necessary static float EFBToScaledXf(float x) { return x * ((float)GetTargetWidth() / (float)EFB_WIDTH); } @@ -170,6 +170,11 @@ protected: private: static unsigned int prev_efb_format; + static unsigned int efb_scale_numeratorX; + static unsigned int efb_scale_numeratorY; + static unsigned int efb_scale_denominatorX; + static unsigned int efb_scale_denominatorY; + static unsigned int ssaa_multiplier; }; extern Renderer *g_renderer;