GPU: Implement non-interleaved interlaced rendering
Fixes screen shaking in True Pinball.
This commit is contained in:
@ -43,9 +43,11 @@ void GPU_SW::Reset()
|
||||
m_vram.fill(0);
|
||||
}
|
||||
|
||||
void GPU_SW::CopyOut15Bit(u32 src_x, u32 src_y, u32* dst_ptr, u32 dst_stride, u32 width, u32 height, bool interlaced)
|
||||
void GPU_SW::CopyOut15Bit(u32 src_x, u32 src_y, u32* dst_ptr, u32 dst_stride, u32 width, u32 height, bool interlaced,
|
||||
bool interleaved)
|
||||
{
|
||||
const u8 interlaced_shift = BoolToUInt8(interlaced);
|
||||
const u8 interleaved_shift = BoolToUInt8(interleaved);
|
||||
|
||||
// Fast path when not wrapping around.
|
||||
if ((src_x + width) <= VRAM_WIDTH && (src_y + height) <= VRAM_HEIGHT)
|
||||
@ -54,7 +56,7 @@ void GPU_SW::CopyOut15Bit(u32 src_x, u32 src_y, u32* dst_ptr, u32 dst_stride, u3
|
||||
height >>= interlaced_shift;
|
||||
|
||||
const u16* src_ptr = &m_vram[src_y * VRAM_WIDTH + src_x];
|
||||
const u32 src_stride = VRAM_WIDTH << interlaced_shift;
|
||||
const u32 src_stride = VRAM_WIDTH << interleaved_shift;
|
||||
for (u32 row = 0; row < height; row++)
|
||||
{
|
||||
const u16* src_row_ptr = src_ptr;
|
||||
@ -80,15 +82,17 @@ void GPU_SW::CopyOut15Bit(u32 src_x, u32 src_y, u32* dst_ptr, u32 dst_stride, u3
|
||||
for (u32 col = src_x; col < end_x; col++)
|
||||
*(dst_row_ptr++) = RGBA5551ToRGBA8888(src_row_ptr[col % VRAM_WIDTH]);
|
||||
|
||||
src_y += (1 << interlaced_shift);
|
||||
src_y += (1 << interleaved_shift);
|
||||
dst_ptr += dst_stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GPU_SW::CopyOut24Bit(u32 src_x, u32 src_y, u32* dst_ptr, u32 dst_stride, u32 width, u32 height, bool interlaced)
|
||||
void GPU_SW::CopyOut24Bit(u32 src_x, u32 src_y, u32* dst_ptr, u32 dst_stride, u32 width, u32 height, bool interlaced,
|
||||
bool interleaved)
|
||||
{
|
||||
const u8 interlaced_shift = BoolToUInt8(interlaced);
|
||||
const u8 interleaved_shift = BoolToUInt8(interleaved);
|
||||
|
||||
if ((src_x + width) <= VRAM_WIDTH && (src_y + height) <= VRAM_HEIGHT)
|
||||
{
|
||||
@ -96,7 +100,7 @@ void GPU_SW::CopyOut24Bit(u32 src_x, u32 src_y, u32* dst_ptr, u32 dst_stride, u3
|
||||
height >>= interlaced_shift;
|
||||
|
||||
const u8* src_ptr = reinterpret_cast<const u8*>(&m_vram[src_y * VRAM_WIDTH + src_x]);
|
||||
const u32 src_stride = (VRAM_WIDTH << interlaced_shift) * sizeof(u16);
|
||||
const u32 src_stride = (VRAM_WIDTH << interleaved_shift) * sizeof(u16);
|
||||
for (u32 row = 0; row < height; row++)
|
||||
{
|
||||
const u8* src_row_ptr = src_ptr;
|
||||
@ -133,7 +137,7 @@ void GPU_SW::CopyOut24Bit(u32 src_x, u32 src_y, u32* dst_ptr, u32 dst_stride, u3
|
||||
*(dst_row_ptr++) = (((ZeroExtend32(s1) << 16) | ZeroExtend32(s0)) >> shift) | 0xFF000000u;
|
||||
}
|
||||
|
||||
src_y += (1 << interlaced_shift);
|
||||
src_y += (1 << interleaved_shift);
|
||||
dst_ptr += dst_stride;
|
||||
}
|
||||
}
|
||||
@ -162,13 +166,15 @@ void GPU_SW::UpdateDisplay()
|
||||
const u32 field = GetInterlacedDisplayLineOffset();
|
||||
if (m_GPUSTAT.display_area_color_depth_24)
|
||||
{
|
||||
CopyOut24Bit(m_crtc_state.regs.X, vram_offset_y + field, m_display_texture_buffer.data() + field * VRAM_WIDTH,
|
||||
VRAM_WIDTH, display_width + texture_offset_x, display_height, true);
|
||||
CopyOut24Bit(m_crtc_state.regs.X, vram_offset_y + (m_GPUSTAT.vertical_resolution ? field : 0u),
|
||||
m_display_texture_buffer.data() + field * VRAM_WIDTH, VRAM_WIDTH, display_width + texture_offset_x,
|
||||
display_height, true, m_GPUSTAT.vertical_resolution);
|
||||
}
|
||||
else
|
||||
{
|
||||
CopyOut15Bit(m_crtc_state.regs.X, vram_offset_y + field, m_display_texture_buffer.data() + field * VRAM_WIDTH,
|
||||
VRAM_WIDTH, display_width + texture_offset_x, display_height, true);
|
||||
CopyOut15Bit(m_crtc_state.regs.X, vram_offset_y + (m_GPUSTAT.vertical_resolution ? field : 0u),
|
||||
m_display_texture_buffer.data() + field * VRAM_WIDTH, VRAM_WIDTH, display_width + texture_offset_x,
|
||||
display_height, true, m_GPUSTAT.vertical_resolution);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -176,12 +182,12 @@ void GPU_SW::UpdateDisplay()
|
||||
if (m_GPUSTAT.display_area_color_depth_24)
|
||||
{
|
||||
CopyOut24Bit(m_crtc_state.regs.X, vram_offset_y, m_display_texture_buffer.data(), VRAM_WIDTH,
|
||||
display_width + texture_offset_x, display_height, false);
|
||||
display_width + texture_offset_x, display_height, false, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
CopyOut15Bit(m_crtc_state.regs.X, vram_offset_y, m_display_texture_buffer.data(), VRAM_WIDTH,
|
||||
display_width + texture_offset_x, display_height, false);
|
||||
display_width + texture_offset_x, display_height, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -196,7 +202,7 @@ void GPU_SW::UpdateDisplay()
|
||||
}
|
||||
else
|
||||
{
|
||||
CopyOut15Bit(0, 0, m_display_texture_buffer.data(), VRAM_WIDTH, VRAM_WIDTH, VRAM_HEIGHT, false);
|
||||
CopyOut15Bit(0, 0, m_display_texture_buffer.data(), VRAM_WIDTH, VRAM_WIDTH, VRAM_HEIGHT, false, false);
|
||||
m_host_display->UpdateTexture(m_display_texture.get(), 0, 0, VRAM_WIDTH, VRAM_HEIGHT,
|
||||
m_display_texture_buffer.data(), VRAM_WIDTH * sizeof(u32));
|
||||
m_host_display->SetDisplayTexture(m_display_texture->GetHandle(), VRAM_WIDTH, VRAM_HEIGHT, 0, 0, VRAM_WIDTH,
|
||||
|
||||
Reference in New Issue
Block a user