mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-07 19:58:32 +09:00
[Fix] (MG_Impl): preserve macOS surface during resize
This commit is contained in:
@@ -229,6 +229,17 @@ namespace MobileGL::MG_Backend {
|
||||
return true;
|
||||
}
|
||||
|
||||
Bool BackendObject::ResizeEGLWindowSurface(Uint32 width, Uint32 height) {
|
||||
const std::lock_guard<std::recursive_mutex> lock(m_eglStateMutex);
|
||||
if (!m_eglSurfaceInitialized || m_eglSurfaceKind != SurfaceKind::Window) {
|
||||
MGLOG_E("ResizeEGLWindowSurface failed: no window surface is initialized");
|
||||
return false;
|
||||
}
|
||||
m_windowHandle.Width = width;
|
||||
m_windowHandle.Height = height;
|
||||
return true;
|
||||
}
|
||||
|
||||
Bool BackendObject::CreateEGLPbufferSurface(EGLint width, EGLint height) {
|
||||
const std::lock_guard<std::recursive_mutex> lock(m_eglStateMutex);
|
||||
if (!m_eglDisplayInitialized) {
|
||||
|
||||
@@ -246,6 +246,7 @@ namespace MobileGL {
|
||||
|
||||
virtual Bool InitializeEGLDisplay(EGLDisplay dpy, EGLint* major, EGLint* minor);
|
||||
virtual Bool CreateEGLWindowSurface(const WindowHandle& handle);
|
||||
virtual Bool ResizeEGLWindowSurface(Uint32 width, Uint32 height);
|
||||
virtual Bool CreateEGLPbufferSurface(EGLint width, EGLint height);
|
||||
virtual Bool MakeEGLCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
|
||||
virtual Bool SwapEGLBuffers(EGLDisplay dpy, EGLSurface draw);
|
||||
|
||||
@@ -434,6 +434,23 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
return BackendObject::CreateEGLWindowSurface(handle);
|
||||
}
|
||||
|
||||
Bool BackendObject_DirectVulkan::ResizeEGLWindowSurface(Uint32 width, Uint32 height) {
|
||||
const std::lock_guard<std::recursive_mutex> lock(m_eglStateMutex);
|
||||
if (!m_initialized) {
|
||||
MGLOG_E("DirectVulkan backend not initialized");
|
||||
return false;
|
||||
}
|
||||
if (!pVulkanRenderer) {
|
||||
MGLOG_E("DirectVulkan renderer is not initialized");
|
||||
return false;
|
||||
}
|
||||
if (!BackendObject::ResizeEGLWindowSurface(width, height)) {
|
||||
return false;
|
||||
}
|
||||
pVulkanRenderer->RequestSwapchainResize(width, height);
|
||||
return true;
|
||||
}
|
||||
|
||||
Bool BackendObject_DirectVulkan::CreateEGLPbufferSurface(EGLint width, EGLint height) {
|
||||
const std::lock_guard<std::recursive_mutex> lock(m_eglStateMutex);
|
||||
if (!m_initialized) {
|
||||
|
||||
@@ -22,6 +22,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
Bool InitCapabilities() override;
|
||||
Bool InitializeEGLDisplay(EGLDisplay dpy, EGLint* major, EGLint* minor) override;
|
||||
Bool CreateEGLWindowSurface(const WindowHandle& handle) override;
|
||||
Bool ResizeEGLWindowSurface(Uint32 width, Uint32 height) override;
|
||||
Bool CreateEGLPbufferSurface(EGLint width, EGLint height) override;
|
||||
Bool MakeEGLCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) override;
|
||||
Bool SwapEGLBuffers(EGLDisplay dpy, EGLSurface draw) override;
|
||||
|
||||
@@ -5389,9 +5389,15 @@ void main() {
|
||||
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) {
|
||||
MGLOG_D("Present, vkQueuePresentKHR got %d, recreating swapchain", result);
|
||||
RecreateSwapchain();
|
||||
m_swapchainResizeRequested = false;
|
||||
result = VK_SUCCESS;
|
||||
}
|
||||
VK_VERIFY(result, "Present, vkQueuePresentKHR");
|
||||
if (m_swapchainResizeRequested) {
|
||||
MGLOG_D("Present, processing requested swapchain resize");
|
||||
RecreateSwapchain();
|
||||
m_swapchainResizeRequested = false;
|
||||
}
|
||||
|
||||
// 3) Advance frame slot.
|
||||
m_frameContext.AdvanceToNext();
|
||||
@@ -5401,6 +5407,7 @@ void main() {
|
||||
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) {
|
||||
MGLOG_D("Present, vkAcquireNextImageKHR got %d, recreating swapchain", result);
|
||||
RecreateSwapchain();
|
||||
m_swapchainResizeRequested = false;
|
||||
result =
|
||||
m_frameContext.WaitAndAcquireNextImage(m_device, m_swapchainObject.GetHandle(), m_imageIndexAcquired);
|
||||
}
|
||||
@@ -6105,6 +6112,17 @@ void main() {
|
||||
return m_physicalDevice;
|
||||
}
|
||||
|
||||
void VulkanRenderer::RequestSwapchainResize(Uint32 width, Uint32 height) {
|
||||
width = std::max<Uint32>(width, 1);
|
||||
height = std::max<Uint32>(height, 1);
|
||||
if (m_config.SurfaceWidth == width && m_config.SurfaceHeight == height) {
|
||||
return;
|
||||
}
|
||||
m_config.SurfaceWidth = width;
|
||||
m_config.SurfaceHeight = height;
|
||||
m_swapchainResizeRequested = true;
|
||||
}
|
||||
|
||||
VkInstance VulkanRenderer::GetInstance() const {
|
||||
return m_instance;
|
||||
}
|
||||
|
||||
@@ -160,6 +160,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
VkInstance GetInstance() const;
|
||||
Bool IsDrawIndirectCountExtensionEnabled() const;
|
||||
|
||||
void RequestSwapchainResize(Uint32 width, Uint32 height);
|
||||
void RecreateSwapchain();
|
||||
|
||||
private:
|
||||
@@ -206,6 +207,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
void* m_platformLibrary = nullptr;
|
||||
void* m_platformCloseDisplay = nullptr;
|
||||
VulkanRendererConfig m_config;
|
||||
Bool m_swapchainResizeRequested = false;
|
||||
|
||||
// Vulkan objects
|
||||
Bool m_validationLayersEnabled = false;
|
||||
|
||||
@@ -256,6 +256,18 @@ namespace MobileGL::MG_Impl::CGLImpl {
|
||||
object.HasDrawable = true;
|
||||
return GetCurrentContext() == ctx ? MakeCurrentLocked(ctx, object) : kCGLNoError;
|
||||
}
|
||||
|
||||
CGLError ResizeSurfaceLocked(ContextObject& object) {
|
||||
if (object.Surface == EGL_NO_SURFACE) {
|
||||
return kCGLBadDrawable;
|
||||
}
|
||||
return EGLImpl::ResizePlatformWindowSurface(
|
||||
object.Display, object.Surface,
|
||||
std::max<GLint>(object.SurfaceBackingSize[0], 1),
|
||||
std::max<GLint>(object.SurfaceBackingSize[1], 1))
|
||||
? kCGLNoError
|
||||
: kCGLBadDrawable;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
CGLError ChoosePixelFormat(const CGLPixelFormatAttribute* attribs, CGLPixelFormatObj* pix, GLint* npix) {
|
||||
@@ -492,8 +504,8 @@ namespace MobileGL::MG_Impl::CGLImpl {
|
||||
}
|
||||
object->SurfaceBackingSize[0] = width;
|
||||
object->SurfaceBackingSize[1] = height;
|
||||
if (object->MetalLayer) {
|
||||
return RecreateSurfaceLocked(ctx, *object);
|
||||
if (object->MetalLayer && object->Surface != EGL_NO_SURFACE) {
|
||||
return ResizeSurfaceLocked(*object);
|
||||
}
|
||||
return kCGLNoError;
|
||||
}
|
||||
@@ -653,6 +665,11 @@ namespace MobileGL::MG_Impl::CGLImpl {
|
||||
object->HasDrawable = true;
|
||||
return kCGLNoError;
|
||||
}
|
||||
if (object->Surface != EGL_NO_SURFACE && object->MetalLayer == metalLayer) {
|
||||
object->View = nsView;
|
||||
object->HasDrawable = true;
|
||||
return ResizeSurfaceLocked(*object);
|
||||
}
|
||||
if (object->Surface != EGL_NO_SURFACE) {
|
||||
EGLImpl::DestroySurface(object->Display, object->Surface);
|
||||
object->Surface = EGL_NO_SURFACE;
|
||||
|
||||
@@ -623,6 +623,28 @@ namespace MobileGL::MG_Impl::EGLImpl {
|
||||
return state->CreatePlatformWindowSurface(dpy, config, native_window, attrib_list);
|
||||
}
|
||||
|
||||
EGLBoolean ResizePlatformWindowSurface(EGLDisplay dpy, EGLSurface surface, EGLint width, EGLint height) {
|
||||
auto* state = GetState();
|
||||
if (!state) {
|
||||
return EGL_FALSE;
|
||||
}
|
||||
if (!state->ResizeSurface(dpy, surface, width, height)) {
|
||||
return EGL_FALSE;
|
||||
}
|
||||
auto* backendObject = GetBackendObject(state);
|
||||
if (!backendObject) {
|
||||
MGLOG_E("activeBackendObject not initialized!");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
width = std::max<EGLint>(width, 1);
|
||||
height = std::max<EGLint>(height, 1);
|
||||
if (!backendObject->ResizeEGLWindowSurface(static_cast<Uint32>(width), static_cast<Uint32>(height))) {
|
||||
state->SetError(EGL_BAD_NATIVE_WINDOW);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
EGLSurface CreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, void* native_pixmap,
|
||||
const EGLAttrib* attrib_list) {
|
||||
auto* state = GetState();
|
||||
|
||||
@@ -57,6 +57,7 @@ namespace MobileGL::MG_Impl::EGLImpl {
|
||||
EGLDisplay GetPlatformDisplay(EGLenum platform, void* native_display, const EGLAttrib* attrib_list);
|
||||
EGLSurface CreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, void* native_window,
|
||||
const EGLAttrib* attrib_list);
|
||||
EGLBoolean ResizePlatformWindowSurface(EGLDisplay dpy, EGLSurface surface, EGLint width, EGLint height);
|
||||
EGLSurface CreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, void* native_pixmap,
|
||||
const EGLAttrib* attrib_list);
|
||||
EGLBoolean WaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags);
|
||||
|
||||
@@ -935,6 +935,23 @@ namespace MobileGL {
|
||||
return true;
|
||||
}
|
||||
|
||||
Bool EGLContext::ResizeSurface(EGLDisplayHandle display, EGLSurfaceHandle surface,
|
||||
EGLint width, EGLint height) {
|
||||
const std::lock_guard<std::recursive_mutex> lock(m_mutex);
|
||||
auto surfaceIt = m_surfaces.find(surface);
|
||||
if (surfaceIt == m_surfaces.end()) {
|
||||
SetError(EGL_BAD_SURFACE);
|
||||
return false;
|
||||
}
|
||||
if (surfaceIt->second.Display != display) {
|
||||
SetError(EGL_BAD_MATCH);
|
||||
return false;
|
||||
}
|
||||
surfaceIt->second.Width = std::max<EGLint>(width, 1);
|
||||
surfaceIt->second.Height = std::max<EGLint>(height, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
Bool EGLContext::QuerySurface(EGLDisplayHandle display, EGLSurfaceHandle surface, EGLint attribute,
|
||||
EGLint* value) const {
|
||||
const std::lock_guard<std::recursive_mutex> lock(m_mutex);
|
||||
|
||||
@@ -74,6 +74,7 @@ namespace MobileGL {
|
||||
EGLSurfaceHandle CreatePlatformPixmapSurface(EGLDisplayHandle display, EGLConfigHandle config,
|
||||
void* nativePixmap, const EGLAttrib* attribList);
|
||||
Bool DestroySurface(EGLDisplayHandle display, EGLSurfaceHandle surface);
|
||||
Bool ResizeSurface(EGLDisplayHandle display, EGLSurfaceHandle surface, EGLint width, EGLint height);
|
||||
Bool QuerySurface(EGLDisplayHandle display, EGLSurfaceHandle surface, EGLint attribute,
|
||||
EGLint* value) const;
|
||||
Bool ValidateSurface(EGLSurfaceHandle surface) const;
|
||||
|
||||
Reference in New Issue
Block a user