image: Keep texture around until new is available

Keep previous texture around during image reloads to avoid flickering.
This commit is contained in:
Sophie Herold 2024-08-16 13:29:27 +02:00
parent 0f69aa39c5
commit be32072d7a
6 changed files with 38 additions and 20 deletions

View file

@ -163,6 +163,7 @@ mod imp {
/// Track changes to this image
pub(super) file_monitor: RefCell<Option<gio::FileMonitor>>,
pub(super) frame_buffer: Arc<SharedFrameBuffer>,
pub(super) previous_frame_buffer: SharedFrameBuffer,
pub(super) decoder: RefCell<Option<Arc<Decoder>>>,
/// Rotation final value (can differ from `rotation` during animation)

View file

@ -89,6 +89,7 @@ impl imp::LpImage {
}
DecoderUpdate::Redraw => {
self.set_loaded(true);
self.previous_frame_buffer.reset();
obj.queue_draw();
self.frame_buffer.rcu(|tiles| {
@ -313,8 +314,13 @@ impl LpImage {
self.imp().set_file_loaded(file).await;
let tiles = &self.imp().frame_buffer;
// Delete all stored textures for reloads
tiles.reset();
let previous_frame_buffer = tiles.reset();
// Store previos frames to show until new texture is loaded
self.imp()
.previous_frame_buffer
.swap(previous_frame_buffer.load_full());
// Reset background color for reloads
imp.set_background_color(None);

View file

@ -126,9 +126,17 @@ impl WidgetImpl for imp::LpImage {
);
// Add texture(s)
self.frame_buffer
.load()
.add_to_snapshot(snapshot, applicable_zoom, &render_options);
let frame_buffer = self.frame_buffer.load();
// Don't use current frame buffer if it empty during an image reload
let use_frame_buffer = if frame_buffer.is_empty() {
// Fallback to previous buffer to show previous image until new one is available
self.previous_frame_buffer.load()
} else {
frame_buffer
};
use_frame_buffer.add_to_snapshot(snapshot, applicable_zoom, &render_options);
snapshot.restore();

View file

@ -97,8 +97,8 @@ impl LpImage {
if self.is_best_fit() {
let zoom_animation = imp.zoom_animation();
zoom_animation.set_value_from(dbg!(self.zoom()));
zoom_animation.set_value_to(dbg!(imp.zoom_level_best_fit_for_rotation(target.get())));
zoom_animation.set_value_from(self.zoom());
zoom_animation.set_value_to(imp.zoom_level_best_fit_for_rotation(target.get()));
zoom_animation.play();
}