From 37b80e21707fe9288d3a5f47fe0ab0a9454b744b Mon Sep 17 00:00:00 2001 From: Scott Mansell Date: Sun, 12 Sep 2021 04:44:25 +1200 Subject: [PATCH 1/2] BPStructs: fix out-of-range EFB copy clamping Previous code from #7950 only clamps correctly when the efb copies left and top coordinates are (0, 0) Now we should handle all situations. Spyro: A hero's tail is an example of a game that does an oversized EFB copy with a non-zero origin. --- Source/Core/VideoCommon/BPStructs.cpp | 30 +++++++++++---------------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/Source/Core/VideoCommon/BPStructs.cpp b/Source/Core/VideoCommon/BPStructs.cpp index 97c78474e1..b00315f9da 100644 --- a/Source/Core/VideoCommon/BPStructs.cpp +++ b/Source/Core/VideoCommon/BPStructs.cpp @@ -3,6 +3,7 @@ #include "VideoCommon/BPStructs.h" +#include #include #include #include @@ -237,26 +238,19 @@ static void BPWritten(const BPCmd& bp) // writing the junk data, we don't write anything to RAM at all for over-sized copies, and clamp // to the EFB borders for over-offset copies. The arcade virtual console games (e.g. 1942) are // known for configuring these out-of-range copies. + + if (u32(srcRect.right) > EFB_WIDTH || u32(srcRect.bottom) > EFB_HEIGHT) + { + WARN_LOG_FMT(VIDEO, "Oversized EFB copy: {}x{} (offset {},{} stride {})", srcRect.GetWidth(), + srcRect.GetHeight(), srcRect.left, srcRect.top, destStride); + + // Clamp the copy region to fit within EFB. So that we don't end up with a stretched image. + srcRect.right = std::clamp(srcRect.right, 0, EFB_WIDTH); + srcRect.bottom = std::clamp(srcRect.bottom, 0, EFB_HEIGHT); + } + u32 copy_width = srcRect.GetWidth(); u32 copy_height = srcRect.GetHeight(); - if (srcRect.right > EFB_WIDTH || srcRect.bottom > EFB_HEIGHT) - { - WARN_LOG_FMT(VIDEO, "Oversized EFB copy: {}x{} (offset {},{} stride {})", copy_width, - copy_height, srcRect.left, srcRect.top, destStride); - - // Adjust the copy size to fit within the EFB. So that we don't end up with a stretched image, - // instead of clamping the source rectangle, we reduce it by the over-sized amount. - if (copy_width > EFB_WIDTH) - { - srcRect.right -= copy_width - EFB_WIDTH; - copy_width = EFB_WIDTH; - } - if (copy_height > EFB_HEIGHT) - { - srcRect.bottom -= copy_height - EFB_HEIGHT; - copy_height = EFB_HEIGHT; - } - } // Check if we are to copy from the EFB or draw to the XFB const UPE_Copy PE_copy = bpmem.triggerEFBCopy; From eb8bfabdfda83dd2cbacfa5c2bc89a5254e587b3 Mon Sep 17 00:00:00 2001 From: Scott Mansell Date: Wed, 15 Sep 2021 11:54:40 +1200 Subject: [PATCH 2/2] BPStructs: make copy width/height const --- Source/Core/VideoCommon/BPStructs.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Core/VideoCommon/BPStructs.cpp b/Source/Core/VideoCommon/BPStructs.cpp index b00315f9da..57a418e8d0 100644 --- a/Source/Core/VideoCommon/BPStructs.cpp +++ b/Source/Core/VideoCommon/BPStructs.cpp @@ -249,8 +249,8 @@ static void BPWritten(const BPCmd& bp) srcRect.bottom = std::clamp(srcRect.bottom, 0, EFB_HEIGHT); } - u32 copy_width = srcRect.GetWidth(); - u32 copy_height = srcRect.GetHeight(); + const u32 copy_width = srcRect.GetWidth(); + const u32 copy_height = srcRect.GetHeight(); // Check if we are to copy from the EFB or draw to the XFB const UPE_Copy PE_copy = bpmem.triggerEFBCopy;