//! The scanout wire protocol — what the compositor says to a native scanout driver (e.g. //! virtio-gpu) over `/protocol/scanout` to put a composited frame on screen. The driver owns //! the panel and the shared scanout surface it handed the compositor (via the display //! service's `attach_scanout`); the compositor composites into that surface, then asks the //! driver to present a damaged rectangle. Tiny by design — one present request. Separate from //! the display protocol because the directions differ: clients call the compositor over //! `/protocol/display`; the compositor calls the driver over `/protocol/scanout`. See //! docs/display-v2.md. //! //! One scanout per driver instance, so `Header.target` is always 0. const envelope = @import("envelope"); /// `present(rect)`: put the given rectangle of the shared scanout surface on the panel (on /// virtio-gpu: transfer-to-host of the region, then a fenced resource flush). pub const Present = extern struct { x: u32 = 0, y: u32 = 0, width: u32 = 0, height: u32 = 0, }; /// `set_mode(width, height)`: change the scanout resolution — the shared surface is sized to /// the largest mode, so this just re-points the scanout rectangle; the surface is unchanged. pub const SetMode = extern struct { width: u32, height: u32 }; /// One offered display mode. pub const Mode = extern struct { width: u32, height: u32 }; pub const max_modes = 4; /// The answer to `get_modes`: a small fixed list of modes. The success/failure verdict is /// the reply's `Status`, so this carries only the modes. pub const Modes = extern struct { count: u32 = 0, _padding: u32 = 0, modes: [max_modes]Mode = @splat(.{ .width = 0, .height = 0 }), }; pub const Protocol = envelope.Define(.{ .name = "scanout", .version = 1, .operations = &.{ .{ .name = "present", .request = Present }, .{ .name = "get_modes", .reply = Modes }, .{ .name = "set_mode", .request = SetMode }, }, }); pub const Operation = Protocol.Operation; /// The call floor, like every synchronous protocol. This module used to declare /// 64 — the *push* floor — which was simply wrong: nothing here is pushed, and a /// provider sizing its receive buffer to 64 refuses (`-E2BIG`) any caller that /// sends up to the floor it is entitled to. pub const message_maximum: usize = Protocol.message_maximum;