mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2025-02-17 03:15:39 +00:00
GPU: Add a Force Progressive Scan option (disable interlacing)
This commit is contained in:
parent
fb0aad0917
commit
df6e079920
|
@ -26,10 +26,14 @@ bool GPU::Initialize(HostDisplay* host_display, System* system, DMA* dma, Interr
|
||||||
m_dma = dma;
|
m_dma = dma;
|
||||||
m_interrupt_controller = interrupt_controller;
|
m_interrupt_controller = interrupt_controller;
|
||||||
m_timers = timers;
|
m_timers = timers;
|
||||||
|
m_force_progressive_scan = m_system->GetSettings().gpu_force_progressive_scan;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU::UpdateSettings() {}
|
void GPU::UpdateSettings()
|
||||||
|
{
|
||||||
|
m_force_progressive_scan = m_system->GetSettings().gpu_force_progressive_scan;
|
||||||
|
}
|
||||||
|
|
||||||
void GPU::Reset()
|
void GPU::Reset()
|
||||||
{
|
{
|
||||||
|
|
|
@ -296,6 +296,9 @@ protected:
|
||||||
// Updates dynamic bits in GPUSTAT (ready to send VRAM/ready to receive DMA)
|
// Updates dynamic bits in GPUSTAT (ready to send VRAM/ready to receive DMA)
|
||||||
void UpdateGPUSTAT();
|
void UpdateGPUSTAT();
|
||||||
|
|
||||||
|
/// Returns true if scanout should be interlaced.
|
||||||
|
bool IsDisplayInterlaced() const { return !m_force_progressive_scan && m_GPUSTAT.In480iMode(); }
|
||||||
|
|
||||||
u32 ReadGPUREAD();
|
u32 ReadGPUREAD();
|
||||||
void WriteGP0(u32 value);
|
void WriteGP0(u32 value);
|
||||||
void WriteGP1(u32 value);
|
void WriteGP1(u32 value);
|
||||||
|
@ -436,6 +439,7 @@ protected:
|
||||||
|
|
||||||
bool m_drawing_area_changed = false;
|
bool m_drawing_area_changed = false;
|
||||||
bool m_drawing_offset_changed = false;
|
bool m_drawing_offset_changed = false;
|
||||||
|
bool m_force_progressive_scan = false;
|
||||||
|
|
||||||
struct CRTCState
|
struct CRTCState
|
||||||
{
|
{
|
||||||
|
|
|
@ -537,12 +537,13 @@ void GPU_HW_D3D11::UpdateDisplay()
|
||||||
const u32 display_height = std::min<u32>(m_crtc_state.display_height, VRAM_HEIGHT - vram_offset_y);
|
const u32 display_height = std::min<u32>(m_crtc_state.display_height, VRAM_HEIGHT - vram_offset_y);
|
||||||
const u32 scaled_display_width = display_width * m_resolution_scale;
|
const u32 scaled_display_width = display_width * m_resolution_scale;
|
||||||
const u32 scaled_display_height = display_height * m_resolution_scale;
|
const u32 scaled_display_height = display_height * m_resolution_scale;
|
||||||
|
const bool interlaced = IsDisplayInterlaced();
|
||||||
|
|
||||||
if (m_GPUSTAT.display_disable)
|
if (m_GPUSTAT.display_disable)
|
||||||
{
|
{
|
||||||
m_host_display->SetDisplayTexture(nullptr, 0, 0, 0, 0, 0, 0, m_crtc_state.display_aspect_ratio);
|
m_host_display->SetDisplayTexture(nullptr, 0, 0, 0, 0, 0, 0, m_crtc_state.display_aspect_ratio);
|
||||||
}
|
}
|
||||||
else if (!m_GPUSTAT.display_area_color_depth_24 && !m_GPUSTAT.vertical_interlace)
|
else if (!m_GPUSTAT.display_area_color_depth_24 && !interlaced)
|
||||||
{
|
{
|
||||||
m_host_display->SetDisplayTexture(m_vram_texture.GetD3DSRV(), scaled_vram_offset_x, scaled_vram_offset_y,
|
m_host_display->SetDisplayTexture(m_vram_texture.GetD3DSRV(), scaled_vram_offset_x, scaled_vram_offset_y,
|
||||||
scaled_display_width, scaled_display_height, m_vram_texture.GetWidth(),
|
scaled_display_width, scaled_display_height, m_vram_texture.GetWidth(),
|
||||||
|
@ -550,12 +551,10 @@ void GPU_HW_D3D11::UpdateDisplay()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const u32 field_offset = BoolToUInt8(m_GPUSTAT.vertical_interlace && m_GPUSTAT.interlaced_field);
|
const u32 field_offset = BoolToUInt8(interlaced && m_GPUSTAT.interlaced_field);
|
||||||
|
|
||||||
ID3D11PixelShader* display_pixel_shader =
|
ID3D11PixelShader* display_pixel_shader =
|
||||||
m_display_pixel_shaders[BoolToUInt8(m_GPUSTAT.display_area_color_depth_24)]
|
m_display_pixel_shaders[BoolToUInt8(m_GPUSTAT.display_area_color_depth_24)][BoolToUInt8(interlaced)].Get();
|
||||||
[BoolToUInt8(m_GPUSTAT.vertical_interlace)]
|
|
||||||
.Get();
|
|
||||||
|
|
||||||
// Because of how the reinterpret shader works, we need to use the downscaled version.
|
// Because of how the reinterpret shader works, we need to use the downscaled version.
|
||||||
if (m_GPUSTAT.display_area_color_depth_24 && m_resolution_scale > 1)
|
if (m_GPUSTAT.display_area_color_depth_24 && m_resolution_scale > 1)
|
||||||
|
|
|
@ -464,12 +464,13 @@ void GPU_HW_OpenGL::UpdateDisplay()
|
||||||
const u32 display_height = std::min<u32>(m_crtc_state.display_height, VRAM_HEIGHT - vram_offset_y);
|
const u32 display_height = std::min<u32>(m_crtc_state.display_height, VRAM_HEIGHT - vram_offset_y);
|
||||||
const u32 scaled_display_width = display_width * m_resolution_scale;
|
const u32 scaled_display_width = display_width * m_resolution_scale;
|
||||||
const u32 scaled_display_height = display_height * m_resolution_scale;
|
const u32 scaled_display_height = display_height * m_resolution_scale;
|
||||||
|
const bool interlaced = IsDisplayInterlaced();
|
||||||
|
|
||||||
if (m_GPUSTAT.display_disable)
|
if (m_GPUSTAT.display_disable)
|
||||||
{
|
{
|
||||||
m_host_display->SetDisplayTexture(nullptr, 0, 0, 0, 0, 0, 0, m_crtc_state.display_aspect_ratio);
|
m_host_display->SetDisplayTexture(nullptr, 0, 0, 0, 0, 0, 0, m_crtc_state.display_aspect_ratio);
|
||||||
}
|
}
|
||||||
else if (!m_GPUSTAT.display_area_color_depth_24 && !m_GPUSTAT.vertical_interlace)
|
else if (!m_GPUSTAT.display_area_color_depth_24 && !interlaced)
|
||||||
{
|
{
|
||||||
m_host_display->SetDisplayTexture(reinterpret_cast<void*>(static_cast<uintptr_t>(m_vram_texture->GetGLId())),
|
m_host_display->SetDisplayTexture(reinterpret_cast<void*>(static_cast<uintptr_t>(m_vram_texture->GetGLId())),
|
||||||
scaled_vram_offset_x, m_vram_texture->GetHeight() - scaled_vram_offset_y,
|
scaled_vram_offset_x, m_vram_texture->GetHeight() - scaled_vram_offset_y,
|
||||||
|
@ -482,13 +483,13 @@ void GPU_HW_OpenGL::UpdateDisplay()
|
||||||
const u32 flipped_vram_offset_y = VRAM_HEIGHT - vram_offset_y - display_height;
|
const u32 flipped_vram_offset_y = VRAM_HEIGHT - vram_offset_y - display_height;
|
||||||
const u32 scaled_flipped_vram_offset_y =
|
const u32 scaled_flipped_vram_offset_y =
|
||||||
m_vram_texture->GetHeight() - scaled_vram_offset_y - scaled_display_height;
|
m_vram_texture->GetHeight() - scaled_vram_offset_y - scaled_display_height;
|
||||||
const u32 field_offset = BoolToUInt8(m_GPUSTAT.vertical_interlace && m_GPUSTAT.interlaced_field);
|
const u32 field_offset = BoolToUInt8(interlaced && m_GPUSTAT.interlaced_field);
|
||||||
|
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
glDisable(GL_SCISSOR_TEST);
|
glDisable(GL_SCISSOR_TEST);
|
||||||
|
|
||||||
const GL::Program& prog = m_display_programs[BoolToUInt8(m_GPUSTAT.display_area_color_depth_24)]
|
const GL::Program& prog =
|
||||||
[BoolToUInt8(m_GPUSTAT.vertical_interlace)];
|
m_display_programs[BoolToUInt8(m_GPUSTAT.display_area_color_depth_24)][BoolToUInt8(interlaced)];
|
||||||
prog.Bind();
|
prog.Bind();
|
||||||
|
|
||||||
// Because of how the reinterpret shader works, we need to use the downscaled version.
|
// Because of how the reinterpret shader works, we need to use the downscaled version.
|
||||||
|
|
|
@ -359,12 +359,13 @@ void GPU_HW_OpenGL_ES::UpdateDisplay()
|
||||||
const u32 display_height = std::min<u32>(m_crtc_state.display_height, VRAM_HEIGHT - vram_offset_y);
|
const u32 display_height = std::min<u32>(m_crtc_state.display_height, VRAM_HEIGHT - vram_offset_y);
|
||||||
const u32 scaled_display_width = display_width * m_resolution_scale;
|
const u32 scaled_display_width = display_width * m_resolution_scale;
|
||||||
const u32 scaled_display_height = display_height * m_resolution_scale;
|
const u32 scaled_display_height = display_height * m_resolution_scale;
|
||||||
|
const bool interlaced = IsDisplayInterlaced();
|
||||||
|
|
||||||
if (m_GPUSTAT.display_disable)
|
if (m_GPUSTAT.display_disable)
|
||||||
{
|
{
|
||||||
m_host_display->SetDisplayTexture(nullptr, 0, 0, 0, 0, 0, 0, m_crtc_state.display_aspect_ratio);
|
m_host_display->SetDisplayTexture(nullptr, 0, 0, 0, 0, 0, 0, m_crtc_state.display_aspect_ratio);
|
||||||
}
|
}
|
||||||
else if (!m_GPUSTAT.display_area_color_depth_24 && !m_GPUSTAT.vertical_interlace)
|
else if (!m_GPUSTAT.display_area_color_depth_24 && !interlaced)
|
||||||
{
|
{
|
||||||
m_host_display->SetDisplayTexture(reinterpret_cast<void*>(static_cast<uintptr_t>(m_vram_texture->GetGLId())),
|
m_host_display->SetDisplayTexture(reinterpret_cast<void*>(static_cast<uintptr_t>(m_vram_texture->GetGLId())),
|
||||||
scaled_vram_offset_x, m_vram_texture->GetHeight() - scaled_vram_offset_y,
|
scaled_vram_offset_x, m_vram_texture->GetHeight() - scaled_vram_offset_y,
|
||||||
|
@ -377,13 +378,13 @@ void GPU_HW_OpenGL_ES::UpdateDisplay()
|
||||||
const u32 flipped_vram_offset_y = VRAM_HEIGHT - vram_offset_y - display_height;
|
const u32 flipped_vram_offset_y = VRAM_HEIGHT - vram_offset_y - display_height;
|
||||||
const u32 scaled_flipped_vram_offset_y =
|
const u32 scaled_flipped_vram_offset_y =
|
||||||
m_vram_texture->GetHeight() - scaled_vram_offset_y - scaled_display_height;
|
m_vram_texture->GetHeight() - scaled_vram_offset_y - scaled_display_height;
|
||||||
const u32 field_offset = BoolToUInt8(m_GPUSTAT.vertical_interlace && m_GPUSTAT.interlaced_field);
|
const u32 field_offset = BoolToUInt8(interlaced && m_GPUSTAT.interlaced_field);
|
||||||
|
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
glDisable(GL_SCISSOR_TEST);
|
glDisable(GL_SCISSOR_TEST);
|
||||||
|
|
||||||
const GL::Program& prog = m_display_programs[BoolToUInt8(m_GPUSTAT.display_area_color_depth_24)]
|
const GL::Program& prog =
|
||||||
[BoolToUInt8(m_GPUSTAT.vertical_interlace)];
|
m_display_programs[BoolToUInt8(m_GPUSTAT.display_area_color_depth_24)][BoolToUInt8(interlaced)];
|
||||||
prog.Bind();
|
prog.Bind();
|
||||||
|
|
||||||
// Because of how the reinterpret shader works, we need to use the downscaled version.
|
// Because of how the reinterpret shader works, we need to use the downscaled version.
|
||||||
|
|
|
@ -24,6 +24,8 @@ void Settings::SetDefaults()
|
||||||
gpu_renderer = GPURenderer::HardwareOpenGL;
|
gpu_renderer = GPURenderer::HardwareOpenGL;
|
||||||
gpu_resolution_scale = 1;
|
gpu_resolution_scale = 1;
|
||||||
gpu_true_color = true;
|
gpu_true_color = true;
|
||||||
|
gpu_texture_filtering = false;
|
||||||
|
gpu_force_progressive_scan = true;
|
||||||
|
|
||||||
display_linear_filtering = true;
|
display_linear_filtering = true;
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ struct Settings
|
||||||
mutable u32 max_gpu_resolution_scale = 1;
|
mutable u32 max_gpu_resolution_scale = 1;
|
||||||
bool gpu_true_color = false;
|
bool gpu_true_color = false;
|
||||||
bool gpu_texture_filtering = false;
|
bool gpu_texture_filtering = false;
|
||||||
|
bool gpu_force_progressive_scan = false;
|
||||||
bool display_linear_filtering = true;
|
bool display_linear_filtering = true;
|
||||||
bool display_fullscreen = false;
|
bool display_fullscreen = false;
|
||||||
|
|
||||||
|
|
|
@ -1180,8 +1180,9 @@ void SDLHostInterface::DrawSettingsWindow()
|
||||||
gpu_settings_changed = true;
|
gpu_settings_changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::Checkbox("True 24-bit Color (disables dithering)", &m_settings.gpu_true_color);
|
gpu_settings_changed |= ImGui::Checkbox("True 24-bit Color (disables dithering)", &m_settings.gpu_true_color);
|
||||||
ImGui::Checkbox("Texture Filtering", &m_settings.gpu_texture_filtering);
|
gpu_settings_changed |= ImGui::Checkbox("Texture Filtering", &m_settings.gpu_texture_filtering);
|
||||||
|
gpu_settings_changed |= ImGui::Checkbox("Force Progressive Scan", &m_settings.gpu_force_progressive_scan);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::EndTabItem();
|
ImGui::EndTabItem();
|
||||||
|
|
Loading…
Reference in a new issue