diff --git a/rpcs3/Emu/RSX/Common/surface_utils.h b/rpcs3/Emu/RSX/Common/surface_utils.h index 6ca3712e12..1ead7ffb41 100644 --- a/rpcs3/Emu/RSX/Common/surface_utils.h +++ b/rpcs3/Emu/RSX/Common/surface_utils.h @@ -546,20 +546,15 @@ namespace rsx const auto parent_w = surface->template get_surface_width(); const auto parent_h = surface->template get_surface_height(); - const auto rect = rsx::intersect_region(surface->base_addr, parent_w, parent_h, 1, base_addr, child_w, child_h, 1, get_rsx_pitch()); - const auto src_offset = std::get<0>(rect); - const auto dst_offset = std::get<1>(rect); - const auto size = std::get<2>(rect); + const auto [src_offset, dst_offset, size] = rsx::intersect_region(surface->base_addr, parent_w, parent_h, 1, base_addr, child_w, child_h, 1, get_rsx_pitch()); - if (src_offset.x >= parent_w || src_offset.y >= parent_h) + if (!size.width || !size.height) { return surface_inheritance_result::none; } - if (dst_offset.x >= child_w || dst_offset.y >= child_h) - { - return surface_inheritance_result::none; - } + ensure(src_offset.x < parent_w && src_offset.y < parent_h); + ensure(dst_offset.x < child_w && dst_offset.y < child_h); // TODO: Eventually need to stack all the overlapping regions, but for now just do the latest rect in the space deferred_clipped_region region; diff --git a/rpcs3/Emu/RSX/Common/texture_cache_helpers.h b/rpcs3/Emu/RSX/Common/texture_cache_helpers.h index a951375813..394053807c 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache_helpers.h +++ b/rpcs3/Emu/RSX/Common/texture_cache_helpers.h @@ -332,24 +332,25 @@ namespace rsx const auto section_bpp = get_format_block_size_in_bytes(section->get_gcm_format()); const auto normalized_width = (section->get_width() * section_bpp) / attr.bpp; - const auto clipped = rsx::intersect_region( + const auto [src_offset, dst_offset, dst_size] = rsx::intersect_region( section->get_section_base(), normalized_width, section->get_height(), section_bpp, /* parent region (extractee) */ address, attr.width, attr.slice_h, attr.bpp, /* child region (extracted) */ attr.pitch); - // Rect intersection test - // TODO: Make the intersection code cleaner with proper 2D regions - if (std::get<0>(clipped).x >= section->get_width()) + if (!dst_size.width || !dst_size.height) { - // Overlap lies outside the image area! + // Out of bounds, invalid intersection return; } + ensure(src_offset.x < normalized_width && src_offset.y < section->get_height()); + ensure(dst_offset.x < attr.width && dst_offset.y < attr.slice_h); + const u32 slice_begin = slice * attr.slice_h; const u32 slice_end = slice_begin + attr.height; - const auto dst_y = std::get<1>(clipped).y; - const auto dst_h = std::get<2>(clipped).height; + const auto dst_y = dst_offset.y; + const auto dst_h = dst_size.height; const auto section_end = dst_y + dst_h; if (dst_y >= slice_end || section_end <= slice_begin) @@ -358,14 +359,14 @@ namespace rsx return; } - const u16 dst_w = static_cast(std::get<2>(clipped).width); + const u16 dst_w = static_cast(dst_size.width); const u16 src_w = static_cast(dst_w * attr.bpp) / section_bpp; const u16 height = std::min(slice_end, section_end) - dst_y; if (scaling) { // Since output is upscaled, also upscale on dst - const auto [_dst_x, _dst_y] = rsx::apply_resolution_scale(static_cast(std::get<1>(clipped).x), static_cast(dst_y - slice_begin), attr.width, attr.height); + const auto [_dst_x, _dst_y] = rsx::apply_resolution_scale(static_cast(dst_offset.x), static_cast(dst_y - slice_begin), attr.width, attr.height); const auto [_dst_w, _dst_h] = rsx::apply_resolution_scale(dst_w, height, attr.width, attr.height); out.push_back @@ -373,16 +374,16 @@ namespace rsx section->get_raw_texture(), surface_transform::identity, 0, - static_cast(std::get<0>(clipped).x), // src.x - static_cast(std::get<0>(clipped).y), // src.y - _dst_x, // dst.x - _dst_y, // dst.y + static_cast(src_offset.x), // src.x + static_cast(src_offset.y), // src.y + _dst_x, // dst.x + _dst_y, // dst.y slice, src_w, height, _dst_w, - _dst_h, - }); + _dst_h + }); } else { @@ -391,16 +392,16 @@ namespace rsx section->get_raw_texture(), surface_transform::identity, 0, - static_cast(std::get<0>(clipped).x), // src.x - static_cast(std::get<0>(clipped).y), // src.y - static_cast(std::get<1>(clipped).x), // dst.x - static_cast(dst_y - slice_begin), // dst.y + static_cast(src_offset.x), // src.x + static_cast(src_offset.y), // src.y + static_cast(dst_offset.x), // dst.x + static_cast(dst_y - slice_begin), // dst.y 0, src_w, height, dst_w, - height, - }); + height + }); } }; diff --git a/rpcs3/Emu/RSX/rsx_utils.h b/rpcs3/Emu/RSX/rsx_utils.h index 5f8aa34b4a..d9e10306b9 100644 --- a/rpcs3/Emu/RSX/rsx_utils.h +++ b/rpcs3/Emu/RSX/rsx_utils.h @@ -570,8 +570,8 @@ namespace rsx const auto src_y = 0u; const auto dst_y = (offset / pitch); const auto dst_x = (offset % pitch) / child_bpp; - const auto w = std::min(parent_w, child_w - dst_x); - const auto h = std::min(parent_h, child_h - dst_y); + const auto w = std::min(parent_w, std::max(child_w, dst_x) - dst_x); // Clamp negatives to 0! + const auto h = std::min(parent_h, std::max(child_h, dst_y) - dst_y); return std::make_tuple({ src_x, src_y }, { dst_x, dst_y }, { w, h }); } @@ -582,8 +582,8 @@ namespace rsx const auto src_x = (offset % pitch) / parent_bpp; const auto dst_x = 0u; const auto dst_y = 0u; - const auto w = std::min(child_w, parent_w - src_x); - const auto h = std::min(child_h, parent_h - src_y); + const auto w = std::min(child_w, std::max(parent_w, src_x) - src_x); + const auto h = std::min(child_h, std::max(parent_h, src_y) - src_y); return std::make_tuple({ src_x, src_y }, { dst_x, dst_y }, { w, h }); }