[MG_Remote, MG_Backend] (P12 review): a server-owned surface resizes the server's window and reports its real size, every server-owned surface keeps its geometry, and Espryt reports a window's extent only for the server's own window

- Client resize: eglResize on a headless client's server-owned surface only rewrote the backend's record of the window - the phone's SurfaceView kept its size - and the client's EGL state answered the size it asked for. The server now recognises the surface as its own (ServerLoop::m_serverOwnedSurfaces, per session) and resizes it as a geometry request (the lease re-taken by its holder, the display waited for), resizes the backend surface to the window's real extent and replies with it; BackendObject_Remote adopts that extent (ServerResizeServerOwnedWindowSurface).
- Size tracking: the client held ONE server-owned surface, so a second one took the first's geometry updates and releasing it left the first with none. ClientSession now tracks every server-owned surface and applies an extent to all of them (they share the server's one window).
- Size reports without the knob: Espryt's new extent publish fired for every window surface of a spawn/tcp session, including windows a client named itself without MOBILEGL_IPC_SURFACE=server, switching their consumer to the reallocating arm. ServerLoop now names its own leased window to the backend (MGPipeServerSetOwnedWindow, split-only) and Espryt publishes the extent only for that window.
This commit is contained in:
2026-09-24 14:03:47 +00:00
parent 277940f39f
commit 29a82617e0
8 changed files with 164 additions and 17 deletions
+31 -13
View File
@@ -39,6 +39,7 @@
#include <chrono>
#include <cstdlib>
#include <cstring>
#include <mutex>
#include <thread>
#include <utility>
#include <vector>
@@ -347,22 +348,27 @@ namespace MobileGL::MG_Remote::Client {
}
}
// P12 (on-screen server window), D1: the session's server-owned window surface - the
// client's EGL handle for it - or EGL_NO_SURFACE. Written on the GL thread by the surface
// RPCs (NoteServerOwnedWindowSurface / ForgetServerOwnedWindowSurface) and read by the
// drain, which runs on the same thread; atomic only because nothing else pins that.
std::atomic<EGLSurface> g_serverOwnedSurface{EGL_NO_SURFACE};
// P12 (on-screen server window), D1: the session's server-owned window surfaces - the
// client's EGL handles for them. Written by the surface RPCs (NoteServerOwnedWindowSurface /
// ForgetServerOwnedWindowSurface) and read by the drain; a mutex because an app may create
// and release surfaces from more than one thread. REVIEW FIX: a SET, not one slot - with one
// slot a second surface took the geometry updates from the first, and releasing the second
// left the first with none. Every one of them is on the server's one window, so an extent
// applies to all of them.
std::mutex g_serverOwnedSurfacesMutex;
std::vector<EGLSurface> g_serverOwnedSurfaces;
// An event's extent is the SERVER's surface size. For the server-owned window that is the
// size the client renders at, so the EGL state's record of the surface follows it:
// eglQuerySurface(EGL_WIDTH/EGL_HEIGHT) is what a headless client sizes its viewport from.
// A format-only event (Width/Height 0) says nothing about the size and changes nothing.
void ApplyServerOwnedSurfaceExtent(Uint32 width, Uint32 height) {
if (width == 0 || height == 0) return;
const EGLSurface surface = g_serverOwnedSurface.load(std::memory_order_acquire);
if (surface == EGL_NO_SURFACE || !MG_State::pEGLContext) return;
(void)MG_State::pEGLContext->SetSurfaceExtent(surface, static_cast<EGLint>(width),
static_cast<EGLint>(height));
if (width == 0 || height == 0 || !MG_State::pEGLContext) return;
const std::lock_guard<std::mutex> lock(g_serverOwnedSurfacesMutex);
for (const EGLSurface surface : g_serverOwnedSurfaces) {
(void)MG_State::pEGLContext->SetSurfaceExtent(surface, static_cast<EGLint>(width),
static_cast<EGLint>(height));
}
}
Uint32 DrainEventRing(Transport::EventRingConsumer& events) {
@@ -2468,13 +2474,25 @@ namespace MobileGL::MG_Remote::Client {
}
void ClientSession::NoteServerOwnedWindowSurface(EGLSurface surface, Uint32 width, Uint32 height) {
g_serverOwnedSurface.store(surface, std::memory_order_release);
{
const std::lock_guard<std::mutex> lock(g_serverOwnedSurfacesMutex);
if (std::find(g_serverOwnedSurfaces.begin(), g_serverOwnedSurfaces.end(), surface) ==
g_serverOwnedSurfaces.end())
g_serverOwnedSurfaces.push_back(surface);
}
ApplyServerOwnedSurfaceExtent(width, height);
}
void ClientSession::ForgetServerOwnedWindowSurface(EGLSurface surface) {
EGLSurface expected = surface;
(void)g_serverOwnedSurface.compare_exchange_strong(expected, EGL_NO_SURFACE, std::memory_order_acq_rel);
const std::lock_guard<std::mutex> lock(g_serverOwnedSurfacesMutex);
g_serverOwnedSurfaces.erase(std::remove(g_serverOwnedSurfaces.begin(), g_serverOwnedSurfaces.end(), surface),
g_serverOwnedSurfaces.end());
}
Bool ClientSession::IsServerOwnedWindowSurface(EGLSurface surface) {
const std::lock_guard<std::mutex> lock(g_serverOwnedSurfacesMutex);
return std::find(g_serverOwnedSurfaces.begin(), g_serverOwnedSurfaces.end(), surface) !=
g_serverOwnedSurfaces.end();
}
Uint64 ClientSession::EventRingCapacityBytes() const { return m_link->Memory().EventRingCapacity(); }