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 interpolatedMoveposition at each frame boundary (frame_time −SAMPLE_OFFSET_NANOS) with a Flutter-parity half-frame prediction window.Down/Up/Cancelphase transitions pass through losslessly — never synthesized, never dropped, never repositioned — so onlyMovepositions are ever resampled (Flutter’sPointerEventResamplercontract, adapted). Samples are kept in one lane perPointerId, 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§
- Pointer
Resampler - 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. - RawPointer
Sample - 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::Primaryfor touch), and a shell-supplied monotonic timestamp (see the module’s Clock domain note). - Resampled
Pointer - One resampled event and the contact it belongs to — what
PointerResampler::resampleemits, so the shell can rebuild theInputEvent::PointerContactcarrier for it.
Constants§
- DEFAULT_
REFRESH_ INTERVAL_ NANOS - Fallback frame-target interval (60Hz) used by
frame_interval_nanoswhen 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::newyields a disabled resampler that delivers every raw sample straight through in arrival order (pre- resampling behavior verbatim). MirrorsFRUST_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
Moveis emitted atframe_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
workoverran itsbudget_nanosdeadline. Instrumentation only — the shell records the overrun (a counter, gated behindperf::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]), elseDEFAULT_REFRESH_INTERVAL_NANOS(60Hz) — covering the first tick (no prior), a clock glitch, and a long idle across skipped ticks.