[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.
This commit is contained in:
2026-10-01 13:45:52 -04:00
parent 6fb880cdf2
commit ebc552a048
2 changed files with 18 additions and 3 deletions
+4 -1
View File
@@ -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);
+14 -2
View File
@@ -12,6 +12,7 @@
#include "../EGLImpl/EGLImpl.h"
#include "../GetProcAddress.h"
#include <Init.h>
#include <Config.h>
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<EGLint>(width),
static_cast<EGLint>(height))) {
@@ -323,8 +329,13 @@ namespace MobileGL::MG_Impl::GLXImpl {
EGL_HEIGHT, static_cast<EGLAttrib>(height),
EGL_NONE,
};
EGLSurface surface = EGLImpl::CreatePlatformWindowSurface(
context.Display, context.Config, reinterpret_cast<void*>(drawable), attribs);
const Bool remotePbuffer = MG_Config::Transport == MG_Config::TransportMode::Spawn;
const EGLint pbufferAttribs[] = {EGL_WIDTH, static_cast<EGLint>(width),
EGL_HEIGHT, static_cast<EGLint>(height), EGL_NONE};
EGLSurface surface = remotePbuffer
? EGLImpl::CreatePbufferSurface(context.Display, context.Config, pbufferAttribs)
: EGLImpl::CreatePlatformWindowSurface(
context.Display, context.Config, reinterpret_cast<void*>(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;