gallery/src/main.rs
Greg Pomerantz 84c6a4170d Fix activity-recreation crash: render-thread GPU uploads + per-world lifecycle
The swipe-up-dismiss + relaunch bug (process survives, activity
re-creates) crashed or left a sparse grid. Root cause chain, fully
documented in docs/BUGS/recreation-stale-textures.md:

- Each android_main (per activity instance) is a fresh Slint world with
  a fresh wgpu device (i-slint-core context is thread-local); the old
  world zombie-parks (Slint 1.18 android backend never delivers
  TerminateWindow/Destroy to it).
- Worker-side GPU uploads + a process-global loader let textures cross
  world/device boundaries: a texture destroyed with its device left a
  stale handle in the registry (wgpu-core assert in transition_resources
  on the render thread) — either killing the process, or, with the
  interim catch_unwind band-aid, keeping a poisoned world alive and
  corrupting the VISIBLE world's imports (the sparse grid). A/B against
  pristine Slint confirmed the mechanism (pristine: 1 self-killing panic
  per recreation + full grid).

Fix:
- gputex rewrite: workers deliver plain RGBA8; the UI drain tick
  uploads to the device captured from the rendering notifier
  (Slint's borrowed-resource contract). Staleness impossible by
  construction. Keepalive thread removed.
- Per-world lifecycle: CURRENT_WORLD gate silences zombie ticks;
  re-init invalidates the dying device + swaps the engine; render
  notifier handles RenderingTeardown/RenderingSetup (in-place cell
  clear — never set_vec mid-render, which desyncs the for-loop).
- Vendor patch surface reduced to the single final-flush hunk
  (catch_unwind guard reverted to pristine).
2026-10-28 20:54:04 -04:00

26 lines
771 B
Rust

use gallery::Main;
use slint::ComponentHandle;
/// Minimal eprintln logger for desktop dev (Android uses the non-blocking nblog).
struct Stdout;
impl log::Log for Stdout {
fn enabled(&self, _metadata: &log::Metadata) -> bool {
_metadata.level() <= log::Level::Info
}
fn log(&self, record: &log::Record) {
if self.enabled(record.metadata()) {
eprintln!("[{}] {}", record.metadata().level(), record.args());
}
}
fn flush(&self) {}
}
fn main() -> Result<(), slint::PlatformError> {
let _ = log::set_boxed_logger(Box::new(Stdout)).map(|()| log::set_max_level(log::LevelFilter::Info));
let main_window = Main::new()?;
gallery::start_scan(&main_window, 0);
main_window.show()?;
main_window.run()
}