diff --git a/MobileGL/MG_Remote/Protocol/SurfaceOpCodec.cpp b/MobileGL/MG_Remote/Protocol/SurfaceOpCodec.cpp index 608bd870..f5a31d68 100644 --- a/MobileGL/MG_Remote/Protocol/SurfaceOpCodec.cpp +++ b/MobileGL/MG_Remote/Protocol/SurfaceOpCodec.cpp @@ -58,6 +58,11 @@ namespace MobileGL::MG_Remote { static_assert(static_cast(::MobileGL::Wire::WindowKind::MetalLayer) == 6); // P12's append, on the same terms: the value is wire ABI. static_assert(static_cast(::MobileGL::Wire::WindowKind::ServerOwned) == 7); + static_assert(static_cast(::MobileGL::Wire::WindowKind::HostFrame) == 8); + static_assert(static_cast(::MobileGL::Wire::SurfaceRefusal::HostFrameOnSetWindowHandle) == + static_cast(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 ""; } @@ -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(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; } diff --git a/MobileGL/MG_Remote/Protocol/SurfaceOpCodec.h b/MobileGL/MG_Remote/Protocol/SurfaceOpCodec.h index 0796e24e..b7113bba 100644 --- a/MobileGL/MG_Remote/Protocol/SurfaceOpCodec.h +++ b/MobileGL/MG_Remote/Protocol/SurfaceOpCodec.h @@ -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); diff --git a/MobileGL/MG_Remote/Protocol/generated/protocol_generated.h b/MobileGL/MG_Remote/Protocol/generated/protocol_generated.h index dc1f997c..fd6d279a 100644 --- a/MobileGL/MG_Remote/Protocol/generated/protocol_generated.h +++ b/MobileGL/MG_Remote/Protocol/generated/protocol_generated.h @@ -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(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(e); return EnumNamesSurfaceRefusal()[index]; } diff --git a/MobileGL/MG_Remote/Protocol/protocol.fbs b/MobileGL/MG_Remote/Protocol/protocol.fbs index d4cf2852..212944a6 100644 --- a/MobileGL/MG_Remote/Protocol/protocol.fbs +++ b/MobileGL/MG_Remote/Protocol/protocol.fbs @@ -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 { diff --git a/MobileGL/MG_Remote/Server/SurfaceControlFrame.cpp b/MobileGL/MG_Remote/Server/SurfaceControlFrame.cpp index 2f5c5dbd..d4230a1f 100644 --- a/MobileGL/MG_Remote/Server/SurfaceControlFrame.cpp +++ b/MobileGL/MG_Remote/Server/SurfaceControlFrame.cpp @@ -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 ""; } diff --git a/MobileGL/MG_Remote/Server/SurfaceControlFrame.h b/MobileGL/MG_Remote/Server/SurfaceControlFrame.h index 7d03552b..a5835453 100644 --- a/MobileGL/MG_Remote/Server/SurfaceControlFrame.h +++ b/MobileGL/MG_Remote/Server/SurfaceControlFrame.h @@ -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);