[Fix] (MG_Backend): track EGL backend surfaces

This commit is contained in:
2026-07-03 09:15:26 +08:00
parent bdf29fc4d5
commit 6ecefaec75
4 changed files with 126 additions and 83 deletions
+93 -45
View File
@@ -202,77 +202,114 @@ namespace MobileGL::MG_Backend {
Bool BackendObject::CreateEGLWindowSurface(EGLSurface surface, const WindowHandle& handle) {
const std::lock_guard<std::recursive_mutex> 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<std::recursive_mutex> 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<std::recursive_mutex> lock(m_eglStateMutex);
return RegisterEGLPbufferSurface(surface, width, height) && ActivateEGLSurface(surface);
}
Bool BackendObject::RegisterEGLWindowSurface(EGLSurface surface, const WindowHandle& handle) {
const std::lock_guard<std::recursive_mutex> 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<EGLint>(std::max<Uint32>(handle.Width, 1)),
.Height = static_cast<EGLint>(std::max<Uint32>(handle.Height, 1)),
};
return true;
}
Bool BackendObject::RegisterEGLPbufferSurface(EGLSurface surface, EGLint width, EGLint height) {
const std::lock_guard<std::recursive_mutex> 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<std::recursive_mutex> 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<std::recursive_mutex> 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<std::recursive_mutex> lock(m_eglStateMutex);
ResetEGLRuntimeState();
m_eglSurfaces.clear();
m_eglDisplay = EGL_NO_DISPLAY;
m_eglDisplayInitialized = false;
m_windowHandle = {};
}
void BackendObject::SetWindowHandle(const WindowHandle& handle) {
+12
View File
@@ -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<std::thread::id, EGLCurrentState> m_eglCurrentThreads;
UnorderedMap<EGLSurface, EGLSurfaceState> m_eglSurfaces;
};
} // namespace MG_Backend
} // namespace MobileGL
@@ -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<std::recursive_mutex> 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);
}
@@ -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;
}