gallery/src/prio.rs
Greg Pomerantz 5a8284e7a9 Port the gallery from Slint to egui (egui 0.31 / egui_glow / winit 0.30 / glow 0.16)
Slint-on-Mali was conclusively janky at its base level (sltest: 0.33-0.83%
slot drops on a scene with no app logic); egui on the same phone measured
3-7x cleaner (egtest: 0.12%, same referee/scene).

Architecture (see HANDOFF §8.11-8.12):
- winit 0.30 ApplicationHandler on android-activity 0.6, raw EGL (ES3),
  egui_glow::EguiGlow. winit 0.30 never delivers RedrawRequested on
  Android → the frame driver is app-owned: World::tick runs every loop
  iteration from about_to_wait (liveness), render when dirty or
  animating, park ~8 ms (one vblank) at rest.
- Virtualized grid painter (3 cols, visible rows ±4), GPU-resident
  textures, turbojpeg worker pool decoding off-thread.
- CRITICAL pixel-pipeline fix: RGB8→Vec<Color32> conversion happens on
  the WORKER (egui 0.31's from_rgba_unmultiplied is O(n) per-pixel,
  8-60 ms/2 MB on the UI thread → 9.57% drops + phone OOM crash).
  UI thread only MOVES the vector into ColorImage.
- Fling: per-event EMA velocity (frame-based dies at slow touch sampling),
  clamp 14000 px/s; decay exp(-7.42 dt).
- Painter::image uv is NORMALIZED (0..1) — a screen-space uv made every
  cell a solid rectangle (the emulator's solid-color test images hid it).
- Memory caps for a personal phone: full cache 6 entries / 16 MP.

Verified on emulator: grid, scroll, fling, viewer, back-key. Phone
deploy: thumbnails render, 8580 files. Pending: user finger test +
fr_capture phone run (per-pixel fix expected to cut render cost
18.8 ms → <8.3 ms).

Deletes: vendor/ (instrumented Slint tree), shim/, build.rs, gputex,
vkshim, baseline60, main.slint — the Slint zero-jank campaign is
concluded in docs/BUGS/.
2026-10-31 13:50:46 -04:00

28 lines
1004 B
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//! UI-thread priority boost (docs/BUGS/scroll-jank-120hz.md §4.1, egui
//! port). The phone's default UI-thread priority (nice 0) gets descheduled
//! 30–100 ms under ambient load — the measured stall class. `set_self_nice`
//! sets the CALLING thread to nice -10 (the UI thread) or +2 (the decode
//! threads, so they never compete with the UI thread).
//!
//! Bionic's `setpriority(PRIO_THREAD, 0, n)` acts on exactly the calling
//! thread (no /proc, no JNI — the old Slint build needed a JNI
//! `setThreadPriority` round-trip for foreign threads; winit 0.30 runs the
//! loop on the calling thread itself, so nothing foreign ever needs
//! adjusting).
#[cfg(target_os = "android")]
extern "C" {
fn setpriority(which: i32, who: u32, prio: i32) -> i32;
}
#[cfg(target_os = "android")]
pub fn set_self_nice(nice: i32) {
const PRIO_THREAD: i32 = 5;
unsafe {
setpriority(PRIO_THREAD, 0, nice);
}
}
#[cfg(not(target_os = "android"))]
pub fn set_self_nice(_nice: i32) {}