Skip to main content

Module resample

Module resample 

Source
Expand description

Pointer-event resampling + deadline-aware pacing helpers shared by the mobile shells.

§What lives here

  • PointerResampler — a pure-logic, host-testable buffer of raw pointer samples (logical coords + a shell-supplied monotonic timestamp) that emits an interpolated Move position at each frame boundary (frame_time − SAMPLE_OFFSET_NANOS) with a Flutter-parity half-frame prediction window. Down/Up/ Cancel phase transitions pass through losslessly — never synthesized, never dropped, never repositioned — so only Move positions are ever resampled (Flutter’s PointerEventResampler contract, adapted). Samples are kept in one lane per PointerId, so simultaneous contacts are each resampled along their own path and never mix.
  • frame_interval_nanos / deadline_overrun — the deadline-aware scheduling helpers: estimate a frame-target budget from the tick-to-tick timestamp delta, and decide whether a frame’s measured work overran it. Instrumentation only — no work-dropping heuristics live here.

§Layering choice

Like crate::frame_gate and crate::perf, this is shell-owned by design and lives in frust-shell-common: it is platform-agnostic, contains no unsafe, no FFI, and no clock read of its own — every timestamp is handed in by the shell (which owns the monotonic clock), keeping this whole module deterministically unit-testable on the host. It compiles unchanged on every target (host / aarch64-linux-android / iOS), preserving the crate’s zero-unsafe, compiles-everywhere charter (see docs/ARCHITECTURE.md’s Layer Dependencies).

§Clock domain

The resampler is domain-agnostic: it only ever differences two timestamps, so a shell may stamp both the raw samples (PointerResampler::push) and the per-frame sample query (PointerResampler::resample) from any single monotonic source of its choosing, as long as both come from the same source. The mobile shells use a per-handle Instant epoch for this (decoupled from the vsync FrameTime clock that drives animation), so a sample stamped at touch arrival and the frame’s sample-time are always comparable.

Structs§

PointerResampler
Buffers raw pointer samples and emits frame-boundary-resampled events, one independent lane per PointerId. See the module docs for the interpolation/prediction contract; construct one per app handle and drive it from the shell’s touch and frame paths.
RawPointerSample
One raw pointer contact as delivered by a platform touch entry point, before resampling: which contact it is, the phase transition, the logical (density-independent) position the shell already converted, the button (always PointerButton::Primary for touch), and a shell-supplied monotonic timestamp (see the module’s Clock domain note).
ResampledPointer
One resampled event and the contact it belongs to — what PointerResampler::resample emits, so the shell can rebuild the InputEvent::PointerContact carrier for it.

Constants§

DEFAULT_REFRESH_INTERVAL_NANOS
Fallback frame-target interval (60Hz) used by frame_interval_nanos when there is no prior tick or the tick-to-tick delta is implausible.
MAX_PLAUSIBLE_INTERVAL_NANOS
Upper plausibility bound for a tick-to-tick interval (100ms ≈ a 10Hz floor): a larger delta (a long idle across skipped ticks, a resumed app) is treated as non-representative and replaced by DEFAULT_REFRESH_INTERVAL_NANOS.
MIN_PLAUSIBLE_INTERVAL_NANOS
Lower plausibility bound for a tick-to-tick interval (1ms ≈ a 1000Hz ceiling): a smaller delta is treated as a clock glitch and replaced by DEFAULT_REFRESH_INTERVAL_NANOS.
NO_RESAMPLE_VAR
The kill-switch environment/compile-time variable: when set to any non-"0" value, PointerResampler::new yields a disabled resampler that delivers every raw sample straight through in arrival order (pre- resampling behavior verbatim). Mirrors FRUST_NO_FRAME_GATE’s compile-time- or-runtime parsing exactly.
PREDICTION_WINDOW_NANOS
The forward-prediction clamp, in nanoseconds: when the sample instant runs past the newest buffered sample (the finger paused, or its samples lag the display), the position is extrapolated along the last segment’s velocity but never more than this far ahead of the newest sample.
SAMPLE_OFFSET_NANOS
How far behind the frame deadline pointer positions are sampled, in nanoseconds: a Move is emitted at frame_time − SAMPLE_OFFSET, slightly in the past so the two raw samples bracketing that instant are usually already in hand (interpolation, not extrapolation) at the common touch/display cadence.

Functions§

deadline_overrun
Whether a frame’s measured work overran its budget_nanos deadline. Instrumentation only — the shell records the overrun (a counter, gated behind perf::enabled()); it never drops or reshapes work on the strength of this.
frame_interval_nanos
Estimate this frame’s deadline budget (the frame-target interval) from two consecutive tick timestamps. Returns the tick-to-tick delta when it is plausible ([MIN_PLAUSIBLE_INTERVAL_NANOS, MAX_PLAUSIBLE_INTERVAL_NANOS]), else DEFAULT_REFRESH_INTERVAL_NANOS (60Hz) — covering the first tick (no prior), a clock glitch, and a long idle across skipped ticks.