GPU-accelerated UI toolkit (Vulkan)
git clone https://git.lucas.co/cce-ui.git
ImageView: say that a borrowed id dies with its renderer
The module already said the view BORROWS its image id and that the app
owns and frees it. What it did not say is that the id can die under the
view without anyone freeing it: a renderer does not outlive its
session, and window_runner builds a new one around the same
Application when it repairs a lost Wayland transport. A draw for an id
the new image table does not hold is skipped rather than reported.
That gap is not hypothetical. cce-designer's page pane was written
straight from these docs, read carefully, and shipped with exactly this
bug (fixed there in 6d0e313); cce-files' preview pane had it too. Both
authors had every reason to think the contract was fully stated.
Docs only — no behavior change.
src/widget/display/image_view.rs | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/src/widget/display/image_view.rs b/src/widget/display/image_view.rs
index 4aa7fb3..986ff0a 100644
--- a/src/widget/display/image_view.rs
+++ b/src/widget/display/image_view.rs
@@ -4,6 +4,21 @@
//! [`crate::vk::free_image`] when done — the widget never uploads or frees GPU
//! resources, so one id can back several views and a dropped view leaks
//! nothing. `image: None` paints only the optional letterbox floor.
+//!
+//! **Borrowing it means the owner has to replace it when the renderer is
+//! rebuilt.** An image id names an entry in one renderer's image table, and a
+//! renderer does not outlive its session: `window_runner` builds a new one
+//! around the same `Application` when it repairs a lost Wayland transport. A
+//! draw for an id the new table does not hold is skipped rather than
+//! reported, so a view left holding a pre-reconnect id goes blank and stays
+//! blank, with nothing logged. Set the image again from
+//! [`Application::renderer_init`] on every renderer after the first — the
+//! app is the only party that can produce those pixels a second time.
+//! ([`crate::upload_icon`] is the one exception, for bundled glyphs: it
+//! re-resolves itself, and `Button::with_icon_name` is how a widget opts into
+//! that.)
+//!
+//! [`Application::renderer_init`]: crate::engine::Application::renderer_init
use crate::scene::layout::{fit_rect, FitMode, Rect, Size};
use crate::scene::paint::PaintCtx;