rsx: Fix 2D intersection tests

This commit is contained in:
kd-11 2022-08-14 19:46:25 +03:00 committed by kd-11
parent 1244044647
commit bacf518189
3 changed files with 30 additions and 34 deletions

View File

@ -546,20 +546,15 @@ namespace rsx
const auto parent_w = surface->template get_surface_width<rsx::surface_metrics::bytes>(); const auto parent_w = surface->template get_surface_width<rsx::surface_metrics::bytes>();
const auto parent_h = surface->template get_surface_height<rsx::surface_metrics::bytes>(); const auto parent_h = surface->template get_surface_height<rsx::surface_metrics::bytes>();
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, dst_offset, size] = 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);
if (src_offset.x >= parent_w || src_offset.y >= parent_h) if (!size.width || !size.height)
{ {
return surface_inheritance_result::none; return surface_inheritance_result::none;
} }
if (dst_offset.x >= child_w || dst_offset.y >= child_h) ensure(src_offset.x < parent_w && src_offset.y < parent_h);
{ ensure(dst_offset.x < child_w && dst_offset.y < child_h);
return surface_inheritance_result::none;
}
// TODO: Eventually need to stack all the overlapping regions, but for now just do the latest rect in the space // TODO: Eventually need to stack all the overlapping regions, but for now just do the latest rect in the space
deferred_clipped_region<T*> region; deferred_clipped_region<T*> region;

View File

@ -332,24 +332,25 @@ namespace rsx
const auto section_bpp = get_format_block_size_in_bytes(section->get_gcm_format()); 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 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) */ 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) */ address, attr.width, attr.slice_h, attr.bpp, /* child region (extracted) */
attr.pitch); attr.pitch);
// Rect intersection test if (!dst_size.width || !dst_size.height)
// TODO: Make the intersection code cleaner with proper 2D regions
if (std::get<0>(clipped).x >= section->get_width())
{ {
// Overlap lies outside the image area! // Out of bounds, invalid intersection
return; 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_begin = slice * attr.slice_h;
const u32 slice_end = slice_begin + attr.height; const u32 slice_end = slice_begin + attr.height;
const auto dst_y = std::get<1>(clipped).y; const auto dst_y = dst_offset.y;
const auto dst_h = std::get<2>(clipped).height; const auto dst_h = dst_size.height;
const auto section_end = dst_y + dst_h; const auto section_end = dst_y + dst_h;
if (dst_y >= slice_end || section_end <= slice_begin) if (dst_y >= slice_end || section_end <= slice_begin)
@ -358,14 +359,14 @@ namespace rsx
return; return;
} }
const u16 dst_w = static_cast<u16>(std::get<2>(clipped).width); const u16 dst_w = static_cast<u16>(dst_size.width);
const u16 src_w = static_cast<u16>(dst_w * attr.bpp) / section_bpp; const u16 src_w = static_cast<u16>(dst_w * attr.bpp) / section_bpp;
const u16 height = std::min(slice_end, section_end) - dst_y; const u16 height = std::min(slice_end, section_end) - dst_y;
if (scaling) if (scaling)
{ {
// Since output is upscaled, also upscale on dst // Since output is upscaled, also upscale on dst
const auto [_dst_x, _dst_y] = rsx::apply_resolution_scale<false>(static_cast<u16>(std::get<1>(clipped).x), static_cast<u16>(dst_y - slice_begin), attr.width, attr.height); const auto [_dst_x, _dst_y] = rsx::apply_resolution_scale<false>(static_cast<u16>(dst_offset.x), static_cast<u16>(dst_y - slice_begin), attr.width, attr.height);
const auto [_dst_w, _dst_h] = rsx::apply_resolution_scale<true>(dst_w, height, attr.width, attr.height); const auto [_dst_w, _dst_h] = rsx::apply_resolution_scale<true>(dst_w, height, attr.width, attr.height);
out.push_back out.push_back
@ -373,16 +374,16 @@ namespace rsx
section->get_raw_texture(), section->get_raw_texture(),
surface_transform::identity, surface_transform::identity,
0, 0,
static_cast<u16>(std::get<0>(clipped).x), // src.x static_cast<u16>(src_offset.x), // src.x
static_cast<u16>(std::get<0>(clipped).y), // src.y static_cast<u16>(src_offset.y), // src.y
_dst_x, // dst.x _dst_x, // dst.x
_dst_y, // dst.y _dst_y, // dst.y
slice, slice,
src_w, src_w,
height, height,
_dst_w, _dst_w,
_dst_h, _dst_h
}); });
} }
else else
{ {
@ -391,16 +392,16 @@ namespace rsx
section->get_raw_texture(), section->get_raw_texture(),
surface_transform::identity, surface_transform::identity,
0, 0,
static_cast<u16>(std::get<0>(clipped).x), // src.x static_cast<u16>(src_offset.x), // src.x
static_cast<u16>(std::get<0>(clipped).y), // src.y static_cast<u16>(src_offset.y), // src.y
static_cast<u16>(std::get<1>(clipped).x), // dst.x static_cast<u16>(dst_offset.x), // dst.x
static_cast<u16>(dst_y - slice_begin), // dst.y static_cast<u16>(dst_y - slice_begin), // dst.y
0, 0,
src_w, src_w,
height, height,
dst_w, dst_w,
height, height
}); });
} }
}; };

View File

@ -570,8 +570,8 @@ namespace rsx
const auto src_y = 0u; const auto src_y = 0u;
const auto dst_y = (offset / pitch); const auto dst_y = (offset / pitch);
const auto dst_x = (offset % pitch) / child_bpp; const auto dst_x = (offset % pitch) / child_bpp;
const auto w = std::min<u32>(parent_w, child_w - dst_x); const auto w = std::min<u32>(parent_w, std::max<u32>(child_w, dst_x) - dst_x); // Clamp negatives to 0!
const auto h = std::min<u32>(parent_h, child_h - dst_y); const auto h = std::min<u32>(parent_h, std::max<u32>(child_h, dst_y) - dst_y);
return std::make_tuple<position2u, position2u, size2u>({ src_x, src_y }, { dst_x, dst_y }, { w, h }); return std::make_tuple<position2u, position2u, size2u>({ 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 src_x = (offset % pitch) / parent_bpp;
const auto dst_x = 0u; const auto dst_x = 0u;
const auto dst_y = 0u; const auto dst_y = 0u;
const auto w = std::min<u32>(child_w, parent_w - src_x); const auto w = std::min<u32>(child_w, std::max<u32>(parent_w, src_x) - src_x);
const auto h = std::min<u32>(child_h, parent_h - src_y); const auto h = std::min<u32>(child_h, std::max<u32>(parent_h, src_y) - src_y);
return std::make_tuple<position2u, position2u, size2u>({ src_x, src_y }, { dst_x, dst_y }, { w, h }); return std::make_tuple<position2u, position2u, size2u>({ src_x, src_y }, { dst_x, dst_y }, { w, h });
} }