GPU: Compute display aspect ratio based on visible area

This commit is contained in:
Connor McLaughlin 2019-10-21 00:18:52 +10:00
parent 2e70c22422
commit 1b8b730f85
3 changed files with 52 additions and 3 deletions

View file

@ -348,6 +348,54 @@ void GPU::UpdateCRTCConfig()
if (cs.display_width != old_horizontal_resolution || cs.display_height != old_vertical_resolution)
Log_InfoPrintf("Visible resolution is now %ux%u", cs.display_width, cs.display_height);
// Compute the aspect ratio necessary to display borders in the inactive region of the picture.
// Convert total dots/lines to time.
const float dot_clock =
(static_cast<float>(MASTER_CLOCK) * (11.0f / 7.0f / static_cast<float>(cs.dot_clock_divider)));
const float dot_clock_period = 1.0f / dot_clock;
const float dots_per_scanline = static_cast<float>(cs.ticks_per_scanline) / static_cast<float>(cs.dot_clock_divider);
const float horizontal_period = dots_per_scanline * dot_clock_period;
const float vertical_period = horizontal_period * static_cast<float>(cs.total_scanlines_per_frame);
// Convert active dots/lines to time.
const float visible_dots_per_scanline =
static_cast<float>(cs.visible_ticks_per_scanline) / static_cast<float>(cs.dot_clock_divider);
const float horizontal_active_time = horizontal_period * visible_dots_per_scanline;
const float vertical_active_time = horizontal_active_time * static_cast<float>(cs.visible_scanlines_per_frame);
// Use the reference active time/lines for the signal to work out the border area, and thus aspect ratio
// transformation for the active area in our framebuffer. For the purposes of these calculations, we're assuming
// progressive scan.
float display_ratio;
if (m_GPUSTAT.pal_mode)
{
// Wikipedia says PAL is active 51.95us of 64.00us, and 576/625 lines.
const float signal_horizontal_active_time = 51.95f;
const float signal_horizontal_total_time = 64.0f;
const float signal_vertical_active_lines = 576.0f;
const float signal_vertical_total_lines = 625.0f;
const float h_ratio =
(horizontal_active_time / horizontal_period) * (signal_horizontal_total_time / signal_horizontal_active_time);
const float v_ratio =
(vertical_active_time / vertical_period) * (signal_vertical_total_lines / signal_vertical_active_lines);
display_ratio = h_ratio / v_ratio;
}
else
{
const float signal_horizontal_active_time = 52.66f;
const float signal_horizontal_total_time = 63.56f;
const float signal_vertical_active_lines = 486.0f;
const float signal_vertical_total_lines = 525.0f;
const float h_ratio =
(horizontal_active_time / horizontal_period) * (signal_horizontal_total_time / signal_horizontal_active_time);
const float v_ratio =
(vertical_active_time / vertical_period) * (signal_vertical_total_lines / signal_vertical_active_lines);
display_ratio = h_ratio / v_ratio;
}
// Ensure the numbers are sane, and not due to a misconfigured active display range.
cs.display_aspect_ratio = (std::isnormal(display_ratio) && display_ratio != 0.0f) ? display_ratio : (4.0f / 3.0f);
UpdateSliceTicks();
}

View file

@ -16,7 +16,6 @@ class Timers;
class GPU
{
public:
static constexpr float DISPLAY_ASPECT_RATIO = 4.0f / 3.0f;
enum : u32
{
VRAM_WIDTH = 1024,
@ -342,6 +341,8 @@ protected:
TickCount current_tick_in_scanline;
u32 current_scanline;
float display_aspect_ratio;
bool in_hblank;
bool in_vblank;
} m_crtc_state = {};

View file

@ -492,7 +492,7 @@ void GPU_HW_OpenGL::UpdateDisplay()
glEnable(GL_SCISSOR_TEST);
m_system->GetHostInterface()->SetDisplayTexture(m_display_texture.get(), 0, 0, display_width, display_height,
DISPLAY_ASPECT_RATIO);
m_crtc_state.display_aspect_ratio);
}
else
{
@ -501,7 +501,7 @@ void GPU_HW_OpenGL::UpdateDisplay()
scaled_display_width, scaled_display_height, 1);
m_system->GetHostInterface()->SetDisplayTexture(m_display_texture.get(), 0, 0, scaled_display_width,
scaled_display_height, DISPLAY_ASPECT_RATIO);
scaled_display_height, m_crtc_state.display_aspect_ratio);
}
}
}