perf: pre-scale generated images in other slides as they pop up

This commit is contained in:
Matias Fontanini 2025-04-17 15:30:23 -07:00
parent 5eee8a9fae
commit 7908b65a51
2 changed files with 38 additions and 15 deletions

View File

@ -173,8 +173,8 @@ impl Presentation {
} }
/// Poll every async render operation in the current slide and check whether they're completed. /// Poll every async render operation in the current slide and check whether they're completed.
pub(crate) fn poll_slide_async_renders(&mut self) -> RenderAsyncState { pub(crate) fn poll_slide_async_renders(&mut self, slide: usize) -> RenderAsyncState {
let slide = self.current_slide_mut(); let slide = &mut self.slides[slide];
let mut slide_state = RenderAsyncState::Rendered; let mut slide_state = RenderAsyncState::Rendered;
for operation in slide.iter_operations_mut() { for operation in slide.iter_operations_mut() {
if let RenderOperation::RenderAsync(operation) = operation { if let RenderOperation::RenderAsync(operation) = operation {

View File

@ -156,12 +156,12 @@ impl<'a> Presenter<'a> {
self.try_scale_transition_images()?; self.try_scale_transition_images()?;
break; break;
} }
CommandSideEffect::NextSlide => { CommandSideEffect::AnimateNextSlide => {
self.next_slide(&mut drawer)?; self.animate_next_slide(&mut drawer)?;
break; break;
} }
CommandSideEffect::PreviousSlide => { CommandSideEffect::AnimatePreviousSlide => {
self.previous_slide(&mut drawer)?; self.animate_previous_slide(&mut drawer)?;
break; break;
} }
CommandSideEffect::None => (), CommandSideEffect::None => (),
@ -203,15 +203,19 @@ impl<'a> Presenter<'a> {
return Ok(false); return Ok(false);
} }
let current_index = self.state.presentation().current_slide_index(); let current_index = self.state.presentation().current_slide_index();
if self.slides_with_pending_async_renders.contains(&current_index) { self.poll_slide_async_renders(current_index)
let state = self.state.presentation_mut().poll_slide_async_renders(); }
fn poll_slide_async_renders(&mut self, slide: usize) -> Result<bool, RenderError> {
if self.slides_with_pending_async_renders.contains(&slide) {
let state = self.state.presentation_mut().poll_slide_async_renders(slide);
match state { match state {
RenderAsyncState::NotStarted | RenderAsyncState::Rendering { modified: false } => (), RenderAsyncState::NotStarted | RenderAsyncState::Rendering { modified: false } => (),
RenderAsyncState::Rendering { modified: true } => { RenderAsyncState::Rendering { modified: true } => {
return Ok(true); return Ok(true);
} }
RenderAsyncState::Rendered | RenderAsyncState::JustFinishedRendering => { RenderAsyncState::Rendered | RenderAsyncState::JustFinishedRendering => {
self.slides_with_pending_async_renders.remove(&current_index); self.slides_with_pending_async_renders.remove(&slide);
return Ok(true); return Ok(true);
} }
}; };
@ -279,7 +283,7 @@ impl<'a> Presenter<'a> {
if !presentation.jump_next() { if !presentation.jump_next() {
false false
} else if presentation.current_slide_index() != current_slide { } else if presentation.current_slide_index() != current_slide {
return CommandSideEffect::NextSlide; return CommandSideEffect::AnimateNextSlide;
} else { } else {
true true
} }
@ -290,7 +294,7 @@ impl<'a> Presenter<'a> {
if !presentation.jump_previous() { if !presentation.jump_previous() {
false false
} else if presentation.current_slide_index() != current_slide { } else if presentation.current_slide_index() != current_slide {
return CommandSideEffect::PreviousSlide; return CommandSideEffect::AnimatePreviousSlide;
} else { } else {
true true
} }
@ -436,10 +440,12 @@ impl<'a> Presenter<'a> {
} }
} }
fn next_slide(&mut self, drawer: &mut TerminalDrawer) -> RenderResult { fn animate_next_slide(&mut self, drawer: &mut TerminalDrawer) -> RenderResult {
let Some(config) = self.options.transition.clone() else { let Some(config) = self.options.transition.clone() else {
return Ok(()); return Ok(());
}; };
self.poll_and_scale_images()?;
let options = drawer.render_engine_options(); let options = drawer.render_engine_options();
let presentation = self.state.presentation_mut(); let presentation = self.state.presentation_mut();
let dimensions = WindowSize::current(self.options.font_size_fallback)?; let dimensions = WindowSize::current(self.options.font_size_fallback)?;
@ -451,14 +457,20 @@ impl<'a> Presenter<'a> {
self.animate_transition(drawer, left, right, direction, dimensions, config) self.animate_transition(drawer, left, right, direction, dimensions, config)
} }
fn previous_slide(&mut self, drawer: &mut TerminalDrawer) -> RenderResult { fn animate_previous_slide(&mut self, drawer: &mut TerminalDrawer) -> RenderResult {
let Some(config) = self.options.transition.clone() else { let Some(config) = self.options.transition.clone() else {
return Ok(()); return Ok(());
}; };
self.poll_and_scale_images()?;
let options = drawer.render_engine_options(); let options = drawer.render_engine_options();
let presentation = self.state.presentation_mut(); let presentation = self.state.presentation_mut();
let dimensions = WindowSize::current(self.options.font_size_fallback)?; let dimensions = WindowSize::current(self.options.font_size_fallback)?;
presentation.jump_next(); presentation.jump_next();
// Re-borrow to avoid calling fns above while mutably borrowing
let presentation = self.state.presentation_mut();
let right = Self::virtual_render(presentation.current_slide(), dimensions.clone(), &options)?; let right = Self::virtual_render(presentation.current_slide(), dimensions.clone(), &options)?;
presentation.jump_previous(); presentation.jump_previous();
let left = Self::virtual_render(presentation.current_slide(), dimensions.clone(), &options)?; let left = Self::virtual_render(presentation.current_slide(), dimensions.clone(), &options)?;
@ -547,6 +559,17 @@ impl<'a> Presenter<'a> {
engine.render(slide.iter_visible_operations())?; engine.render(slide.iter_visible_operations())?;
Ok(term.into_contents()) Ok(term.into_contents())
} }
fn poll_and_scale_images(&mut self) -> RenderResult {
let mut needs_scaling = false;
for index in 0..self.state.presentation().iter_slides().count() {
needs_scaling = self.poll_slide_async_renders(index)? || needs_scaling;
}
if needs_scaling {
self.try_scale_transition_images()?;
}
Ok(())
}
} }
enum CommandSideEffect { enum CommandSideEffect {
@ -554,8 +577,8 @@ enum CommandSideEffect {
Suspend, Suspend,
Redraw, Redraw,
Reload, Reload,
NextSlide, AnimateNextSlide,
PreviousSlide, AnimatePreviousSlide,
None, None,
} }