Skip to content

Commit

Permalink
Partial texture updates with parts of efb copies
Browse files Browse the repository at this point in the history
As long as an efb copy overlaps a normal texture, copy the overlapping part from the efb copy into the normal texture. Before the pr, this was restricted to efb copies that are completely within the normal texture.

This is supposed to fix the invisible character in Donkey Kong Returns, which was caused by dolphin-emu#3165, because it tries to load smaller textures than the created efb copies.
  • Loading branch information
mimimi085181 committed Nov 17, 2015
1 parent 24c7d23 commit c1880e7
Showing 1 changed file with 43 additions and 18 deletions.
61 changes: 43 additions & 18 deletions Source/Core/VideoCommon/TextureCacheBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,24 +229,43 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::DoPartialTextureUpdates(Tex
TCacheEntryBase* entry = iter->second;
if (entry != entry_to_update
&& entry->IsEfbCopy()
&& entry_to_update->addr <= entry->addr
&& entry->addr + entry->size_in_bytes <= entry_to_update->addr + entry_to_update->size_in_bytes
&& entry->OverlapsMemoryRange(entry_to_update->addr, entry_to_update->size_in_bytes)
&& entry->frameCount == FRAMECOUNT_INVALID
&& entry->memory_stride == numBlocksX * block_size)
{
ERROR_LOG(VIDEO, "trying to update: 0x%08x-0x%08x with 0x%08x-0x%08x", entry_to_update->addr, entry_to_update->addr + entry_to_update->size_in_bytes, entry->addr, entry->addr + entry->size_in_bytes);
if (entry->hash == entry->CalculateHash())
{
u32 block_offset = (entry->addr - entry_to_update->addr) / block_size;
u32 block_x = block_offset % numBlocksX;
u32 block_y = block_offset / numBlocksX;

u32 x = block_x * block_width;
u32 y = block_y * block_height;
u32 src_x, src_y, dst_x, dst_y;
MathUtil::Rectangle<int> srcrect, dstrect;
srcrect.left = 0;
srcrect.top = 0;
dstrect.left = 0;
dstrect.top = 0;

if (entry->addr >= entry_to_update->addr)
{
u32 block_offset = (entry->addr - entry_to_update->addr) / block_size;
u32 block_x = block_offset % numBlocksX;
u32 block_y = block_offset / numBlocksX;

dst_x = block_x * block_width;
dst_y = block_y * block_height;
src_x = 0;
src_y = 0;
}
else
{
u32 block_offset = (entry_to_update->addr - entry->addr) / block_size;
u32 block_x = block_offset % numBlocksX;
u32 block_y = block_offset / numBlocksX;

src_x = block_x * block_width;
src_y = block_y * block_height;
dst_x = 0;
dst_y = 0;
}
u32 copy_width = std::min(entry->native_width - src_x, entry_to_update->native_width - dst_x);
u32 copy_height = std::min(entry->native_height - src_y, entry_to_update->native_height - dst_y);

ERROR_LOG(VIDEO, "hash ok, src: %4d/%4d(%4d/%4d), dst %4d/%4d(%4d/%4d) size: %4d/%4d", src_x, src_y, entry->native_width, entry->native_height, dst_x, dst_y, entry_to_update->native_width, entry_to_update->native_height, copy_width, copy_height);

if (entry_need_scaling)
{
entry_need_scaling = false;
Expand All @@ -270,8 +289,12 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::DoPartialTextureUpdates(Tex
newentry->SetHashes(entry_to_update->base_hash, entry_to_update->hash);
newentry->frameCount = frameCount;
newentry->is_efb_copy = false;
srcrect.left = 0;
srcrect.top = 0;
srcrect.right = entry_to_update->config.width;
srcrect.bottom = entry_to_update->config.height;
dstrect.left = 0;
dstrect.top = 0;
dstrect.right = w;
dstrect.bottom = h;
newentry->CopyRectangleFromTexture(entry_to_update, srcrect, dstrect);
Expand All @@ -281,12 +304,14 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::DoPartialTextureUpdates(Tex
textures_by_address.emplace(key, entry_to_update);
}
}
srcrect.right = entry->config.width;
srcrect.bottom = entry->config.height;
dstrect.left = x * entry_to_update->config.width / entry_to_update->native_width;
dstrect.top = y * entry_to_update->config.height / entry_to_update->native_height;
dstrect.right = (x + entry->native_width) * entry_to_update->config.width / entry_to_update->native_width;
dstrect.bottom = (y + entry->native_height) * entry_to_update->config.height / entry_to_update->native_height;
srcrect.left = src_x * entry_to_update->config.width / entry_to_update->native_width;
srcrect.top = src_y * entry_to_update->config.height / entry_to_update->native_height;
srcrect.right = (src_x + copy_width) * entry_to_update->config.width / entry_to_update->native_width;
srcrect.bottom = (src_y + copy_height) * entry_to_update->config.height / entry_to_update->native_height;
dstrect.left = dst_x * entry_to_update->config.width / entry_to_update->native_width;
dstrect.top = dst_y * entry_to_update->config.height / entry_to_update->native_height;
dstrect.right = (dst_x + copy_width) * entry_to_update->config.width / entry_to_update->native_width;
dstrect.bottom = (dst_y + copy_height) * entry_to_update->config.height / entry_to_update->native_height;
entry_to_update->CopyRectangleFromTexture(entry, srcrect, dstrect);
// Mark the texture update as used, so it isn't applied more than once
entry->frameCount = frameCount;
Expand Down

0 comments on commit c1880e7

Please sign in to comment.