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.
This commit is contained in:
Scott Mansell 2021-09-12 04:44:25 +12:00
parent 1b32a61d6a
commit 37b80e2170
1 changed files with 12 additions and 18 deletions

View File

@ -3,6 +3,7 @@
#include "VideoCommon/BPStructs.h" #include "VideoCommon/BPStructs.h"
#include <algorithm>
#include <cmath> #include <cmath>
#include <cstring> #include <cstring>
#include <string> #include <string>
@ -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 // 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 // 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. // 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<int>(srcRect.right, 0, EFB_WIDTH);
srcRect.bottom = std::clamp<int>(srcRect.bottom, 0, EFB_HEIGHT);
}
u32 copy_width = srcRect.GetWidth(); u32 copy_width = srcRect.GetWidth();
u32 copy_height = srcRect.GetHeight(); 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 // Check if we are to copy from the EFB or draw to the XFB
const UPE_Copy PE_copy = bpmem.triggerEFBCopy; const UPE_Copy PE_copy = bpmem.triggerEFBCopy;