mirror of
https://github.com/libretro/ppsspp.git
synced 2025-02-16 06:57:46 +00:00
d3d: Oops, switch over block transfer logic.
This commit is contained in:
parent
ddc9aaa4e8
commit
9d24de3269
@ -19,7 +19,9 @@
|
||||
|
||||
#include "Common/ChunkFile.h"
|
||||
#include "base/logging.h"
|
||||
#include "Core/Debugger/Breakpoints.h"
|
||||
#include "Core/MemMap.h"
|
||||
#include "Core/MIPS/MIPS.h"
|
||||
#include "Core/Host.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Core/Reporting.h"
|
||||
@ -1808,31 +1810,50 @@ void DIRECTX9_GPU::DoBlockTransfer() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Do the copy! (Hm, if we detect a drawn video frame (see below) then we could maybe skip this?)
|
||||
// Can use GetPointerUnchecked because we checked the addresses above. We could also avoid them
|
||||
// entirely by walking a couple of pointers...
|
||||
for (int y = 0; y < height; y++) {
|
||||
const u8 *src = Memory::GetPointerUnchecked(srcBasePtr + ((y + srcY) * srcStride + srcX) * bpp);
|
||||
u8 *dst = Memory::GetPointerUnchecked(dstBasePtr + ((y + dstY) * dstStride + dstX) * bpp);
|
||||
memcpy(dst, src, width * bpp);
|
||||
// Check that the last address of both source and dest are valid addresses
|
||||
|
||||
u32 srcLastAddr = srcBasePtr + ((height - 1 + srcY) * srcStride + (srcX + width - 1)) * bpp;
|
||||
u32 dstLastAddr = dstBasePtr + ((height - 1 + dstY) * dstStride + (dstX + width - 1)) * bpp;
|
||||
|
||||
if (!Memory::IsValidAddress(srcLastAddr)) {
|
||||
ERROR_LOG_REPORT(G3D, "Bottom-right corner of source of block transfer is at an invalid address: %08x", srcLastAddr);
|
||||
return;
|
||||
}
|
||||
if (!Memory::IsValidAddress(dstLastAddr)) {
|
||||
ERROR_LOG_REPORT(G3D, "Bottom-right corner of destination of block transfer is at an invalid address: %08x", srcLastAddr);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Notify all overlapping FBOs that they need to reload.
|
||||
// Tell the framebuffer manager to take action if possible. If it does the entire thing, let's just return.
|
||||
if (!framebufferManager_.NotifyBlockTransferBefore(dstBasePtr, dstStride, dstX, dstY, srcBasePtr, srcStride, srcX, srcY, width, height, bpp)) {
|
||||
// Do the copy! (Hm, if we detect a drawn video frame (see below) then we could maybe skip this?)
|
||||
// Can use GetPointerUnchecked because we checked the addresses above. We could also avoid them
|
||||
// entirely by walking a couple of pointers...
|
||||
if (srcStride == dstStride && (u32)width == srcStride) {
|
||||
// Common case in God of War, let's do it all in one chunk.
|
||||
u32 srcLineStartAddr = srcBasePtr + (srcY * srcStride + srcX) * bpp;
|
||||
u32 dstLineStartAddr = dstBasePtr + (dstY * dstStride + dstX) * bpp;
|
||||
const u8 *src = Memory::GetPointerUnchecked(srcLineStartAddr);
|
||||
u8 *dst = Memory::GetPointerUnchecked(dstLineStartAddr);
|
||||
memcpy(dst, src, width * height * bpp);
|
||||
} else {
|
||||
for (int y = 0; y < height; y++) {
|
||||
u32 srcLineStartAddr = srcBasePtr + ((y + srcY) * srcStride + srcX) * bpp;
|
||||
u32 dstLineStartAddr = dstBasePtr + ((y + dstY) * dstStride + dstX) * bpp;
|
||||
|
||||
textureCache_.Invalidate(dstBasePtr + (dstY * dstStride + dstX) * bpp, height * dstStride * bpp, GPU_INVALIDATE_HINT);
|
||||
const u8 *src = Memory::GetPointerUnchecked(srcLineStartAddr);
|
||||
u8 *dst = Memory::GetPointerUnchecked(dstLineStartAddr);
|
||||
memcpy(dst, src, width * bpp);
|
||||
}
|
||||
}
|
||||
|
||||
// A few games use this INSTEAD of actually drawing the video image to the screen, they just blast it to
|
||||
// the backbuffer. Detect this and have the framebuffermanager draw the pixels.
|
||||
|
||||
u32 backBuffer = framebufferManager_.PrevDisplayFramebufAddr();
|
||||
u32 displayBuffer = framebufferManager_.DisplayFramebufAddr();
|
||||
|
||||
if (((backBuffer != 0 && dstBasePtr == backBuffer) ||
|
||||
(displayBuffer != 0 && dstBasePtr == displayBuffer)) &&
|
||||
dstStride == 512 && height == 272) {
|
||||
framebufferManager_.DrawFramebuffer(Memory::GetPointerUnchecked(dstBasePtr), GE_FORMAT_8888, 512, false);
|
||||
textureCache_.Invalidate(dstBasePtr + (dstY * dstStride + dstX) * bpp, height * dstStride * bpp, GPU_INVALIDATE_HINT);
|
||||
framebufferManager_.NotifyBlockTransferAfter(dstBasePtr, dstStride, dstX, dstY, srcBasePtr, srcStride, srcX, srcY, width, height, bpp);
|
||||
}
|
||||
|
||||
CBreakPoints::ExecMemCheck(srcBasePtr + (srcY * srcStride + srcX) * bpp, false, height * srcStride * bpp, currentMIPS->pc);
|
||||
CBreakPoints::ExecMemCheck(dstBasePtr + (srcY * dstStride + srcX) * bpp, true, height * dstStride * bpp, currentMIPS->pc);
|
||||
|
||||
// TODO: Correct timing appears to be 1.9, but erring a bit low since some of our other timing is inaccurate.
|
||||
cyclesExecuted += ((height * width * bpp) * 16) / 10;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user