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/.
28 lines
1004 B
Rust
28 lines
1004 B
Rust
//! 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) {}
|