Retired frees only images no one else holds

An image shared with something still drawing waits for a later paint.
This commit is contained in:
ZacharyZhang-NY committed 2026-10-08 16:30:51 -04:00
1 parent cd50824049
commit dac2c5a39f
2 files changed
+18 -2

No files matched your search

+5 -2
View File
@@ -14,9 +14,12 @@ impl Retired {
self.0.push(image);
}
/// Frees every retired image; call while painting.
/// Frees images no one else holds; call while painting.
pub fn release(&mut self, window: &mut Window) {
for image in self.0.drain(..) {
// A shared image may still be drawn; it waits.
let (free, held): (Vec<_>, Vec<_>) = self.0.drain(..).partition(|image| Arc::strong_count(image) == 1);
self.0 = held;
for image in free {
if let Err(error) = window.drop_image(image) {
log::error!("images: a retired image stayed: {error}");
}
+13
View File
@@ -261,4 +261,17 @@ fn a_retired_image_is_freed_at_the_next_paint(cx: &mut TestAppContext) {
});
cx.run_until_parked();
assert!(view.read_with(cx, |painted, _| painted.retired.is_empty()), "the old image was freed");
// One still held elsewhere waits until it is let go.
let pixels = image::RgbaImage::from_pixel(2, 2, image::Rgba([4, 5, 6, 255]));
let shared = std::sync::Arc::new(gpui::RenderImage::new([image::Frame::new(pixels)]));
view.update(cx, |painted, cx| {
painted.retired.push(shared.clone());
cx.notify();
});
cx.run_until_parked();
assert!(!view.read_with(cx, |painted, _| painted.retired.is_empty()), "a held image waits");
drop(shared);
view.update(cx, |_, cx| cx.notify());
cx.run_until_parked();
assert!(view.read_with(cx, |painted, _| painted.retired.is_empty()), "then it is freed");
}