rsx: Perform region clipping in a normalized coordinate space

- Depending on what the caller wants to do, the scaling will be different for src vs dst calculations.
  We cannot reliably handle this in the callee
This commit is contained in:
kd-11 2023-05-17 18:22:58 +03:00 committed by kd-11
parent d894ccb4ea
commit edb2b60f2f
3 changed files with 26 additions and 21 deletions

View file

@ -560,7 +560,7 @@ namespace rsx
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 [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, dst_offset, size] = rsx::intersect_region(surface->base_addr, parent_w, parent_h, base_addr, child_w, child_h, get_rsx_pitch());
if (!size.width || !size.height)
{

View file

@ -323,50 +323,55 @@ namespace rsx
slice,
src_width, src_height,
dst_width, dst_height
});
});
};
auto add_local_resource = [&](auto& section, u32 address, u16 slice, bool scaling = true)
{
// Intersect this resource with the original one
// Intersect this resource with the original one.
// Note that intersection takes place in a normalized coordinate space (bpp = 1)
const u32 section_bpp = get_format_block_size_in_bytes(section->get_gcm_format());
const u32 normalized_width = (section->get_width() * section_bpp) / attr.bpp;
const u32 normalized_section_width = (section->get_width() * section_bpp);
const u32 normalized_attr_width = (attr.width * attr.bpp);
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) */
auto [src_offset, dst_offset, dimensions] = rsx::intersect_region(
section->get_section_base(), normalized_section_width, section->get_height(), /* parent region (extractee) */
address, normalized_attr_width, attr.slice_h, /* child region (extracted) */
attr.pitch);
if (!dst_size.width || !dst_size.height)
if (!dimensions.width || !dimensions.height)
{
// 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);
// The intersection takes place in a normalized coordinate space. Now we convert back to domain-specific
src_offset.x /= section_bpp;
dst_offset.x /= attr.bpp;
const size2u dst_size = { dimensions.width / attr.bpp, dimensions.height };
const size2u src_size = { dimensions.width / section_bpp, dimensions.height };
const u32 slice_begin = slice * attr.slice_h;
const u32 slice_end = slice_begin + attr.height;
const u32 dst_slice_begin = slice * attr.slice_h; // Output slice low watermark
const u32 dst_slice_end = slice_begin + attr.height; // Output slice high watermark
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)
const auto write_section_end = dst_y + dst_h;
if (dst_y >= dst_slice_end || write_section_end <= dst_slice_begin)
{
// Belongs to a different slice
return;
}
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 height = std::min(slice_end, section_end) - dst_y;
const u16 src_w = static_cast<u16>(src_size.width);
const u16 height = std::min(dst_slice_end, write_section_end) - dst_y;
if (scaling)
{
// Since output is upscaled, also upscale on dst
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_x, _dst_y] = rsx::apply_resolution_scale<false>(static_cast<u16>(dst_offset.x), static_cast<u16>(dst_y - dst_slice_begin), 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

View file

@ -559,8 +559,8 @@ namespace rsx
* Extracts from 'parent' a region that fits in 'child'
*/
static inline std::tuple<position2u, position2u, size2u> intersect_region(
u32 parent_address, u16 parent_w, u16 parent_h, u16 parent_bpp,
u32 child_address, u16 child_w, u16 child_h, u32 child_bpp,
u32 parent_address, u16 parent_w, u16 parent_h,
u32 child_address, u16 child_w, u16 child_h,
u32 pitch)
{
if (child_address < parent_address)
@ -569,7 +569,7 @@ namespace rsx
const auto src_x = 0u;
const auto src_y = 0u;
const auto dst_y = (offset / pitch);
const auto dst_x = (offset % pitch) / child_bpp;
const auto dst_x = (offset % pitch);
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, std::max<u32>(child_h, dst_y) - dst_y);
@ -579,7 +579,7 @@ namespace rsx
{
const auto offset = child_address - parent_address;
const auto src_y = (offset / pitch);
const auto src_x = (offset % pitch) / parent_bpp;
const auto src_x = (offset % pitch);
const auto dst_x = 0u;
const auto dst_y = 0u;
const auto w = std::min<u32>(child_w, std::max<u32>(parent_w, src_x) - src_x);