mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 18:13:23 +09:00
[Feature] (disaggregated): WindowKind::HostFrame - the host-framed surface crosses the wire
The last thing between the host-framed surface and a run: the sub-byte on the wire that names it. ServerOwned had one (7) and the host frame had none, so the encoder refused the op with UnknownWindowKind - a correct refusal, and the reason the first run of MOBILEGL_IPC_SURFACE=host failed in the codec rather than anywhere near the pixels. - protocol.fbs: WindowKind::HostFrame = 8, appended, legal on CreateWindowSurface only and always with nativeToken 0 - the same rules ServerOwned carries, for the same reason: no pointer of any process's window system crosses (Rule G/H). - SurfaceRefusal: HostFrameOnSetWindowHandle = 5, its own code rather than reusing the server-owned one: a refusal that names the wrong owner sends the next reader to the wrong place. - SurfaceOpCodec: the encode and decode arms, the two wire errors that go with them (HostFrameTokenNotZero latches as corruption, HostFrameOnSetWindowHandle is a named refusal), and the range bound that had ServerOwned as its upper limit now ends at HostFrame. - protocol_generated.h regenerated with the pinned submodule's flatc (scripts/gen_protocol.py), diff being exactly the two appended enumerators. Both ends must be rebuilt together, as any protocol revision here: the container's client and the device's server went out with this on either side.
This commit is contained in:
@@ -58,6 +58,11 @@ namespace MobileGL::MG_Remote {
|
||||
static_assert(static_cast<Uint8>(::MobileGL::Wire::WindowKind::MetalLayer) == 6);
|
||||
// P12's append, on the same terms: the value is wire ABI.
|
||||
static_assert(static_cast<Uint8>(::MobileGL::Wire::WindowKind::ServerOwned) == 7);
|
||||
static_assert(static_cast<Uint8>(::MobileGL::Wire::WindowKind::HostFrame) == 8);
|
||||
static_assert(static_cast<Uint8>(::MobileGL::Wire::SurfaceRefusal::HostFrameOnSetWindowHandle) ==
|
||||
static_cast<Uint8>(Server::SurfaceRefusalCode::HostFrameOnSetWindowHandle));
|
||||
static_assert(Server::kHostFrameWindowBackend > Server::kServerOwnedWindowBackend,
|
||||
"kHostFrameWindowBackend must not collide with the server-owned tag");
|
||||
// The frame's refusal codes ARE the wire's SurfaceRefusal (SurfaceControlFrame.h), pinned
|
||||
// value by value so a schema edit that renumbers either side fails here.
|
||||
using Server::SurfaceRefusalCode;
|
||||
@@ -94,6 +99,8 @@ namespace MobileGL::MG_Remote {
|
||||
case SurfaceWireError::AndroidNativeWindowArrived: return "AndroidNativeWindowArrived";
|
||||
case SurfaceWireError::ServerOwnedTokenNotZero: return "ServerOwnedTokenNotZero";
|
||||
case SurfaceWireError::ServerOwnedOnSetWindowHandle: return "ServerOwnedOnSetWindowHandle";
|
||||
case SurfaceWireError::HostFrameTokenNotZero: return "HostFrameTokenNotZero";
|
||||
case SurfaceWireError::HostFrameOnSetWindowHandle: return "HostFrameOnSetWindowHandle";
|
||||
}
|
||||
return "<unknown SurfaceWireError>";
|
||||
}
|
||||
@@ -167,6 +174,15 @@ namespace MobileGL::MG_Remote {
|
||||
}
|
||||
windowKind = ::MobileGL::Wire::WindowKind::ServerOwned;
|
||||
nativeToken = 0;
|
||||
} else if (frame.windowBackend == Server::kHostFrameWindowBackend) {
|
||||
// MOBILEGL_IPC_SURFACE=host: the frames are the DISPLAY HOST's, taken by the
|
||||
// server from the host frame bridge. As for the server-owned tag - a creation
|
||||
// only, and the token is 0 whatever the frame carried.
|
||||
if (frame.kind != SurfaceControlOp::CreateWindowSurface) {
|
||||
return SurfaceWireError::HostFrameOnSetWindowHandle;
|
||||
}
|
||||
windowKind = ::MobileGL::Wire::WindowKind::HostFrame;
|
||||
nativeToken = 0;
|
||||
} else if (!WireWindowKindForWindowBackend(
|
||||
static_cast<MG_Backend::WindowBackend>(frame.windowBackend), &windowKind)) {
|
||||
return SurfaceWireError::UnknownWindowKind;
|
||||
@@ -213,6 +229,21 @@ namespace MobileGL::MG_Remote {
|
||||
*frame = decoded;
|
||||
return SurfaceWireError::None;
|
||||
}
|
||||
if (op.windowKind() == ::MobileGL::Wire::WindowKind::HostFrame) {
|
||||
// MOBILEGL_IPC_SURFACE=host. As above: a creation only, and a token of 0
|
||||
// only - anything else is a value from the peer's window system trying to
|
||||
// cross (Rule G), which is corruption rather than a refusal.
|
||||
if (kind != SurfaceControlOp::CreateWindowSurface) {
|
||||
return SurfaceWireError::HostFrameOnSetWindowHandle;
|
||||
}
|
||||
if (op.nativeToken() != 0) {
|
||||
return SurfaceWireError::HostFrameTokenNotZero;
|
||||
}
|
||||
decoded.windowBackend = Server::kHostFrameWindowBackend;
|
||||
decoded.nativeToken = 0;
|
||||
*frame = decoded;
|
||||
return SurfaceWireError::None;
|
||||
}
|
||||
if (op.windowKind() == ::MobileGL::Wire::WindowKind::AndroidNativeWindow) {
|
||||
// The one refusal that is not corruption: the window kind is LEGAL and the token
|
||||
// is an ANativeWindow*, which names memory in the CLIENT's process. Real window
|
||||
@@ -225,10 +256,10 @@ namespace MobileGL::MG_Remote {
|
||||
}
|
||||
MG_Backend::WindowBackend backend;
|
||||
if (!WindowBackendForWireWindowKind(op.windowKind(), &backend)) {
|
||||
// THE UPPER BOUND IS THE LAST APPENDED KIND (P12: ServerOwned), for the reason
|
||||
// THE UPPER BOUND IS THE LAST APPENDED KIND (P12: HostFrame), for the reason
|
||||
// SurfaceControlOpForWireKind's bound gives.
|
||||
return ::flatbuffers::IsOutRange(op.windowKind(), ::MobileGL::Wire::WindowKind::None,
|
||||
::MobileGL::Wire::WindowKind::ServerOwned)
|
||||
::MobileGL::Wire::WindowKind::HostFrame)
|
||||
? SurfaceWireError::UnknownWindowKind
|
||||
: SurfaceWireError::WindowKindNamesNoBackend;
|
||||
}
|
||||
|
||||
@@ -68,6 +68,9 @@ namespace MobileGL::MG_Remote {
|
||||
// CreateWindowSurface only, and only with nativeToken 0:
|
||||
ServerOwnedTokenNotZero, // -> Fatal{ProtocolCorruption, "SurfaceOp.nativeToken"}, latched
|
||||
ServerOwnedOnSetWindowHandle, // -> a NAMED REFUSAL (reply ok=false), not a latch
|
||||
// MOBILEGL_IPC_SURFACE=host, the same two rules for the other on-screen shape:
|
||||
HostFrameTokenNotZero, // -> Fatal{ProtocolCorruption, "SurfaceOp.nativeToken"}, latched
|
||||
HostFrameOnSetWindowHandle, // -> a NAMED REFUSAL (reply ok=false), not a latch
|
||||
};
|
||||
|
||||
const char* SurfaceWireErrorName(SurfaceWireError error);
|
||||
|
||||
@@ -341,11 +341,12 @@ enum class WindowKind : uint8_t {
|
||||
Pbuffer = 5,
|
||||
MetalLayer = 6,
|
||||
ServerOwned = 7,
|
||||
HostFrame = 8,
|
||||
MIN = None,
|
||||
MAX = ServerOwned
|
||||
MAX = HostFrame
|
||||
};
|
||||
|
||||
inline const WindowKind (&EnumValuesWindowKind())[8] {
|
||||
inline const WindowKind (&EnumValuesWindowKind())[9] {
|
||||
static const WindowKind values[] = {
|
||||
WindowKind::None,
|
||||
WindowKind::AndroidNativeWindow,
|
||||
@@ -354,13 +355,14 @@ inline const WindowKind (&EnumValuesWindowKind())[8] {
|
||||
WindowKind::Surfaceless,
|
||||
WindowKind::Pbuffer,
|
||||
WindowKind::MetalLayer,
|
||||
WindowKind::ServerOwned
|
||||
WindowKind::ServerOwned,
|
||||
WindowKind::HostFrame
|
||||
};
|
||||
return values;
|
||||
}
|
||||
|
||||
inline const char * const *EnumNamesWindowKind() {
|
||||
static const char * const names[9] = {
|
||||
static const char * const names[10] = {
|
||||
"None",
|
||||
"AndroidNativeWindow",
|
||||
"X11",
|
||||
@@ -369,13 +371,14 @@ inline const char * const *EnumNamesWindowKind() {
|
||||
"Pbuffer",
|
||||
"MetalLayer",
|
||||
"ServerOwned",
|
||||
"HostFrame",
|
||||
nullptr
|
||||
};
|
||||
return names;
|
||||
}
|
||||
|
||||
inline const char *EnumNameWindowKind(WindowKind e) {
|
||||
if (::flatbuffers::IsOutRange(e, WindowKind::None, WindowKind::ServerOwned)) return "";
|
||||
if (::flatbuffers::IsOutRange(e, WindowKind::None, WindowKind::HostFrame)) return "";
|
||||
const size_t index = static_cast<size_t>(e);
|
||||
return EnumNamesWindowKind()[index];
|
||||
}
|
||||
@@ -386,35 +389,38 @@ enum class SurfaceRefusal : uint8_t {
|
||||
NoServerWindow = 2,
|
||||
SurfaceModeMismatch = 3,
|
||||
ServerOwnedOnSetWindowHandle = 4,
|
||||
HostFrameOnSetWindowHandle = 5,
|
||||
MIN = None,
|
||||
MAX = ServerOwnedOnSetWindowHandle
|
||||
MAX = HostFrameOnSetWindowHandle
|
||||
};
|
||||
|
||||
inline const SurfaceRefusal (&EnumValuesSurfaceRefusal())[5] {
|
||||
inline const SurfaceRefusal (&EnumValuesSurfaceRefusal())[6] {
|
||||
static const SurfaceRefusal values[] = {
|
||||
SurfaceRefusal::None,
|
||||
SurfaceRefusal::NoServerDisplay,
|
||||
SurfaceRefusal::NoServerWindow,
|
||||
SurfaceRefusal::SurfaceModeMismatch,
|
||||
SurfaceRefusal::ServerOwnedOnSetWindowHandle
|
||||
SurfaceRefusal::ServerOwnedOnSetWindowHandle,
|
||||
SurfaceRefusal::HostFrameOnSetWindowHandle
|
||||
};
|
||||
return values;
|
||||
}
|
||||
|
||||
inline const char * const *EnumNamesSurfaceRefusal() {
|
||||
static const char * const names[6] = {
|
||||
static const char * const names[7] = {
|
||||
"None",
|
||||
"NoServerDisplay",
|
||||
"NoServerWindow",
|
||||
"SurfaceModeMismatch",
|
||||
"ServerOwnedOnSetWindowHandle",
|
||||
"HostFrameOnSetWindowHandle",
|
||||
nullptr
|
||||
};
|
||||
return names;
|
||||
}
|
||||
|
||||
inline const char *EnumNameSurfaceRefusal(SurfaceRefusal e) {
|
||||
if (::flatbuffers::IsOutRange(e, SurfaceRefusal::None, SurfaceRefusal::ServerOwnedOnSetWindowHandle)) return "";
|
||||
if (::flatbuffers::IsOutRange(e, SurfaceRefusal::None, SurfaceRefusal::HostFrameOnSetWindowHandle)) return "";
|
||||
const size_t index = static_cast<size_t>(e);
|
||||
return EnumNamesSurfaceRefusal()[index];
|
||||
}
|
||||
|
||||
@@ -274,6 +274,12 @@ enum WindowKind : ubyte {
|
||||
// SurfaceView) and has none of its own to name, so `nativeToken` is always 0 and no pointer
|
||||
// crosses (Rule G/H). Legal on CreateWindowSurface only; SetWindowHandle may not name it.
|
||||
ServerOwned = 7,
|
||||
// P12, appended: the OTHER on-screen shape, and its mirror image. The client names no
|
||||
// window here either - but the frames are the DISPLAY HOST's: it allocates them, offers
|
||||
// each one over the host frame bridge, and puts them on the glass itself, while the
|
||||
// server draws into them. `nativeToken` is always 0, as for ServerOwned, and it is legal
|
||||
// on CreateWindowSurface only.
|
||||
HostFrame = 8,
|
||||
}
|
||||
|
||||
// P12, appended: WHY A SURFACE OP WAS DECLINED, so the client can name the refusal in its own log
|
||||
@@ -285,6 +291,7 @@ enum SurfaceRefusal : ubyte {
|
||||
NoServerWindow = 2, // the server owns a display, but no window came within its wait
|
||||
SurfaceModeMismatch = 3, // the session's surface mode (on-screen / offscreen) is the other one
|
||||
ServerOwnedOnSetWindowHandle = 4, // SetWindowHandle named the server's own window
|
||||
HostFrameOnSetWindowHandle = 5, // SetWindowHandle named the display host's frames
|
||||
}
|
||||
|
||||
table SurfaceOp {
|
||||
|
||||
@@ -60,6 +60,7 @@ namespace MobileGL::MG_Remote::Server {
|
||||
case SurfaceRefusalCode::NoServerWindow: return "NoServerWindow";
|
||||
case SurfaceRefusalCode::SurfaceModeMismatch: return "SurfaceModeMismatch";
|
||||
case SurfaceRefusalCode::ServerOwnedOnSetWindowHandle: return "ServerOwnedOnSetWindowHandle";
|
||||
case SurfaceRefusalCode::HostFrameOnSetWindowHandle: return "HostFrameOnSetWindowHandle";
|
||||
}
|
||||
return "<unknown SurfaceRefusalCode>";
|
||||
}
|
||||
|
||||
@@ -105,6 +105,7 @@ namespace MobileGL::MG_Remote::Server {
|
||||
NoServerWindow = 2, // a display, but no window within the wait
|
||||
SurfaceModeMismatch = 3, // D4: the session's surface mode is the other one
|
||||
ServerOwnedOnSetWindowHandle = 4, // SetWindowHandle named the server's own window
|
||||
HostFrameOnSetWindowHandle = 5, // SetWindowHandle named the display host's frames
|
||||
};
|
||||
|
||||
const char* SurfaceRefusalCodeName(SurfaceRefusalCode code);
|
||||
|
||||
Reference in New Issue
Block a user