mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-23 14:25:37 +00:00
libretro: Better handle resolution changes
This commit is contained in:
parent
e15fafe428
commit
343e3ba3b7
|
@ -50,7 +50,15 @@ static void LibretroLogCallback(void* pUserParam, const char* channelName, const
|
||||||
|
|
||||||
LibretroHostInterface::LibretroHostInterface() = default;
|
LibretroHostInterface::LibretroHostInterface() = default;
|
||||||
|
|
||||||
LibretroHostInterface::~LibretroHostInterface() = default;
|
LibretroHostInterface::~LibretroHostInterface()
|
||||||
|
{
|
||||||
|
// should be cleaned up by the context destroy, but just in case
|
||||||
|
if (m_hw_render_display)
|
||||||
|
{
|
||||||
|
m_hw_render_display->DestroyRenderDevice();
|
||||||
|
m_hw_render_display.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void LibretroHostInterface::InitLogging()
|
void LibretroHostInterface::InitLogging()
|
||||||
{
|
{
|
||||||
|
@ -682,6 +690,27 @@ static std::optional<GPURenderer> RetroHwContextToRenderer(retro_hw_context_type
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::optional<GPURenderer> RenderAPIToRenderer(HostDisplay::RenderAPI api)
|
||||||
|
{
|
||||||
|
switch (api)
|
||||||
|
{
|
||||||
|
case HostDisplay::RenderAPI::OpenGL:
|
||||||
|
case HostDisplay::RenderAPI::OpenGLES:
|
||||||
|
return GPURenderer::HardwareOpenGL;
|
||||||
|
|
||||||
|
case HostDisplay::RenderAPI::Vulkan:
|
||||||
|
return GPURenderer::HardwareVulkan;
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
case HostDisplay::RenderAPI::D3D11:
|
||||||
|
return GPURenderer::HardwareD3D11;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default:
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool LibretroHostInterface::RequestHardwareRendererContext()
|
bool LibretroHostInterface::RequestHardwareRendererContext()
|
||||||
{
|
{
|
||||||
GPURenderer renderer = Settings::DEFAULT_GPU_RENDERER;
|
GPURenderer renderer = Settings::DEFAULT_GPU_RENDERER;
|
||||||
|
@ -757,49 +786,59 @@ void LibretroHostInterface::HardwareRendererContextReset()
|
||||||
|
|
||||||
void LibretroHostInterface::SwitchToHardwareRenderer()
|
void LibretroHostInterface::SwitchToHardwareRenderer()
|
||||||
{
|
{
|
||||||
std::optional<GPURenderer> renderer = RetroHwContextToRenderer(m_hw_render_callback.context_type);
|
// use the existing device if we just resized the window
|
||||||
if (!renderer.has_value())
|
std::optional<GPURenderer> renderer;
|
||||||
|
std::unique_ptr<HostDisplay> display = std::move(m_hw_render_display);
|
||||||
|
if (display)
|
||||||
{
|
{
|
||||||
Log_ErrorPrintf("Unknown context type %u", static_cast<unsigned>(m_hw_render_callback.context_type));
|
Log_InfoPrintf("Using existing hardware display");
|
||||||
return;
|
renderer = RenderAPIToRenderer(display->GetRenderAPI());
|
||||||
}
|
}
|
||||||
|
else
|
||||||
std::unique_ptr<HostDisplay> display = nullptr;
|
|
||||||
switch (renderer.value())
|
|
||||||
{
|
{
|
||||||
case GPURenderer::HardwareOpenGL:
|
renderer = RetroHwContextToRenderer(m_hw_render_callback.context_type);
|
||||||
display = std::make_unique<LibretroOpenGLHostDisplay>();
|
if (!renderer.has_value())
|
||||||
break;
|
{
|
||||||
|
Log_ErrorPrintf("Unknown context type %u", static_cast<unsigned>(m_hw_render_callback.context_type));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
case GPURenderer::HardwareVulkan:
|
switch (renderer.value())
|
||||||
display = std::make_unique<LibretroVulkanHostDisplay>();
|
{
|
||||||
break;
|
case GPURenderer::HardwareOpenGL:
|
||||||
|
display = std::make_unique<LibretroOpenGLHostDisplay>();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GPURenderer::HardwareVulkan:
|
||||||
|
display = std::make_unique<LibretroVulkanHostDisplay>();
|
||||||
|
break;
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
case GPURenderer::HardwareD3D11:
|
case GPURenderer::HardwareD3D11:
|
||||||
display = std::make_unique<LibretroD3D11HostDisplay>();
|
display = std::make_unique<LibretroD3D11HostDisplay>();
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Log_ErrorPrintf("Unhandled renderer '%s'", Settings::GetRendererName(renderer.value()));
|
Log_ErrorPrintf("Unhandled renderer '%s'", Settings::GetRendererName(renderer.value()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct retro_system_av_info avi;
|
||||||
|
g_libretro_host_interface.GetSystemAVInfo(&avi, true);
|
||||||
|
|
||||||
|
WindowInfo wi;
|
||||||
|
wi.type = WindowInfo::Type::Libretro;
|
||||||
|
wi.display_connection = &g_libretro_host_interface.m_hw_render_callback;
|
||||||
|
wi.surface_width = avi.geometry.base_width;
|
||||||
|
wi.surface_height = avi.geometry.base_height;
|
||||||
|
wi.surface_scale = 1.0f;
|
||||||
|
if (!display || !display->CreateRenderDevice(wi, {}, g_libretro_host_interface.m_settings.gpu_use_debug_device) ||
|
||||||
|
!display->InitializeRenderDevice({}, m_settings.gpu_use_debug_device))
|
||||||
|
{
|
||||||
|
Log_ErrorPrintf("Failed to create hardware host display");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct retro_system_av_info avi;
|
|
||||||
g_libretro_host_interface.GetSystemAVInfo(&avi, true);
|
|
||||||
|
|
||||||
WindowInfo wi;
|
|
||||||
wi.type = WindowInfo::Type::Libretro;
|
|
||||||
wi.display_connection = &g_libretro_host_interface.m_hw_render_callback;
|
|
||||||
wi.surface_width = avi.geometry.base_width;
|
|
||||||
wi.surface_height = avi.geometry.base_height;
|
|
||||||
wi.surface_scale = 1.0f;
|
|
||||||
if (!display || !display->CreateRenderDevice(wi, {}, g_libretro_host_interface.m_settings.gpu_use_debug_device) ||
|
|
||||||
!display->InitializeRenderDevice({}, m_settings.gpu_use_debug_device))
|
|
||||||
{
|
|
||||||
Log_ErrorPrintf("Failed to create hardware host display");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::swap(display, g_libretro_host_interface.m_display);
|
std::swap(display, g_libretro_host_interface.m_display);
|
||||||
|
@ -810,21 +849,31 @@ void LibretroHostInterface::SwitchToHardwareRenderer()
|
||||||
|
|
||||||
void LibretroHostInterface::HardwareRendererContextDestroy()
|
void LibretroHostInterface::HardwareRendererContextDestroy()
|
||||||
{
|
{
|
||||||
g_libretro_host_interface.m_hw_render_callback_valid = false;
|
|
||||||
|
|
||||||
// switch back to software
|
// switch back to software
|
||||||
if (g_libretro_host_interface.m_using_hardware_renderer)
|
if (g_libretro_host_interface.m_using_hardware_renderer)
|
||||||
{
|
{
|
||||||
Log_InfoPrintf("Lost hardware renderer context, switching to software renderer");
|
Log_InfoPrintf("Lost hardware renderer context, switching to software renderer");
|
||||||
g_libretro_host_interface.SwitchToSoftwareRenderer();
|
g_libretro_host_interface.SwitchToSoftwareRenderer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (g_libretro_host_interface.m_hw_render_display)
|
||||||
|
{
|
||||||
|
g_libretro_host_interface.m_hw_render_display->DestroyRenderDevice();
|
||||||
|
g_libretro_host_interface.m_hw_render_display.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
g_libretro_host_interface.m_hw_render_callback_valid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LibretroHostInterface::SwitchToSoftwareRenderer()
|
void LibretroHostInterface::SwitchToSoftwareRenderer()
|
||||||
{
|
{
|
||||||
std::unique_ptr<HostDisplay> display = std::make_unique<LibretroHostDisplay>();
|
// keep the hw renderer around in case we need it later
|
||||||
std::swap(display, g_libretro_host_interface.m_display);
|
if (m_using_hardware_renderer)
|
||||||
g_libretro_host_interface.m_system->RecreateGPU(GPURenderer::Software);
|
{
|
||||||
display->DestroyRenderDevice();
|
m_hw_render_display = std::move(m_display);
|
||||||
m_using_hardware_renderer = false;
|
m_using_hardware_renderer = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_display = std::make_unique<LibretroHostDisplay>();
|
||||||
|
m_system->RecreateGPU(GPURenderer::Software);
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,7 @@ private:
|
||||||
static void HardwareRendererContextDestroy();
|
static void HardwareRendererContextDestroy();
|
||||||
|
|
||||||
retro_hw_render_callback m_hw_render_callback = {};
|
retro_hw_render_callback m_hw_render_callback = {};
|
||||||
|
std::unique_ptr<HostDisplay> m_hw_render_display;
|
||||||
bool m_hw_render_callback_valid = false;
|
bool m_hw_render_callback_valid = false;
|
||||||
bool m_using_hardware_renderer = false;
|
bool m_using_hardware_renderer = false;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue