diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index 82e5772b15..3f5fce3d10 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -608,7 +608,7 @@ void Renderer::SetBlendingState(const BlendingState& state) } // This function has the final picture. We adjust the aspect ratio here. -void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ticks, float Gamma) +void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region, u64 ticks, float Gamma) { ResetAPIState(); @@ -624,9 +624,8 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ti // activate linear filtering for the buffer copies D3D::SetLinearCopySampler(); auto* xfb_texture = static_cast(texture); - TargetRectangle source_rc = xfb_texture->GetConfig().GetRect(); - BlitScreen(source_rc, targetRc, xfb_texture->GetRawTexIdentifier(), + BlitScreen(xfb_region, targetRc, xfb_texture->GetRawTexIdentifier(), xfb_texture->GetConfig().width, xfb_texture->GetConfig().height, Gamma); // Reset viewport for drawing text diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp index 05aaef66c4..46c9787eb5 100644 --- a/Source/Core/VideoBackends/OGL/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Render.cpp @@ -1325,7 +1325,7 @@ void Renderer::SetBlendingState(const BlendingState& state) } // This function has the final picture. We adjust the aspect ratio here. -void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ticks, float Gamma) +void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region, u64 ticks, float Gamma) { if (g_ogl_config.bSupportsDebug) { @@ -1337,10 +1337,8 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ti auto* xfb_texture = static_cast(texture); - TargetRectangle sourceRc = ConvertEFBRectangle(rc); - sourceRc.left = 0; - sourceRc.right = xfb_texture->GetConfig().width; - sourceRc.top = xfb_texture->GetConfig().height; + TargetRectangle sourceRc = xfb_region; + sourceRc.top = xfb_region.GetHeight(); sourceRc.bottom = 0; ResetAPIState(); diff --git a/Source/Core/VideoBackends/Software/SWOGLWindow.cpp b/Source/Core/VideoBackends/Software/SWOGLWindow.cpp index bead74872d..8027d3fb68 100644 --- a/Source/Core/VideoBackends/Software/SWOGLWindow.cpp +++ b/Source/Core/VideoBackends/Software/SWOGLWindow.cpp @@ -90,7 +90,7 @@ void SWOGLWindow::PrintText(const std::string& text, int x, int y, u32 color) m_text.push_back({text, x, y, color}); } -void SWOGLWindow::ShowImage(AbstractTexture* image, float aspect) +void SWOGLWindow::ShowImage(AbstractTexture* image, const EFBRectangle& xfb_region) { SW::SWTexture* sw_image = static_cast(image); GLInterface->Update(); // just updates the render window position and the backbuffer size @@ -103,6 +103,8 @@ void SWOGLWindow::ShowImage(AbstractTexture* image, float aspect) glActiveTexture(GL_TEXTURE9); glBindTexture(GL_TEXTURE_2D, m_image_texture); + // TODO: Apply xfb_region + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 4-byte pixel alignment glPixelStorei(GL_UNPACK_ROW_LENGTH, sw_image->GetConfig().width); diff --git a/Source/Core/VideoBackends/Software/SWOGLWindow.h b/Source/Core/VideoBackends/Software/SWOGLWindow.h index 68fbcc133e..64ee2414bc 100644 --- a/Source/Core/VideoBackends/Software/SWOGLWindow.h +++ b/Source/Core/VideoBackends/Software/SWOGLWindow.h @@ -9,6 +9,7 @@ #include #include "Common/CommonTypes.h" +#include "VideoCommon/VideoCommon.h" class AbstractTexture; @@ -23,7 +24,7 @@ public: void PrintText(const std::string& text, int x, int y, u32 color); // Image to show, will be swapped immediately - void ShowImage(AbstractTexture* image, float aspect); + void ShowImage(AbstractTexture* image, const EFBRectangle& xfb_region); int PeekMessages(); diff --git a/Source/Core/VideoBackends/Software/SWRenderer.cpp b/Source/Core/VideoBackends/Software/SWRenderer.cpp index 97311d0e1f..3c05068606 100644 --- a/Source/Core/VideoBackends/Software/SWRenderer.cpp +++ b/Source/Core/VideoBackends/Software/SWRenderer.cpp @@ -43,13 +43,13 @@ void SWRenderer::RenderText(const std::string& pstr, int left, int top, u32 colo } // Called on the GPU thread -void SWRenderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ticks, float Gamma) +void SWRenderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region, u64 ticks, float Gamma) { OSD::DoCallbacks(OSD::CallbackType::OnFrame); DrawDebugText(); - SWOGLWindow::s_instance->ShowImage(texture, 1.0); + SWOGLWindow::s_instance->ShowImage(texture, xfb_region); UpdateActiveConfig(); } diff --git a/Source/Core/VideoBackends/Vulkan/Renderer.cpp b/Source/Core/VideoBackends/Vulkan/Renderer.cpp index af0bfba451..d5d105ff6b 100644 --- a/Source/Core/VideoBackends/Vulkan/Renderer.cpp +++ b/Source/Core/VideoBackends/Vulkan/Renderer.cpp @@ -481,7 +481,7 @@ void Renderer::ReinterpretPixelData(unsigned int convtype) BindEFBToStateTracker(); } -void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ticks, float Gamma) +void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region, u64 ticks, float Gamma) { // Pending/batched EFB pokes should be included in the final image. FramebufferManager::GetInstance()->FlushEFBPokes(); @@ -504,7 +504,7 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ti // Draw to the screen if we have a swap chain. if (m_swap_chain) { - DrawScreen(xfb_texture); + DrawScreen(xfb_texture, xfb_region); // Submit the current command buffer, signaling rendering finished semaphore when it's done // Because this final command buffer is rendering to the swap chain, we need to wait for @@ -552,7 +552,7 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ti g_shader_cache->RetrieveAsyncShaders(); } -void Renderer::DrawScreen(VKTexture* xfb_texture) +void Renderer::DrawScreen(VKTexture* xfb_texture, const EFBRectangle& xfb_region) { VkResult res; if (!g_command_buffer_mgr->CheckLastPresentFail()) @@ -605,7 +605,8 @@ void Renderer::DrawScreen(VKTexture* xfb_texture) // Draw TargetRectangle source_rc = xfb_texture->GetConfig().GetRect(); - BlitScreen(m_swap_chain->GetRenderPass(), GetTargetRectangle(), source_rc, xfb_texture->GetRawTexIdentifier()); + BlitScreen(m_swap_chain->GetRenderPass(), GetTargetRectangle(), xfb_region, + xfb_texture->GetRawTexIdentifier()); // Draw OSD Util::SetViewportAndScissor(g_command_buffer_mgr->GetCurrentCommandBuffer(), 0, 0, diff --git a/Source/Core/VideoBackends/Vulkan/Renderer.h b/Source/Core/VideoBackends/Vulkan/Renderer.h index a94d44138b..2fbf240122 100644 --- a/Source/Core/VideoBackends/Vulkan/Renderer.h +++ b/Source/Core/VideoBackends/Vulkan/Renderer.h @@ -86,7 +86,7 @@ private: void DestroyShaders(); // Draw the frame, as well as the OSD to the swap chain. - void DrawScreen(VKTexture* xfb_texture); + void DrawScreen(VKTexture* xfb_texture, const EFBRectangle& xfb_region); // Copies/scales an image to the currently-bound framebuffer. void BlitScreen(VkRenderPass render_pass, const TargetRectangle& dst_rect, diff --git a/Source/Core/VideoCommon/BPStructs.cpp b/Source/Core/VideoCommon/BPStructs.cpp index 93de3aabe5..5bf53832c3 100644 --- a/Source/Core/VideoCommon/BPStructs.cpp +++ b/Source/Core/VideoCommon/BPStructs.cpp @@ -270,7 +270,8 @@ static void BPWritten(const BPCmd& bp) if (g_ActiveConfig.bImmediateXFB) { // below div two to convert from bytes to pixels - it expects width, not stride - g_renderer->Swap(destAddr, destStride / 2, destStride / 2, height, false, srcRect, CoreTiming::GetTicks()); + g_renderer->Swap(destAddr, destStride / 2, destStride / 2, height, srcRect, + CoreTiming::GetTicks()); } else { diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp index e63282d527..8a5ab459d0 100644 --- a/Source/Core/VideoCommon/RenderBase.cpp +++ b/Source/Core/VideoCommon/RenderBase.cpp @@ -651,10 +651,14 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const m_last_xfb_texture = xfb_entry->texture.get(); m_last_xfb_id = xfb_entry->id; m_last_xfb_ticks = ticks; - m_last_xfb_horizontal_scale = horizontal_scale; + + auto xfb_rect = xfb_entry->texture->GetConfig().GetRect(); + xfb_rect.right -= EFBToScaledX(fbStride - fbWidth); + + m_last_xfb_region = xfb_rect; // TODO: merge more generic parts into VideoCommon - g_renderer->SwapImpl(xfb_entry->texture.get(), rc, ticks, xfb_entry->gamma); + g_renderer->SwapImpl(xfb_entry->texture.get(), xfb_rect, ticks, xfb_entry->gamma); m_fps_counter.Update(); update_frame_count = true; @@ -693,7 +697,7 @@ bool Renderer::IsFrameDumping() void Renderer::DoDumpFrame() { - UpdateFrameDumpTexture(m_last_xfb_horizontal_scale); + UpdateFrameDumpTexture(); auto result = m_dump_texture->Map(); if (result.has_value()) @@ -704,7 +708,7 @@ void Renderer::DoDumpFrame() } } -void Renderer::UpdateFrameDumpTexture(float horizontal_scale) +void Renderer::UpdateFrameDumpTexture() { int target_width, target_height; std::tie(target_width, target_height) = CalculateOutputDimensions( @@ -719,9 +723,7 @@ void Renderer::UpdateFrameDumpTexture(float horizontal_scale) config.rendertarget = true; m_dump_texture = g_texture_cache->CreateTexture(config); } - auto source_rect = m_last_xfb_texture->GetConfig().GetRect(); - source_rect.right /= horizontal_scale; - m_dump_texture->CopyRectangleFromTexture(m_last_xfb_texture, source_rect, + m_dump_texture->CopyRectangleFromTexture(m_last_xfb_texture, m_last_xfb_region, EFBRectangle{0, 0, target_width, target_height}); } diff --git a/Source/Core/VideoCommon/RenderBase.h b/Source/Core/VideoCommon/RenderBase.h index 6698f2f66f..8abfdb9894 100644 --- a/Source/Core/VideoCommon/RenderBase.h +++ b/Source/Core/VideoCommon/RenderBase.h @@ -185,7 +185,7 @@ private: void RunFrameDumps(); void ShutdownFrameDumping(); std::tuple CalculateOutputDimensions(int width, int height); - void UpdateFrameDumpTexture(float horizontal_scale); + void UpdateFrameDumpTexture(); PEControl::PixelFormat m_prev_efb_format = PEControl::INVALID_FMT; unsigned int m_efb_scale = 1; @@ -214,7 +214,7 @@ private: AbstractTexture* m_last_xfb_texture = nullptr; u64 m_last_xfb_id = std::numeric_limits::max(); u64 m_last_xfb_ticks = 0; - float m_last_xfb_horizontal_scale = 0.0f; + EFBRectangle m_last_xfb_region; std::unique_ptr m_dump_texture;