rsx: Fix overlapping transfer of nv3089::image_in when out_pitch != in_pitch

or out_pitch != out_bpp * out_w
This commit is contained in:
Eladash 2019-08-10 07:07:01 +03:00 committed by Ani
parent 19825366f5
commit 527b1bb071
3 changed files with 98 additions and 25 deletions

View File

@ -1067,23 +1067,86 @@ namespace rsx
if (method_registers.blit_engine_context_surface() != blit_engine::context_surface::swizzle2d)
{
if (need_convert || need_clip)
if (!need_convert)
{
if (need_clip)
const bool is_overlapping = scale_x > 0 && scale_y > 0 && dst_dma == src_dma && [&]() -> bool
{
if (need_convert)
const u32 src_max = src_offset + in_pitch * (in_h - 1) + (in_bpp * in_w);
const u32 dst_max = dst_offset + out_pitch * (out_h - 1) + (out_bpp * out_w);
return (src_offset >= dst_offset && src_offset < dst_max) ||
(dst_offset >= src_offset && dst_offset < src_max);
}();
if (is_overlapping)
{
if (need_clip)
{
temp2.resize(out_pitch * std::max(convert_h, (u32)clip_h));
temp2.resize(out_pitch * clip_h);
convert_scale_image(temp2.data(), out_format, convert_w, convert_h, out_pitch,
pixels_src, in_format, in_w, in_h, in_pitch, slice_h, in_inter == blit_engine::transfer_interpolator::foh);
clip_image_may_overlap(pixels_dst, pixels_src, clip_x, clip_y, clip_w, clip_h, out_bpp, in_pitch, out_pitch, temp2.data());
}
else if (out_pitch != in_pitch || out_pitch != out_bpp * out_w)
{
const u32 buffer_pitch = out_bpp * out_w;
temp2.resize(buffer_pitch * out_h);
std::add_pointer_t<u8> buf = temp2.data(), pixels = pixels_src;
clip_image(pixels_dst, temp2.data(), clip_x, clip_y, clip_w, clip_h, out_bpp, out_pitch, out_pitch);
// Read the whole buffer from source
for (u32 y = 0; y < out_h; ++y)
{
std::memcpy(buf, pixels, buffer_pitch);
pixels += in_pitch;
buf += buffer_pitch;
}
buf = temp2.data(), pixels = pixels_dst;
// Write to destination
for (u32 y = 0; y < out_h; ++y)
{
std::memcpy(pixels, buf, buffer_pitch);
pixels += out_pitch;
buf += buffer_pitch;
}
}
else
{
std::memmove(pixels_dst, pixels_src, out_pitch * out_h);
}
}
else
{
if (need_clip)
{
clip_image(pixels_dst, pixels_src, clip_x, clip_y, clip_w, clip_h, out_bpp, in_pitch, out_pitch);
}
else if (out_pitch != in_pitch || out_pitch != out_bpp * out_w)
{
u8 *dst = pixels_dst, *src = pixels_src;
for (u32 y = 0; y < out_h; ++y)
{
std::memcpy(dst, src, out_w * out_bpp);
dst += out_pitch;
src += in_pitch;
}
}
else
{
std::memcpy(pixels_dst, pixels_src, out_pitch * out_h);
}
}
}
else
{
if (need_clip)
{
temp2.resize(out_pitch * std::max(convert_h, (u32)clip_h));
convert_scale_image(temp2.data(), out_format, convert_w, convert_h, out_pitch,
pixels_src, in_format, in_w, in_h, in_pitch, slice_h, in_inter == blit_engine::transfer_interpolator::foh);
clip_image(pixels_dst, temp2.data(), clip_x, clip_y, clip_w, clip_h, out_bpp, out_pitch, out_pitch);
}
else
{
@ -1091,23 +1154,6 @@ namespace rsx
pixels_src, in_format, in_w, in_h, in_pitch, slice_h, in_inter == blit_engine::transfer_interpolator::foh);
}
}
else
{
if (out_pitch != in_pitch || out_pitch != out_bpp * out_w)
{
for (u32 y = 0; y < out_h; ++y)
{
u8 *dst = pixels_dst + out_pitch * y;
u8 *src = pixels_src + in_pitch * y;
std::memmove(dst, src, out_w * out_bpp);
}
}
else
{
std::memmove(pixels_dst, pixels_src, out_pitch * out_h);
}
}
}
else
{

View File

@ -32,12 +32,38 @@ namespace rsx
for (int y = 0; y < clip_h; ++y)
{
std::memmove(pixels_dst, pixels_src, row_length);
std::memcpy(pixels_dst, pixels_src, row_length);
pixels_src += src_pitch;
pixels_dst += dst_pitch;
}
}
void clip_image_may_overlap(u8 *dst, const u8 *src, int clip_x, int clip_y, int clip_w, int clip_h, int bpp, int src_pitch, int dst_pitch, u8 *buffer)
{
src += clip_y * src_pitch + clip_x * bpp;
const u32 buffer_pitch = bpp * clip_w;
u8* buf = buffer;
// Read the whole buffer from source
for (u32 y = 0; y < clip_h; ++y)
{
std::memcpy(buf, src, buffer_pitch);
src += src_pitch;
buf += buffer_pitch;
}
buf = buffer;
// Write to destination
for (u32 y = 0; y < clip_h; ++y)
{
std::memcpy(dst, buf, buffer_pitch);
dst += dst_pitch;
buf += buffer_pitch;
}
}
//Convert decoded integer values for CONSTANT_BLEND_FACTOR into f32 array in 0-1 range
std::array<float, 4> get_constant_blend_colors()
{

View File

@ -425,6 +425,7 @@ namespace rsx
const u8 *src, AVPixelFormat src_format, int src_width, int src_height, int src_pitch, int src_slice_h, bool bilinear);
void clip_image(u8 *dst, const u8 *src, int clip_x, int clip_y, int clip_w, int clip_h, int bpp, int src_pitch, int dst_pitch);
void clip_image_may_overlap(u8 *dst, const u8 *src, int clip_x, int clip_y, int clip_w, int clip_h, int bpp, int src_pitch, int dst_pitch, u8* buffer);
void convert_le_f32_to_be_d24(void *dst, void *src, u32 row_length_in_texels, u32 num_rows);
void convert_le_d24x8_to_be_d24x8(void *dst, void *src, u32 row_length_in_texels, u32 num_rows);