image: Keep texture around until new is available
Keep previous texture around during image reloads to avoid flickering.
This commit is contained in:
parent
0f69aa39c5
commit
be32072d7a
6 changed files with 38 additions and 20 deletions
1
news.d/47.rc/fixed-avoid-flickering-when-reloading-image
Normal file
1
news.d/47.rc/fixed-avoid-flickering-when-reloading-image
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Flickering while images are reloaded. Instead, keep the old textures around until a new texture is available.
|
||||||
|
|
@ -177,19 +177,18 @@ impl FrameBuffer {
|
||||||
self.current().cleanup(zoom, viewport);
|
self.current().cleanup(zoom, viewport);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Delete all stored information
|
|
||||||
///
|
|
||||||
/// Used when reloading image
|
|
||||||
pub fn reset(&mut self) {
|
|
||||||
self.update_sender = None;
|
|
||||||
self.images.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn contains(&self, zoom: f64, coordinates: Coordinates) -> bool {
|
pub fn contains(&self, zoom: f64, coordinates: Coordinates) -> bool {
|
||||||
self.images
|
self.images
|
||||||
.front()
|
.front()
|
||||||
.map_or(false, |x| x.contains(zoom, coordinates))
|
.map_or(false, |x| x.contains(zoom, coordinates))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if there are no textures
|
||||||
|
pub fn is_empty(&self) -> bool {
|
||||||
|
self.images
|
||||||
|
.front()
|
||||||
|
.map_or(false, |x| x.tile_layers.is_empty())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
|
|
@ -623,12 +622,15 @@ impl SharedFrameBuffer {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset(&self) {
|
/// Reset to default and return old store
|
||||||
self.buffer.rcu(|tiling_store| {
|
///
|
||||||
let mut new_store = (**tiling_store).clone();
|
/// Used when reloading images
|
||||||
new_store.reset();
|
pub fn reset(&self) -> Self {
|
||||||
Arc::new(new_store)
|
let old_buffer = self.buffer.swap(Default::default());
|
||||||
});
|
|
||||||
|
Self {
|
||||||
|
buffer: ArcSwap::new(old_buffer),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_layer_tiling_or_default(&self, zoom: f64, viewport: graphene::Rect) -> Tiling {
|
pub fn get_layer_tiling_or_default(&self, zoom: f64, viewport: graphene::Rect) -> Tiling {
|
||||||
|
|
|
||||||
|
|
@ -163,6 +163,7 @@ mod imp {
|
||||||
/// Track changes to this image
|
/// Track changes to this image
|
||||||
pub(super) file_monitor: RefCell<Option<gio::FileMonitor>>,
|
pub(super) file_monitor: RefCell<Option<gio::FileMonitor>>,
|
||||||
pub(super) frame_buffer: Arc<SharedFrameBuffer>,
|
pub(super) frame_buffer: Arc<SharedFrameBuffer>,
|
||||||
|
pub(super) previous_frame_buffer: SharedFrameBuffer,
|
||||||
pub(super) decoder: RefCell<Option<Arc<Decoder>>>,
|
pub(super) decoder: RefCell<Option<Arc<Decoder>>>,
|
||||||
|
|
||||||
/// Rotation final value (can differ from `rotation` during animation)
|
/// Rotation final value (can differ from `rotation` during animation)
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,7 @@ impl imp::LpImage {
|
||||||
}
|
}
|
||||||
DecoderUpdate::Redraw => {
|
DecoderUpdate::Redraw => {
|
||||||
self.set_loaded(true);
|
self.set_loaded(true);
|
||||||
|
self.previous_frame_buffer.reset();
|
||||||
|
|
||||||
obj.queue_draw();
|
obj.queue_draw();
|
||||||
self.frame_buffer.rcu(|tiles| {
|
self.frame_buffer.rcu(|tiles| {
|
||||||
|
|
@ -313,8 +314,13 @@ impl LpImage {
|
||||||
self.imp().set_file_loaded(file).await;
|
self.imp().set_file_loaded(file).await;
|
||||||
|
|
||||||
let tiles = &self.imp().frame_buffer;
|
let tiles = &self.imp().frame_buffer;
|
||||||
|
|
||||||
// Delete all stored textures for reloads
|
// 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
|
// Reset background color for reloads
|
||||||
imp.set_background_color(None);
|
imp.set_background_color(None);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -126,9 +126,17 @@ impl WidgetImpl for imp::LpImage {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Add texture(s)
|
// Add texture(s)
|
||||||
self.frame_buffer
|
let frame_buffer = self.frame_buffer.load();
|
||||||
.load()
|
|
||||||
.add_to_snapshot(snapshot, applicable_zoom, &render_options);
|
// 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();
|
snapshot.restore();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -97,8 +97,8 @@ impl LpImage {
|
||||||
if self.is_best_fit() {
|
if self.is_best_fit() {
|
||||||
let zoom_animation = imp.zoom_animation();
|
let zoom_animation = imp.zoom_animation();
|
||||||
|
|
||||||
zoom_animation.set_value_from(dbg!(self.zoom()));
|
zoom_animation.set_value_from(self.zoom());
|
||||||
zoom_animation.set_value_to(dbg!(imp.zoom_level_best_fit_for_rotation(target.get())));
|
zoom_animation.set_value_to(imp.zoom_level_best_fit_for_rotation(target.get()));
|
||||||
zoom_animation.play();
|
zoom_animation.play();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue