mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-26 15:45:42 +00:00
GPU: Rewrite CRTC display modeling and overscan handling
This commit is contained in:
parent
fe824d6c89
commit
148279e2f2
256
src/core/gpu.cpp
256
src/core/gpu.cpp
|
@ -36,6 +36,9 @@ bool GPU::Initialize(HostDisplay* host_display, System* system, DMA* dma, Interr
|
||||||
void GPU::UpdateSettings()
|
void GPU::UpdateSettings()
|
||||||
{
|
{
|
||||||
m_force_progressive_scan = m_system->GetSettings().display_force_progressive_scan;
|
m_force_progressive_scan = m_system->GetSettings().display_force_progressive_scan;
|
||||||
|
|
||||||
|
// Crop mode calls this, so recalculate the display area
|
||||||
|
UpdateCRTCDisplayParameters();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU::Reset()
|
void GPU::Reset()
|
||||||
|
@ -107,12 +110,14 @@ bool GPU::DoState(StateWrapper& sw)
|
||||||
sw.Do(&m_crtc_state.regs.horizontal_display_range);
|
sw.Do(&m_crtc_state.regs.horizontal_display_range);
|
||||||
sw.Do(&m_crtc_state.regs.vertical_display_range);
|
sw.Do(&m_crtc_state.regs.vertical_display_range);
|
||||||
sw.Do(&m_crtc_state.dot_clock_divider);
|
sw.Do(&m_crtc_state.dot_clock_divider);
|
||||||
sw.Do(&m_crtc_state.visible_display_width);
|
sw.Do(&m_crtc_state.display_width);
|
||||||
sw.Do(&m_crtc_state.visible_display_height);
|
sw.Do(&m_crtc_state.display_height);
|
||||||
sw.Do(&m_crtc_state.active_display_left);
|
sw.Do(&m_crtc_state.display_origin_left);
|
||||||
sw.Do(&m_crtc_state.active_display_top);
|
sw.Do(&m_crtc_state.display_origin_top);
|
||||||
sw.Do(&m_crtc_state.active_display_width);
|
sw.Do(&m_crtc_state.display_vram_left);
|
||||||
sw.Do(&m_crtc_state.active_display_height);
|
sw.Do(&m_crtc_state.display_vram_top);
|
||||||
|
sw.Do(&m_crtc_state.display_vram_width);
|
||||||
|
sw.Do(&m_crtc_state.display_vram_height);
|
||||||
sw.Do(&m_crtc_state.horizontal_total);
|
sw.Do(&m_crtc_state.horizontal_total);
|
||||||
sw.Do(&m_crtc_state.horizontal_display_start);
|
sw.Do(&m_crtc_state.horizontal_display_start);
|
||||||
sw.Do(&m_crtc_state.horizontal_display_end);
|
sw.Do(&m_crtc_state.horizontal_display_end);
|
||||||
|
@ -319,7 +324,6 @@ void GPU::UpdateCRTCConfig()
|
||||||
{
|
{
|
||||||
static constexpr std::array<u16, 8> dot_clock_dividers = {{10, 8, 5, 4, 7, 7, 7, 7}};
|
static constexpr std::array<u16, 8> dot_clock_dividers = {{10, 8, 5, 4, 7, 7, 7, 7}};
|
||||||
CRTCState& cs = m_crtc_state;
|
CRTCState& cs = m_crtc_state;
|
||||||
const DisplayCropMode crop_mode = m_system->GetSettings().display_crop_mode;
|
|
||||||
|
|
||||||
if (m_GPUSTAT.pal_mode)
|
if (m_GPUSTAT.pal_mode)
|
||||||
{
|
{
|
||||||
|
@ -343,99 +347,154 @@ void GPU::UpdateCRTCConfig()
|
||||||
|
|
||||||
const u8 horizontal_resolution_index = m_GPUSTAT.horizontal_resolution_1 | (m_GPUSTAT.horizontal_resolution_2 << 2);
|
const u8 horizontal_resolution_index = m_GPUSTAT.horizontal_resolution_1 | (m_GPUSTAT.horizontal_resolution_2 << 2);
|
||||||
cs.dot_clock_divider = dot_clock_dividers[horizontal_resolution_index];
|
cs.dot_clock_divider = dot_clock_dividers[horizontal_resolution_index];
|
||||||
cs.horizontal_display_start = static_cast<TickCount>(std::min<u32>(cs.regs.X1, cs.horizontal_total));
|
cs.horizontal_display_start = std::min<u16>(cs.regs.X1, cs.horizontal_total);
|
||||||
cs.horizontal_display_end = static_cast<TickCount>(std::min<u32>(cs.regs.X2, cs.horizontal_total));
|
cs.horizontal_display_end = std::min<u16>(cs.regs.X2, cs.horizontal_total);
|
||||||
cs.vertical_display_start = static_cast<TickCount>(std::min<u32>(cs.regs.Y1, cs.vertical_total));
|
cs.vertical_display_start = std::min<u16>(cs.regs.Y1, cs.vertical_total);
|
||||||
cs.vertical_display_end = static_cast<TickCount>(std::min<u32>(cs.regs.Y2, cs.vertical_total));
|
cs.vertical_display_end = std::min<u16>(cs.regs.Y2, cs.vertical_total);
|
||||||
|
|
||||||
// determine the active display size
|
UpdateCRTCDisplayParameters();
|
||||||
cs.active_display_width = std::clamp<u16>((cs.regs.X2 - cs.regs.X1) / cs.dot_clock_divider, 1, VRAM_WIDTH);
|
UpdateSliceTicks();
|
||||||
cs.active_display_height =
|
}
|
||||||
std::clamp<u16>((cs.regs.Y2 - cs.regs.Y1), 1, VRAM_HEIGHT >> BoolToUInt8(m_GPUSTAT.In480iMode()));
|
|
||||||
|
|
||||||
// Construct screen borders from configured active area and the standard visible range.
|
void GPU::UpdateCRTCDisplayParameters()
|
||||||
// TODO: Ensure it doesn't overflow
|
{
|
||||||
const u16 horizontal_start_display_tick = (crop_mode == DisplayCropMode::None ? 488 : 608);
|
CRTCState& cs = m_crtc_state;
|
||||||
const u16 horizontal_end_display_tick = (crop_mode == DisplayCropMode::None ? 2800 : 2560);
|
const DisplayCropMode crop_mode = m_system->GetSettings().display_crop_mode;
|
||||||
cs.visible_display_width = horizontal_end_display_tick / cs.dot_clock_divider;
|
|
||||||
cs.active_display_left =
|
|
||||||
(std::max<u16>(m_crtc_state.regs.X1, horizontal_start_display_tick) - horizontal_start_display_tick) /
|
|
||||||
cs.dot_clock_divider;
|
|
||||||
|
|
||||||
const u16 vertical_start_display_line = (crop_mode == DisplayCropMode::None ? 8 : (m_GPUSTAT.pal_mode ? 20 : 16));
|
u16 horizontal_display_start_tick, horizontal_display_end_tick;
|
||||||
const u16 vertical_end_display_line =
|
u16 vertical_display_start_line, vertical_display_end_line;
|
||||||
(crop_mode == DisplayCropMode::None ? static_cast<u16>(cs.vertical_total) :
|
if (m_GPUSTAT.pal_mode)
|
||||||
static_cast<u16>(m_GPUSTAT.pal_mode ? 308 : 256));
|
{
|
||||||
const u16 bottom_padding = vertical_end_display_line - std::min<u16>(m_crtc_state.regs.Y2, vertical_end_display_line);
|
// TODO: Verify PAL numbers.
|
||||||
cs.active_display_top =
|
switch (crop_mode)
|
||||||
std::max<u16>(m_crtc_state.regs.Y1, vertical_start_display_line) - vertical_start_display_line;
|
{
|
||||||
cs.visible_display_height = cs.active_display_top + cs.active_display_height + bottom_padding;
|
case DisplayCropMode::None:
|
||||||
|
horizontal_display_start_tick = 487;
|
||||||
|
horizontal_display_end_tick = 3282;
|
||||||
|
vertical_display_start_line = 12;
|
||||||
|
vertical_display_end_line = 312;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DisplayCropMode::Overscan:
|
||||||
|
horizontal_display_start_tick = 628;
|
||||||
|
horizontal_display_end_tick = 3188;
|
||||||
|
vertical_display_start_line = 19;
|
||||||
|
vertical_display_end_line = 307;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DisplayCropMode::Borders:
|
||||||
|
default:
|
||||||
|
horizontal_display_start_tick = m_crtc_state.horizontal_display_start;
|
||||||
|
horizontal_display_end_tick = m_crtc_state.horizontal_display_end;
|
||||||
|
vertical_display_start_line = m_crtc_state.vertical_display_start;
|
||||||
|
vertical_display_end_line = m_crtc_state.vertical_display_end;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (crop_mode)
|
||||||
|
{
|
||||||
|
case DisplayCropMode::None:
|
||||||
|
horizontal_display_start_tick = 488;
|
||||||
|
horizontal_display_end_tick = 3288;
|
||||||
|
vertical_display_start_line = 8;
|
||||||
|
vertical_display_end_line = 260;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DisplayCropMode::Overscan:
|
||||||
|
horizontal_display_start_tick = 608;
|
||||||
|
horizontal_display_end_tick = 3168;
|
||||||
|
vertical_display_start_line = 16;
|
||||||
|
vertical_display_end_line = 256;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DisplayCropMode::Borders:
|
||||||
|
default:
|
||||||
|
horizontal_display_start_tick = m_crtc_state.horizontal_display_start;
|
||||||
|
horizontal_display_end_tick = m_crtc_state.horizontal_display_end;
|
||||||
|
vertical_display_start_line = m_crtc_state.vertical_display_start;
|
||||||
|
vertical_display_end_line = m_crtc_state.vertical_display_end;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const u8 height_shift = BoolToUInt8(m_GPUSTAT.In480iMode());
|
||||||
|
|
||||||
|
// Determine screen size.
|
||||||
|
cs.display_width = std::max<u16>(
|
||||||
|
((horizontal_display_end_tick - horizontal_display_start_tick) + (cs.dot_clock_divider - 1)) / cs.dot_clock_divider,
|
||||||
|
1u);
|
||||||
|
cs.display_height = std::max<u16>((vertical_display_end_line - vertical_display_start_line) << height_shift, 1u);
|
||||||
|
|
||||||
|
// Determine if we need to adjust the VRAM rectangle (because the display is starting outside the visible area) or add
|
||||||
|
// padding.
|
||||||
|
if (cs.horizontal_display_start >= horizontal_display_start_tick)
|
||||||
|
{
|
||||||
|
cs.display_origin_left = (cs.horizontal_display_start - horizontal_display_start_tick) / cs.dot_clock_divider;
|
||||||
|
cs.display_vram_left = m_crtc_state.regs.X;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cs.display_origin_left = 0;
|
||||||
|
cs.display_vram_left = std::min<u16>(
|
||||||
|
m_crtc_state.regs.X + ((horizontal_display_start_tick - cs.horizontal_display_start) / cs.dot_clock_divider),
|
||||||
|
VRAM_WIDTH - 1);
|
||||||
|
|
||||||
|
// for 24-bit scanout we must stay aligned
|
||||||
|
if (m_GPUSTAT.display_area_color_depth_24 && ((cs.display_vram_left - cs.regs.X) & 1u))
|
||||||
|
cs.display_vram_left--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cs.horizontal_display_end <= horizontal_display_end_tick)
|
||||||
|
{
|
||||||
|
cs.display_vram_width = std::min<u16>(
|
||||||
|
std::max<u16>(
|
||||||
|
(((cs.horizontal_display_end - std::max(cs.horizontal_display_start, horizontal_display_start_tick)) +
|
||||||
|
(cs.dot_clock_divider - 1)) /
|
||||||
|
cs.dot_clock_divider),
|
||||||
|
1u),
|
||||||
|
VRAM_WIDTH - cs.display_vram_left);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cs.display_vram_width = std::min<u16>(
|
||||||
|
std::max<u16>(
|
||||||
|
(((horizontal_display_end_tick - std::max(cs.horizontal_display_start, horizontal_display_start_tick)) +
|
||||||
|
(cs.dot_clock_divider - 1)) /
|
||||||
|
cs.dot_clock_divider),
|
||||||
|
1u),
|
||||||
|
VRAM_WIDTH - cs.display_vram_left);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cs.vertical_display_start >= vertical_display_start_line)
|
||||||
|
{
|
||||||
|
cs.display_origin_top = (cs.vertical_display_start - vertical_display_start_line) << height_shift;
|
||||||
|
cs.display_vram_top = m_crtc_state.regs.Y;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cs.display_origin_top = 0;
|
||||||
|
cs.display_vram_top =
|
||||||
|
std::min<u16>(m_crtc_state.regs.Y + ((cs.vertical_display_start - vertical_display_start_line) << height_shift),
|
||||||
|
VRAM_HEIGHT - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cs.vertical_display_end <= vertical_display_end_line)
|
||||||
|
{
|
||||||
|
cs.display_vram_height = std::min<u16>(
|
||||||
|
(cs.vertical_display_end - std::max(cs.vertical_display_start, vertical_display_start_line)) << height_shift,
|
||||||
|
VRAM_HEIGHT - cs.display_vram_top);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cs.display_vram_height = std::min<u16>(
|
||||||
|
(vertical_display_end_line - std::max(cs.vertical_display_start, vertical_display_start_line)) << height_shift,
|
||||||
|
VRAM_HEIGHT - cs.display_vram_top);
|
||||||
|
}
|
||||||
|
|
||||||
// Aspect ratio is always 4:3.
|
// Aspect ratio is always 4:3.
|
||||||
cs.display_aspect_ratio = 4.0f / 3.0f;
|
cs.display_aspect_ratio = 4.0f / 3.0f;
|
||||||
|
|
||||||
if (crop_mode == DisplayCropMode::Borders)
|
|
||||||
{
|
|
||||||
// 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.horizontal_total) / 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.vertical_total);
|
|
||||||
|
|
||||||
// Convert active dots/lines to time.
|
|
||||||
const float visible_dots_per_scanline = static_cast<float>(cs.active_display_width);
|
|
||||||
const float horizontal_active_time = horizontal_period * visible_dots_per_scanline;
|
|
||||||
const float vertical_active_time = horizontal_active_time * static_cast<float>(cs.regs.Y2 - cs.regs.Y1);
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
cs.visible_display_width = cs.active_display_width;
|
|
||||||
cs.visible_display_height = cs.active_display_height;
|
|
||||||
cs.active_display_left = 0;
|
|
||||||
cs.active_display_top = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Log_DevPrintf("Screen resolution: %ux%u", cs.visible_display_width, cs.visible_display_height);
|
|
||||||
Log_DevPrintf("Active display: %ux%u @ %u,%u (VRAM %u,%u)", cs.active_display_width, cs.active_display_height,
|
|
||||||
cs.active_display_left, cs.active_display_top, cs.regs.X.GetValue(), cs.regs.Y.GetValue());
|
|
||||||
Log_DevPrintf("Padding: Left=%u, Top=%u, Right=%u, Bottom=%u", cs.active_display_left, cs.active_display_top,
|
|
||||||
cs.visible_display_width - cs.active_display_width - cs.active_display_left,
|
|
||||||
cs.visible_display_height - cs.active_display_height - cs.active_display_top);
|
|
||||||
|
|
||||||
UpdateSliceTicks();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TickCount GPU::GetPendingGPUTicks() const
|
TickCount GPU::GetPendingGPUTicks() const
|
||||||
|
@ -679,6 +738,7 @@ void GPU::WriteGP1(u32 value)
|
||||||
m_crtc_state.regs.display_address_start = param & CRTCState::Regs::DISPLAY_ADDRESS_START_MASK;
|
m_crtc_state.regs.display_address_start = param & CRTCState::Regs::DISPLAY_ADDRESS_START_MASK;
|
||||||
Log_DebugPrintf("Display address start <- 0x%08X", m_crtc_state.regs.display_address_start);
|
Log_DebugPrintf("Display address start <- 0x%08X", m_crtc_state.regs.display_address_start);
|
||||||
m_system->IncrementInternalFrameNumber();
|
m_system->IncrementInternalFrameNumber();
|
||||||
|
UpdateCRTCDisplayParameters();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1065,7 +1125,6 @@ void GPU::DrawDebugStateWindow()
|
||||||
m_GPUSTAT.interlaced_field ? "odd" : "even");
|
m_GPUSTAT.interlaced_field ? "odd" : "even");
|
||||||
ImGui::Text("Display Disable: %s", m_GPUSTAT.display_disable ? "Yes" : "No");
|
ImGui::Text("Display Disable: %s", m_GPUSTAT.display_disable ? "Yes" : "No");
|
||||||
ImGui::Text("Drawing Even Line: %s", m_GPUSTAT.drawing_even_line ? "Yes" : "No");
|
ImGui::Text("Drawing Even Line: %s", m_GPUSTAT.drawing_even_line ? "Yes" : "No");
|
||||||
ImGui::Text("Display Resolution: %ux%u", cs.active_display_width, cs.active_display_height);
|
|
||||||
ImGui::Text("Color Depth: %u-bit", m_GPUSTAT.display_area_color_depth_24 ? 24 : 15);
|
ImGui::Text("Color Depth: %u-bit", m_GPUSTAT.display_area_color_depth_24 ? 24 : 15);
|
||||||
ImGui::Text("Start Offset: (%u, %u)", cs.regs.X.GetValue(), cs.regs.Y.GetValue());
|
ImGui::Text("Start Offset: (%u, %u)", cs.regs.X.GetValue(), cs.regs.Y.GetValue());
|
||||||
ImGui::Text("Display Total: %u (%u) horizontal, %u vertical", cs.horizontal_total,
|
ImGui::Text("Display Total: %u (%u) horizontal, %u vertical", cs.horizontal_total,
|
||||||
|
@ -1074,6 +1133,13 @@ void GPU::DrawDebugStateWindow()
|
||||||
cs.regs.X1.GetValue() / cs.dot_clock_divider, cs.regs.X2.GetValue() / cs.dot_clock_divider,
|
cs.regs.X1.GetValue() / cs.dot_clock_divider, cs.regs.X2.GetValue() / cs.dot_clock_divider,
|
||||||
cs.regs.Y1.GetValue(), cs.regs.Y2.GetValue());
|
cs.regs.Y1.GetValue(), cs.regs.Y2.GetValue());
|
||||||
ImGui::Text("Current Scanline: %u (tick %u)", cs.current_scanline, cs.current_tick_in_scanline);
|
ImGui::Text("Current Scanline: %u (tick %u)", cs.current_scanline, cs.current_tick_in_scanline);
|
||||||
|
ImGui::Text("Display resolution: %ux%u", cs.display_width, cs.display_height);
|
||||||
|
ImGui::Text("Display origin: %u, %u", cs.display_origin_left, cs.display_origin_top);
|
||||||
|
ImGui::Text("Active display: %ux%u @ (%u, %u)", cs.display_vram_width, cs.display_vram_height, cs.display_vram_left,
|
||||||
|
cs.display_vram_top);
|
||||||
|
ImGui::Text("Padding: Left=%u, Top=%u, Right=%u, Bottom=%u", cs.display_origin_left, cs.display_origin_top,
|
||||||
|
cs.display_width - cs.display_vram_width - cs.display_origin_left,
|
||||||
|
cs.display_height - cs.display_vram_height - cs.display_origin_top);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::CollapsingHeader("GPU", ImGuiTreeNodeFlags_DefaultOpen))
|
if (ImGui::CollapsingHeader("GPU", ImGuiTreeNodeFlags_DefaultOpen))
|
||||||
|
|
|
@ -313,6 +313,7 @@ protected:
|
||||||
|
|
||||||
// Sets dots per scanline
|
// Sets dots per scanline
|
||||||
void UpdateCRTCConfig();
|
void UpdateCRTCConfig();
|
||||||
|
void UpdateCRTCDisplayParameters();
|
||||||
|
|
||||||
// Update ticks for this execution slice
|
// Update ticks for this execution slice
|
||||||
void UpdateSliceTicks();
|
void UpdateSliceTicks();
|
||||||
|
@ -547,19 +548,26 @@ protected:
|
||||||
|
|
||||||
u16 dot_clock_divider;
|
u16 dot_clock_divider;
|
||||||
|
|
||||||
u16 visible_display_width;
|
// Size of the simulated screen in pixels. Depending on crop mode, this may include overscan area.
|
||||||
u16 visible_display_height;
|
u16 display_width;
|
||||||
u16 active_display_left;
|
u16 display_height;
|
||||||
u16 active_display_top;
|
|
||||||
u16 active_display_width;
|
|
||||||
u16 active_display_height;
|
|
||||||
|
|
||||||
TickCount horizontal_total;
|
// Top-left corner where the VRAM is displayed. Depending on the CRTC config, this may indicate padding.
|
||||||
TickCount horizontal_display_start;
|
u16 display_origin_left;
|
||||||
TickCount horizontal_display_end;
|
u16 display_origin_top;
|
||||||
u32 vertical_total;
|
|
||||||
u32 vertical_display_start;
|
// Rectangle describing the displayed area of VRAM, in coordinates.
|
||||||
u32 vertical_display_end;
|
u16 display_vram_left;
|
||||||
|
u16 display_vram_top;
|
||||||
|
u16 display_vram_width;
|
||||||
|
u16 display_vram_height;
|
||||||
|
|
||||||
|
u16 horizontal_total;
|
||||||
|
u16 horizontal_display_start;
|
||||||
|
u16 horizontal_display_end;
|
||||||
|
u16 vertical_total;
|
||||||
|
u16 vertical_display_start;
|
||||||
|
u16 vertical_display_end;
|
||||||
|
|
||||||
TickCount fractional_ticks;
|
TickCount fractional_ticks;
|
||||||
TickCount current_tick_in_scanline;
|
TickCount current_tick_in_scanline;
|
||||||
|
@ -568,15 +576,6 @@ protected:
|
||||||
float display_aspect_ratio;
|
float display_aspect_ratio;
|
||||||
bool in_hblank;
|
bool in_hblank;
|
||||||
bool in_vblank;
|
bool in_vblank;
|
||||||
|
|
||||||
/// Returns a rectangle representing the active display region within the visible area of the screen, i.e. where the
|
|
||||||
/// VRAM texture should be "scanned out" to. Areas outside this region (the border) should be displayed as black.
|
|
||||||
Common::Rectangle<s32> GetActiveDisplayRectangle() const
|
|
||||||
{
|
|
||||||
return Common::Rectangle<s32>::FromExtents(
|
|
||||||
static_cast<s32>(ZeroExtend32(active_display_left)), static_cast<s32>(ZeroExtend32(active_display_top)),
|
|
||||||
static_cast<s32>(ZeroExtend32(active_display_width)), static_cast<s32>(ZeroExtend32(active_display_height)));
|
|
||||||
}
|
|
||||||
} m_crtc_state = {};
|
} m_crtc_state = {};
|
||||||
|
|
||||||
State m_state = State::Idle;
|
State m_state = State::Idle;
|
||||||
|
|
|
@ -490,7 +490,7 @@ void GPU_HW::DispatchRenderCommand(RenderCommand rc, u32 num_vertices, const u32
|
||||||
(m_draw_mode.GetTexturePageRectangle().Intersects(m_vram_dirty_rect) ||
|
(m_draw_mode.GetTexturePageRectangle().Intersects(m_vram_dirty_rect) ||
|
||||||
(m_draw_mode.IsUsingPalette() && m_draw_mode.GetTexturePaletteRectangle().Intersects(m_vram_dirty_rect))))
|
(m_draw_mode.IsUsingPalette() && m_draw_mode.GetTexturePaletteRectangle().Intersects(m_vram_dirty_rect))))
|
||||||
{
|
{
|
||||||
Log_DevPrintf("Invalidating VRAM read cache due to drawing area overlap");
|
//Log_DevPrintf("Invalidating VRAM read cache due to drawing area overlap");
|
||||||
if (!IsFlushed())
|
if (!IsFlushed())
|
||||||
FlushRender();
|
FlushRender();
|
||||||
|
|
||||||
|
|
|
@ -525,18 +525,17 @@ void GPU_HW_D3D11::UpdateDisplay()
|
||||||
{
|
{
|
||||||
m_host_display->SetDisplayTexture(m_vram_texture.GetD3DSRV(), m_vram_texture.GetWidth(), m_vram_texture.GetHeight(),
|
m_host_display->SetDisplayTexture(m_vram_texture.GetD3DSRV(), m_vram_texture.GetWidth(), m_vram_texture.GetHeight(),
|
||||||
0, 0, m_vram_texture.GetWidth(), m_vram_texture.GetHeight());
|
0, 0, m_vram_texture.GetWidth(), m_vram_texture.GetHeight());
|
||||||
m_host_display->SetDisplayParameters(VRAM_WIDTH, VRAM_HEIGHT, Common::Rectangle<s32>(0, 0, VRAM_WIDTH, VRAM_HEIGHT),
|
m_host_display->SetDisplayParameters(VRAM_WIDTH, VRAM_HEIGHT, 0, 0, VRAM_WIDTH, VRAM_HEIGHT,
|
||||||
static_cast<float>(VRAM_WIDTH) / static_cast<float>(VRAM_HEIGHT));
|
static_cast<float>(VRAM_WIDTH) / static_cast<float>(VRAM_HEIGHT));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const u32 vram_offset_x = m_crtc_state.regs.X;
|
const u32 vram_offset_x = m_crtc_state.display_vram_left;
|
||||||
const u32 vram_offset_y = m_crtc_state.regs.Y;
|
const u32 vram_offset_y = m_crtc_state.display_vram_top;
|
||||||
const u32 scaled_vram_offset_x = vram_offset_x * m_resolution_scale;
|
const u32 scaled_vram_offset_x = vram_offset_x * m_resolution_scale;
|
||||||
const u32 scaled_vram_offset_y = vram_offset_y * m_resolution_scale;
|
const u32 scaled_vram_offset_y = vram_offset_y * m_resolution_scale;
|
||||||
const u32 display_width = std::min<u32>(m_crtc_state.active_display_width, VRAM_WIDTH - vram_offset_x);
|
const u32 display_width = m_crtc_state.display_vram_width;
|
||||||
const u32 display_height = std::min<u32>(m_crtc_state.active_display_height << BoolToUInt8(m_GPUSTAT.In480iMode()),
|
const u32 display_height = m_crtc_state.display_vram_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();
|
const bool interlaced = IsDisplayInterlaced();
|
||||||
|
@ -594,8 +593,10 @@ void GPU_HW_D3D11::UpdateDisplay()
|
||||||
RestoreGraphicsAPIState();
|
RestoreGraphicsAPIState();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_host_display->SetDisplayParameters(m_crtc_state.visible_display_width, m_crtc_state.visible_display_height,
|
m_host_display->SetDisplayParameters(m_crtc_state.display_width, m_crtc_state.display_height,
|
||||||
m_crtc_state.GetActiveDisplayRectangle(), m_crtc_state.display_aspect_ratio);
|
m_crtc_state.display_origin_left, m_crtc_state.display_origin_top,
|
||||||
|
m_crtc_state.display_vram_width, m_crtc_state.display_vram_height,
|
||||||
|
m_crtc_state.display_aspect_ratio);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -479,18 +479,17 @@ void GPU_HW_OpenGL::UpdateDisplay()
|
||||||
m_vram_texture.GetWidth(), static_cast<s32>(m_vram_texture.GetHeight()), 0,
|
m_vram_texture.GetWidth(), static_cast<s32>(m_vram_texture.GetHeight()), 0,
|
||||||
m_vram_texture.GetHeight(), m_vram_texture.GetWidth(),
|
m_vram_texture.GetHeight(), m_vram_texture.GetWidth(),
|
||||||
-static_cast<s32>(m_vram_texture.GetHeight()));
|
-static_cast<s32>(m_vram_texture.GetHeight()));
|
||||||
m_host_display->SetDisplayParameters(VRAM_WIDTH, VRAM_HEIGHT, Common::Rectangle<s32>(0, 0, VRAM_WIDTH, VRAM_HEIGHT),
|
m_host_display->SetDisplayParameters(VRAM_WIDTH, VRAM_HEIGHT, 0, 0, VRAM_WIDTH, VRAM_HEIGHT,
|
||||||
static_cast<float>(VRAM_WIDTH) / static_cast<float>(VRAM_HEIGHT));
|
static_cast<float>(VRAM_WIDTH) / static_cast<float>(VRAM_HEIGHT));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const u32 vram_offset_x = m_crtc_state.regs.X;
|
const u32 vram_offset_x = m_crtc_state.display_vram_left;
|
||||||
const u32 vram_offset_y = m_crtc_state.regs.Y;
|
const u32 vram_offset_y = m_crtc_state.display_vram_top;
|
||||||
const u32 scaled_vram_offset_x = vram_offset_x * m_resolution_scale;
|
const u32 scaled_vram_offset_x = vram_offset_x * m_resolution_scale;
|
||||||
const u32 scaled_vram_offset_y = vram_offset_y * m_resolution_scale;
|
const u32 scaled_vram_offset_y = vram_offset_y * m_resolution_scale;
|
||||||
const u32 display_width = std::min<u32>(m_crtc_state.active_display_width, VRAM_WIDTH - vram_offset_x);
|
const u32 display_width = m_crtc_state.display_vram_width;
|
||||||
const u32 display_height = std::min<u32>(m_crtc_state.active_display_height << BoolToUInt8(m_GPUSTAT.In480iMode()),
|
const u32 display_height = m_crtc_state.display_vram_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();
|
const bool interlaced = IsDisplayInterlaced();
|
||||||
|
@ -572,8 +571,10 @@ void GPU_HW_OpenGL::UpdateDisplay()
|
||||||
glEnable(GL_SCISSOR_TEST);
|
glEnable(GL_SCISSOR_TEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_host_display->SetDisplayParameters(m_crtc_state.visible_display_width, m_crtc_state.visible_display_height,
|
m_host_display->SetDisplayParameters(m_crtc_state.display_width, m_crtc_state.display_height,
|
||||||
m_crtc_state.GetActiveDisplayRectangle(), m_crtc_state.display_aspect_ratio);
|
m_crtc_state.display_origin_left, m_crtc_state.display_origin_top,
|
||||||
|
m_crtc_state.display_vram_width, m_crtc_state.display_vram_height,
|
||||||
|
m_crtc_state.display_aspect_ratio);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -343,18 +343,17 @@ void GPU_HW_OpenGL_ES::UpdateDisplay()
|
||||||
m_vram_texture.GetWidth(), static_cast<s32>(m_vram_texture.GetHeight()), 0,
|
m_vram_texture.GetWidth(), static_cast<s32>(m_vram_texture.GetHeight()), 0,
|
||||||
m_vram_texture.GetHeight(), m_vram_texture.GetWidth(),
|
m_vram_texture.GetHeight(), m_vram_texture.GetWidth(),
|
||||||
-static_cast<s32>(m_vram_texture.GetHeight()));
|
-static_cast<s32>(m_vram_texture.GetHeight()));
|
||||||
m_host_display->SetDisplayParameters(VRAM_WIDTH, VRAM_HEIGHT, Common::Rectangle<s32>(0, 0, VRAM_WIDTH, VRAM_HEIGHT),
|
m_host_display->SetDisplayParameters(VRAM_WIDTH, VRAM_HEIGHT, 0, 0, VRAM_WIDTH, VRAM_HEIGHT,
|
||||||
static_cast<float>(VRAM_WIDTH) / static_cast<float>(VRAM_HEIGHT));
|
static_cast<float>(VRAM_WIDTH) / static_cast<float>(VRAM_HEIGHT));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const u32 vram_offset_x = m_crtc_state.regs.X;
|
const u32 vram_offset_x = m_crtc_state.display_vram_left;
|
||||||
const u32 vram_offset_y = m_crtc_state.regs.Y;
|
const u32 vram_offset_y = m_crtc_state.display_vram_top;
|
||||||
const u32 scaled_vram_offset_x = vram_offset_x * m_resolution_scale;
|
const u32 scaled_vram_offset_x = vram_offset_x * m_resolution_scale;
|
||||||
const u32 scaled_vram_offset_y = vram_offset_y * m_resolution_scale;
|
const u32 scaled_vram_offset_y = vram_offset_y * m_resolution_scale;
|
||||||
const u32 display_width = std::min<u32>(m_crtc_state.active_display_width, VRAM_WIDTH - vram_offset_x);
|
const u32 display_width = m_crtc_state.display_vram_width;
|
||||||
const u32 display_height = std::min<u32>(m_crtc_state.active_display_height << BoolToUInt8(m_GPUSTAT.In480iMode()),
|
const u32 display_height = m_crtc_state.display_vram_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();
|
const bool interlaced = IsDisplayInterlaced();
|
||||||
|
@ -436,8 +435,10 @@ void GPU_HW_OpenGL_ES::UpdateDisplay()
|
||||||
glEnable(GL_SCISSOR_TEST);
|
glEnable(GL_SCISSOR_TEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_host_display->SetDisplayParameters(m_crtc_state.visible_display_width, m_crtc_state.visible_display_height,
|
m_host_display->SetDisplayParameters(m_crtc_state.display_width, m_crtc_state.display_height,
|
||||||
m_crtc_state.GetActiveDisplayRectangle(), m_crtc_state.display_aspect_ratio);
|
m_crtc_state.display_origin_left, m_crtc_state.display_origin_top,
|
||||||
|
m_crtc_state.display_vram_width, m_crtc_state.display_vram_height,
|
||||||
|
m_crtc_state.display_aspect_ratio);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -84,11 +84,10 @@ void GPU_SW::UpdateDisplay()
|
||||||
if (!m_system->GetSettings().debugging.show_vram)
|
if (!m_system->GetSettings().debugging.show_vram)
|
||||||
{
|
{
|
||||||
// TODO: Handle interlacing
|
// TODO: Handle interlacing
|
||||||
const u32 vram_offset_x = m_crtc_state.regs.X;
|
const u32 vram_offset_x = m_crtc_state.display_vram_left;
|
||||||
const u32 vram_offset_y = m_crtc_state.regs.Y;
|
const u32 vram_offset_y = m_crtc_state.display_vram_top;
|
||||||
const u32 display_width = std::min<u32>(m_crtc_state.active_display_width, VRAM_WIDTH - vram_offset_x);
|
const u32 display_width = m_crtc_state.display_vram_width;
|
||||||
const u32 display_height = std::min<u32>(m_crtc_state.active_display_height << BoolToUInt8(m_GPUSTAT.In480iMode()),
|
const u32 display_height = m_crtc_state.display_vram_height;
|
||||||
VRAM_HEIGHT - vram_offset_y);
|
|
||||||
|
|
||||||
if (m_GPUSTAT.display_disable)
|
if (m_GPUSTAT.display_disable)
|
||||||
{
|
{
|
||||||
|
@ -110,8 +109,10 @@ void GPU_SW::UpdateDisplay()
|
||||||
m_display_texture_buffer.data(), display_width * sizeof(u32));
|
m_display_texture_buffer.data(), display_width * sizeof(u32));
|
||||||
m_host_display->SetDisplayTexture(m_display_texture->GetHandle(), VRAM_WIDTH, VRAM_HEIGHT, 0, 0, display_width,
|
m_host_display->SetDisplayTexture(m_display_texture->GetHandle(), VRAM_WIDTH, VRAM_HEIGHT, 0, 0, display_width,
|
||||||
display_height);
|
display_height);
|
||||||
m_host_display->SetDisplayParameters(m_crtc_state.visible_display_width, m_crtc_state.visible_display_height,
|
m_host_display->SetDisplayParameters(m_crtc_state.display_width, m_crtc_state.display_height,
|
||||||
m_crtc_state.GetActiveDisplayRectangle(), m_crtc_state.display_aspect_ratio);
|
m_crtc_state.display_origin_left, m_crtc_state.display_origin_top,
|
||||||
|
m_crtc_state.display_vram_width, m_crtc_state.display_vram_height,
|
||||||
|
m_crtc_state.display_aspect_ratio);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -120,7 +121,7 @@ void GPU_SW::UpdateDisplay()
|
||||||
m_display_texture_buffer.data(), VRAM_WIDTH * sizeof(u32));
|
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,
|
m_host_display->SetDisplayTexture(m_display_texture->GetHandle(), VRAM_WIDTH, VRAM_HEIGHT, 0, 0, VRAM_WIDTH,
|
||||||
VRAM_HEIGHT);
|
VRAM_HEIGHT);
|
||||||
m_host_display->SetDisplayParameters(VRAM_WIDTH, VRAM_HEIGHT, Common::Rectangle<s32>(0, 0, VRAM_WIDTH, VRAM_HEIGHT),
|
m_host_display->SetDisplayParameters(VRAM_WIDTH, VRAM_HEIGHT, 0, 0, VRAM_WIDTH, VRAM_HEIGHT,
|
||||||
static_cast<float>(VRAM_WIDTH) / static_cast<float>(VRAM_HEIGHT));
|
static_cast<float>(VRAM_WIDTH) / static_cast<float>(VRAM_HEIGHT));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,35 +20,71 @@ void HostDisplay::WindowResized(s32 new_window_width, s32 new_window_height)
|
||||||
|
|
||||||
std::tuple<s32, s32, s32, s32> HostDisplay::CalculateDrawRect() const
|
std::tuple<s32, s32, s32, s32> HostDisplay::CalculateDrawRect() const
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
|
// convert display region to correct pixel aspect ratio
|
||||||
|
float display_width, display_height, active_left, active_top, active_width, active_height;
|
||||||
|
if (m_display_width >= m_display_height)
|
||||||
|
{
|
||||||
|
display_width = static_cast<float>(m_display_width);
|
||||||
|
display_height = static_cast<float>(m_display_width) / m_display_pixel_aspect_ratio;
|
||||||
|
|
||||||
|
const float scale = display_height / static_cast<float>(m_display_height);
|
||||||
|
active_left = static_cast<float>(m_display_active_left);
|
||||||
|
active_top = static_cast<float>(m_display_active_top) * scale;
|
||||||
|
active_width = static_cast<float>(m_display_active_width);
|
||||||
|
active_height = static_cast<float>(m_display_active_width) / m_display_pixel_aspect_ratio;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
display_width = static_cast<float>(m_display_height) * m_display_pixel_aspect_ratio;
|
||||||
|
display_height = static_cast<float>(m_display_height);
|
||||||
|
|
||||||
|
const float scale = display_width / static_cast<float>(m_display_width);
|
||||||
|
active_left = static_cast<float>(m_display_active_left) * scale;
|
||||||
|
active_top = static_cast<float>(m_display_active_top);
|
||||||
|
active_width = static_cast<float>(m_display_active_height) * m_display_pixel_aspect_ratio;
|
||||||
|
active_height = static_cast<float>(m_display_active_height);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
const float y_scale =
|
||||||
|
(static_cast<float>(m_display_width) / static_cast<float>(m_display_height)) / m_display_pixel_aspect_ratio;
|
||||||
|
const float display_width = static_cast<float>(m_display_width);
|
||||||
|
const float display_height = static_cast<float>(m_display_height) * y_scale;
|
||||||
|
const float active_left = static_cast<float>(m_display_active_left);
|
||||||
|
const float active_top = static_cast<float>(m_display_active_top) * y_scale;
|
||||||
|
const float active_width = static_cast<float>(m_display_active_width);
|
||||||
|
const float active_height = static_cast<float>(m_display_active_height) * y_scale;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// now fit it within the window
|
||||||
const s32 window_width = m_window_width;
|
const s32 window_width = m_window_width;
|
||||||
const s32 window_height = m_window_height - m_display_top_margin;
|
const s32 window_height = m_window_height - m_display_top_margin;
|
||||||
const float window_ratio = static_cast<float>(window_width) / static_cast<float>(window_height);
|
const float window_ratio = static_cast<float>(window_width) / static_cast<float>(window_height);
|
||||||
|
|
||||||
float scale;
|
float scale;
|
||||||
int left, top, width, height;
|
int top_padding = 0, left_padding = 0;
|
||||||
if (window_ratio >= m_display_aspect_ratio)
|
|
||||||
|
if ((display_width / display_height) >= window_ratio)
|
||||||
{
|
{
|
||||||
width = static_cast<int>(static_cast<float>(window_height) * m_display_aspect_ratio);
|
// align in middle vertically
|
||||||
height = static_cast<int>(window_height);
|
scale = static_cast<float>(window_width) / display_width;
|
||||||
scale = static_cast<float>(window_height) / static_cast<float>(m_display_height);
|
top_padding = (window_height - static_cast<s32>(display_height * scale)) / 2;
|
||||||
left = (window_width - width) / 2;
|
|
||||||
top = 0;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
width = static_cast<int>(window_width);
|
// align in middle horizontally
|
||||||
height = static_cast<int>(float(window_width) / m_display_aspect_ratio);
|
scale = static_cast<float>(window_height) / display_height;
|
||||||
scale = static_cast<float>(window_width) / static_cast<float>(m_display_width);
|
left_padding = (window_width - static_cast<s32>(display_width * scale)) / 2;
|
||||||
left = 0;
|
|
||||||
top = (window_height - height) / 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// add in padding
|
int left, top, width, height;
|
||||||
left += static_cast<s32>(static_cast<float>(m_display_area.left) * scale);
|
width = static_cast<s32>(active_width * scale);
|
||||||
top += static_cast<s32>(static_cast<float>(m_display_area.top) * scale);
|
height = static_cast<s32>(active_height * scale);
|
||||||
width -= static_cast<s32>(static_cast<float>(m_display_area.left + (m_display_width - m_display_area.right)) * scale);
|
left = static_cast<s32>(active_left * scale);
|
||||||
height -=
|
top = static_cast<s32>(active_top * scale);
|
||||||
static_cast<s32>(static_cast<float>(m_display_area.top + (m_display_height - m_display_area.bottom)) * scale);
|
|
||||||
|
left += std::max(left_padding, 0);
|
||||||
|
top += std::max(top_padding, 0);
|
||||||
|
|
||||||
// add in margin
|
// add in margin
|
||||||
top += m_display_top_margin;
|
top += m_display_top_margin;
|
||||||
|
@ -153,15 +189,15 @@ bool HostDisplay::WriteDisplayTextureToFile(const char* filename, bool full_reso
|
||||||
s32 resize_height = 0;
|
s32 resize_height = 0;
|
||||||
if (apply_aspect_ratio && full_resolution)
|
if (apply_aspect_ratio && full_resolution)
|
||||||
{
|
{
|
||||||
if (m_display_aspect_ratio > 1.0f)
|
if (m_display_pixel_aspect_ratio > 1.0f)
|
||||||
{
|
{
|
||||||
resize_width = m_display_texture_view_width;
|
resize_width = m_display_texture_view_width;
|
||||||
resize_height = static_cast<s32>(static_cast<float>(resize_width) / m_display_aspect_ratio);
|
resize_height = static_cast<s32>(static_cast<float>(resize_width) / m_display_pixel_aspect_ratio);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
resize_height = m_display_texture_view_height;
|
resize_height = m_display_texture_view_height;
|
||||||
resize_width = static_cast<s32>(static_cast<float>(resize_height) * m_display_aspect_ratio);
|
resize_width = static_cast<s32>(static_cast<float>(resize_height) * m_display_pixel_aspect_ratio);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (apply_aspect_ratio)
|
else if (apply_aspect_ratio)
|
||||||
|
|
|
@ -80,13 +80,16 @@ public:
|
||||||
m_display_changed = true;
|
m_display_changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetDisplayParameters(s32 display_width, s32 display_height, const Common::Rectangle<s32>& display_area,
|
void SetDisplayParameters(s32 display_width, s32 display_height, s32 active_left, s32 active_top, s32 active_width,
|
||||||
float pixel_aspect_ratio)
|
s32 active_height, float pixel_aspect_ratio)
|
||||||
{
|
{
|
||||||
m_display_width = display_width;
|
m_display_width = display_width;
|
||||||
m_display_height = display_height;
|
m_display_height = display_height;
|
||||||
m_display_area = display_area;
|
m_display_active_left = active_left;
|
||||||
m_display_aspect_ratio = pixel_aspect_ratio;
|
m_display_active_top = active_top;
|
||||||
|
m_display_active_width = active_width;
|
||||||
|
m_display_active_height = active_height;
|
||||||
|
m_display_pixel_aspect_ratio = pixel_aspect_ratio;
|
||||||
m_display_changed = true;
|
m_display_changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,8 +112,11 @@ protected:
|
||||||
|
|
||||||
s32 m_display_width = 0;
|
s32 m_display_width = 0;
|
||||||
s32 m_display_height = 0;
|
s32 m_display_height = 0;
|
||||||
Common::Rectangle<s32> m_display_area{};
|
s32 m_display_active_left = 0;
|
||||||
float m_display_aspect_ratio = 1.0f;
|
s32 m_display_active_top = 0;
|
||||||
|
s32 m_display_active_width = 0;
|
||||||
|
s32 m_display_active_height = 0;
|
||||||
|
float m_display_pixel_aspect_ratio = 1.0f;
|
||||||
|
|
||||||
void* m_display_texture_handle = nullptr;
|
void* m_display_texture_handle = nullptr;
|
||||||
s32 m_display_texture_width = 0;
|
s32 m_display_texture_width = 0;
|
||||||
|
|
Loading…
Reference in a new issue