#ifndef VGPU_STREAM_ENGINE_H #define VGPU_STREAM_ENGINE_H /* stream.h — OS-agnostic streaming protocol over the shared contract. * Declares the neutral region-view handle (resolved contract pointers) and the * seqlock publish / control-reconcile API. No platform headers: the engine * operates purely on the contract; a platform layer (e.g. src/stream/win32/) * builds the region and hands its pointers in as a vgpu_region_view. */ #include #include "vgpu_stream.h" /* contract: producer/control types, slot geometry */ /* Neutral view of the live contract: the three resolved blocks the engine * publishes into / reconciles against. The platform region owns the backing * memory; this is a borrowed view (no ownership). */ typedef struct { vgpu_producer_t* producer; vgpu_control_t* control; uint8_t* ring; } vgpu_region_view; /* Resolved view of the control block after a clean generation read. */ typedef struct { uint32_t gen; /* even generation that was read (for ctrl_ack) */ uint32_t desired_state; /* VGPU_CMD_* */ uint32_t target_fps; uint32_t draw_cursor; uint32_t full_frame_req; uint32_t consumer_tick; uint32_t attached; } vgpu_control_view; /* Seqlock-publish a tight BGRA frame into the next ring slot. * Clamps by SLOT_STRIDE (rejects frames that do not fit). Writes desc[], * bumps frame_id, release-stores latest. Returns 0 on publish, 1 if dropped * (frame too large for a slot). */ int vgpu_publish_frame(const vgpu_region_view* rv, const uint8_t* tight_bgra, uint32_t width, uint32_t height, uint64_t timestamp_ns); /* Read control block under its generation seqlock (bounded retry). Returns 1 * on a clean read (view filled), 0 if the writer kept it busy past the limit. */ int vgpu_control_read(const vgpu_region_view* rv, vgpu_control_view* out); /* Echo the applied generation back to the host. */ void vgpu_publish_ctrl_ack(const vgpu_region_view* rv, uint32_t gen); /* Status / lifecycle helpers (cold line). */ void vgpu_set_status(const vgpu_region_view* rv, uint32_t status); void vgpu_set_backend(const vgpu_region_view* rv, uint32_t backend); void vgpu_set_error(const vgpu_region_view* rv, uint32_t error_code); void vgpu_set_applied_fps(const vgpu_region_view* rv, uint32_t fps); void vgpu_bump_run_epoch(const vgpu_region_view* rv); void vgpu_tick_heartbeat(const vgpu_region_view* rv); void vgpu_publish_full_frame_ack(const vgpu_region_view* rv, uint32_t req); /* Publish the on-screen cursor position (host-RO). Position is sensor data and is * reported independent of control.draw_cursor (host may draw its own overlay even when the * producer does not composite the cursor). x,y are screen coords (signed; multi-monitor may * be negative); visible!=0 when the cursor is shown. Packs x|y into one 8-aligned 64-bit * field (single atomic store) and bumps cursor_seq last. */ void vgpu_publish_cursor(const vgpu_region_view* rv, int32_t x, int32_t y, uint32_t visible); /* Publish Tier-1 cursor shape data (host-RO), written under the same cursor_seq gate as * vgpu_publish_cursor: call this BEFORE vgpu_publish_cursor so the position publish bumps * cursor_seq last and gates the whole cursor line consistently. hot_x/hot_y are the glyph * hotspot; gw/gh are glyph dims; cursor_id is a VGPU_CURSOR_ID_* shape identity. */ void vgpu_publish_cursor_shape(const vgpu_region_view* rv, uint32_t hot_x, uint32_t hot_y, uint32_t gw, uint32_t gh, uint32_t cursor_id); /* Publish the monotonic timestamp (ns) of the last scene-content change. Single 8-aligned * atomic store (heartbeat pattern). The producer reports the raw stamp only; the host derives * "ms idle" by subtracting from its own clock — no behavioural distillation in the producer. */ void vgpu_publish_content_change(const vgpu_region_view* rv, uint64_t change_ns); /* Publish display geometry under the geom_seq seqlock (odd/even, like the frame seqlock). * Sampled rarely (session start + reactive resample on desc-size delta / backend recreate), * read by the host with bounded retry. virt_* is the virtual-desktop bbox (interprets negative * cursor_pos); cap_x/cap_y is the captured output's origin in virtual-desktop coords (the * captured surface SIZE comes from desc.width/height, not from here). dpi/refresh_mhz describe * the captured output (96=100% / milli-Hz; 0=unknown). */ void vgpu_publish_geometry(const vgpu_region_view* rv, int32_t virt_x, int32_t virt_y, uint32_t virt_w, uint32_t virt_h, int32_t cap_x, int32_t cap_y, uint32_t dpi, uint32_t refresh_mhz); #endif /* VGPU_STREAM_ENGINE_H */