libretro: Better handle resolution changes

This commit is contained in:
Connor McLaughlin 2020-07-04 21:23:59 +10:00
parent e15fafe428
commit 343e3ba3b7
2 changed files with 92 additions and 42 deletions

View file

@ -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,14 +786,23 @@ 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
std::optional<GPURenderer> renderer;
std::unique_ptr<HostDisplay> display = std::move(m_hw_render_display);
if (display)
{
Log_InfoPrintf("Using existing hardware display");
renderer = RenderAPIToRenderer(display->GetRenderAPI());
}
else
{
renderer = RetroHwContextToRenderer(m_hw_render_callback.context_type);
if (!renderer.has_value()) if (!renderer.has_value())
{ {
Log_ErrorPrintf("Unknown context type %u", static_cast<unsigned>(m_hw_render_callback.context_type)); Log_ErrorPrintf("Unknown context type %u", static_cast<unsigned>(m_hw_render_callback.context_type));
return; return;
} }
std::unique_ptr<HostDisplay> display = nullptr;
switch (renderer.value()) switch (renderer.value())
{ {
case GPURenderer::HardwareOpenGL: case GPURenderer::HardwareOpenGL:
@ -801,6 +839,7 @@ void LibretroHostInterface::SwitchToHardwareRenderer()
Log_ErrorPrintf("Failed to create hardware host display"); Log_ErrorPrintf("Failed to create hardware host display");
return; return;
} }
}
std::swap(display, g_libretro_host_interface.m_display); std::swap(display, g_libretro_host_interface.m_display);
g_libretro_host_interface.m_system->RecreateGPU(renderer.value()); g_libretro_host_interface.m_system->RecreateGPU(renderer.value());
@ -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);
} }

View file

@ -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;
}; };