mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-11 21:58:31 +09:00
[Fix] (MG_Backend): track EGL backend surfaces
This commit is contained in:
@@ -202,77 +202,114 @@ namespace MobileGL::MG_Backend {
|
|||||||
|
|
||||||
Bool BackendObject::CreateEGLWindowSurface(EGLSurface surface, const WindowHandle& handle) {
|
Bool BackendObject::CreateEGLWindowSurface(EGLSurface surface, const WindowHandle& handle) {
|
||||||
const std::lock_guard<std::recursive_mutex> lock(m_eglStateMutex);
|
const std::lock_guard<std::recursive_mutex> lock(m_eglStateMutex);
|
||||||
if (!m_eglDisplayInitialized) {
|
return RegisterEGLWindowSurface(surface, handle) && ActivateEGLSurface(surface);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Bool BackendObject::ResizeEGLWindowSurface(EGLSurface surface, Uint32 width, Uint32 height) {
|
Bool BackendObject::ResizeEGLWindowSurface(EGLSurface surface, Uint32 width, Uint32 height) {
|
||||||
const std::lock_guard<std::recursive_mutex> lock(m_eglStateMutex);
|
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");
|
MGLOG_E("ResizeEGLWindowSurface failed: no window surface is initialized");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
m_windowHandle.Width = width;
|
surfaceIt->second.Window.Width = width;
|
||||||
m_windowHandle.Height = height;
|
surfaceIt->second.Window.Height = height;
|
||||||
|
if (m_eglSurface == surface) {
|
||||||
|
m_windowHandle.Width = width;
|
||||||
|
m_windowHandle.Height = height;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Bool BackendObject::CreateEGLPbufferSurface(EGLSurface surface, EGLint width, EGLint height) {
|
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);
|
const std::lock_guard<std::recursive_mutex> lock(m_eglStateMutex);
|
||||||
if (!m_eglDisplayInitialized) {
|
if (!m_eglDisplayInitialized) {
|
||||||
MGLOG_E("CreateEGLPbufferSurface failed: EGL display is not initialized");
|
MGLOG_E("RegisterEGLWindowSurface failed: EGL display is not initialized");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (surface == EGL_NO_SURFACE) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
if (width <= 0 || height <= 0) {
|
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;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!InitPbufferSurface(width, height)) {
|
if (surfaceState->Kind == SurfaceKind::Window) {
|
||||||
MGLOG_E("CreateEGLPbufferSurface failed: backend InitPbufferSurface failed");
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_eglSurface = surface;
|
m_eglSurface = surface;
|
||||||
m_eglSurfaceInitialized = true;
|
m_eglSurfaceInitialized = true;
|
||||||
m_eglSurfaceKind = SurfaceKind::Pbuffer;
|
m_eglSurfaceKind = surfaceState->Kind;
|
||||||
m_eglCurrentThreads.clear();
|
m_eglCurrentThreads.clear();
|
||||||
m_backendCapabilitiesInitialized = false;
|
m_backendCapabilitiesInitialized = false;
|
||||||
return true;
|
return true;
|
||||||
@@ -291,10 +328,20 @@ namespace MobileGL::MG_Backend {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!m_eglSurfaceInitialized) {
|
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;
|
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");
|
MGLOG_E("MakeEGLCurrent failed: EGL surface is not backed by this backend");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -326,6 +373,7 @@ namespace MobileGL::MG_Backend {
|
|||||||
m_backendCapabilitiesInitialized = false;
|
m_backendCapabilitiesInitialized = false;
|
||||||
m_eglSurfaceKind = SurfaceKind::None;
|
m_eglSurfaceKind = SurfaceKind::None;
|
||||||
m_eglSurface = EGL_NO_SURFACE;
|
m_eglSurface = EGL_NO_SURFACE;
|
||||||
|
m_windowHandle = {};
|
||||||
m_eglCurrentThreads.clear();
|
m_eglCurrentThreads.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -370,18 +418,18 @@ namespace MobileGL::MG_Backend {
|
|||||||
++currentIt;
|
++currentIt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_eglSurfaces.erase(surface);
|
||||||
if (m_eglSurface == surface) {
|
if (m_eglSurface == surface) {
|
||||||
ResetEGLRuntimeState();
|
ResetEGLRuntimeState();
|
||||||
m_windowHandle = {};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BackendObject::ReleaseEGLResources() {
|
void BackendObject::ReleaseEGLResources() {
|
||||||
const std::lock_guard<std::recursive_mutex> lock(m_eglStateMutex);
|
const std::lock_guard<std::recursive_mutex> lock(m_eglStateMutex);
|
||||||
ResetEGLRuntimeState();
|
ResetEGLRuntimeState();
|
||||||
|
m_eglSurfaces.clear();
|
||||||
m_eglDisplay = EGL_NO_DISPLAY;
|
m_eglDisplay = EGL_NO_DISPLAY;
|
||||||
m_eglDisplayInitialized = false;
|
m_eglDisplayInitialized = false;
|
||||||
m_windowHandle = {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BackendObject::SetWindowHandle(const WindowHandle& handle) {
|
void BackendObject::SetWindowHandle(const WindowHandle& handle) {
|
||||||
|
|||||||
@@ -276,7 +276,18 @@ namespace MobileGL {
|
|||||||
EGLContext Context = EGL_NO_CONTEXT;
|
EGLContext Context = EGL_NO_CONTEXT;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct EGLSurfaceState {
|
||||||
|
SurfaceKind Kind = SurfaceKind::None;
|
||||||
|
WindowHandle Window;
|
||||||
|
EGLint Width = 1;
|
||||||
|
EGLint Height = 1;
|
||||||
|
};
|
||||||
|
|
||||||
void ResetEGLRuntimeState();
|
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);
|
virtual Bool InitPbufferSurface(EGLint width, EGLint height);
|
||||||
FormatCapabilityCache& MutableFormatCapabilities();
|
FormatCapabilityCache& MutableFormatCapabilities();
|
||||||
|
|
||||||
@@ -290,6 +301,7 @@ namespace MobileGL {
|
|||||||
Bool m_backendCapabilitiesInitialized = false;
|
Bool m_backendCapabilitiesInitialized = false;
|
||||||
SurfaceKind m_eglSurfaceKind = SurfaceKind::None;
|
SurfaceKind m_eglSurfaceKind = SurfaceKind::None;
|
||||||
UnorderedMap<std::thread::id, EGLCurrentState> m_eglCurrentThreads;
|
UnorderedMap<std::thread::id, EGLCurrentState> m_eglCurrentThreads;
|
||||||
|
UnorderedMap<EGLSurface, EGLSurfaceState> m_eglSurfaces;
|
||||||
};
|
};
|
||||||
} // namespace MG_Backend
|
} // namespace MG_Backend
|
||||||
} // namespace MobileGL
|
} // namespace MobileGL
|
||||||
|
|||||||
@@ -420,20 +420,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Bool sameHandle = m_eglSurfaceInitialized && m_eglSurface == surface &&
|
return RegisterEGLWindowSurface(surface, handle);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Bool BackendObject_DirectVulkan::ResizeEGLWindowSurface(EGLSurface surface, Uint32 width, Uint32 height) {
|
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");
|
MGLOG_E("DirectVulkan backend not initialized");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!pVulkanRenderer) {
|
|
||||||
MGLOG_E("DirectVulkan renderer is not initialized");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!BackendObject::ResizeEGLWindowSurface(surface, width, height)) {
|
if (!BackendObject::ResizeEGLWindowSurface(surface, width, height)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
pVulkanRenderer->RequestSwapchainResize(width, height);
|
if (pVulkanRenderer && m_eglSurface == surface) {
|
||||||
|
pVulkanRenderer->RequestSwapchainResize(width, height);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -459,25 +444,11 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
MGLOG_E("DirectVulkan backend not initialized");
|
MGLOG_E("DirectVulkan backend not initialized");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (m_eglSurfaceInitialized && m_eglSurface == surface && m_eglSurfaceKind == SurfaceKind::Pbuffer) {
|
return RegisterEGLPbufferSurface(surface, width, height);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (m_eglSurfaceInitialized || pVulkanRenderer) {
|
|
||||||
pVulkanRenderer.reset();
|
|
||||||
ResetEGLRuntimeState();
|
|
||||||
}
|
|
||||||
return BackendObject::CreateEGLPbufferSurface(surface, width, height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Bool BackendObject_DirectVulkan::MakeEGLCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) {
|
Bool BackendObject_DirectVulkan::MakeEGLCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) {
|
||||||
const std::lock_guard<std::recursive_mutex> lock(m_eglStateMutex);
|
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);
|
return BackendObject::MakeEGLCurrent(dpy, draw, read, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1962,7 +1962,13 @@ void main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VulkanRenderer::Shutdown() {
|
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();
|
DestroyDeferredDepthMipmapCleanup();
|
||||||
DestroyComputePipelines();
|
DestroyComputePipelines();
|
||||||
@@ -1982,7 +1988,9 @@ void main() {
|
|||||||
m_bufferManager.Shutdown();
|
m_bufferManager.Shutdown();
|
||||||
m_transientVertexIndexBufferSlicesThisFrame.clear();
|
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) {
|
if (m_uniformManager) {
|
||||||
m_uniformManager->Shutdown();
|
m_uniformManager->Shutdown();
|
||||||
@@ -1990,7 +1998,11 @@ void main() {
|
|||||||
}
|
}
|
||||||
m_programFactory.reset();
|
m_programFactory.reset();
|
||||||
|
|
||||||
ShutdownSwapchain();
|
if (m_renderPassManager) {
|
||||||
|
ShutdownSwapchain();
|
||||||
|
} else if (m_device != VK_NULL_HANDLE) {
|
||||||
|
m_swapchainObject.Shutdown(m_device);
|
||||||
|
}
|
||||||
m_renderPassManager.reset();
|
m_renderPassManager.reset();
|
||||||
if (m_clearManager) {
|
if (m_clearManager) {
|
||||||
m_clearManager->Shutdown();
|
m_clearManager->Shutdown();
|
||||||
@@ -2009,7 +2021,7 @@ void main() {
|
|||||||
}
|
}
|
||||||
s_vkCmdDrawIndexedIndirectCount = nullptr;
|
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);
|
vkDestroySurfaceKHR(m_instance, m_surface, nullptr);
|
||||||
m_surface = VK_NULL_HANDLE;
|
m_surface = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user