docs: HANDOFF §8.12 (egui port + tttest harness), README reflects the egui stack

This commit is contained in:
Greg Pomerantz 2026-10-31 13:54:56 -04:00
parent d82ecf74ac
commit 9b12dc4731
2 changed files with 75 additions and 7 deletions

View File

@ -850,6 +850,71 @@ afterwards (`grep FR fr.log`). If smooth → port the gallery app layer
(db/scan/turbojpeg/LRU/GPU-upload, all renderer-agnostic) to an egui (db/scan/turbojpeg/LRU/GPU-upload, all renderer-agnostic) to an egui
grid + the about_to_wait frame driver + EGL setup from egtest. grid + the about_to_wait frame driver + EGL setup from egtest.
### 8.12 Gallery egui port + tttest (Tauri) harness (2026-10-31, `5a8284e`, `d82ecf7`)
**The port is DONE and compiling** (`5a8284e`): all Slint code removed
(vendor/, shim/, gputex, vkshim, baseline60, main.slint), replaced by
egui 0.31 / egui_glow / winit 0.30 / glow 0.16 / egl 0.2 / android-activity
0.6. File map: `src/lib.rs` (app state, full cache, scan, viewer math,
android_main: EGL + WinitHarness + app-owned frame driver), `src/ui.rs`
(World: tick/frame/touch/paint), `src/images.rs` (turbojpeg → RGB8 →
Vec<Color32> on the worker).
**The frame driver** (egtest's architecture, now in the gallery):
`about_to_wait` runs `World::tick` EVERY loop iteration (liveness — at
rest the tick notices scan writes / decode landings, sets dirty,
schedules a render); then: animating → spin+render on the 120 Hz grid;
dirty → one render; else park ~8 ms. `nice -10` on the UI thread.
**The performance bug that crashed the phone**: `ColorImage::
from_rgba_unmultiplied` is O(n) per-pixel (measured 8–60 ms per 2 MB
on the Pixel 9 Pro) and was running on the UI thread inside
`apply_plan` (8–16 ms/frame → 9.57% drops, median render 18.78 ms vs
the 8.3 ms budget). Plus ~4 transient 2 MB buffers/frame → OOM-class
pressure on a personal phone (the crash). **Fix**: workers produce
`Vec<egui::Color32>` directly (`images::to_pixels`); the UI thread only
MOVES the vector into `ColorImage { size, pixels }` (O(1)). Cache
caps tightened: 6 entries / 16 MP.
**Other port gotchas** (all fixed, all in code comments):
- `Painter::image`'s `uv` is NORMALIZED 0..1 — a screen-space uv made
every cell one clamped corner pixel (solid rectangles; the
emulator's solid-color test images hid it). Use `FULL_UV`.
- Fling velocity: per-EVENT delta EMA (0.8/0.2, ~60 ms memory),
clamped 14000 px/s. Frame-based velocity dies when touch events
sample slower than rAF (adb `input swipe` ≈ 17 Hz).
- winit 0.30 never delivers `RedrawRequested` on Android → the
app-owned driver above (driving from `about_to_wait`).
- egui 0.31 `Painter` is shared (`&Painter`): use `ui.painter_at(rect)`
for clipped cell painting.
**Emulator: fully verified** — grid renders real thumbnails, drag +
fling scroll, tap→viewer, ×/back close, status strip. **Phone:**
thumbnails render, 8580 files scanned; the per-pixel fix is BUILT
(`target/release/apk/gallery.apk`, framelog) but NOT YET MEASURED —
phone was left alone after the crash (personal device). **Pending:**
(1) user clearance, (2) install the fixed APK, (3) `fr_capture.py
--manual 45` expecting render cost 18.78 → <8.3 ms, (4) USER FINGER
TEST — is it smooth where Slint felt janky? If drops remain, next
suspect: egui mesh build for 33+ cells in `paint+swap`.
**tttest** (`d82ecf7`, `harnesses/tttest/`): the third harness stack
— Tauri 2 → wry → Android WebView (Chromium). Identical scene to
sltest (8580 rows, 150+2 px, alternating colors), virtualized 26-element
DOM pool, custom touch drag+fling in JS, rAF-driven. FR lines cross
the Tauri event bridge at 1/s → Rust writer thread →
`/sdcard/Android/data/wow.gmp.tttest/files/Documents/fr.log` (Tauri
document_dir; the framework creates it — raw std::fs mkdir of the app
external tree is SELinux-denied). `fr_capture.py` now launches any
package (monkey LAUNCHER fallback) and finds all three log paths.
Emulator: 1319 frames, 60 Hz clean, 5 isolated drops (all at swipe
injection), JS render cost med 2 ms. JS gotchas: `touch-action` is NOT
inherited (each `.row` must claim it or the WebView steals the pan);
fling velocity must be per-event EMA. aarch64 build: 11 MB APK,
compiles; phone test pending. **This is the A/B/C complete**: sltest
(Slint/Skia) 0.33–0.83% vs egtest (egui/glow) 0.12% vs tttest
(WebView) — the finger test on the phone is still the final referee.
### 8.8 Jank-hunt round 2 + the keep-alive incident (2026-10-28) ### 8.8 Jank-hunt round 2 + the keep-alive incident (2026-10-28)
Follow-up on "still seeing jank" (post-GPU-texture). Instrumentation: Follow-up on "still seeing jank" (post-GPU-texture). Instrumentation:

View File

@ -1,12 +1,16 @@
# gallery # gallery
A high-performance image gallery for Android (primary), Linux and macOS — A high-performance image gallery for Android (primary), Linux and macOS —
Rust + [Slint](https://slint.dev) 1.18. Rust + [egui](https://egui.rs) 0.31 (egui_glow / winit 0.30 / glow 0.16).
Ported from Slint 1.18 after the zero-jank campaign showed Slint-on-Mali
janky at its base level while egui measured 3–7× cleaner (HANDOFF.md
§8.11–8.12). The Slint tree is preserved in git history and
`docs/BUGS/`.
**Status: M1 (metadata scan + DB) done.** See **[HANDOFF.md](HANDOFF.md)** — **Status: M0–M4 ported to egui, zero-jank tuning in progress.** See
the development hand-off with the full plan: architecture, thumbnail **[HANDOFF.md](HANDOFF.md)** — the development hand-off: architecture,
pipeline, milestones M1–M7, Slint gotchas, permission flow, and performance thumbnail pipeline, milestones M1–M7, the Slint jank campaign, the egui
targets. Next: M2 (thumbnail engine). port, and the sltest/egtest/tttest harnesses (A/B/C: Slint/egui/WebView).
## Build ## Build
@ -22,5 +26,4 @@ for exact paths/env).
## License ## License
GPL-3.0 (see [LICENSE](LICENSE)). Built on Slint, used under the Slint GPL-3.0 (see [LICENSE](LICENSE)). Built on egui (MIT/Apache-2.0).
royalty-free license for proprietary apps (see HANDOFF.md §10.4).