From 7f772be8658983a44f1d27089516243b682b410f Mon Sep 17 00:00:00 2001 From: keith Date: Thu, 19 Dec 2019 01:05:04 -0800 Subject: [PATCH] progressive rendering done --- src/editor/mod.rs | 11 ++++++++++- src/events.rs | 2 ++ src/renderer/mod.rs | 42 +++++++++++++++++------------------------- src/window.rs | 27 +++++++++++++++++++++------ 4 files changed, 50 insertions(+), 32 deletions(-) diff --git a/src/editor/mod.rs b/src/editor/mod.rs index 956ff27..69f9df2 100644 --- a/src/editor/mod.rs +++ b/src/editor/mod.rs @@ -1,5 +1,7 @@ use std::collections::HashMap; +use std::sync::Arc; use skulpin::skia_safe::colors; +use skulpin::winit::window::Window; mod cursor; mod style; @@ -21,6 +23,9 @@ pub struct Editor { pub grid: Vec>, pub dirty: Vec>, pub should_clear: bool, + + pub window: Option>, + pub title: String, pub size: (u64, u64), pub cursor: Cursor, @@ -35,6 +40,9 @@ impl Editor { grid: Vec::new(), dirty: Vec::new(), should_clear: true, + + window: None, + title: "Neovide".to_string(), cursor: Cursor::new(), size: (width, height), @@ -54,6 +62,7 @@ impl Editor { RedrawEvent::ModeChange { mode_index } => self.cursor.change_mode(mode_index, &self.defined_styles), RedrawEvent::BusyStart => self.cursor.enabled = false, RedrawEvent::BusyStop => self.cursor.enabled = true, + RedrawEvent::Flush => { self.window.as_ref().map(|window| window.request_redraw()); }, RedrawEvent::Resize { width, height, .. } => self.resize((width, height)), RedrawEvent::DefaultColorsSet { colors } => self.default_colors = colors, RedrawEvent::HighlightAttributesDefine { id, style } => { self.defined_styles.insert(id, style); }, @@ -61,7 +70,7 @@ impl Editor { RedrawEvent::Clear { .. } => self.clear(), RedrawEvent::CursorGoto { row, column, .. } => self.cursor.position = (row, column), RedrawEvent::Scroll { top, bottom, left, right, rows, columns, .. } => self.scroll_region(top, bottom, left, right, rows, columns) - } + }; } pub fn build_draw_commands(&mut self) -> (Vec, bool) { diff --git a/src/events.rs b/src/events.rs index 0e9a6a7..e23fd38 100644 --- a/src/events.rs +++ b/src/events.rs @@ -50,6 +50,7 @@ pub enum RedrawEvent { ModeChange { mode_index: u64 }, BusyStart, BusyStop, + Flush, Resize { grid: u64, width: u64, height: u64 }, DefaultColorsSet { colors: Colors }, HighlightAttributesDefine { id: u64, style: Style }, @@ -290,6 +291,7 @@ pub fn parse_redraw_event(event_value: Value) -> Result> { "mode_change" => Some(parse_mode_change(event_parameters)?), "busy_start" => Some(RedrawEvent::BusyStart), "busy_stop" => Some(RedrawEvent::BusyStop), + "flush" => Some(RedrawEvent::Flush), "grid_resize" => Some(parse_grid_resize(event_parameters)?), "default_colors_set" => Some(parse_default_colors(event_parameters)?), "hl_attr_define" => Some(parse_hl_attr_define(event_parameters)?), diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index b7c5b1c..5b47396 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -1,13 +1,11 @@ use std::sync::{Arc, Mutex}; use skulpin::CoordinateSystemHelper; -use skulpin::skia_safe::{Canvas, Paint, Surface, Budgeted, Image, Rect, Typeface, Font, FontStyle, colors}; +use skulpin::skia_safe::{Canvas, Paint, Surface, Budgeted, Rect, Typeface, Font, FontStyle, colors}; use skulpin::skia_safe::gpu::SurfaceOrigin; mod caching_shaper; -mod fps_tracker; use caching_shaper::CachingShaper; -use fps_tracker::FpsTracker; use crate::editor::{Editor, CursorShape, Style, Colors}; @@ -25,8 +23,6 @@ pub struct Renderer { pub font_width: f32, pub font_height: f32, cursor_pos: (f32, f32), - - fps_tracker: FpsTracker } impl Renderer { @@ -44,9 +40,7 @@ impl Renderer { let font_height = metrics.descent - metrics.ascent; let cursor_pos = (0.0, 0.0); - let fps_tracker = FpsTracker::new(); - - Renderer { editor, surface, paint, font, shaper, font_width, font_height, cursor_pos, fps_tracker } + Renderer { editor, surface, paint, font, shaper, font_width, font_height, cursor_pos } } fn draw_background(&mut self, canvas: &mut Canvas, text: &str, grid_pos: (u64, u64), style: &Style, default_colors: &Colors) { @@ -82,18 +76,12 @@ impl Renderer { } } - fn draw_text(&mut self, canvas: &mut Canvas, text: &str, grid_pos: (u64, u64), style: &Style, default_colors: &Colors) { - self.draw_background(canvas, text, grid_pos, style, default_colors); - self.draw_foreground(canvas, text, grid_pos, style, default_colors); - } - - pub fn draw(&mut self, gpu_canvas: &mut Canvas, coordinate_system_helper: &CoordinateSystemHelper) { - let ((draw_commands, should_clear), default_colors, (width, height), cursor) = { + pub fn draw(&mut self, gpu_canvas: &mut Canvas, coordinate_system_helper: &CoordinateSystemHelper) -> bool { + let ((draw_commands, should_clear), default_colors, cursor) = { let mut editor = self.editor.lock().unwrap(); ( editor.build_draw_commands(), editor.default_colors.clone(), - editor.size.clone(), editor.cursor.clone() ) }; @@ -120,25 +108,27 @@ impl Renderer { for command in draw_commands.iter() { self.draw_background(&mut canvas, &command.text, command.grid_position.clone(), &command.style, &default_colors); } - for command in draw_commands { + for command in draw_commands.iter() { self.draw_foreground(&mut canvas, &command.text, command.grid_position.clone(), &command.style, &default_colors); } - self.fps_tracker.record_frame(); - self.draw_text(canvas, &self.fps_tracker.fps.to_string(), (width - 2, height - 1), &Style::new(default_colors.clone()), &default_colors); + let image = surface.image_snapshot(); + let window_size = coordinate_system_helper.window_logical_size(); + let image_destination = Rect::new(0.0, 0.0, window_size.width as f32, window_size.height as f32); + gpu_canvas.draw_image_rect(image, None, &image_destination, &self.paint); + + self.surface = Some(surface); let (cursor_grid_x, cursor_grid_y) = cursor.position; let target_cursor_x = cursor_grid_x as f32 * self.font_width; let target_cursor_y = cursor_grid_y as f32 * self.font_height; let (previous_cursor_x, previous_cursor_y) = self.cursor_pos; - coordinate_system_helper.use_physical_coordinates(gpu_canvas); - gpu_canvas.draw_image(surface.image_snapshot(), (0, 0), Some(&self.paint)); + let delta_cursor_x = target_cursor_x - previous_cursor_x; + let delta_cursor_y = target_cursor_y - previous_cursor_y; - self.surface = Some(surface); - - let cursor_x = (target_cursor_x - previous_cursor_x) * 0.5 + previous_cursor_x; - let cursor_y = (target_cursor_y - previous_cursor_y) * 0.5 + previous_cursor_y; + let cursor_x = delta_cursor_x * 0.5 + previous_cursor_x; + let cursor_y = delta_cursor_y * 0.5 + previous_cursor_y; self.cursor_pos = (cursor_x, cursor_y); if cursor.enabled { let cursor_width = match cursor.shape { @@ -164,5 +154,7 @@ impl Renderer { (cursor_x, cursor_y), &self.paint); } } + + delta_cursor_x.abs() > 0.001 || delta_cursor_y.abs() > 0.001 } } diff --git a/src/window.rs b/src/window.rs index f08b993..da1b9f6 100644 --- a/src/window.rs +++ b/src/window.rs @@ -10,6 +10,8 @@ use crate::editor::Editor; use crate::keybindings::construct_keybinding_string; use crate::renderer::Renderer; +const EXTRA_LIVE_FRAMES: usize = 10; + pub fn ui_loop(editor: Arc>, nvim: Neovim, initial_size: (u64, u64)) { let mut nvim = nvim; let mut renderer = Renderer::new(editor.clone()); @@ -21,15 +23,14 @@ pub fn ui_loop(editor: Arc>, nvim: Neovim, initial_size: (u64, u64 (height as f32 * renderer.font_height + 1.0) as f64 ); - let window = WindowBuilder::new() + let window = Arc::new(WindowBuilder::new() .with_title("Neovide") .with_inner_size(logical_size) .build(&event_loop) - .expect("Failed to create window"); + .expect("Failed to create window")); let mut skulpin_renderer = RendererBuilder::new() .coordinate_system(CoordinateSystem::Logical) - .present_mode_priority(vec![PresentMode::Immediate]) .build(&window) .expect("Failed to create renderer"); @@ -38,6 +39,12 @@ pub fn ui_loop(editor: Arc>, nvim: Neovim, initial_size: (u64, u64 icu::init(); + { + let mut editor = editor.lock().unwrap(); + editor.window = Some(window.clone()); + } + + let mut live_frames = 0; event_loop.run(move |event, _window_target, control_flow| { match event { Event::WindowEvent { @@ -127,15 +134,23 @@ pub fn ui_loop(editor: Arc>, nvim: Neovim, initial_size: (u64, u64 } Event::EventsCleared => { - window.request_redraw(); + if live_frames > 0 { + live_frames = live_frames - 1; + window.request_redraw(); + *control_flow = ControlFlow::Poll; + } else { + *control_flow = ControlFlow::Wait; + } }, Event::WindowEvent { event: WindowEvent::RedrawRequested, .. } => { - if let Err(e) = skulpin_renderer.draw(&window, |canvas, coordinate_system_helper| { - renderer.draw(canvas, coordinate_system_helper); + if let Err(e) = skulpin_renderer.draw(&window.clone(), |canvas, coordinate_system_helper| { + if renderer.draw(canvas, coordinate_system_helper) { + live_frames = EXTRA_LIVE_FRAMES; + } }) { println!("Error during draw: {:?}", e); *control_flow = ControlFlow::Exit