mirror of
https://github.com/WinampDesktop/winamp.git
synced 2025-06-15 19:05:45 -04:00
GPU: Implement "Crop Mode" (none, overscan, all borders)
This commit is contained in:
151
src/core/gpu.cpp
151
src/core/gpu.cpp
@ -3,6 +3,7 @@
|
||||
#include "common/log.h"
|
||||
#include "common/state_wrapper.h"
|
||||
#include "dma.h"
|
||||
#include "host_display.h"
|
||||
#include "host_interface.h"
|
||||
#include "interrupt_controller.h"
|
||||
#include "stb_image_write.h"
|
||||
@ -26,7 +27,7 @@ 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;
|
||||
m_force_progressive_scan = m_system->GetSettings().display_force_progressive_scan;
|
||||
m_tick_event =
|
||||
m_system->CreateTimingEvent("GPU Tick", 1, 1, std::bind(&GPU::Execute, this, std::placeholders::_1), true);
|
||||
return true;
|
||||
@ -34,7 +35,8 @@ bool GPU::Initialize(HostDisplay* host_display, System* system, DMA* dma, Interr
|
||||
|
||||
void GPU::UpdateSettings()
|
||||
{
|
||||
m_force_progressive_scan = m_system->GetSettings().gpu_force_progressive_scan;
|
||||
m_force_progressive_scan = m_system->GetSettings().display_force_progressive_scan;
|
||||
UpdateCRTCConfig();
|
||||
}
|
||||
|
||||
void GPU::Reset()
|
||||
@ -108,8 +110,12 @@ bool GPU::DoState(StateWrapper& sw)
|
||||
sw.Do(&m_crtc_state.regs.horizontal_display_range);
|
||||
sw.Do(&m_crtc_state.regs.vertical_display_range);
|
||||
sw.Do(&m_crtc_state.dot_clock_divider);
|
||||
sw.Do(&m_crtc_state.display_width);
|
||||
sw.Do(&m_crtc_state.display_height);
|
||||
sw.Do(&m_crtc_state.visible_display_width);
|
||||
sw.Do(&m_crtc_state.visible_display_height);
|
||||
sw.Do(&m_crtc_state.active_display_left);
|
||||
sw.Do(&m_crtc_state.active_display_top);
|
||||
sw.Do(&m_crtc_state.active_display_width);
|
||||
sw.Do(&m_crtc_state.active_display_height);
|
||||
sw.Do(&m_crtc_state.horizontal_total);
|
||||
sw.Do(&m_crtc_state.horizontal_display_start);
|
||||
sw.Do(&m_crtc_state.horizontal_display_end);
|
||||
@ -161,6 +167,7 @@ bool GPU::DoState(StateWrapper& sw)
|
||||
// Restore mask setting.
|
||||
m_GPUSTAT.bits = old_GPUSTAT;
|
||||
|
||||
UpdateCRTCConfig();
|
||||
UpdateDisplay();
|
||||
UpdateSliceTicks();
|
||||
}
|
||||
@ -285,8 +292,9 @@ void GPU::Synchronize()
|
||||
|
||||
void GPU::UpdateCRTCConfig()
|
||||
{
|
||||
static constexpr std::array<TickCount, 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;
|
||||
const DisplayCropMode crop_mode = m_system->GetSettings().display_crop_mode;
|
||||
|
||||
if (m_GPUSTAT.pal_mode)
|
||||
{
|
||||
@ -303,6 +311,7 @@ void GPU::UpdateCRTCConfig()
|
||||
const float vertical_frequency =
|
||||
static_cast<float>(static_cast<double>((u64(MASTER_CLOCK) * 11) / 7) / static_cast<double>(ticks_per_frame));
|
||||
m_system->SetThrottleFrequency(vertical_frequency);
|
||||
m_tick_event->SetInterval(cs.horizontal_total);
|
||||
|
||||
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];
|
||||
@ -311,63 +320,92 @@ void GPU::UpdateCRTCConfig()
|
||||
cs.vertical_display_start = static_cast<TickCount>(std::min<u32>(cs.regs.Y1, cs.vertical_total));
|
||||
cs.vertical_display_end = static_cast<TickCount>(std::min<u32>(cs.regs.Y2, cs.vertical_total));
|
||||
|
||||
// check for a change in resolution
|
||||
const u32 old_horizontal_resolution = cs.display_width;
|
||||
const u32 old_vertical_resolution = cs.display_height;
|
||||
const u32 visible_lines = cs.regs.Y2 - cs.regs.Y1;
|
||||
cs.display_width = std::max<u32>((cs.regs.X2 - cs.regs.X1) / cs.dot_clock_divider, 1);
|
||||
cs.display_height = visible_lines << BoolToUInt8(m_GPUSTAT.In480iMode());
|
||||
// determine the active display size
|
||||
cs.active_display_width = std::clamp<u16>((cs.regs.X2 - cs.regs.X1) / cs.dot_clock_divider, 1, VRAM_WIDTH);
|
||||
cs.active_display_height =
|
||||
std::clamp<u16>((cs.regs.Y2 - cs.regs.Y1), 1, VRAM_HEIGHT >> BoolToUInt8(m_GPUSTAT.In480iMode()));
|
||||
|
||||
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);
|
||||
// Construct screen borders from configured active area and the standard visible range.
|
||||
// TODO: Ensure it doesn't overflow
|
||||
const u16 horizontal_start_display_tick = (crop_mode == DisplayCropMode::None ? 488 : 608);
|
||||
const u16 horizontal_end_display_tick = (crop_mode == DisplayCropMode::None ? 2800 : 2560);
|
||||
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;
|
||||
|
||||
// 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);
|
||||
const u16 vertical_start_display_line = (crop_mode == DisplayCropMode::None ? 8 : (m_GPUSTAT.pal_mode ? 20 : 16));
|
||||
const u16 vertical_end_display_line =
|
||||
(crop_mode == DisplayCropMode::None ? static_cast<u16>(cs.vertical_total) :
|
||||
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);
|
||||
cs.active_display_top =
|
||||
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;
|
||||
|
||||
// Convert active dots/lines to time.
|
||||
const float visible_dots_per_scanline = static_cast<float>(cs.display_width);
|
||||
const float horizontal_active_time = horizontal_period * visible_dots_per_scanline;
|
||||
const float vertical_active_time = horizontal_active_time * static_cast<float>(visible_lines);
|
||||
// Aspect ratio is always 4:3.
|
||||
cs.display_aspect_ratio = 4.0f / 3.0f;
|
||||
|
||||
// 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)
|
||||
if (crop_mode == DisplayCropMode::Borders)
|
||||
{
|
||||
// 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;
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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);
|
||||
m_tick_event->SetInterval(cs.horizontal_total);
|
||||
Log_InfoPrintf("Screen resolution: %ux%u", cs.visible_display_width, cs.visible_display_height);
|
||||
Log_InfoPrintf("Active display: %ux%u @ %u,%u", cs.active_display_width, cs.active_display_height,
|
||||
cs.active_display_left, cs.active_display_top);
|
||||
Log_InfoPrintf("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);
|
||||
}
|
||||
|
||||
static TickCount GPUTicksToSystemTicks(u32 gpu_ticks)
|
||||
@ -581,6 +619,7 @@ void GPU::WriteGP1(u32 value)
|
||||
const bool disable = ConvertToBoolUnchecked(value & 0x01);
|
||||
Log_DebugPrintf("Display %s", disable ? "disabled" : "enabled");
|
||||
m_GPUSTAT.display_disable = disable;
|
||||
UpdateCRTCConfig();
|
||||
}
|
||||
break;
|
||||
|
||||
@ -940,7 +979,7 @@ void GPU::DrawDebugStateWindow()
|
||||
m_GPUSTAT.interlaced_field ? "odd" : "even");
|
||||
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("Display Resolution: %ux%u", cs.display_width, cs.display_height);
|
||||
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("Start Offset: (%u, %u)", cs.regs.X.GetValue(), cs.regs.Y.GetValue());
|
||||
ImGui::Text("Display Total: %u (%u) horizontal, %u vertical", cs.horizontal_total,
|
||||
|
@ -496,28 +496,32 @@ protected:
|
||||
union
|
||||
{
|
||||
u32 display_address_start;
|
||||
BitField<u32, u32, 0, 10> X;
|
||||
BitField<u32, u32, 10, 9> Y;
|
||||
BitField<u32, u16, 0, 10> X;
|
||||
BitField<u32, u16, 10, 9> Y;
|
||||
};
|
||||
union
|
||||
{
|
||||
u32 horizontal_display_range;
|
||||
BitField<u32, u32, 0, 12> X1;
|
||||
BitField<u32, u32, 12, 12> X2;
|
||||
BitField<u32, u16, 0, 12> X1;
|
||||
BitField<u32, u16, 12, 12> X2;
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
u32 vertical_display_range;
|
||||
BitField<u32, u32, 0, 10> Y1;
|
||||
BitField<u32, u32, 10, 10> Y2;
|
||||
BitField<u32, u16, 0, 10> Y1;
|
||||
BitField<u32, u16, 10, 10> Y2;
|
||||
};
|
||||
} regs;
|
||||
|
||||
TickCount dot_clock_divider;
|
||||
u16 dot_clock_divider;
|
||||
|
||||
u32 display_width;
|
||||
u32 display_height;
|
||||
u16 visible_display_width;
|
||||
u16 visible_display_height;
|
||||
u16 active_display_left;
|
||||
u16 active_display_top;
|
||||
u16 active_display_width;
|
||||
u16 active_display_height;
|
||||
|
||||
TickCount horizontal_total;
|
||||
TickCount horizontal_display_start;
|
||||
@ -533,6 +537,15 @@ protected:
|
||||
float display_aspect_ratio;
|
||||
bool in_hblank;
|
||||
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 = {};
|
||||
|
||||
State m_state = State::Idle;
|
||||
|
@ -14,7 +14,7 @@ GPU_HW_D3D11::~GPU_HW_D3D11()
|
||||
{
|
||||
if (m_host_display)
|
||||
{
|
||||
m_host_display->SetDisplayTexture(nullptr, 0, 0, 0, 0, 0, 0, 1.0f);
|
||||
m_host_display->ClearDisplayTexture();
|
||||
ResetGraphicsAPIState();
|
||||
}
|
||||
}
|
||||
@ -521,9 +521,11 @@ void GPU_HW_D3D11::UpdateDisplay()
|
||||
|
||||
if (m_system->GetSettings().debugging.show_vram)
|
||||
{
|
||||
m_host_display->SetDisplayTexture(m_vram_texture.GetD3DSRV(), 0, 0, m_vram_texture.GetWidth(),
|
||||
m_vram_texture.GetHeight(), m_vram_texture.GetWidth(), m_vram_texture.GetHeight(),
|
||||
1.0f);
|
||||
m_host_display->SetDisplayTexture(
|
||||
m_vram_texture.GetD3DSRV(), m_vram_texture.GetWidth(), m_vram_texture.GetHeight(),
|
||||
Common::Rectangle<s32>(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), 1.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -531,21 +533,23 @@ void GPU_HW_D3D11::UpdateDisplay()
|
||||
const u32 vram_offset_y = m_crtc_state.regs.Y;
|
||||
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 display_width = std::min<u32>(m_crtc_state.display_width, VRAM_WIDTH - vram_offset_x);
|
||||
const u32 display_height = std::min<u32>(m_crtc_state.display_height, VRAM_HEIGHT - vram_offset_y);
|
||||
const u32 display_width = std::min<u32>(m_crtc_state.active_display_width, VRAM_WIDTH - vram_offset_x);
|
||||
const u32 display_height = std::min<u32>(m_crtc_state.active_display_height << BoolToUInt8(m_GPUSTAT.In480iMode()),
|
||||
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);
|
||||
m_host_display->ClearDisplayTexture();
|
||||
}
|
||||
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(),
|
||||
m_vram_texture.GetHeight(), m_crtc_state.display_aspect_ratio);
|
||||
m_host_display->SetDisplayTexture(
|
||||
m_vram_texture.GetD3DSRV(), m_vram_texture.GetWidth(), m_vram_texture.GetHeight(),
|
||||
Common::Rectangle<s32>::FromExtents(scaled_vram_offset_x, scaled_vram_offset_y, scaled_display_width,
|
||||
scaled_display_height));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -570,9 +574,9 @@ void GPU_HW_D3D11::UpdateDisplay()
|
||||
SetViewportAndScissor(0, field_offset, display_width, display_height);
|
||||
DrawUtilityShader(display_pixel_shader, uniforms, sizeof(uniforms));
|
||||
|
||||
m_host_display->SetDisplayTexture(m_display_texture.GetD3DSRV(), 0, 0, display_width, display_height,
|
||||
m_display_texture.GetWidth(), m_display_texture.GetHeight(),
|
||||
m_crtc_state.display_aspect_ratio);
|
||||
m_host_display->SetDisplayTexture(m_display_texture.GetD3DSRV(), m_display_texture.GetWidth(),
|
||||
m_display_texture.GetHeight(),
|
||||
Common::Rectangle<s32>(0, 0, display_width, display_height));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -583,13 +587,16 @@ void GPU_HW_D3D11::UpdateDisplay()
|
||||
SetViewportAndScissor(0, field_offset, scaled_display_width, scaled_display_height);
|
||||
DrawUtilityShader(display_pixel_shader, uniforms, sizeof(uniforms));
|
||||
|
||||
m_host_display->SetDisplayTexture(m_display_texture.GetD3DSRV(), 0, 0, scaled_display_width,
|
||||
scaled_display_height, m_display_texture.GetWidth(),
|
||||
m_display_texture.GetHeight(), m_crtc_state.display_aspect_ratio);
|
||||
m_host_display->SetDisplayTexture(m_display_texture.GetD3DSRV(), m_display_texture.GetWidth(),
|
||||
m_display_texture.GetHeight(),
|
||||
Common::Rectangle<s32>(0, 0, scaled_display_width, scaled_display_height));
|
||||
}
|
||||
|
||||
RestoreGraphicsAPIState();
|
||||
}
|
||||
|
||||
m_host_display->SetDisplayParameters(m_crtc_state.visible_display_width, m_crtc_state.visible_display_height,
|
||||
m_crtc_state.GetActiveDisplayRectangle(), m_crtc_state.display_aspect_ratio);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@ GPU_HW_OpenGL::~GPU_HW_OpenGL()
|
||||
|
||||
if (m_host_display)
|
||||
{
|
||||
m_host_display->SetDisplayTexture(nullptr, 0, 0, 0, 0, 0, 0, 1.0f);
|
||||
m_host_display->ClearDisplayTexture();
|
||||
ResetGraphicsAPIState();
|
||||
}
|
||||
}
|
||||
@ -70,9 +70,6 @@ bool GPU_HW_OpenGL::Initialize(HostDisplay* host_display, System* system, DMA* d
|
||||
return false;
|
||||
}
|
||||
|
||||
m_host_display->SetDisplayTexture(reinterpret_cast<void*>(static_cast<uintptr_t>(m_vram_texture.GetGLId())), 0, 0,
|
||||
m_display_texture.GetWidth(), m_display_texture.GetHeight(),
|
||||
m_display_texture.GetWidth(), m_display_texture.GetHeight(), 1.0f);
|
||||
RestoreGraphicsAPIState();
|
||||
return true;
|
||||
}
|
||||
@ -479,10 +476,12 @@ void GPU_HW_OpenGL::UpdateDisplay()
|
||||
|
||||
if (m_system->GetSettings().debugging.show_vram)
|
||||
{
|
||||
m_host_display->SetDisplayTexture(reinterpret_cast<void*>(static_cast<uintptr_t>(m_vram_texture.GetGLId())), 0,
|
||||
m_vram_texture.GetHeight(), m_vram_texture.GetWidth(),
|
||||
-static_cast<s32>(m_vram_texture.GetHeight()), m_vram_texture.GetWidth(),
|
||||
m_vram_texture.GetHeight(), 1.0f);
|
||||
m_host_display->SetDisplayTexture(
|
||||
reinterpret_cast<void*>(static_cast<uintptr_t>(m_vram_texture.GetGLId())), m_vram_texture.GetWidth(),
|
||||
-static_cast<s32>(m_vram_texture.GetHeight()),
|
||||
Common::Rectangle<s32>(0, m_vram_texture.GetHeight(), m_vram_texture.GetWidth(), 0));
|
||||
m_host_display->SetDisplayParameters(VRAM_WIDTH, VRAM_HEIGHT,
|
||||
Common::Rectangle<s32>(0, 0, VRAM_WIDTH, VRAM_HEIGHT), 1.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -490,23 +489,23 @@ void GPU_HW_OpenGL::UpdateDisplay()
|
||||
const u32 vram_offset_y = m_crtc_state.regs.Y;
|
||||
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 display_width = std::min<u32>(m_crtc_state.display_width, VRAM_WIDTH - vram_offset_x);
|
||||
const u32 display_height = std::min<u32>(m_crtc_state.display_height, VRAM_HEIGHT - vram_offset_y);
|
||||
const u32 display_width = std::min<u32>(m_crtc_state.active_display_width, VRAM_WIDTH - vram_offset_x);
|
||||
const u32 display_height = std::min<u32>(m_crtc_state.active_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);
|
||||
m_host_display->ClearDisplayTexture();
|
||||
}
|
||||
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())),
|
||||
scaled_vram_offset_x, m_vram_texture.GetHeight() - scaled_vram_offset_y,
|
||||
scaled_display_width, -static_cast<s32>(scaled_display_height),
|
||||
m_vram_texture.GetWidth(), m_vram_texture.GetHeight(),
|
||||
m_crtc_state.display_aspect_ratio);
|
||||
m_host_display->SetDisplayTexture(
|
||||
reinterpret_cast<void*>(static_cast<uintptr_t>(m_vram_texture.GetGLId())), m_vram_texture.GetWidth(),
|
||||
m_vram_texture.GetHeight(),
|
||||
Common::Rectangle<s32>(scaled_vram_offset_x, m_vram_texture.GetHeight() - scaled_vram_offset_y,
|
||||
scaled_display_width, -static_cast<s32>(scaled_display_height)));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -545,10 +544,10 @@ void GPU_HW_OpenGL::UpdateDisplay()
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
|
||||
m_host_display->SetDisplayTexture(reinterpret_cast<void*>(static_cast<uintptr_t>(m_display_texture.GetGLId())),
|
||||
0, display_height, display_width, -static_cast<s32>(display_height),
|
||||
m_display_texture.GetWidth(), m_display_texture.GetHeight(),
|
||||
m_crtc_state.display_aspect_ratio);
|
||||
m_host_display->SetDisplayTexture(
|
||||
reinterpret_cast<void*>(static_cast<uintptr_t>(m_display_texture.GetGLId())), m_display_texture.GetWidth(),
|
||||
m_display_texture.GetHeight(),
|
||||
Common::Rectangle<s32>(0, display_height, display_width, -static_cast<s32>(display_height)));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -564,9 +563,9 @@ void GPU_HW_OpenGL::UpdateDisplay()
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
|
||||
m_host_display->SetDisplayTexture(reinterpret_cast<void*>(static_cast<uintptr_t>(m_display_texture.GetGLId())),
|
||||
0, scaled_display_height, scaled_display_width,
|
||||
-static_cast<s32>(scaled_display_height), m_display_texture.GetWidth(),
|
||||
m_display_texture.GetHeight(), m_crtc_state.display_aspect_ratio);
|
||||
m_display_texture.GetWidth(), m_display_texture.GetHeight(),
|
||||
Common::Rectangle<s32>(0, scaled_display_height, scaled_display_width,
|
||||
-static_cast<s32>(scaled_display_height)));
|
||||
}
|
||||
|
||||
// restore state
|
||||
@ -574,6 +573,9 @@ void GPU_HW_OpenGL::UpdateDisplay()
|
||||
glViewport(0, 0, m_vram_texture.GetWidth(), m_vram_texture.GetHeight());
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
}
|
||||
|
||||
m_host_display->SetDisplayParameters(m_crtc_state.visible_display_width, m_crtc_state.visible_display_height,
|
||||
m_crtc_state.GetActiveDisplayRectangle(), m_crtc_state.display_aspect_ratio);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@ GPU_HW_OpenGL_ES::~GPU_HW_OpenGL_ES()
|
||||
// TODO: Destroy objects...
|
||||
if (m_host_display)
|
||||
{
|
||||
m_host_display->SetDisplayTexture(nullptr, 0, 0, 0, 0, 0, 0, 1.0f);
|
||||
m_host_display->ClearDisplayTexture();
|
||||
ResetGraphicsAPIState();
|
||||
}
|
||||
}
|
||||
@ -44,9 +44,6 @@ bool GPU_HW_OpenGL_ES::Initialize(HostDisplay* host_display, System* system, DMA
|
||||
return false;
|
||||
}
|
||||
|
||||
m_host_display->SetDisplayTexture(reinterpret_cast<void*>(static_cast<uintptr_t>(m_vram_texture.GetGLId())), 0, 0,
|
||||
m_display_texture.GetWidth(), m_display_texture.GetHeight(),
|
||||
m_display_texture.GetWidth(), m_display_texture.GetHeight(), 1.0f);
|
||||
RestoreGraphicsAPIState();
|
||||
return true;
|
||||
}
|
||||
@ -346,10 +343,12 @@ void GPU_HW_OpenGL_ES::UpdateDisplay()
|
||||
|
||||
if (m_system->GetSettings().debugging.show_vram)
|
||||
{
|
||||
m_host_display->SetDisplayTexture(reinterpret_cast<void*>(static_cast<uintptr_t>(m_vram_texture.GetGLId())), 0,
|
||||
m_vram_texture.GetHeight(), m_vram_texture.GetWidth(),
|
||||
-static_cast<s32>(m_vram_texture.GetHeight()), m_vram_texture.GetWidth(),
|
||||
m_vram_texture.GetHeight(), 1.0f);
|
||||
m_host_display->SetDisplayTexture(
|
||||
reinterpret_cast<void*>(static_cast<uintptr_t>(m_vram_texture.GetGLId())), m_vram_texture.GetWidth(),
|
||||
-static_cast<s32>(m_vram_texture.GetHeight()),
|
||||
Common::Rectangle<s32>(0, m_vram_texture.GetHeight(), m_vram_texture.GetWidth(), 0));
|
||||
m_host_display->SetDisplayParameters(VRAM_WIDTH, VRAM_HEIGHT, Common::Rectangle<s32>(0, 0, VRAM_WIDTH, VRAM_HEIGHT),
|
||||
1.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -357,23 +356,23 @@ void GPU_HW_OpenGL_ES::UpdateDisplay()
|
||||
const u32 vram_offset_y = m_crtc_state.regs.Y;
|
||||
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 display_width = std::min<u32>(m_crtc_state.display_width, VRAM_WIDTH - vram_offset_x);
|
||||
const u32 display_height = std::min<u32>(m_crtc_state.display_height, VRAM_HEIGHT - vram_offset_y);
|
||||
const u32 display_width = std::min<u32>(m_crtc_state.active_display_width, VRAM_WIDTH - vram_offset_x);
|
||||
const u32 display_height = std::min<u32>(m_crtc_state.active_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);
|
||||
m_host_display->ClearDisplayTexture();
|
||||
}
|
||||
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())),
|
||||
scaled_vram_offset_x, m_vram_texture.GetHeight() - scaled_vram_offset_y,
|
||||
scaled_display_width, -static_cast<s32>(scaled_display_height),
|
||||
m_vram_texture.GetWidth(), m_vram_texture.GetHeight(),
|
||||
m_crtc_state.display_aspect_ratio);
|
||||
m_host_display->SetDisplayTexture(
|
||||
reinterpret_cast<void*>(static_cast<uintptr_t>(m_vram_texture.GetGLId())), m_vram_texture.GetWidth(),
|
||||
m_vram_texture.GetHeight(),
|
||||
Common::Rectangle<s32>(scaled_vram_offset_x, m_vram_texture.GetHeight() - scaled_vram_offset_y,
|
||||
scaled_display_width, -static_cast<s32>(scaled_display_height)));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -412,10 +411,10 @@ void GPU_HW_OpenGL_ES::UpdateDisplay()
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
|
||||
m_host_display->SetDisplayTexture(reinterpret_cast<void*>(static_cast<uintptr_t>(m_display_texture.GetGLId())),
|
||||
0, display_height, display_width, -static_cast<s32>(display_height),
|
||||
m_display_texture.GetWidth(), m_display_texture.GetHeight(),
|
||||
m_crtc_state.display_aspect_ratio);
|
||||
m_host_display->SetDisplayTexture(
|
||||
reinterpret_cast<void*>(static_cast<uintptr_t>(m_display_texture.GetGLId())), m_display_texture.GetWidth(),
|
||||
m_display_texture.GetHeight(),
|
||||
Common::Rectangle<s32>(0, display_height, display_width, -static_cast<s32>(display_height)));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -431,9 +430,9 @@ void GPU_HW_OpenGL_ES::UpdateDisplay()
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
|
||||
m_host_display->SetDisplayTexture(reinterpret_cast<void*>(static_cast<uintptr_t>(m_display_texture.GetGLId())),
|
||||
0, scaled_display_height, scaled_display_width,
|
||||
-static_cast<s32>(scaled_display_height), m_display_texture.GetWidth(),
|
||||
m_display_texture.GetHeight(), m_crtc_state.display_aspect_ratio);
|
||||
m_display_texture.GetWidth(), m_display_texture.GetHeight(),
|
||||
Common::Rectangle<s32>(0, scaled_display_height, scaled_display_width,
|
||||
-static_cast<s32>(scaled_display_height)));
|
||||
}
|
||||
|
||||
// restore state
|
||||
@ -441,6 +440,9 @@ void GPU_HW_OpenGL_ES::UpdateDisplay()
|
||||
glViewport(0, 0, m_vram_texture.GetWidth(), m_vram_texture.GetHeight());
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
}
|
||||
|
||||
m_host_display->SetDisplayParameters(m_crtc_state.visible_display_width, m_crtc_state.visible_display_height,
|
||||
m_crtc_state.GetActiveDisplayRectangle(), m_crtc_state.display_aspect_ratio);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,8 @@ GPU_SW::GPU_SW()
|
||||
|
||||
GPU_SW::~GPU_SW()
|
||||
{
|
||||
m_host_display->SetDisplayTexture(nullptr, 0, 0, 0, 0, 0, 0, 1.0f);
|
||||
if (m_host_display)
|
||||
m_host_display->ClearDisplayTexture();
|
||||
}
|
||||
|
||||
bool GPU_SW::IsHardwareRenderer() const
|
||||
@ -113,21 +114,17 @@ void GPU_SW::UpdateDisplay()
|
||||
// fill display texture
|
||||
m_display_texture_buffer.resize(VRAM_WIDTH * VRAM_HEIGHT);
|
||||
|
||||
u32 display_width;
|
||||
u32 display_height;
|
||||
float display_aspect_ratio;
|
||||
if (!m_system->GetSettings().debugging.show_vram)
|
||||
{
|
||||
// TODO: Handle interlacing
|
||||
const u32 vram_offset_x = m_crtc_state.regs.X;
|
||||
const u32 vram_offset_y = m_crtc_state.regs.Y;
|
||||
display_width = std::min<u32>(m_crtc_state.display_width, VRAM_WIDTH - vram_offset_x);
|
||||
display_height = std::min<u32>(m_crtc_state.display_height, VRAM_HEIGHT - vram_offset_y);
|
||||
display_aspect_ratio = m_crtc_state.display_aspect_ratio;
|
||||
const u32 display_width = std::min<u32>(m_crtc_state.active_display_width, VRAM_WIDTH - vram_offset_x);
|
||||
const u32 display_height = std::min<u32>(m_crtc_state.active_display_height, VRAM_HEIGHT - vram_offset_y);
|
||||
|
||||
if (m_GPUSTAT.display_disable)
|
||||
{
|
||||
m_host_display->SetDisplayTexture(nullptr, 0, 0, 0, 0, 0, 0, display_aspect_ratio);
|
||||
m_host_display->ClearDisplayTexture();
|
||||
return;
|
||||
}
|
||||
else if (m_GPUSTAT.display_area_color_depth_24)
|
||||
@ -140,20 +137,24 @@ void GPU_SW::UpdateDisplay()
|
||||
CopyOut15Bit(m_vram.data() + vram_offset_y * VRAM_WIDTH + vram_offset_x, VRAM_WIDTH,
|
||||
m_display_texture_buffer.data(), display_width, display_width, display_height);
|
||||
}
|
||||
|
||||
m_host_display->UpdateTexture(m_display_texture.get(), 0, 0, display_width, display_height,
|
||||
m_display_texture_buffer.data(), display_width * sizeof(u32));
|
||||
m_host_display->SetDisplayTexture(m_display_texture->GetHandle(), VRAM_WIDTH, VRAM_HEIGHT,
|
||||
Common::Rectangle<s32>(0, 0, display_width, display_height));
|
||||
m_host_display->SetDisplayParameters(m_crtc_state.visible_display_width, m_crtc_state.visible_display_height,
|
||||
m_crtc_state.GetActiveDisplayRectangle(), m_crtc_state.display_aspect_ratio);
|
||||
}
|
||||
else
|
||||
{
|
||||
display_width = VRAM_WIDTH;
|
||||
display_height = VRAM_HEIGHT;
|
||||
display_aspect_ratio = 1.0f;
|
||||
CopyOut15Bit(m_vram.data(), VRAM_WIDTH, m_display_texture_buffer.data(), display_width, display_width,
|
||||
display_height);
|
||||
CopyOut15Bit(m_vram.data(), VRAM_WIDTH, m_display_texture_buffer.data(), VRAM_WIDTH, VRAM_HEIGHT, VRAM_HEIGHT);
|
||||
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,
|
||||
Common::Rectangle<s32>(0, 0, VRAM_WIDTH, VRAM_HEIGHT));
|
||||
m_host_display->SetDisplayParameters(VRAM_WIDTH, VRAM_HEIGHT,
|
||||
Common::Rectangle<s32>(0, 0, VRAM_WIDTH, VRAM_HEIGHT), 1.0f);
|
||||
}
|
||||
|
||||
m_host_display->UpdateTexture(m_display_texture.get(), 0, 0, display_width, display_height,
|
||||
m_display_texture_buffer.data(), display_width * sizeof(u32));
|
||||
m_host_display->SetDisplayTexture(m_display_texture->GetHandle(), 0, 0, display_width, display_height, VRAM_WIDTH,
|
||||
VRAM_HEIGHT, display_aspect_ratio);
|
||||
}
|
||||
|
||||
void GPU_SW::DispatchRenderCommand(RenderCommand rc, u32 num_vertices, const u32* command_ptr)
|
||||
|
@ -4,24 +4,45 @@ HostDisplayTexture::~HostDisplayTexture() = default;
|
||||
|
||||
HostDisplay::~HostDisplay() = default;
|
||||
|
||||
std::tuple<int, int, int, int> HostDisplay::CalculateDrawRect(int window_width, int window_height, float display_ratio)
|
||||
void HostDisplay::WindowResized(s32 new_window_width, s32 new_window_height)
|
||||
{
|
||||
const float window_ratio = float(window_width) / float(window_height);
|
||||
m_window_width = new_window_width;
|
||||
m_window_height = new_window_height;
|
||||
}
|
||||
|
||||
std::tuple<s32, s32, s32, s32> HostDisplay::CalculateDrawRect() const
|
||||
{
|
||||
const s32 window_width = m_window_width;
|
||||
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);
|
||||
|
||||
float scale;
|
||||
int left, top, width, height;
|
||||
if (window_ratio >= display_ratio)
|
||||
if (window_ratio >= m_display_aspect_ratio)
|
||||
{
|
||||
width = static_cast<int>(float(window_height) * display_ratio);
|
||||
width = static_cast<int>(static_cast<float>(window_height) * m_display_aspect_ratio);
|
||||
height = static_cast<int>(window_height);
|
||||
scale = static_cast<float>(window_height) / static_cast<float>(m_display_height);
|
||||
left = (window_width - width) / 2;
|
||||
top = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
width = static_cast<int>(window_width);
|
||||
height = static_cast<int>(float(window_width) / display_ratio);
|
||||
height = static_cast<int>(float(window_width) / m_display_aspect_ratio);
|
||||
scale = static_cast<float>(window_width) / static_cast<float>(m_display_width);
|
||||
left = 0;
|
||||
top = (window_height - height) / 2;
|
||||
}
|
||||
|
||||
// add in padding
|
||||
left += static_cast<s32>(static_cast<float>(m_display_area.left) * scale);
|
||||
top += static_cast<s32>(static_cast<float>(m_display_area.top) * scale);
|
||||
width -= static_cast<s32>(static_cast<float>(m_display_area.left + (m_display_width - m_display_area.right)) * scale);
|
||||
height -=
|
||||
static_cast<s32>(static_cast<float>(m_display_area.top + (m_display_height - m_display_area.bottom)) * scale);
|
||||
|
||||
// add in margin
|
||||
top += m_display_top_margin;
|
||||
return std::tie(left, top, width, height);
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#include "common/rectangle.h"
|
||||
#include "types.h"
|
||||
#include <memory>
|
||||
#include <tuple>
|
||||
@ -36,6 +37,9 @@ public:
|
||||
/// Switches the render window, recreating the surface.
|
||||
virtual void ChangeRenderWindow(void* new_window) = 0;
|
||||
|
||||
/// Call when the window size changes externally to recreate any resources.
|
||||
virtual void WindowResized(s32 new_window_width, s32 new_window_height);
|
||||
|
||||
/// Creates an abstracted RGBA8 texture. If dynamic, the texture can be updated with UpdateTexture() below.
|
||||
virtual std::unique_ptr<HostDisplayTexture> CreateTexture(u32 width, u32 height, const void* data, u32 data_stride,
|
||||
bool dynamic = false) = 0;
|
||||
@ -46,42 +50,59 @@ public:
|
||||
|
||||
virtual void SetVSync(bool enabled) = 0;
|
||||
|
||||
virtual std::tuple<u32, u32> GetWindowSize() const = 0;
|
||||
virtual void WindowResized() = 0;
|
||||
|
||||
const s32 GetDisplayTopMargin() const { return m_display_top_margin; }
|
||||
|
||||
void SetDisplayTexture(void* texture_handle, s32 offset_x, s32 offset_y, s32 width, s32 height, u32 texture_width,
|
||||
u32 texture_height, float aspect_ratio)
|
||||
void ClearDisplayTexture()
|
||||
{
|
||||
m_display_texture_handle = nullptr;
|
||||
m_display_texture_width = 0;
|
||||
m_display_texture_height = 0;
|
||||
m_display_texture_rect = {};
|
||||
m_display_changed = true;
|
||||
}
|
||||
|
||||
void SetDisplayTexture(void* texture_handle, s32 texture_width, s32 texture_height,
|
||||
const Common::Rectangle<s32>& texture_rect)
|
||||
{
|
||||
m_display_texture_handle = texture_handle;
|
||||
m_display_offset_x = offset_x;
|
||||
m_display_offset_y = offset_y;
|
||||
m_display_width = width;
|
||||
m_display_height = height;
|
||||
m_display_texture_width = texture_width;
|
||||
m_display_texture_height = texture_height;
|
||||
m_display_aspect_ratio = aspect_ratio;
|
||||
m_display_texture_changed = true;
|
||||
m_display_texture_rect = texture_rect;
|
||||
m_display_changed = true;
|
||||
}
|
||||
|
||||
void SetDisplayParameters(s32 display_width, s32 display_height, const Common::Rectangle<s32>& display_area,
|
||||
float pixel_aspect_ratio)
|
||||
{
|
||||
m_display_width = display_width;
|
||||
m_display_height = display_height;
|
||||
m_display_area = display_area;
|
||||
m_display_aspect_ratio = pixel_aspect_ratio;
|
||||
m_display_changed = true;
|
||||
}
|
||||
|
||||
void SetDisplayLinearFiltering(bool enabled) { m_display_linear_filtering = enabled; }
|
||||
void SetDisplayTopMargin(s32 height) { m_display_top_margin = height; }
|
||||
|
||||
// Helper function for computing the draw rectangle in a larger window.
|
||||
static std::tuple<int, int, int, int> CalculateDrawRect(int window_width, int window_height, float display_ratio);
|
||||
std::tuple<s32, s32, s32, s32> CalculateDrawRect() const;
|
||||
|
||||
protected:
|
||||
void* m_display_texture_handle = nullptr;
|
||||
s32 m_display_offset_x = 0;
|
||||
s32 m_display_offset_y = 0;
|
||||
s32 m_window_width = 0;
|
||||
s32 m_window_height = 0;
|
||||
|
||||
s32 m_display_width = 0;
|
||||
s32 m_display_height = 0;
|
||||
u32 m_display_texture_width = 0;
|
||||
u32 m_display_texture_height = 0;
|
||||
s32 m_display_top_margin = 0;
|
||||
Common::Rectangle<s32> m_display_area{};
|
||||
float m_display_aspect_ratio = 1.0f;
|
||||
|
||||
bool m_display_texture_changed = false;
|
||||
void* m_display_texture_handle = nullptr;
|
||||
s32 m_display_texture_width = 0;
|
||||
s32 m_display_texture_height = 0;
|
||||
Common::Rectangle<s32> m_display_texture_rect{};
|
||||
|
||||
s32 m_display_top_margin = 0;
|
||||
|
||||
bool m_display_linear_filtering = false;
|
||||
bool m_display_changed = false;
|
||||
};
|
||||
|
@ -813,9 +813,10 @@ void HostInterface::SetDefaultSettings(SettingsInterface& si)
|
||||
si.SetIntValue("GPU", "ResolutionScale", 1);
|
||||
si.SetBoolValue("GPU", "TrueColor", true);
|
||||
si.SetBoolValue("GPU", "TextureFiltering", false);
|
||||
si.SetBoolValue("GPU", "ForceProgressiveScan", true);
|
||||
si.SetBoolValue("GPU", "UseDebugDevice", false);
|
||||
|
||||
si.SetBoolValue("Display", "CropMode", "Overscan");
|
||||
si.SetBoolValue("Display", "ForceProgressiveScan", true);
|
||||
si.SetBoolValue("Display", "LinearFiltering", true);
|
||||
si.SetBoolValue("Display", "Fullscreen", false);
|
||||
si.SetBoolValue("Display", "VSync", true);
|
||||
@ -855,11 +856,12 @@ void HostInterface::UpdateSettings(const std::function<void()>& apply_callback)
|
||||
const u32 old_gpu_resolution_scale = m_settings.gpu_resolution_scale;
|
||||
const bool old_gpu_true_color = m_settings.gpu_true_color;
|
||||
const bool old_gpu_texture_filtering = m_settings.gpu_texture_filtering;
|
||||
const bool old_gpu_force_progressive_scan = m_settings.gpu_force_progressive_scan;
|
||||
const bool old_display_force_progressive_scan = m_settings.display_force_progressive_scan;
|
||||
const bool old_gpu_debug_device = m_settings.gpu_use_debug_device;
|
||||
const bool old_vsync_enabled = m_settings.video_sync_enabled;
|
||||
const bool old_audio_sync_enabled = m_settings.audio_sync_enabled;
|
||||
const bool old_speed_limiter_enabled = m_settings.speed_limiter_enabled;
|
||||
const DisplayCropMode old_display_crop_mode = m_settings.display_crop_mode;
|
||||
const bool old_display_linear_filtering = m_settings.display_linear_filtering;
|
||||
const bool old_cdrom_read_thread = m_settings.cdrom_read_thread;
|
||||
std::array<ControllerType, NUM_CONTROLLER_AND_CARD_PORTS> old_controller_types = m_settings.controller_types;
|
||||
@ -906,7 +908,8 @@ void HostInterface::UpdateSettings(const std::function<void()>& apply_callback)
|
||||
if (m_settings.gpu_resolution_scale != old_gpu_resolution_scale ||
|
||||
m_settings.gpu_true_color != old_gpu_true_color ||
|
||||
m_settings.gpu_texture_filtering != old_gpu_texture_filtering ||
|
||||
m_settings.gpu_force_progressive_scan != old_gpu_force_progressive_scan)
|
||||
m_settings.display_force_progressive_scan != old_display_force_progressive_scan ||
|
||||
m_settings.display_crop_mode != old_display_crop_mode)
|
||||
{
|
||||
m_system->UpdateGPUSettings();
|
||||
}
|
||||
|
@ -2,4 +2,4 @@
|
||||
#include "types.h"
|
||||
|
||||
static constexpr u32 SAVE_STATE_MAGIC = 0x43435544;
|
||||
static constexpr u32 SAVE_STATE_VERSION = 1;
|
||||
static constexpr u32 SAVE_STATE_VERSION = 2;
|
||||
|
@ -24,9 +24,12 @@ void Settings::Load(SettingsInterface& si)
|
||||
gpu_resolution_scale = static_cast<u32>(si.GetIntValue("GPU", "ResolutionScale", 1));
|
||||
gpu_true_color = si.GetBoolValue("GPU", "TrueColor", false);
|
||||
gpu_texture_filtering = si.GetBoolValue("GPU", "TextureFiltering", false);
|
||||
gpu_force_progressive_scan = si.GetBoolValue("GPU", "ForceProgressiveScan", true);
|
||||
gpu_use_debug_device = si.GetBoolValue("GPU", "UseDebugDevice", false);
|
||||
|
||||
display_crop_mode = ParseDisplayCropMode(
|
||||
si.GetStringValue("Display", "CropMode", GetDisplayCropModeName(DisplayCropMode::None)).c_str())
|
||||
.value_or(DisplayCropMode::None);
|
||||
display_force_progressive_scan = si.GetBoolValue("Display", "ForceProgressiveScan", true);
|
||||
display_linear_filtering = si.GetBoolValue("Display", "LinearFiltering", true);
|
||||
display_fullscreen = si.GetBoolValue("Display", "Fullscreen", false);
|
||||
video_sync_enabled = si.GetBoolValue("Display", "VSync", true);
|
||||
@ -76,9 +79,9 @@ void Settings::Save(SettingsInterface& si) const
|
||||
si.SetIntValue("GPU", "ResolutionScale", static_cast<long>(gpu_resolution_scale));
|
||||
si.SetBoolValue("GPU", "TrueColor", gpu_true_color);
|
||||
si.SetBoolValue("GPU", "TextureFiltering", gpu_texture_filtering);
|
||||
si.SetBoolValue("GPU", "ForceProgressiveScan", gpu_force_progressive_scan);
|
||||
si.SetBoolValue("GPU", "UseDebugDevice", gpu_use_debug_device);
|
||||
|
||||
si.SetBoolValue("Display", "ForceProgressiveScan", display_force_progressive_scan);
|
||||
si.SetBoolValue("Display", "LinearFiltering", display_linear_filtering);
|
||||
si.SetBoolValue("Display", "Fullscreen", display_fullscreen);
|
||||
si.SetBoolValue("Display", "VSync", video_sync_enabled);
|
||||
@ -213,6 +216,33 @@ const char* Settings::GetRendererDisplayName(GPURenderer renderer)
|
||||
return s_gpu_renderer_display_names[static_cast<int>(renderer)];
|
||||
}
|
||||
|
||||
static std::array<const char*, 3> s_display_crop_mode_names = {{"None", "Overscan", "Borders"}};
|
||||
static std::array<const char*, 3> s_display_crop_mode_display_names = {{"None", "Only Overscan Area", "All Borders"}};
|
||||
|
||||
std::optional<DisplayCropMode> Settings::ParseDisplayCropMode(const char* str)
|
||||
{
|
||||
int index = 0;
|
||||
for (const char* name : s_display_crop_mode_names)
|
||||
{
|
||||
if (StringUtil::Strcasecmp(name, str) == 0)
|
||||
return static_cast<DisplayCropMode>(index);
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const char* Settings::GetDisplayCropModeName(DisplayCropMode crop_mode)
|
||||
{
|
||||
return s_display_crop_mode_names[static_cast<int>(crop_mode)];
|
||||
}
|
||||
|
||||
const char* Settings::GetDisplayCropModeDisplayName(DisplayCropMode crop_mode)
|
||||
{
|
||||
return s_display_crop_mode_display_names[static_cast<int>(crop_mode)];
|
||||
}
|
||||
|
||||
static std::array<const char*, 3> s_audio_backend_names = {{"Null", "Cubeb", "SDL"}};
|
||||
static std::array<const char*, 3> s_audio_backend_display_names = {{"Null (No Output)", "Cubeb", "SDL"}};
|
||||
|
||||
|
@ -48,8 +48,9 @@ struct Settings
|
||||
u32 gpu_resolution_scale = 1;
|
||||
bool gpu_true_color = false;
|
||||
bool gpu_texture_filtering = false;
|
||||
bool gpu_force_progressive_scan = false;
|
||||
bool gpu_use_debug_device = false;
|
||||
DisplayCropMode display_crop_mode = DisplayCropMode::None;
|
||||
bool display_force_progressive_scan = false;
|
||||
bool display_linear_filtering = true;
|
||||
bool display_fullscreen = false;
|
||||
bool video_sync_enabled = true;
|
||||
@ -97,6 +98,10 @@ struct Settings
|
||||
static const char* GetRendererName(GPURenderer renderer);
|
||||
static const char* GetRendererDisplayName(GPURenderer renderer);
|
||||
|
||||
static std::optional<DisplayCropMode> ParseDisplayCropMode(const char* str);
|
||||
static const char* GetDisplayCropModeName(DisplayCropMode crop_mode);
|
||||
static const char* GetDisplayCropModeDisplayName(DisplayCropMode crop_mode);
|
||||
|
||||
static std::optional<AudioBackend> ParseAudioBackend(const char* str);
|
||||
static const char* GetAudioBackendName(AudioBackend backend);
|
||||
static const char* GetAudioBackendDisplayName(AudioBackend backend);
|
||||
|
@ -49,6 +49,14 @@ enum class GPURenderer : u8
|
||||
Count
|
||||
};
|
||||
|
||||
enum class DisplayCropMode : u8
|
||||
{
|
||||
None,
|
||||
Overscan,
|
||||
Borders,
|
||||
Count
|
||||
};
|
||||
|
||||
enum class AudioBackend : u8
|
||||
{
|
||||
Null,
|
||||
|
Reference in New Issue
Block a user