Skip to content

Commit

Permalink
images: wait for first frame of decoded images
Browse files Browse the repository at this point in the history
Avoid flickering with the interim black frame but waiting up to 125ms
for the first frame to be decoded.

refs: #3882
  • Loading branch information
wez committed Jul 9, 2023
1 parent c399ee6 commit 96f5c2b
Showing 1 changed file with 35 additions and 2 deletions.
37 changes: 35 additions & 2 deletions wezterm-gui/src/glyphcache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use std::cell::RefCell;
use std::collections::HashMap;
use std::io::{Read, Seek};
use std::rc::Rc;
use std::sync::mpsc::{sync_channel, Receiver, SyncSender, TryRecvError};
use std::sync::mpsc::{sync_channel, Receiver, RecvTimeoutError, SyncSender, TryRecvError};
use std::sync::{Arc, MutexGuard};
use std::time::{Duration, Instant};
use termwiz::color::RgbColor;
Expand Down Expand Up @@ -439,6 +439,31 @@ impl FrameState {
}
}

fn wait_for_first_frame(&mut self, duration: Duration) {
if !self.frames.is_empty() {
// Already decoded the first frame
return;
}

match &mut self.source {
FrameSource::Decoder(rx) => match rx.recv_timeout(duration) {
Ok(frame) => {
self.frames.push(frame.clone());
self.current_frame = frame;
self.load_state = LoadState::Loaded;
}
Err(RecvTimeoutError::Timeout) => {}
Err(RecvTimeoutError::Disconnected) => {
self.source = FrameSource::FrameIndex(0);
log::warn!("image decoder thread terminated");
self.current_frame.duration = Duration::from_secs(86400);
self.frames.push(self.current_frame.clone());
}
},
FrameSource::FrameIndex(_) => {}
}
}

fn load_next_frame(&mut self) -> bool {
match &mut self.source {
FrameSource::Decoder(rx) => match rx.try_recv() {
Expand Down Expand Up @@ -981,8 +1006,16 @@ impl GlyphCache {
let mut next = None;
let mut decoded_frame_start = decoded.frame_start.borrow_mut();
let mut decoded_current_frame = decoded.current_frame.borrow_mut();
let now = Instant::now();

// Wait up to the approx limit of human tolerable delay for
// the first frame to be decoded, so that we can avoid showing
// a flash of the black frame in the common case
let max_duration = Duration::from_millis(125).max(min_frame_duration);
if let Some(remain) = max_duration.checked_sub(decoded_frame_start.elapsed()) {
frames.wait_for_first_frame(remain);
}

let now = Instant::now();
// We round up the frame duration to at least the minimum
// frame duration that wezterm can use when rendering.
// There's no point trying to deal with smaller intervals
Expand Down

0 comments on commit 96f5c2b

Please sign in to comment.