mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-15 22:13:24 +09:00
Breaks the one process = one server = one session = one context equation
that the whole stack's correctness used to rest on. Design and per-slice
shape: docs/Disaggregated/design/11-state-ownership.md.
S1 wire: bind_context ring record (opcode 84) announces the current
context at the make-current edge; CreateContext/DestroyContext join the
SurfaceOp control frames; control revision 5 -> 6; the server keeps a
per-session token table and refuses unknown tokens by name.
S2 server: SessionRuntime per session with thread-scoped resolution
(singletons become fallbacks), per-thread gPipeInputs, per-session latch
domains, per-thread segment resolvers; the in-process unix supervisor
serves up to MOBILEGL_IPC_INPROC_MAX_SESSIONS (16) concurrent sessions;
surface mode is declared per session and the display lease refuses a
second on-screen session by name.
S3 frontend: ShareGroupState owns the shared object stores and name
generators (buffer/texture/renderbuffer/sampler/program), GLContext keeps
per-context bindings/errors/container objects; pGLContext becomes
thread-local with a process default context preserving the single-context
world verbatim; eglCreateContext builds a real GLContext and joins the
sharing context's group.
S4 backend: native EGL tuples keyed by (session, context token);
InitDisplayAndContext's unconditional teardown is gone - creating a
second context or surface no longer destroys the first; eglCreateContext
sharing is wired to the native driver; bind_context is the native switch
point.
S5 applier: MGPipeApplierState splits into MGPipeObjectRecords (per
share group) and MGPipeWorkingState (per context), resolved through a
{session, token} registry with a thread-local cached fast path.
Tests: MultiSessionTest (incl. two sessions x two contexts interleaved
with real clear/readback witnesses), ApplierOwnershipTest (with a
null-resolver negative control), ContextStateOwnershipTest,
ServerLoopEglTest native-context liveness; 99/99 of the acceptance set
green on the host build.
Known debts (documented in the design doc): twin registries still keyed
by handle alone, no per-record ContextSlot, process-global backend
generations, MakeCurrent dedup per current binding.
75 lines
3.6 KiB
C++
75 lines
3.6 KiB
C++
// MobileGL - MobileGL/MG_Remote/Server/SurfaceControlFrame.cpp
|
|
// Copyright (c) 2025-2026 MobileGL-Dev
|
|
// Licensed under the GNU Lesser General Public License v3.0:
|
|
// https://www.gnu.org/licenses/gpl-3.0.txt
|
|
// https://www.gnu.org/licenses/lgpl-3.0.txt
|
|
// SPDX-License-Identifier: LGPL-3.0-only
|
|
// End of Source File Header
|
|
|
|
#include "SurfaceControlFrame.h"
|
|
|
|
namespace MobileGL::MG_Remote::Server {
|
|
|
|
const char* SurfaceControlOpName(SurfaceControlOp op) {
|
|
switch (op) {
|
|
case SurfaceControlOp::None: return "None";
|
|
case SurfaceControlOp::InitializeDisplay: return "InitializeDisplay";
|
|
case SurfaceControlOp::CreateWindowSurface: return "CreateWindowSurface";
|
|
case SurfaceControlOp::CreatePbufferSurface: return "CreatePbufferSurface";
|
|
case SurfaceControlOp::ResizeWindowSurface: return "ResizeWindowSurface";
|
|
case SurfaceControlOp::ReleaseSurface: return "ReleaseSurface";
|
|
case SurfaceControlOp::MakeCurrent: return "MakeCurrent";
|
|
case SurfaceControlOp::ReleaseCurrent: return "ReleaseCurrent";
|
|
case SurfaceControlOp::SetSwapInterval: return "SetSwapInterval";
|
|
case SurfaceControlOp::ReleaseResources: return "ReleaseResources";
|
|
case SurfaceControlOp::SetWindowHandle: return "SetWindowHandle";
|
|
case SurfaceControlOp::InitCapabilities: return "InitCapabilities";
|
|
case SurfaceControlOp::CreateContext: return "CreateContext";
|
|
case SurfaceControlOp::DestroyContext: return "DestroyContext";
|
|
case SurfaceControlOp::SwapBuffersInprocOnly: return "SwapBuffersInprocOnly";
|
|
case SurfaceControlOp::InitWindowSurfaceInprocOnly: return "InitWindowSurfaceInprocOnly";
|
|
case SurfaceControlOp::ProbeForTesting: return "ProbeForTesting";
|
|
}
|
|
return "<unknown SurfaceControlOp>";
|
|
}
|
|
|
|
bool SurfaceControlOpHasWireKind(SurfaceControlOp op) {
|
|
switch (op) {
|
|
case SurfaceControlOp::InitializeDisplay:
|
|
case SurfaceControlOp::CreateWindowSurface:
|
|
case SurfaceControlOp::CreatePbufferSurface:
|
|
case SurfaceControlOp::ResizeWindowSurface:
|
|
case SurfaceControlOp::ReleaseSurface:
|
|
case SurfaceControlOp::MakeCurrent:
|
|
case SurfaceControlOp::ReleaseCurrent:
|
|
case SurfaceControlOp::SetSwapInterval:
|
|
case SurfaceControlOp::ReleaseResources:
|
|
case SurfaceControlOp::SetWindowHandle:
|
|
// cp: the request half of InitCapabilities. Its ANSWER is a CapsSnapshot
|
|
// frame, which is why this row was missing; the request still has to
|
|
// cross, because under spawn the apply thread is in another process.
|
|
case SurfaceControlOp::InitCapabilities:
|
|
// P14 S1: the context lifecycle. The client's eglCreateContext/eglDestroyContext have a
|
|
// live caller under spawn (EGLImpl), so unlike the inproc-only trio beside them these two
|
|
// MUST cross - the server it is asking is in another process.
|
|
case SurfaceControlOp::CreateContext:
|
|
case SurfaceControlOp::DestroyContext:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
const char* SurfaceRefusalCodeName(SurfaceRefusalCode code) {
|
|
switch (code) {
|
|
case SurfaceRefusalCode::None: return "None";
|
|
case SurfaceRefusalCode::NoServerDisplay: return "NoServerDisplay";
|
|
case SurfaceRefusalCode::NoServerWindow: return "NoServerWindow";
|
|
case SurfaceRefusalCode::SurfaceModeMismatch: return "SurfaceModeMismatch";
|
|
case SurfaceRefusalCode::ServerOwnedOnSetWindowHandle: return "ServerOwnedOnSetWindowHandle";
|
|
}
|
|
return "<unknown SurfaceRefusalCode>";
|
|
}
|
|
|
|
} // namespace MobileGL::MG_Remote::Server
|