fix(canvas): release closed panels' thumbnails while a visible page renders (#6227)

This commit is contained in:
quincy-jc authored and GitHub committed 2026-11-09 08:47:32 +08:00
1 parent dec32d0501
commit 0bfcc8024e
2 files changed
+64 -1

No files matched your search

+6 -1
View File
@@ -458,7 +458,12 @@ impl DocView {
&& !self.errors.contains_key(&r.page)
});
if visible_mains_pending {
// Caches are kept; demand is re-evaluated next frame once pixels arrive.
// Caches are kept; demand is re-evaluated next frame once pixels arrive. Thumbnails
// nothing shows any more (their panel closed) go now, though: no consumer is waiting.
if self.thumb_demand.is_empty() {
self.thumbs.clear();
self.stale_thumbs.clear();
}
return queue;
}
let thumbs = self.thumbnail_requests(info, ppp);
+58
View File
@@ -1428,6 +1428,64 @@ fn thumbnails_release_on_scroll_panel_close_and_request_again_after_eviction() {
assert!(v.prepare_render_queue(&info, 1.0).is_empty(), "closing consumers cancels thumbnail work");
}
#[test]
fn closing_the_last_thumbnail_consumer_releases_thumbnails_while_a_visible_page_renders() {
let ctx = egui::Context::default();
let info = thumbnail_info(1);
let mut v = DocView::new(DocId(1), &info, ViewDefaults::default());
v.need_thumbnail(0, true);
let first = v.prepare_render_queue(&info, 1.0);
v.last_queue = first.clone();
assert_eq!(v.receive_result(&ctx, solid_result(first[0], 132, 171)), 132 * 171 * 4);
let main = RenderRequest { scale: 1.0, tag: 1000, ..Default::default() };
v.begin_render_frame();
v.need_thumbnail(0, true);
v.frame_queue = vec![main];
v.frame_visible.insert(0);
assert_eq!(v.prepare_render_queue(&info, 1.0), vec![main]);
assert!(!v.thumbs.is_empty(), "a thumbnail still shown waits for the page");
v.begin_render_frame();
v.frame_queue = vec![main];
v.frame_visible.insert(0);
v.stale_thumbs.insert(0);
assert_eq!(v.prepare_render_queue(&info, 1.0), vec![main]);
assert!(v.thumbs.is_empty(), "nothing shows it any more, whatever the page is doing");
assert!(v.stale_thumbs.is_empty(), "nor is it remembered as out of date");
// Shown again once the page is drawn: the thumbnail is asked for afresh.
v.last_queue = vec![main];
assert!(v.receive_result(&ctx, solid_result(main, 100, 130)) > 0);
v.begin_render_frame();
v.frame_visible.insert(0);
v.need_thumbnail(0, true);
let queue = v.prepare_render_queue(&info, 1.0);
assert!(queue.iter().any(|r| r.page == 0 && r.tag & THUMB_TAG != 0), "the thumbnail is asked for again: {queue:?}");
}
/// While anything still shows a thumbnail, the thumbnails all wait for the visible page, as before:
/// only the last consumer closing lets them go early.
#[test]
fn a_thumbnail_still_shown_keeps_the_others_while_a_visible_page_renders() {
let ctx = egui::Context::default();
// Pages 0 and 3 are the same size.
let info = thumbnail_info(4);
let mut v = DocView::new(DocId(1), &info, ViewDefaults::default());
v.need_thumbnail(0, true);
v.need_thumbnail(3, true);
let first = v.prepare_render_queue(&info, 1.0);
v.last_queue = first.clone();
for r in &first {
assert!(v.receive_result(&ctx, solid_result(*r, 132, 171)) > 0, "thumbnail of page {} taken", r.page);
}
assert_eq!(v.thumbs.len(), 2);
let main = RenderRequest { scale: 1.0, tag: 1000, ..Default::default() };
v.begin_render_frame();
v.need_thumbnail(0, true);
v.frame_queue = vec![main];
v.frame_visible.insert(0);
assert_eq!(v.prepare_render_queue(&info, 1.0), vec![main]);
assert!(v.thumbs.contains_key(&0) && v.thumbs.contains_key(&3), "both wait for the page");
}
#[test]
fn stale_results_are_rejected_before_conversion_after_dpi_invalidation_and_suspend() {
let ctx = egui::Context::default();