From df6e0799205c6cb901878b298096e51b387eb071 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Tue, 10 Dec 2019 22:52:46 +1000 Subject: [PATCH] GPU: Add a Force Progressive Scan option (disable interlacing) --- src/core/gpu.cpp | 6 +++++- src/core/gpu.h | 4 ++++ src/core/gpu_hw_d3d11.cpp | 9 ++++----- src/core/gpu_hw_opengl.cpp | 9 +++++---- src/core/gpu_hw_opengl_es.cpp | 9 +++++---- src/core/settings.cpp | 2 ++ src/core/settings.h | 1 + src/duckstation/sdl_host_interface.cpp | 5 +++-- 8 files changed, 29 insertions(+), 16 deletions(-) diff --git a/src/core/gpu.cpp b/src/core/gpu.cpp index 74acb953e..91ed82c5f 100644 --- a/src/core/gpu.cpp +++ b/src/core/gpu.cpp @@ -26,10 +26,14 @@ bool GPU::Initialize(HostDisplay* host_display, System* system, DMA* dma, Interr m_dma = dma; m_interrupt_controller = interrupt_controller; m_timers = timers; + m_force_progressive_scan = m_system->GetSettings().gpu_force_progressive_scan; return true; } -void GPU::UpdateSettings() {} +void GPU::UpdateSettings() +{ + m_force_progressive_scan = m_system->GetSettings().gpu_force_progressive_scan; +} void GPU::Reset() { diff --git a/src/core/gpu.h b/src/core/gpu.h index f7ede1803..8462dc242 100644 --- a/src/core/gpu.h +++ b/src/core/gpu.h @@ -296,6 +296,9 @@ protected: // Updates dynamic bits in GPUSTAT (ready to send VRAM/ready to receive DMA) void UpdateGPUSTAT(); + /// Returns true if scanout should be interlaced. + bool IsDisplayInterlaced() const { return !m_force_progressive_scan && m_GPUSTAT.In480iMode(); } + u32 ReadGPUREAD(); void WriteGP0(u32 value); void WriteGP1(u32 value); @@ -436,6 +439,7 @@ protected: bool m_drawing_area_changed = false; bool m_drawing_offset_changed = false; + bool m_force_progressive_scan = false; struct CRTCState { diff --git a/src/core/gpu_hw_d3d11.cpp b/src/core/gpu_hw_d3d11.cpp index ad8fe2dcb..c658258d7 100644 --- a/src/core/gpu_hw_d3d11.cpp +++ b/src/core/gpu_hw_d3d11.cpp @@ -537,12 +537,13 @@ void GPU_HW_D3D11::UpdateDisplay() const u32 display_height = std::min(m_crtc_state.display_height, VRAM_HEIGHT - vram_offset_y); const u32 scaled_display_width = display_width * m_resolution_scale; const u32 scaled_display_height = display_height * m_resolution_scale; + const bool interlaced = IsDisplayInterlaced(); if (m_GPUSTAT.display_disable) { 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, scaled_display_width, scaled_display_height, m_vram_texture.GetWidth(), @@ -550,12 +551,10 @@ void GPU_HW_D3D11::UpdateDisplay() } 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 = - m_display_pixel_shaders[BoolToUInt8(m_GPUSTAT.display_area_color_depth_24)] - [BoolToUInt8(m_GPUSTAT.vertical_interlace)] - .Get(); + m_display_pixel_shaders[BoolToUInt8(m_GPUSTAT.display_area_color_depth_24)][BoolToUInt8(interlaced)].Get(); // 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) diff --git a/src/core/gpu_hw_opengl.cpp b/src/core/gpu_hw_opengl.cpp index e980a003f..f293f6120 100644 --- a/src/core/gpu_hw_opengl.cpp +++ b/src/core/gpu_hw_opengl.cpp @@ -464,12 +464,13 @@ void GPU_HW_OpenGL::UpdateDisplay() const u32 display_height = std::min(m_crtc_state.display_height, VRAM_HEIGHT - vram_offset_y); const u32 scaled_display_width = display_width * m_resolution_scale; const u32 scaled_display_height = display_height * m_resolution_scale; + const bool interlaced = IsDisplayInterlaced(); if (m_GPUSTAT.display_disable) { 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(static_cast(m_vram_texture->GetGLId())), 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 scaled_flipped_vram_offset_y = 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_SCISSOR_TEST); - const GL::Program& prog = m_display_programs[BoolToUInt8(m_GPUSTAT.display_area_color_depth_24)] - [BoolToUInt8(m_GPUSTAT.vertical_interlace)]; + const GL::Program& prog = + m_display_programs[BoolToUInt8(m_GPUSTAT.display_area_color_depth_24)][BoolToUInt8(interlaced)]; prog.Bind(); // Because of how the reinterpret shader works, we need to use the downscaled version. diff --git a/src/core/gpu_hw_opengl_es.cpp b/src/core/gpu_hw_opengl_es.cpp index 94528722c..b1a01d844 100644 --- a/src/core/gpu_hw_opengl_es.cpp +++ b/src/core/gpu_hw_opengl_es.cpp @@ -359,12 +359,13 @@ void GPU_HW_OpenGL_ES::UpdateDisplay() const u32 display_height = std::min(m_crtc_state.display_height, VRAM_HEIGHT - vram_offset_y); const u32 scaled_display_width = display_width * m_resolution_scale; const u32 scaled_display_height = display_height * m_resolution_scale; + const bool interlaced = IsDisplayInterlaced(); if (m_GPUSTAT.display_disable) { 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(static_cast(m_vram_texture->GetGLId())), 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 scaled_flipped_vram_offset_y = 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_SCISSOR_TEST); - const GL::Program& prog = m_display_programs[BoolToUInt8(m_GPUSTAT.display_area_color_depth_24)] - [BoolToUInt8(m_GPUSTAT.vertical_interlace)]; + const GL::Program& prog = + m_display_programs[BoolToUInt8(m_GPUSTAT.display_area_color_depth_24)][BoolToUInt8(interlaced)]; prog.Bind(); // Because of how the reinterpret shader works, we need to use the downscaled version. diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 62c78c1b3..627967d81 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -24,6 +24,8 @@ void Settings::SetDefaults() gpu_renderer = GPURenderer::HardwareOpenGL; gpu_resolution_scale = 1; gpu_true_color = true; + gpu_texture_filtering = false; + gpu_force_progressive_scan = true; display_linear_filtering = true; diff --git a/src/core/settings.h b/src/core/settings.h index d8d4c197c..fc63ced2d 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -21,6 +21,7 @@ struct Settings mutable u32 max_gpu_resolution_scale = 1; bool gpu_true_color = false; bool gpu_texture_filtering = false; + bool gpu_force_progressive_scan = false; bool display_linear_filtering = true; bool display_fullscreen = false; diff --git a/src/duckstation/sdl_host_interface.cpp b/src/duckstation/sdl_host_interface.cpp index 222fda412..73d7ab7ae 100644 --- a/src/duckstation/sdl_host_interface.cpp +++ b/src/duckstation/sdl_host_interface.cpp @@ -1180,8 +1180,9 @@ void SDLHostInterface::DrawSettingsWindow() gpu_settings_changed = true; } - 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("True 24-bit Color (disables dithering)", &m_settings.gpu_true_color); + 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();