From 6e2223b517acb6bd4c97c9fcd9dcba91d4a2e917 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sun, 15 Dec 2024 22:04:54 +1000 Subject: [PATCH] OpenGLDevice: Fix surfaceless context switch --- src/core/host.cpp | 6 ++++++ src/util/gpu_device.cpp | 9 +++++++-- src/util/gpu_device.h | 1 + src/util/opengl_context_egl.cpp | 6 ++++-- src/util/opengl_device.cpp | 6 ++++++ src/util/opengl_device.h | 1 + 6 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/core/host.cpp b/src/core/host.cpp index 6083c6ee1..cc5da139f 100644 --- a/src/core/host.cpp +++ b/src/core/host.cpp @@ -459,7 +459,13 @@ void Host::UpdateDisplayWindow(bool fullscreen) // if surfaceless, just leave it if (wi->IsSurfaceless()) + { + DEV_LOG("Switching to surfaceless device"); + if (!g_gpu_device->SwitchToSurfacelessRendering(&error)) + ERROR_LOG("Failed to switch to surfaceless, rendering commands may fail: {}", error.GetDescription()); + return; + } if (!g_gpu_device->RecreateMainSwapChain(wi.value(), vsync_mode, allow_present_throttle, fullscreen_mode.has_value() ? &fullscreen_mode.value() : nullptr, diff --git a/src/util/gpu_device.cpp b/src/util/gpu_device.cpp index 231283c2a..73ecaa862 100644 --- a/src/util/gpu_device.cpp +++ b/src/util/gpu_device.cpp @@ -472,6 +472,12 @@ void GPUDevice::Destroy() DestroyDevice(); } +bool GPUDevice::SwitchToSurfacelessRendering(Error* error) +{ + // noop on everything except GL because of it's context nonsense + return true; +} + bool GPUDevice::RecreateMainSwapChain(const WindowInfo& wi, GPUVSyncMode vsync_mode, bool allow_present_throttle, const ExclusiveFullscreenMode* exclusive_fullscreen_mode, std::optional exclusive_fullscreen_control, Error* error) @@ -723,8 +729,7 @@ void GPUDevice::RenderImGui(GPUSwapChain* swap_chain) 0.0f, 0.0f, static_cast(swap_chain->GetWidth()), static_cast(swap_chain->GetHeight()), 0.0f, 1.0f); if (swap_chain->GetPreRotation() != WindowInfo::PreRotation::Identity) { - mproj = - GSMatrix4x4::RotationZ(WindowInfo::GetZRotationForPreRotation(swap_chain->GetPreRotation())) * mproj; + mproj = GSMatrix4x4::RotationZ(WindowInfo::GetZRotationForPreRotation(swap_chain->GetPreRotation())) * mproj; } PushUniformBuffer(&mproj, sizeof(mproj)); diff --git a/src/util/gpu_device.h b/src/util/gpu_device.h index ffcd7fd10..14c46d344 100644 --- a/src/util/gpu_device.h +++ b/src/util/gpu_device.h @@ -720,6 +720,7 @@ public: const ExclusiveFullscreenMode* exclusive_fullscreen_mode, std::optional exclusive_fullscreen_control, Error* error) = 0; + virtual bool SwitchToSurfacelessRendering(Error* error); bool RecreateMainSwapChain(const WindowInfo& wi, GPUVSyncMode vsync_mode, bool allow_present_throttle, const ExclusiveFullscreenMode* exclusive_fullscreen_mode, diff --git a/src/util/opengl_context_egl.cpp b/src/util/opengl_context_egl.cpp index a2ddc9061..2d7f9addb 100644 --- a/src/util/opengl_context_egl.cpp +++ b/src/util/opengl_context_egl.cpp @@ -8,6 +8,8 @@ #include "common/error.h" #include "common/log.h" +#include "glad/gl.h" + #include #include #include @@ -164,7 +166,7 @@ EGLSurface OpenGLContextEGL::CreatePlatformSurface(EGLConfig config, const Windo bool OpenGLContextEGL::SupportsSurfaceless() const { - return GLAD_EGL_KHR_surfaceless_context; + return (!IsGLES() || GLAD_GL_OES_surfaceless_context) && GLAD_EGL_KHR_surfaceless_context; } EGLDisplay OpenGLContextEGL::TryGetPlatformDisplay(void* display, EGLenum platform, const char* platform_ext) @@ -294,7 +296,7 @@ void OpenGLContextEGL::DestroySurface(SurfaceHandle handle) EGLSurface surface = (EGLSurface)handle; if (m_current_surface == surface) { - eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, SupportsSurfaceless() ? m_context : EGL_NO_CONTEXT); m_current_surface = EGL_NO_SURFACE; } diff --git a/src/util/opengl_device.cpp b/src/util/opengl_device.cpp index 19d20f74f..4b181ffbc 100644 --- a/src/util/opengl_device.cpp +++ b/src/util/opengl_device.cpp @@ -637,6 +637,12 @@ std::unique_ptr OpenGLDevice::CreateSwapChain(const WindowInfo& wi return std::make_unique(wi_copy, vsync_mode, allow_present_throttle, surface_handle); } +bool OpenGLDevice::SwitchToSurfacelessRendering(Error* error) +{ + // We need to switch to surfaceless if we're temporarily destroying, otherwise we can't issue GL commands. + return m_gl_context->MakeCurrent(nullptr, error); +} + std::string OpenGLDevice::GetDriverInfo() const { const char* gl_vendor = reinterpret_cast(glGetString(GL_VENDOR)); diff --git a/src/util/opengl_device.h b/src/util/opengl_device.h index 4cf1be950..5846b34b0 100644 --- a/src/util/opengl_device.h +++ b/src/util/opengl_device.h @@ -52,6 +52,7 @@ public: const ExclusiveFullscreenMode* exclusive_fullscreen_mode, std::optional exclusive_fullscreen_control, Error* error) override; + bool SwitchToSurfacelessRendering(Error* error) override; std::unique_ptr CreateTexture(u32 width, u32 height, u32 layers, u32 levels, u32 samples, GPUTexture::Type type, GPUTexture::Format format, GPUTexture::Flags flags, const void* data = nullptr, u32 data_stride = 0,