2026-06-17 12:55:19 +03:00
|
|
|
#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 <stdint.h>
|
|
|
|
|
#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);
|
|
|
|
|
|
2026-06-18 22:06:55 +03:00
|
|
|
/* 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);
|
|
|
|
|
|
2026-06-17 12:55:19 +03:00
|
|
|
#endif /* VGPU_STREAM_ENGINE_H */
|