mirror of https://github.com/PCSX2/pcsx2.git
Qt: Recreate new window immediately when switching APIs
This commit is contained in:
parent
7f24a5cf82
commit
3cae728aba
|
@ -254,13 +254,14 @@ void Host::SetRelativeMouseMode(bool enabled)
|
|||
{
|
||||
}
|
||||
|
||||
std::optional<WindowInfo> Host::AcquireRenderWindow(RenderAPI api)
|
||||
std::optional<WindowInfo> Host::AcquireRenderWindow()
|
||||
{
|
||||
return GSRunner::GetPlatformWindowInfo();
|
||||
}
|
||||
|
||||
std::optional<WindowInfo> Host::UpdateRenderWindow()
|
||||
std::optional<WindowInfo> Host::UpdateRenderWindow(bool recreate_window)
|
||||
{
|
||||
// We shouldn't ever recreate with the runner, so this is okay..
|
||||
return GSRunner::GetPlatformWindowInfo();
|
||||
}
|
||||
|
||||
|
|
|
@ -2233,23 +2233,24 @@ std::optional<WindowInfo> MainWindow::createDisplayWindow(bool fullscreen, bool
|
|||
return wi;
|
||||
}
|
||||
|
||||
std::optional<WindowInfo> MainWindow::updateDisplayWindow(bool fullscreen, bool render_to_main, bool surfaceless)
|
||||
std::optional<WindowInfo> MainWindow::updateDisplayWindow(bool recreate_window, bool fullscreen, bool render_to_main, bool surfaceless)
|
||||
{
|
||||
DevCon.WriteLn("updateDisplayWindow() fullscreen=%s render_to_main=%s surfaceless=%s", fullscreen ? "true" : "false",
|
||||
render_to_main ? "true" : "false", surfaceless ? "true" : "false");
|
||||
DevCon.WriteLn("updateDisplayWindow() recreate=%s fullscreen=%s render_to_main=%s surfaceless=%s", recreate_window ? "true" : "false",
|
||||
fullscreen ? "true" : "false", render_to_main ? "true" : "false", surfaceless ? "true" : "false");
|
||||
|
||||
QWidget* container = m_display_container ? static_cast<QWidget*>(m_display_container) : static_cast<QWidget*>(m_display_widget);
|
||||
const bool is_fullscreen = isRenderingFullscreen();
|
||||
const bool is_rendering_to_main = isRenderingToMain();
|
||||
const bool changing_surfaceless = (!m_display_widget != surfaceless);
|
||||
if (fullscreen == is_fullscreen && is_rendering_to_main == render_to_main && !changing_surfaceless)
|
||||
if (!recreate_window && fullscreen == is_fullscreen && is_rendering_to_main == render_to_main && !changing_surfaceless)
|
||||
return m_display_widget->getWindowInfo();
|
||||
|
||||
// Skip recreating the surface if we're just transitioning between fullscreen and windowed with render-to-main off.
|
||||
// .. except on Wayland, where everything tends to break if you don't recreate.
|
||||
const bool has_container = (m_display_container != nullptr);
|
||||
const bool needs_container = DisplayContainer::isNeeded(fullscreen, render_to_main);
|
||||
if (!is_rendering_to_main && !render_to_main && has_container == needs_container && !needs_container && !changing_surfaceless)
|
||||
if (!recreate_window && !is_rendering_to_main && !render_to_main && has_container == needs_container && !needs_container &&
|
||||
!changing_surfaceless)
|
||||
{
|
||||
DevCon.WriteLn("Toggling to %s without recreating surface", (fullscreen ? "fullscreen" : "windowed"));
|
||||
|
||||
|
|
|
@ -129,7 +129,7 @@ private Q_SLOTS:
|
|||
void onUpdateCheckComplete();
|
||||
|
||||
std::optional<WindowInfo> createDisplayWindow(bool fullscreen, bool render_to_main);
|
||||
std::optional<WindowInfo> updateDisplayWindow(bool fullscreen, bool render_to_main, bool surfaceless);
|
||||
std::optional<WindowInfo> updateDisplayWindow(bool recreate_window, bool fullscreen, bool render_to_main, bool surfaceless);
|
||||
void displayResizeRequested(qint32 width, qint32 height);
|
||||
void relativeMouseModeRequested(bool enabled);
|
||||
void destroyDisplay();
|
||||
|
|
|
@ -901,9 +901,9 @@ std::optional<WindowInfo> EmuThread::acquireRenderWindow()
|
|||
return emit onCreateDisplayRequested(m_is_fullscreen, m_is_rendering_to_main);
|
||||
}
|
||||
|
||||
std::optional<WindowInfo> EmuThread::updateRenderWindow()
|
||||
std::optional<WindowInfo> EmuThread::updateRenderWindow(bool recreate_window)
|
||||
{
|
||||
return emit onUpdateDisplayRequested(m_is_fullscreen, !m_is_fullscreen && m_is_rendering_to_main, m_is_surfaceless);
|
||||
return emit onUpdateDisplayRequested(recreate_window, m_is_fullscreen, !m_is_fullscreen && m_is_rendering_to_main, m_is_surfaceless);
|
||||
}
|
||||
|
||||
void EmuThread::releaseRenderWindow()
|
||||
|
@ -911,14 +911,14 @@ void EmuThread::releaseRenderWindow()
|
|||
emit onDestroyDisplayRequested();
|
||||
}
|
||||
|
||||
std::optional<WindowInfo> Host::AcquireRenderWindow(RenderAPI api)
|
||||
std::optional<WindowInfo> Host::AcquireRenderWindow()
|
||||
{
|
||||
return g_emu_thread->acquireRenderWindow();
|
||||
}
|
||||
|
||||
std::optional<WindowInfo> Host::UpdateRenderWindow()
|
||||
std::optional<WindowInfo> Host::UpdateRenderWindow(bool recreate_window)
|
||||
{
|
||||
return g_emu_thread->updateRenderWindow();
|
||||
return g_emu_thread->updateRenderWindow(recreate_window);
|
||||
}
|
||||
|
||||
void Host::ReleaseRenderWindow()
|
||||
|
|
|
@ -70,7 +70,7 @@ public:
|
|||
|
||||
/// Called back from the GS thread when the display state changes (e.g. fullscreen, render to main).
|
||||
std::optional<WindowInfo> acquireRenderWindow();
|
||||
std::optional<WindowInfo> updateRenderWindow();
|
||||
std::optional<WindowInfo> updateRenderWindow(bool recreate_window);
|
||||
void connectDisplaySignals(DisplayWidget* widget);
|
||||
void releaseRenderWindow();
|
||||
|
||||
|
@ -118,7 +118,7 @@ Q_SIGNALS:
|
|||
bool messageConfirmed(const QString& title, const QString& message);
|
||||
|
||||
std::optional<WindowInfo> onCreateDisplayRequested(bool fullscreen, bool render_to_main);
|
||||
std::optional<WindowInfo> onUpdateDisplayRequested(bool fullscreen, bool render_to_main, bool surfaceless);
|
||||
std::optional<WindowInfo> onUpdateDisplayRequested(bool recreate_window, bool fullscreen, bool render_to_main, bool surfaceless);
|
||||
void onResizeDisplayRequested(qint32 width, qint32 height);
|
||||
void onDestroyDisplayRequested();
|
||||
void onRelativeMouseModeRequested(bool enabled);
|
||||
|
|
|
@ -73,7 +73,6 @@ static HRESULT s_hr = E_FAIL;
|
|||
|
||||
Pcsx2Config::GSOptions GSConfig;
|
||||
|
||||
static RenderAPI s_render_api;
|
||||
static u64 s_next_manual_present_time;
|
||||
|
||||
int GSinit()
|
||||
|
@ -171,18 +170,17 @@ static void UpdateExclusiveFullscreen(bool force_off)
|
|||
}
|
||||
}
|
||||
|
||||
static bool OpenGSDevice(GSRendererType renderer, bool clear_state_on_fail)
|
||||
static bool OpenGSDevice(GSRendererType renderer, bool clear_state_on_fail, bool reopening, bool recreate_window)
|
||||
{
|
||||
s_render_api = GetAPIForRenderer(renderer);
|
||||
|
||||
std::optional<WindowInfo> wi = Host::AcquireRenderWindow(s_render_api);
|
||||
std::optional<WindowInfo> wi = reopening ? Host::UpdateRenderWindow(recreate_window) : Host::AcquireRenderWindow();
|
||||
if (!wi.has_value())
|
||||
{
|
||||
Console.Error("Failed to acquire render window.");
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (s_render_api)
|
||||
const RenderAPI new_api = GetAPIForRenderer(renderer);
|
||||
switch (new_api)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
case RenderAPI::D3D11:
|
||||
|
@ -199,7 +197,6 @@ static bool OpenGSDevice(GSRendererType renderer, bool clear_state_on_fail)
|
|||
#endif
|
||||
#ifdef ENABLE_OPENGL
|
||||
case RenderAPI::OpenGL:
|
||||
case RenderAPI::OpenGLES:
|
||||
g_gs_device = std::make_unique<GSDeviceOGL>();
|
||||
break;
|
||||
#endif
|
||||
|
@ -211,7 +208,7 @@ static bool OpenGSDevice(GSRendererType renderer, bool clear_state_on_fail)
|
|||
#endif
|
||||
|
||||
default:
|
||||
Console.Error("Unsupported render API %s", GSDevice::RenderAPIToString(s_render_api));
|
||||
Console.Error("Unsupported render API %s", GSDevice::RenderAPIToString(new_api));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -239,8 +236,7 @@ static bool OpenGSDevice(GSRendererType renderer, bool clear_state_on_fail)
|
|||
|
||||
GSConfig.OsdShowGPU = EmuConfig.GS.OsdShowGPU && g_gs_device->SetGPUTimingEnabled(true);
|
||||
|
||||
s_render_api = g_gs_device->GetRenderAPI();
|
||||
Console.WriteLn(Color_StrongGreen, "%s Graphics Driver Info:", GSDevice::RenderAPIToString(s_render_api));
|
||||
Console.WriteLn(Color_StrongGreen, "%s Graphics Driver Info:", GSDevice::RenderAPIToString(new_api));
|
||||
Console.Indent().WriteLn(g_gs_device->GetDriverInfo());
|
||||
|
||||
// Switch to exclusive fullscreen if enabled.
|
||||
|
@ -250,7 +246,7 @@ static bool OpenGSDevice(GSRendererType renderer, bool clear_state_on_fail)
|
|||
return true;
|
||||
}
|
||||
|
||||
static void CloseGSDevice(bool clear_state)
|
||||
static void CloseGSDevice(bool clear_state, bool reopening)
|
||||
{
|
||||
if (!g_gs_device)
|
||||
return;
|
||||
|
@ -260,7 +256,8 @@ static void CloseGSDevice(bool clear_state)
|
|||
g_gs_device->Destroy();
|
||||
g_gs_device.reset();
|
||||
|
||||
Host::ReleaseRenderWindow();
|
||||
if (!reopening)
|
||||
Host::ReleaseRenderWindow();
|
||||
}
|
||||
|
||||
static bool OpenGSRenderer(GSRendererType renderer, u8* basemem)
|
||||
|
@ -337,19 +334,24 @@ bool GSreopen(bool recreate_device, bool recreate_renderer, const Pcsx2Config::G
|
|||
|
||||
if (recreate_device)
|
||||
{
|
||||
CloseGSDevice(false);
|
||||
// We need a new render window when changing APIs.
|
||||
const bool recreate_window = (g_gs_device->GetRenderAPI() != GetAPIForRenderer(GSConfig.Renderer));
|
||||
CloseGSDevice(false, true);
|
||||
|
||||
if (!OpenGSDevice(GSConfig.Renderer, false) || (recreate_renderer && !OpenGSRenderer(GSConfig.Renderer, basemem)))
|
||||
if (!OpenGSDevice(GSConfig.Renderer, false, true, recreate_window) ||
|
||||
(recreate_renderer && !OpenGSRenderer(GSConfig.Renderer, basemem)))
|
||||
{
|
||||
Host::AddKeyedOSDMessage(
|
||||
"GSReopenFailed", "Failed to reopen, restoring old configuration.", Host::OSD_CRITICAL_ERROR_DURATION);
|
||||
|
||||
CloseGSDevice(false);
|
||||
CloseGSDevice(false, true);
|
||||
|
||||
GSConfig = old_config;
|
||||
if (!OpenGSDevice(GSConfig.Renderer, false) || (recreate_renderer && !OpenGSRenderer(GSConfig.Renderer, basemem)))
|
||||
if (!OpenGSDevice(GSConfig.Renderer, false, true, recreate_window) ||
|
||||
(recreate_renderer && !OpenGSRenderer(GSConfig.Renderer, basemem)))
|
||||
{
|
||||
pxFailRel("Failed to reopen GS on old config");
|
||||
Host::ReleaseRenderWindow();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -385,12 +387,12 @@ bool GSopen(const Pcsx2Config::GSOptions& config, GSRendererType renderer, u8* b
|
|||
GSConfig = config;
|
||||
GSConfig.Renderer = renderer;
|
||||
|
||||
bool res = OpenGSDevice(renderer, true);
|
||||
bool res = OpenGSDevice(renderer, true, false, false);
|
||||
if (res)
|
||||
{
|
||||
res = OpenGSRenderer(renderer, basemem);
|
||||
if (!res)
|
||||
CloseGSDevice(true);
|
||||
CloseGSDevice(true, false);
|
||||
}
|
||||
|
||||
if (!res)
|
||||
|
@ -408,7 +410,7 @@ bool GSopen(const Pcsx2Config::GSOptions& config, GSRendererType renderer, u8* b
|
|||
void GSclose()
|
||||
{
|
||||
CloseGSRenderer();
|
||||
CloseGSDevice(true);
|
||||
CloseGSDevice(true, false);
|
||||
}
|
||||
|
||||
void GSreset(bool hardware_reset)
|
||||
|
@ -627,7 +629,7 @@ void GSUpdateDisplayWindow()
|
|||
UpdateExclusiveFullscreen(true);
|
||||
g_gs_device->DestroySurface();
|
||||
|
||||
const std::optional<WindowInfo> wi = Host::UpdateRenderWindow();
|
||||
const std::optional<WindowInfo> wi = Host::UpdateRenderWindow(false);
|
||||
if (!wi.has_value())
|
||||
{
|
||||
pxFailRel("Failed to get window info after update.");
|
||||
|
@ -726,7 +728,7 @@ void GSgetInternalResolution(int* width, int* height)
|
|||
void GSgetStats(std::string& info)
|
||||
{
|
||||
GSPerfMon& pm = g_perfmon;
|
||||
const char* api_name = GSDevice::RenderAPIToString(s_render_api);
|
||||
const char* api_name = GSDevice::RenderAPIToString(g_gs_device->GetRenderAPI());
|
||||
if (GSConfig.Renderer == GSRendererType::SW)
|
||||
{
|
||||
const double fps = GetVerticalFrequency();
|
||||
|
@ -793,7 +795,7 @@ void GSgetTitleStats(std::string& info)
|
|||
static constexpr const char* deinterlace_modes[] = {
|
||||
"Automatic", "None", "Weave tff", "Weave bff", "Bob tff", "Bob bff", "Blend tff", "Blend bff", "Adaptive tff", "Adaptive bff"};
|
||||
|
||||
const char* api_name = GSDevice::RenderAPIToString(s_render_api);
|
||||
const char* api_name = GSDevice::RenderAPIToString(g_gs_device->GetRenderAPI());
|
||||
const char* hw_sw_name = (GSConfig.Renderer == GSRendererType::Null) ? " Null" : (GSConfig.UseHardwareRenderer() ? " HW" : " SW");
|
||||
const char* deinterlace_mode = deinterlace_modes[static_cast<int>(GSConfig.InterlaceMode)];
|
||||
|
||||
|
@ -900,15 +902,10 @@ void GSSwitchRenderer(GSRendererType new_renderer)
|
|||
if (!g_gs_renderer || GSConfig.Renderer == new_renderer)
|
||||
return;
|
||||
|
||||
RenderAPI existing_api = g_gs_device->GetRenderAPI();
|
||||
if (existing_api == RenderAPI::OpenGLES)
|
||||
existing_api = RenderAPI::OpenGL;
|
||||
|
||||
const bool is_software_switch = (new_renderer == GSRendererType::SW || GSConfig.Renderer == GSRendererType::SW);
|
||||
const bool recreate_display = (!is_software_switch && existing_api != GetAPIForRenderer(new_renderer));
|
||||
const Pcsx2Config::GSOptions old_config(GSConfig);
|
||||
GSConfig.Renderer = new_renderer;
|
||||
if (!GSreopen(recreate_display, true, old_config))
|
||||
if (!GSreopen(!is_software_switch, true, old_config))
|
||||
pxFailRel("Failed to reopen GS for renderer switch.");
|
||||
}
|
||||
|
||||
|
|
|
@ -32,8 +32,7 @@ enum class RenderAPI
|
|||
Metal,
|
||||
D3D12,
|
||||
Vulkan,
|
||||
OpenGL,
|
||||
OpenGLES
|
||||
OpenGL
|
||||
};
|
||||
|
||||
// ST_WRITE is defined in libc, avoid this
|
||||
|
@ -129,11 +128,11 @@ struct GSRecoverableError : GSError
|
|||
namespace Host
|
||||
{
|
||||
/// Called when the GS is creating a render device.
|
||||
std::optional<WindowInfo> AcquireRenderWindow(RenderAPI api);
|
||||
std::optional<WindowInfo> AcquireRenderWindow();
|
||||
|
||||
/// Called on the MTGS thread when a request to update the display is received.
|
||||
/// This could be a fullscreen transition, for example.
|
||||
std::optional<WindowInfo> UpdateRenderWindow();
|
||||
std::optional<WindowInfo> UpdateRenderWindow(bool recreate_window);
|
||||
|
||||
/// Called before drawing the OSD and other display elements.
|
||||
void BeginPresentFrame();
|
||||
|
|
|
@ -105,7 +105,6 @@ const char* GSDevice::RenderAPIToString(RenderAPI api)
|
|||
CASE(Metal);
|
||||
CASE(Vulkan);
|
||||
CASE(OpenGL);
|
||||
CASE(OpenGLES);
|
||||
#undef CASE
|
||||
// clang-format on
|
||||
default:
|
||||
|
@ -323,7 +322,7 @@ void GSDevice::Recycle(GSTexture* t)
|
|||
bool GSDevice::UsesLowerLeftOrigin() const
|
||||
{
|
||||
const RenderAPI api = GetRenderAPI();
|
||||
return (api == RenderAPI::OpenGL || api == RenderAPI::OpenGLES);
|
||||
return (api == RenderAPI::OpenGL);
|
||||
}
|
||||
|
||||
void GSDevice::AgePool()
|
||||
|
|
|
@ -60,7 +60,7 @@ GSTexture* GSDeviceOGL::CreateSurface(GSTexture::Type type, int width, int heigh
|
|||
|
||||
RenderAPI GSDeviceOGL::GetRenderAPI() const
|
||||
{
|
||||
return m_gl_context->IsGLES() ? RenderAPI::OpenGLES : RenderAPI::OpenGL;
|
||||
return RenderAPI::OpenGL;
|
||||
}
|
||||
|
||||
bool GSDeviceOGL::HasSurface() const
|
||||
|
|
|
@ -105,12 +105,12 @@ void Host::SetRelativeMouseMode(bool enabled)
|
|||
{
|
||||
}
|
||||
|
||||
std::optional<WindowInfo> Host::AcquireRenderWindow(RenderAPI api)
|
||||
std::optional<WindowInfo> Host::AcquireRenderWindow()
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<WindowInfo> Host::UpdateRenderWindow()
|
||||
std::optional<WindowInfo> Host::UpdateRenderWindow(bool recreate_window)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue