mirror of
https://github.com/storytold/lightcraft.git
synced 2026-10-14 19:27:01 -04:00
M5.6: a zoomed window waits for the original another window is decoding (decoded 2-3 times)
The Before window waited for the original only when the After's window job was already pending, but side by side the Before is asked for first in the frame, so both decoded the 64 MP raw at once; and a window asked for again while the first was still decoding (a pan, the layout settling at startup) started another full decode beside it (three decodes seen at startup). Any window now waits while a window job is pending and the original isn't held, and follows from the decoded original.
This commit is contained in:
4 files changed
+42
-15
No files matched your search
@@ -309,10 +309,11 @@ fn request_window(app: &mut LightcraftApp, c: &WindowCtx, v: &WindowView) -> Opt
|
||||
to_px * (v.visible.bottom() - v.target.top()),
|
||||
);
|
||||
let win = crate::region::window_for(fw, fh, visible, crate::region::max_span(c.texture_side))?;
|
||||
// the Before side waits for the original the After is decoding (see `defer_before_window`)
|
||||
// a window waits for the original another window job is decoding (see `defer_window`)
|
||||
let original_held = app.session.media.has_source(c.id, lightcraft_engine::SourceLevel::for_size(fw.max(fh)));
|
||||
if crate::region::defer_before_window(v.before, app.renderer.is_pending(Slot::Region), original_held) {
|
||||
return app.region_before_view.filter(|w| w.photo == c.id);
|
||||
let window_pending = app.renderer.is_pending(Slot::Region) || app.renderer.is_pending(Slot::RegionBefore);
|
||||
if crate::region::defer_window(window_pending, original_held) {
|
||||
return if v.before { app.region_before_view } else { app.region_view }.filter(|w| w.photo == c.id);
|
||||
}
|
||||
let job = if v.before {
|
||||
app.session.region_job_before(c.id, fw, fh, win, !c.crop_tool)
|
||||
|
||||
@@ -174,11 +174,13 @@ pub fn window_clip(mode: crate::state::BeforeAfter, before_side: bool, pane: egu
|
||||
clip.intersect(canvas)
|
||||
}
|
||||
|
||||
/// Whether the Before window waits for the After's. Both are cut from the same decoded original;
|
||||
/// asked for together while it isn't held yet, each worker decodes its own copy (two full-size
|
||||
/// decodes, two uploads, one thrown away). The Before follows once the original is in.
|
||||
pub fn defer_before_window(before_side: bool, after_pending: bool, original_held: bool) -> bool {
|
||||
before_side && after_pending && !original_held
|
||||
/// Whether a window waits for the one already being rendered. All windows are cut from the same
|
||||
/// decoded original; asked for while it isn't held yet (the Before and After together, in either
|
||||
/// order, or a new window while the first is still decoding), each worker decodes its own copy
|
||||
/// (two or three full-size decodes and uploads, all but one thrown away). The waiting window
|
||||
/// follows once the original is in.
|
||||
pub fn defer_window(window_pending: bool, original_held: bool) -> bool {
|
||||
window_pending && !original_held
|
||||
}
|
||||
|
||||
/// Whether the picture on screen has the frame's aspect (to the one pixel a texture's whole-pixel
|
||||
@@ -427,14 +429,13 @@ mod tests {
|
||||
assert_eq!(window_clip(Original, true, canvas, canvas, img), canvas);
|
||||
}
|
||||
|
||||
// Given Before and After windows asked for at once at first open, only the After's goes: the
|
||||
// Before's waits for the decoded original instead of decoding another copy
|
||||
// Given a window asked for while another is rendering and the original isn't decoded yet, it
|
||||
// waits for the decoded original instead of decoding another copy
|
||||
#[test]
|
||||
fn the_before_window_waits_for_the_original_the_after_is_decoding() {
|
||||
assert!(defer_before_window(true, true, false));
|
||||
assert!(!defer_before_window(true, true, true), "the original is in");
|
||||
assert!(!defer_before_window(true, false, false), "nothing is decoding it");
|
||||
assert!(!defer_before_window(false, true, false), "the After never waits");
|
||||
fn a_window_waits_for_the_original_another_is_decoding() {
|
||||
assert!(defer_window(true, false));
|
||||
assert!(!defer_window(true, true), "the original is in");
|
||||
assert!(!defer_window(false, false), "nothing is decoding it");
|
||||
}
|
||||
|
||||
// Hostile numbers give a plan, never a panic
|
||||
|
||||
@@ -452,6 +452,28 @@ mod in_the_loupe {
|
||||
assert_eq!(main.size, before_main.size, "and the same whole-frame size under them");
|
||||
}
|
||||
|
||||
// Given Before/After side by side, when I zoom to 1:1, then one window job decodes the original
|
||||
// and the other side waits for it (the Before, asked for first, used to start a second decode
|
||||
// beside the After's); both windows still arrive
|
||||
#[test]
|
||||
fn side_by_side_at_one_to_one_decodes_the_original_once() {
|
||||
let (mut h, _) = detail();
|
||||
let id = h.app.session.active().expect("a photo is open");
|
||||
h.app.ui.before_after = crate::state::BeforeAfter::SideBySide;
|
||||
h.app.ui.zoom = crate::state::Zoom::Percent(100.0);
|
||||
let pending = |h: &Headless| [Slot::Region, Slot::RegionBefore].into_iter().filter(|s| h.app.renderer.is_pending(*s)).count();
|
||||
for _ in 0..100 {
|
||||
h.step();
|
||||
if pending(&h) > 0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert!(!h.app.session.media.has_source(id, lightcraft_engine::SourceLevel::Full), "the original is still decoding");
|
||||
assert_eq!(pending(&h), 1, "one window job decodes it");
|
||||
h.settle(SETTLE);
|
||||
assert!(tile(&h, Slot::Region).is_some() && tile(&h, Slot::RegionBefore).is_some(), "both windows arrived");
|
||||
}
|
||||
|
||||
// Given the Before view alone (\), only the Before gets a window
|
||||
#[test]
|
||||
fn the_original_view_windows_only_the_before() {
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
high-resolution cameras such as the Sony A7R VI (64 MP). Their decoded original (~800 MB) is bigger than the
|
||||
default cache share (768 MB), so it was evicted as soon as it was stored. The original of the photo shown in Detail
|
||||
now stays, like its preview, until another photo or view is shown.
|
||||
- Zooming in with Before/After side by side decodes the original once: the Before side used to decode its own copy
|
||||
beside the After's, and a window asked for again while the first was still decoding (a pan, the layout settling)
|
||||
started yet another decode.
|
||||
|
||||
## 2026-10-11
|
||||
|
||||
|
||||
Reference in new issue
Block a user