mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-17 00:28:31 +09:00
109 lines
6.1 KiB
C++
109 lines
6.1 KiB
C++
// MobileGL - MobileGL/MG_Remote/CapsCodec.h
|
|
// 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
|
|
|
|
// The MGPCaps snapshot's serializers, and the CallMask encoding. Owner: package w1 (the two
|
|
// blob codecs) and s1 (the handshake asserts). Signatures by c0.
|
|
//
|
|
// MGPCaps (MG_Pipe/MGPipeTypes.h:126-139) has four members. Two are flat and cross by memcpy
|
|
// (DynamicBackendParameters Dynamic, Uint64 CallMask); two are MGPBlobRefs over containers
|
|
// and HAVE NO SERIALIZER IN THE TREE - the header says so itself at MGPipeTypes.h:134-136,
|
|
// "Their serializers land with the transport (P5)". They are:
|
|
//
|
|
// FormatCapabilities -> FormatCapabilityCache (MG_Backend/BackendObject.h:93-98):
|
|
// FullCaps + CaveatCaps (bitfield tables) + SampleCounts, a Vector<Int> per
|
|
// (target, format) pair. The Vector is why this cannot be a memcpy.
|
|
// RendererInfo -> RendererInfo (MG_Util/Types.h:317): three Strings, an
|
|
// Optional<String>, and a Vector<GLExtension> inside GLInfo.
|
|
//
|
|
// THE ABI RULING (table 0). MGPCaps has only a COMPOSITIONAL size assertion
|
|
// (MGPipeTypes.h:145-146) because DynamicBackendParameters still carries SizeT and GLenum
|
|
// members - P0.5's fixed-width rewrite did not happen. P5 does NOT rewrite it. Instead the
|
|
// handshake asserts that both peers agree on sizeof(DynamicBackendParameters),
|
|
// sizeof(MGPCaps) and the build fingerprint, and Fatal{AbiMismatch} otherwise. P6's spawn is
|
|
// same-machine and same-binary, so it inherits this unchanged; the fixed-width rewrite is on
|
|
// P7's account.
|
|
|
|
#pragma once
|
|
#include <Includes.h>
|
|
|
|
#include <MG_Backend/BackendObject.h>
|
|
#include <MG_Pipe/MGPipe.h>
|
|
|
|
#include "Transport/SessionRings.h" // AbiFingerprintInputs / MixAbiFingerprint
|
|
|
|
namespace MobileGL::MG_Remote {
|
|
|
|
// ---- CallMask's layout (c0's ruling, extending R-8) ---------------------------------
|
|
//
|
|
// R-8 requires the client's liveness gates - MGPipeResourceSubsystemEnabled() and
|
|
// P4aFamilyHasItsConsumer() - to answer from MGPCaps::CallMask instead of from
|
|
// MGPipeGetResourceOps(), because that op table is the SERVER's registration: under
|
|
// inproc a client reading it is right by accident, and under spawn it is null and five
|
|
// whole record families silently emit nothing.
|
|
//
|
|
// But CallMask as declared carries only the nine MGPCapBit FEATURE bits
|
|
// (MGPipeTypes.h:108-124) and has no per-family bit at all, so "read the CallMask" was
|
|
// not yet an implementable instruction. It is now:
|
|
//
|
|
// bits 0..8 MGPCapBit, unchanged. kCapNeedsHostIndexBytes and kCapNeedsHostUboBytes
|
|
// are BOTH ZERO in P5 by ruling (table 0), which is what keeps every
|
|
// MGHostSpan out of the first IPC frame.
|
|
// bits 9..31 reserved for further MGPCapBits.
|
|
// bits 32..47 THE CONSUMER MASK: bit (32 + n) means "the server has a consumer for
|
|
// MGPipe subsystem bit n" - i.e. the server's own subsystem mask, shifted.
|
|
// Sixteen bits covers bits 0..12 allocated through P4a with room to P8.
|
|
// bits 48..63 reserved.
|
|
//
|
|
// protocol.fbs:94's `tableSlotMask: ulong` is DELETED rather than renamed (R-8 offered
|
|
// either). Two reasons, and the second is decisive: ARCHITECTURE.md:114 says CallMask
|
|
// REPLACES "is this table slot null" as the capability probe, so a field whose comment is
|
|
// "which GLFunctionsTable slots the peer registered" re-introduces exactly what it
|
|
// replaced; and GLFunctionsTable has SIXTY-NINE function-pointer slots
|
|
// (BackendObject.h:117-292), so a 64-bit mask cannot address it and never could.
|
|
inline constexpr Uint32 kMGCapsConsumerBitShift = 32;
|
|
inline constexpr Uint64 kMGCapsConsumerMask = 0xFFFFull << kMGCapsConsumerBitShift;
|
|
|
|
// Server side: fold the subsystems this server actually consumes into a CallMask.
|
|
inline constexpr Uint64 MGCapsConsumerBits(Uint64 subsystemMask) {
|
|
return (subsystemMask & 0xFFFFull) << kMGCapsConsumerBitShift;
|
|
}
|
|
|
|
// Client side: the ONE legal spelling of "does the server consume this family".
|
|
// `subsystemBit` is a kMGPipeSubsystem* constant (MG_Pipe/MGPipe.h), not an index.
|
|
inline constexpr Bool MGCapsServerConsumes(Uint64 callMask, Uint64 subsystemBit) {
|
|
return (callMask & MGCapsConsumerBits(subsystemBit)) != 0;
|
|
}
|
|
|
|
// ---- the two blob codecs ------------------------------------------------------------
|
|
//
|
|
// Byte-stable within one build; the handshake's fingerprint is what makes that enough.
|
|
// Both decoders must tolerate a truncated or over-long buffer by returning false, never
|
|
// by reading past `size`: these bytes arrive over the wire.
|
|
Bool EncodeFormatCapabilities(const MG_Backend::FormatCapabilityCache& cache, Vector<Uint8>& out);
|
|
Bool DecodeFormatCapabilities(const void* bytes, Uint64 size, MG_Backend::FormatCapabilityCache& out);
|
|
|
|
Bool EncodeRendererInfo(const RendererInfo& info, Vector<Uint8>& out);
|
|
Bool DecodeRendererInfo(const void* bytes, Uint64 size, RendererInfo& out);
|
|
|
|
// ---- the ABI assertion the handshake carries ----------------------------------------
|
|
//
|
|
// The inputs, as this build sees them: sizeof(DynamicBackendParameters), sizeof(MGPCaps),
|
|
// sizeof(GLFunctionsTable), the format-capability table's extents, the two caps-blob codec
|
|
// versions, MGPWireOp::kOpCount, the protocol ABI version and the compile-time git stamp.
|
|
// Public so that the sensitivity control can pin every one of them to the real value AND
|
|
// perturb them one at a time through the same mixer the handshake uses.
|
|
Transport::AbiFingerprintInputs CapsAbiFingerprintInputs();
|
|
|
|
// What Hello/Welcome carry and compare: EXACTLY Transport::MixAbiFingerprint(
|
|
// CapsAbiFingerprintInputs()) - one implementation, no second hash (ID-46 finding 6). A
|
|
// mismatch is Fatal{AbiMismatch} and never a downgrade, because every alternative silently
|
|
// reads one struct as another.
|
|
Uint64 CapsAbiFingerprint();
|
|
|
|
} // namespace MobileGL::MG_Remote
|