From ebc552a0487a55c3247e1f838abfbf1015bcdc34 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Thu, 1 Oct 2026 13:45:52 -0400 Subject: [PATCH] [Fix] (WSI): report Wayland present failure and keep GLX drawables off XIDs Wayland Present() failure now returns EGL_BAD_SURFACE instead of being dropped. In spawn mode a GLX X drawable is backed by a remote pbuffer so the XID is never mistaken for an Android ANativeWindow; X11 pixel present and remote resize are still unimplemented. --- MobileGL/MG_Impl/EGLImpl/EGLImpl.cpp | 5 ++++- MobileGL/MG_Impl/GLXImpl/GLXImpl.cpp | 16 ++++++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/MobileGL/MG_Impl/EGLImpl/EGLImpl.cpp b/MobileGL/MG_Impl/EGLImpl/EGLImpl.cpp index c1e2fa3c..acecc544 100644 --- a/MobileGL/MG_Impl/EGLImpl/EGLImpl.cpp +++ b/MobileGL/MG_Impl/EGLImpl/EGLImpl.cpp @@ -302,7 +302,10 @@ namespace MobileGL::MG_Impl::EGLImpl { #if MOBILEGL_WAYLAND_WINDOWS // A Wayland window shows what is attached to it: the frame is read back and attached // BEFORE the swap, while it is still the drawable's content. - if (auto it = WaylandSurfaces().find(draw); it != WaylandSurfaces().end()) (void)it->second->Present(); + if (auto it = WaylandSurfaces().find(draw); it != WaylandSurfaces().end() && !it->second->Present()) { + state->SetError(EGL_BAD_SURFACE); + return EGL_FALSE; + } #endif if (!backendObject->SwapEGLBuffers(dpy, draw)) { MGLOG_E_ONCE("eglSwapBuffers failed on thread=%s dpy=%p draw=%p", CurrentThreadIdString().c_str(), dpy, draw); diff --git a/MobileGL/MG_Impl/GLXImpl/GLXImpl.cpp b/MobileGL/MG_Impl/GLXImpl/GLXImpl.cpp index 02037555..ce46a82c 100644 --- a/MobileGL/MG_Impl/GLXImpl/GLXImpl.cpp +++ b/MobileGL/MG_Impl/GLXImpl/GLXImpl.cpp @@ -12,6 +12,7 @@ #include "../EGLImpl/EGLImpl.h" #include "../GetProcAddress.h" #include +#include namespace MobileGL::MG_Impl::GLXImpl { namespace { @@ -187,6 +188,7 @@ namespace MobileGL::MG_Impl::GLXImpl { Uint32 Width = 0; Uint32 Height = 0; std::chrono::steady_clock::time_point LastSizePoll{}; + Bool RemotePbuffer = false; }; std::recursive_mutex& RegistryMutex() { @@ -294,6 +296,10 @@ namespace MobileGL::MG_Impl::GLXImpl { if (width == surface.Width && height == surface.Height) { return; } + // A remote X drawable is backed by a pbuffer; an XID has no meaning + // to the Android worker. Its allocation cannot be resized by the + // native-window hook. Keep the current allocation until recreated. + if (surface.RemotePbuffer) return; if (EGLImpl::ResizePlatformWindowSurface(surface.Display, surface.Surface, static_cast(width), static_cast(height))) { @@ -323,8 +329,13 @@ namespace MobileGL::MG_Impl::GLXImpl { EGL_HEIGHT, static_cast(height), EGL_NONE, }; - EGLSurface surface = EGLImpl::CreatePlatformWindowSurface( - context.Display, context.Config, reinterpret_cast(drawable), attribs); + const Bool remotePbuffer = MG_Config::Transport == MG_Config::TransportMode::Spawn; + const EGLint pbufferAttribs[] = {EGL_WIDTH, static_cast(width), + EGL_HEIGHT, static_cast(height), EGL_NONE}; + EGLSurface surface = remotePbuffer + ? EGLImpl::CreatePbufferSurface(context.Display, context.Config, pbufferAttribs) + : EGLImpl::CreatePlatformWindowSurface( + context.Display, context.Config, reinterpret_cast(drawable), attribs); if (surface == EGL_NO_SURFACE) { MGLOG_E_ONCE("glx: failed to create window surface for drawable 0x%lx (%ux%u)", drawable, width, height); @@ -336,6 +347,7 @@ namespace MobileGL::MG_Impl::GLXImpl { record.Surface = surface; record.Width = width; record.Height = height; + record.RemotePbuffer = remotePbuffer; record.LastSizePoll = std::chrono::steady_clock::now(); auto [inserted, _] = surfaces.emplace(drawable, record); return &inserted->second;