From 6ecefaec75419abf16ed79a081641af2823405de Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Fri, 3 Jul 2026 09:15:26 +0800 Subject: [PATCH] [Fix] (MG_Backend): track EGL backend surfaces --- MobileGL/MG_Backend/BackendObject.cpp | 138 ++++++++++++------ MobileGL/MG_Backend/BackendObject.h | 12 ++ .../BackendObject_DirectVulkan.cpp | 39 +---- .../DirectVulkan/Renderer/VulkanRenderer.cpp | 20 ++- 4 files changed, 126 insertions(+), 83 deletions(-) diff --git a/MobileGL/MG_Backend/BackendObject.cpp b/MobileGL/MG_Backend/BackendObject.cpp index 6a8a4f89..d8502838 100644 --- a/MobileGL/MG_Backend/BackendObject.cpp +++ b/MobileGL/MG_Backend/BackendObject.cpp @@ -202,77 +202,114 @@ namespace MobileGL::MG_Backend { Bool BackendObject::CreateEGLWindowSurface(EGLSurface surface, const WindowHandle& handle) { const std::lock_guard lock(m_eglStateMutex); - if (!m_eglDisplayInitialized) { - MGLOG_E("CreateEGLWindowSurface failed: EGL display is not initialized"); - return false; - } - if (surface == EGL_NO_SURFACE) { - MGLOG_E("CreateEGLWindowSurface failed: invalid EGLSurface"); - return false; - } - if (handle.Backend == WindowBackend::Unknown || !handle.Handle) { - MGLOG_E("CreateEGLWindowSurface failed: invalid native window handle"); - return false; - } - - if (m_eglSurfaceInitialized && m_eglSurface == surface && m_eglSurfaceKind == SurfaceKind::Window && - m_windowHandle.Backend == handle.Backend && m_windowHandle.Handle == handle.Handle && - m_windowHandle.Width == handle.Width && m_windowHandle.Height == handle.Height) { - return true; - } - - SetWindowHandle(handle); - if (!InitWindowSurface()) { - MGLOG_E("CreateEGLWindowSurface failed: backend InitWindowSurface failed"); - return false; - } - - m_eglSurface = surface; - m_eglSurfaceInitialized = true; - m_eglSurfaceKind = SurfaceKind::Window; - m_eglCurrentThreads.clear(); - m_backendCapabilitiesInitialized = false; - return true; + return RegisterEGLWindowSurface(surface, handle) && ActivateEGLSurface(surface); } Bool BackendObject::ResizeEGLWindowSurface(EGLSurface surface, Uint32 width, Uint32 height) { const std::lock_guard lock(m_eglStateMutex); - if (!m_eglSurfaceInitialized || m_eglSurface != surface || m_eglSurfaceKind != SurfaceKind::Window) { + auto surfaceIt = m_eglSurfaces.find(surface); + if (surfaceIt == m_eglSurfaces.end() || surfaceIt->second.Kind != SurfaceKind::Window) { MGLOG_E("ResizeEGLWindowSurface failed: no window surface is initialized"); return false; } - m_windowHandle.Width = width; - m_windowHandle.Height = height; + surfaceIt->second.Window.Width = width; + surfaceIt->second.Window.Height = height; + if (m_eglSurface == surface) { + m_windowHandle.Width = width; + m_windowHandle.Height = height; + } return true; } Bool BackendObject::CreateEGLPbufferSurface(EGLSurface surface, EGLint width, EGLint height) { + const std::lock_guard lock(m_eglStateMutex); + return RegisterEGLPbufferSurface(surface, width, height) && ActivateEGLSurface(surface); + } + + Bool BackendObject::RegisterEGLWindowSurface(EGLSurface surface, const WindowHandle& handle) { const std::lock_guard lock(m_eglStateMutex); if (!m_eglDisplayInitialized) { - MGLOG_E("CreateEGLPbufferSurface failed: EGL display is not initialized"); + MGLOG_E("RegisterEGLWindowSurface failed: EGL display is not initialized"); return false; } if (surface == EGL_NO_SURFACE) { - MGLOG_E("CreateEGLPbufferSurface failed: invalid EGLSurface"); + MGLOG_E("RegisterEGLWindowSurface failed: invalid EGLSurface"); + return false; + } + if (handle.Backend == WindowBackend::Unknown || !handle.Handle) { + MGLOG_E("RegisterEGLWindowSurface failed: invalid native window handle"); + return false; + } + + auto& state = m_eglSurfaces[surface]; + state = EGLSurfaceState{ + .Kind = SurfaceKind::Window, + .Window = handle, + .Width = static_cast(std::max(handle.Width, 1)), + .Height = static_cast(std::max(handle.Height, 1)), + }; + return true; + } + + Bool BackendObject::RegisterEGLPbufferSurface(EGLSurface surface, EGLint width, EGLint height) { + const std::lock_guard lock(m_eglStateMutex); + if (!m_eglDisplayInitialized) { + MGLOG_E("RegisterEGLPbufferSurface failed: EGL display is not initialized"); + return false; + } + if (surface == EGL_NO_SURFACE) { + MGLOG_E("RegisterEGLPbufferSurface failed: invalid EGLSurface"); return false; } if (width <= 0 || height <= 0) { - MGLOG_E("CreateEGLPbufferSurface failed: invalid size %dx%d", width, height); + MGLOG_E("RegisterEGLPbufferSurface failed: invalid size %dx%d", width, height); return false; } - if (m_eglSurfaceInitialized && m_eglSurface == surface && m_eglSurfaceKind == SurfaceKind::Pbuffer) { + m_eglSurfaces[surface] = EGLSurfaceState{ + .Kind = SurfaceKind::Pbuffer, + .Width = width, + .Height = height, + }; + return true; + } + + const BackendObject::EGLSurfaceState* BackendObject::GetRegisteredEGLSurface(EGLSurface surface) const { + const std::lock_guard lock(m_eglStateMutex); + auto surfaceIt = m_eglSurfaces.find(surface); + return surfaceIt == m_eglSurfaces.end() ? nullptr : &surfaceIt->second; + } + + Bool BackendObject::ActivateEGLSurface(EGLSurface surface) { + const std::lock_guard lock(m_eglStateMutex); + const auto* surfaceState = GetRegisteredEGLSurface(surface); + if (!surfaceState) { + MGLOG_E("ActivateEGLSurface failed: EGL surface is not registered"); + return false; + } + if (m_eglSurfaceInitialized && m_eglSurface == surface) { return true; } - if (!InitPbufferSurface(width, height)) { - MGLOG_E("CreateEGLPbufferSurface failed: backend InitPbufferSurface failed"); + if (surfaceState->Kind == SurfaceKind::Window) { + SetWindowHandle(surfaceState->Window); + if (!InitWindowSurface()) { + MGLOG_E("ActivateEGLSurface failed: backend InitWindowSurface failed"); + return false; + } + } else if (surfaceState->Kind == SurfaceKind::Pbuffer) { + if (!InitPbufferSurface(surfaceState->Width, surfaceState->Height)) { + MGLOG_E("ActivateEGLSurface failed: backend InitPbufferSurface failed"); + return false; + } + } else { + MGLOG_E("ActivateEGLSurface failed: unsupported surface kind"); return false; } m_eglSurface = surface; m_eglSurfaceInitialized = true; - m_eglSurfaceKind = SurfaceKind::Pbuffer; + m_eglSurfaceKind = surfaceState->Kind; m_eglCurrentThreads.clear(); m_backendCapabilitiesInitialized = false; return true; @@ -291,10 +328,20 @@ namespace MobileGL::MG_Backend { return false; } if (!m_eglSurfaceInitialized) { - MGLOG_E("MakeEGLCurrent failed: EGL surface is not initialized"); + if (draw != read || !ActivateEGLSurface(draw)) { + MGLOG_E("MakeEGLCurrent failed: EGL surface is not initialized"); + return false; + } + } + if (!GetRegisteredEGLSurface(draw) || !GetRegisteredEGLSurface(read)) { + MGLOG_E("MakeEGLCurrent failed: EGL surface is not registered"); return false; } - if (draw != m_eglSurface || read != m_eglSurface) { + if (draw != read) { + MGLOG_E("MakeEGLCurrent failed: separate draw/read surfaces are not supported"); + return false; + } + if (draw != m_eglSurface && !ActivateEGLSurface(draw)) { MGLOG_E("MakeEGLCurrent failed: EGL surface is not backed by this backend"); return false; } @@ -326,6 +373,7 @@ namespace MobileGL::MG_Backend { m_backendCapabilitiesInitialized = false; m_eglSurfaceKind = SurfaceKind::None; m_eglSurface = EGL_NO_SURFACE; + m_windowHandle = {}; m_eglCurrentThreads.clear(); } @@ -370,18 +418,18 @@ namespace MobileGL::MG_Backend { ++currentIt; } + m_eglSurfaces.erase(surface); if (m_eglSurface == surface) { ResetEGLRuntimeState(); - m_windowHandle = {}; } } void BackendObject::ReleaseEGLResources() { const std::lock_guard lock(m_eglStateMutex); ResetEGLRuntimeState(); + m_eglSurfaces.clear(); m_eglDisplay = EGL_NO_DISPLAY; m_eglDisplayInitialized = false; - m_windowHandle = {}; } void BackendObject::SetWindowHandle(const WindowHandle& handle) { diff --git a/MobileGL/MG_Backend/BackendObject.h b/MobileGL/MG_Backend/BackendObject.h index 45c18893..8af4ab9f 100644 --- a/MobileGL/MG_Backend/BackendObject.h +++ b/MobileGL/MG_Backend/BackendObject.h @@ -276,7 +276,18 @@ namespace MobileGL { EGLContext Context = EGL_NO_CONTEXT; }; + struct EGLSurfaceState { + SurfaceKind Kind = SurfaceKind::None; + WindowHandle Window; + EGLint Width = 1; + EGLint Height = 1; + }; + void ResetEGLRuntimeState(); + Bool RegisterEGLWindowSurface(EGLSurface surface, const WindowHandle& handle); + Bool RegisterEGLPbufferSurface(EGLSurface surface, EGLint width, EGLint height); + const EGLSurfaceState* GetRegisteredEGLSurface(EGLSurface surface) const; + Bool ActivateEGLSurface(EGLSurface surface); virtual Bool InitPbufferSurface(EGLint width, EGLint height); FormatCapabilityCache& MutableFormatCapabilities(); @@ -290,6 +301,7 @@ namespace MobileGL { Bool m_backendCapabilitiesInitialized = false; SurfaceKind m_eglSurfaceKind = SurfaceKind::None; UnorderedMap m_eglCurrentThreads; + UnorderedMap m_eglSurfaces; }; } // namespace MG_Backend } // namespace MobileGL diff --git a/MobileGL/MG_Backend/DirectVulkan/BackendObject_DirectVulkan.cpp b/MobileGL/MG_Backend/DirectVulkan/BackendObject_DirectVulkan.cpp index 1bb45b80..aac88071 100644 --- a/MobileGL/MG_Backend/DirectVulkan/BackendObject_DirectVulkan.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/BackendObject_DirectVulkan.cpp @@ -420,20 +420,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { return false; } - const Bool sameHandle = m_eglSurfaceInitialized && m_eglSurface == surface && - m_eglSurfaceKind == SurfaceKind::Window && m_windowHandle.Backend == handle.Backend && - m_windowHandle.Handle == handle.Handle && m_windowHandle.Width == handle.Width && - m_windowHandle.Height == handle.Height; - if (sameHandle) { - return true; - } - - if (m_eglSurfaceInitialized || pVulkanRenderer) { - pVulkanRenderer.reset(); - ResetEGLRuntimeState(); - } - - return BackendObject::CreateEGLWindowSurface(surface, handle); + return RegisterEGLWindowSurface(surface, handle); } Bool BackendObject_DirectVulkan::ResizeEGLWindowSurface(EGLSurface surface, Uint32 width, Uint32 height) { @@ -442,14 +429,12 @@ namespace MobileGL::MG_Backend::DirectVulkan { MGLOG_E("DirectVulkan backend not initialized"); return false; } - if (!pVulkanRenderer) { - MGLOG_E("DirectVulkan renderer is not initialized"); - return false; - } if (!BackendObject::ResizeEGLWindowSurface(surface, width, height)) { return false; } - pVulkanRenderer->RequestSwapchainResize(width, height); + if (pVulkanRenderer && m_eglSurface == surface) { + pVulkanRenderer->RequestSwapchainResize(width, height); + } return true; } @@ -459,25 +444,11 @@ namespace MobileGL::MG_Backend::DirectVulkan { MGLOG_E("DirectVulkan backend not initialized"); return false; } - if (m_eglSurfaceInitialized && m_eglSurface == surface && m_eglSurfaceKind == SurfaceKind::Pbuffer) { - return true; - } - if (m_eglSurfaceInitialized || pVulkanRenderer) { - pVulkanRenderer.reset(); - ResetEGLRuntimeState(); - } - return BackendObject::CreateEGLPbufferSurface(surface, width, height); + return RegisterEGLPbufferSurface(surface, width, height); } Bool BackendObject_DirectVulkan::MakeEGLCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) { const std::lock_guard lock(m_eglStateMutex); - if (IsReleaseCurrentRequest(dpy, draw, read, ctx)) { - return BackendObject::MakeEGLCurrent(dpy, draw, read, ctx); - } - if (!pVulkanRenderer) { - MGLOG_E("DirectVulkan renderer is not initialized"); - return false; - } return BackendObject::MakeEGLCurrent(dpy, draw, read, ctx); } diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp index af01c1bd..400a6fc9 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp @@ -1962,7 +1962,13 @@ void main() { } void VulkanRenderer::Shutdown() { - VK_VERIFY(vkDeviceWaitIdle(m_device)); + if (m_instance == VK_NULL_HANDLE && m_device == VK_NULL_HANDLE && m_surface == VK_NULL_HANDLE) { + return; + } + + if (m_device != VK_NULL_HANDLE) { + VK_VERIFY(vkDeviceWaitIdle(m_device)); + } DestroyDeferredDepthMipmapCleanup(); DestroyComputePipelines(); @@ -1982,7 +1988,9 @@ void main() { m_bufferManager.Shutdown(); m_transientVertexIndexBufferSlicesThisFrame.clear(); - m_frameContext.Destroy(m_device, m_commandPool); + if (m_device != VK_NULL_HANDLE) { + m_frameContext.Destroy(m_device, m_commandPool); + } if (m_uniformManager) { m_uniformManager->Shutdown(); @@ -1990,7 +1998,11 @@ void main() { } m_programFactory.reset(); - ShutdownSwapchain(); + if (m_renderPassManager) { + ShutdownSwapchain(); + } else if (m_device != VK_NULL_HANDLE) { + m_swapchainObject.Shutdown(m_device); + } m_renderPassManager.reset(); if (m_clearManager) { m_clearManager->Shutdown(); @@ -2009,7 +2021,7 @@ void main() { } s_vkCmdDrawIndexedIndirectCount = nullptr; - if (m_surface != VK_NULL_HANDLE) { + if (m_instance != VK_NULL_HANDLE && m_surface != VK_NULL_HANDLE) { vkDestroySurfaceKHR(m_instance, m_surface, nullptr); m_surface = VK_NULL_HANDLE; }