mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 18:13:23 +09:00
[MG_Remote, MG_Test, scripts] (P12): WindowKind::ServerOwned on the wire - control revision 3 with SurfaceRefusal and SurfaceReply width/height/refusal, the codec's ServerOwned rules (creation only, token 0, SetWindowHandle a named refusal) on a frame-local marker, and the non-zero-token latch row
This commit is contained in:
@@ -56,6 +56,26 @@ namespace MobileGL::MG_Remote {
|
||||
static_cast<Uint8>(::MobileGL::Wire::SurfaceOpKind::SetWindowHandle) == 10 &&
|
||||
static_cast<Uint8>(::MobileGL::Wire::SurfaceOpKind::InitCapabilities) == 11);
|
||||
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);
|
||||
// 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;
|
||||
static_assert(static_cast<Uint8>(SurfaceRefusalCode::None) ==
|
||||
static_cast<Uint8>(::MobileGL::Wire::SurfaceRefusal::None));
|
||||
static_assert(static_cast<Uint8>(SurfaceRefusalCode::NoServerDisplay) ==
|
||||
static_cast<Uint8>(::MobileGL::Wire::SurfaceRefusal::NoServerDisplay));
|
||||
static_assert(static_cast<Uint8>(SurfaceRefusalCode::NoServerWindow) ==
|
||||
static_cast<Uint8>(::MobileGL::Wire::SurfaceRefusal::NoServerWindow));
|
||||
static_assert(static_cast<Uint8>(SurfaceRefusalCode::SurfaceModeMismatch) ==
|
||||
static_cast<Uint8>(::MobileGL::Wire::SurfaceRefusal::SurfaceModeMismatch));
|
||||
static_assert(static_cast<Uint8>(SurfaceRefusalCode::ServerOwnedOnSetWindowHandle) ==
|
||||
static_cast<Uint8>(::MobileGL::Wire::SurfaceRefusal::ServerOwnedOnSetWindowHandle));
|
||||
// The frame-local ServerOwned tag names no WindowBackend, by construction (D2: no
|
||||
// BackendObject.h enumerator for it - that header is in the pull build, gate G1).
|
||||
static_assert(Server::kServerOwnedWindowBackend >=
|
||||
static_cast<Int>(MG_Backend::WindowBackend::WindowBackendCount),
|
||||
"kServerOwnedWindowBackend collides with a real WindowBackend");
|
||||
|
||||
bool OpNeedsAWindowBackend(SurfaceControlOp op) {
|
||||
return op == SurfaceControlOp::CreateWindowSurface || op == SurfaceControlOp::SetWindowHandle;
|
||||
@@ -72,6 +92,8 @@ namespace MobileGL::MG_Remote {
|
||||
case SurfaceWireError::UnknownWindowKind: return "UnknownWindowKind";
|
||||
case SurfaceWireError::MetalLayerArrived: return "MetalLayerArrived";
|
||||
case SurfaceWireError::AndroidNativeWindowArrived: return "AndroidNativeWindowArrived";
|
||||
case SurfaceWireError::ServerOwnedTokenNotZero: return "ServerOwnedTokenNotZero";
|
||||
case SurfaceWireError::ServerOwnedOnSetWindowHandle: return "ServerOwnedOnSetWindowHandle";
|
||||
}
|
||||
return "<unknown SurfaceWireError>";
|
||||
}
|
||||
@@ -130,17 +152,28 @@ namespace MobileGL::MG_Remote {
|
||||
: SurfaceWireError::InprocOnlyOpOnTheWire;
|
||||
}
|
||||
::MobileGL::Wire::WindowKind windowKind = ::MobileGL::Wire::WindowKind::None;
|
||||
Uint64 nativeToken = frame.nativeToken;
|
||||
if (frame.kind == SurfaceControlOp::CreatePbufferSurface) {
|
||||
// The op implies the shape; the frame carries no windowBackend for it.
|
||||
windowKind = ::MobileGL::Wire::WindowKind::Pbuffer;
|
||||
} else if (OpNeedsAWindowBackend(frame.kind)) {
|
||||
if (!WireWindowKindForWindowBackend(
|
||||
static_cast<MG_Backend::WindowBackend>(frame.windowBackend), &windowKind)) {
|
||||
if (frame.windowBackend == Server::kServerOwnedWindowBackend) {
|
||||
// P12 (D2): the SERVER's window. Only a creation may ask for it - the server picks
|
||||
// the window, so there is nothing for SetWindowHandle to set - and the token is 0
|
||||
// whatever the frame carried: the client's own window value (it may have none)
|
||||
// never reaches the wire (Rule G/H).
|
||||
if (frame.kind != SurfaceControlOp::CreateWindowSurface) {
|
||||
return SurfaceWireError::ServerOwnedOnSetWindowHandle;
|
||||
}
|
||||
windowKind = ::MobileGL::Wire::WindowKind::ServerOwned;
|
||||
nativeToken = 0;
|
||||
} else if (!WireWindowKindForWindowBackend(
|
||||
static_cast<MG_Backend::WindowBackend>(frame.windowBackend), &windowKind)) {
|
||||
return SurfaceWireError::UnknownWindowKind;
|
||||
}
|
||||
}
|
||||
const auto op = ::MobileGL::Wire::CreateSurfaceOp(
|
||||
*builder, frame.seq, kind, frame.display, frame.surface, windowKind, frame.nativeToken,
|
||||
*builder, frame.seq, kind, frame.display, frame.surface, windowKind, nativeToken,
|
||||
frame.width, frame.height, frame.swapInterval, frame.readSurface, frame.context);
|
||||
const auto envelope = ::MobileGL::Wire::CreateCtrlEnvelope(*builder, ::MobileGL::Wire::CtrlMsg::SurfaceOp, op.Union());
|
||||
::MobileGL::Wire::FinishCtrlEnvelopeBuffer(*builder, envelope);
|
||||
@@ -163,6 +196,23 @@ namespace MobileGL::MG_Remote {
|
||||
decoded.height = op.height();
|
||||
decoded.swapInterval = op.swapInterval();
|
||||
if (OpNeedsAWindowBackend(kind)) {
|
||||
if (op.windowKind() == ::MobileGL::Wire::WindowKind::ServerOwned) {
|
||||
// P12 (D2). Asked BEFORE the Android refusal below, which it is not: the window is
|
||||
// the server's own. A creation only (SetWindowHandle may not name it - a named
|
||||
// refusal, not corruption: nothing about the bytes is malformed), and a token of 0
|
||||
// only (anything else is a value from the peer's window system trying to cross,
|
||||
// Rule G - that one is corruption).
|
||||
if (kind != SurfaceControlOp::CreateWindowSurface) {
|
||||
return SurfaceWireError::ServerOwnedOnSetWindowHandle;
|
||||
}
|
||||
if (op.nativeToken() != 0) {
|
||||
return SurfaceWireError::ServerOwnedTokenNotZero;
|
||||
}
|
||||
decoded.windowBackend = Server::kServerOwnedWindowBackend;
|
||||
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
|
||||
@@ -175,8 +225,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
|
||||
// SurfaceControlOpForWireKind's bound gives.
|
||||
return ::flatbuffers::IsOutRange(op.windowKind(), ::MobileGL::Wire::WindowKind::None,
|
||||
::MobileGL::Wire::WindowKind::MetalLayer)
|
||||
::MobileGL::Wire::WindowKind::ServerOwned)
|
||||
? SurfaceWireError::UnknownWindowKind
|
||||
: SurfaceWireError::WindowKindNamesNoBackend;
|
||||
}
|
||||
@@ -189,8 +241,10 @@ namespace MobileGL::MG_Remote {
|
||||
|
||||
void EncodeSurfaceReplyFrame(const SurfaceControlFrame& frame,
|
||||
flatbuffers::FlatBufferBuilder* builder) {
|
||||
const auto reply = ::MobileGL::Wire::CreateSurfaceReply(*builder, frame.seq, frame.ok, frame.eglMajor,
|
||||
frame.eglMinor, /*defaultFb=*/0, frame.eventHead);
|
||||
// P12: the reply's surface geometry and refusal (SurfaceReply.width/height/refusal).
|
||||
const auto reply = ::MobileGL::Wire::CreateSurfaceReply(
|
||||
*builder, frame.seq, frame.ok, frame.eglMajor, frame.eglMinor, /*defaultFb=*/0, frame.eventHead,
|
||||
frame.width, frame.height, static_cast<::MobileGL::Wire::SurfaceRefusal>(frame.refusal));
|
||||
const auto envelope =
|
||||
::MobileGL::Wire::CreateCtrlEnvelope(*builder, ::MobileGL::Wire::CtrlMsg::SurfaceReply, reply.Union());
|
||||
::MobileGL::Wire::FinishCtrlEnvelopeBuffer(*builder, envelope);
|
||||
@@ -202,6 +256,9 @@ namespace MobileGL::MG_Remote {
|
||||
frame->eglMajor = reply.eglMajor();
|
||||
frame->eglMinor = reply.eglMinor();
|
||||
frame->eventHead = reply.eventHead();
|
||||
frame->width = reply.width();
|
||||
frame->height = reply.height();
|
||||
frame->refusal = static_cast<Uint8>(reply.refusal());
|
||||
}
|
||||
|
||||
MobileGLResult ServerApplyWireSurfaceOp(const ::MobileGL::Wire::SurfaceOp& op, SurfaceControlFrame* replyOut) {
|
||||
@@ -211,10 +268,39 @@ namespace MobileGL::MG_Remote {
|
||||
if (SessionLatched()) return MOBILEGL_ERR_PROTOCOL_MISMATCH;
|
||||
SurfaceControlFrame frame;
|
||||
const SurfaceWireError error = DecodeWireSurfaceOp(op, &frame);
|
||||
if (error == SurfaceWireError::ServerOwnedOnSetWindowHandle) {
|
||||
// P12 (D2): A NAMED REFUSAL, NOT A LATCH. Nothing in the bytes is malformed - the op
|
||||
// simply asks for something the protocol does not do (the server chooses its own
|
||||
// window at CreateWindowSurface; there is nothing for SetWindowHandle to set). So it
|
||||
// is answered ok=false, by name, and the session goes on, armed or not.
|
||||
MGLOG_E("MG_Remote server: Refuse ServerOwned on SetWindowHandle - a wire SetWindowHandle "
|
||||
"(seq %llu) named WindowKind::ServerOwned. The server-owned window is chosen by the "
|
||||
"server when CreateWindowSurface asks for it; SetWindowHandle may not name it "
|
||||
"(refusal ServerOwnedOnSetWindowHandle, session not latched)",
|
||||
static_cast<unsigned long long>(op.seq()));
|
||||
if (replyOut != nullptr) {
|
||||
*replyOut = SurfaceControlFrame{};
|
||||
replyOut->seq = op.seq();
|
||||
replyOut->ok = false;
|
||||
replyOut->refusal = static_cast<Uint8>(Server::SurfaceRefusalCode::ServerOwnedOnSetWindowHandle);
|
||||
}
|
||||
return MOBILEGL_ERR_UNSUPPORTED;
|
||||
}
|
||||
if (error != SurfaceWireError::None) {
|
||||
// PH-1 (3): the op's bytes are the peer's. Each of the three refusals latches in an
|
||||
// armed session child and the op is answered with no dispatch; unarmed they die.
|
||||
if (error == SurfaceWireError::AndroidNativeWindowArrived) {
|
||||
if (error == SurfaceWireError::ServerOwnedTokenNotZero) {
|
||||
// P12 (D2): WindowKind::ServerOwned names the SERVER's window, so its token is 0 by
|
||||
// definition. A non-zero one is a value from the peer's window system trying to
|
||||
// cross (Rule G) - the peer's corrupt bytes, latched like the rows beside it.
|
||||
(void)SessionLatch(MGFatalFamily::ProtocolCorruption,
|
||||
"MGPipe: Fatal{ProtocolCorruption, \"SurfaceOp.nativeToken\"} - a wire %s named "
|
||||
"WindowKind::ServerOwned with native token 0x%llx. The server-owned window is the "
|
||||
"server's own and its token is always 0: no value from the client's window system "
|
||||
"crosses (Rule G)",
|
||||
::MobileGL::Wire::EnumNameSurfaceOpKind(op.kind()),
|
||||
static_cast<unsigned long long>(op.nativeToken()));
|
||||
} else if (error == SurfaceWireError::AndroidNativeWindowArrived) {
|
||||
(void)SessionLatch(MGFatalFamily::UnmigratedSurface,
|
||||
"MGPipe: Fatal{UnmigratedSurface, \"AndroidNativeWindow@P12\"} - a wire "
|
||||
"SurfaceOp (%s) named an ANativeWindow*, which is a pointer into the "
|
||||
|
||||
Reference in New Issue
Block a user