progressive rendering done

macos-click-through
keith 5 years ago
parent 06eb849497
commit 7f772be865

@ -1,5 +1,7 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::Arc;
use skulpin::skia_safe::colors; use skulpin::skia_safe::colors;
use skulpin::winit::window::Window;
mod cursor; mod cursor;
mod style; mod style;
@ -21,6 +23,9 @@ pub struct Editor {
pub grid: Vec<Vec<GridCell>>, pub grid: Vec<Vec<GridCell>>,
pub dirty: Vec<Vec<bool>>, pub dirty: Vec<Vec<bool>>,
pub should_clear: bool, pub should_clear: bool,
pub window: Option<Arc<Window>>,
pub title: String, pub title: String,
pub size: (u64, u64), pub size: (u64, u64),
pub cursor: Cursor, pub cursor: Cursor,
@ -35,6 +40,9 @@ impl Editor {
grid: Vec::new(), grid: Vec::new(),
dirty: Vec::new(), dirty: Vec::new(),
should_clear: true, should_clear: true,
window: None,
title: "Neovide".to_string(), title: "Neovide".to_string(),
cursor: Cursor::new(), cursor: Cursor::new(),
size: (width, height), size: (width, height),
@ -54,6 +62,7 @@ impl Editor {
RedrawEvent::ModeChange { mode_index } => self.cursor.change_mode(mode_index, &self.defined_styles), RedrawEvent::ModeChange { mode_index } => self.cursor.change_mode(mode_index, &self.defined_styles),
RedrawEvent::BusyStart => self.cursor.enabled = false, RedrawEvent::BusyStart => self.cursor.enabled = false,
RedrawEvent::BusyStop => self.cursor.enabled = true, 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::Resize { width, height, .. } => self.resize((width, height)),
RedrawEvent::DefaultColorsSet { colors } => self.default_colors = colors, RedrawEvent::DefaultColorsSet { colors } => self.default_colors = colors,
RedrawEvent::HighlightAttributesDefine { id, style } => { self.defined_styles.insert(id, style); }, RedrawEvent::HighlightAttributesDefine { id, style } => { self.defined_styles.insert(id, style); },
@ -61,7 +70,7 @@ impl Editor {
RedrawEvent::Clear { .. } => self.clear(), RedrawEvent::Clear { .. } => self.clear(),
RedrawEvent::CursorGoto { row, column, .. } => self.cursor.position = (row, column), 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) 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<DrawCommand>, bool) { pub fn build_draw_commands(&mut self) -> (Vec<DrawCommand>, bool) {

@ -50,6 +50,7 @@ pub enum RedrawEvent {
ModeChange { mode_index: u64 }, ModeChange { mode_index: u64 },
BusyStart, BusyStart,
BusyStop, BusyStop,
Flush,
Resize { grid: u64, width: u64, height: u64 }, Resize { grid: u64, width: u64, height: u64 },
DefaultColorsSet { colors: Colors }, DefaultColorsSet { colors: Colors },
HighlightAttributesDefine { id: u64, style: Style }, HighlightAttributesDefine { id: u64, style: Style },
@ -290,6 +291,7 @@ pub fn parse_redraw_event(event_value: Value) -> Result<Vec<RedrawEvent>> {
"mode_change" => Some(parse_mode_change(event_parameters)?), "mode_change" => Some(parse_mode_change(event_parameters)?),
"busy_start" => Some(RedrawEvent::BusyStart), "busy_start" => Some(RedrawEvent::BusyStart),
"busy_stop" => Some(RedrawEvent::BusyStop), "busy_stop" => Some(RedrawEvent::BusyStop),
"flush" => Some(RedrawEvent::Flush),
"grid_resize" => Some(parse_grid_resize(event_parameters)?), "grid_resize" => Some(parse_grid_resize(event_parameters)?),
"default_colors_set" => Some(parse_default_colors(event_parameters)?), "default_colors_set" => Some(parse_default_colors(event_parameters)?),
"hl_attr_define" => Some(parse_hl_attr_define(event_parameters)?), "hl_attr_define" => Some(parse_hl_attr_define(event_parameters)?),

@ -1,13 +1,11 @@
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use skulpin::CoordinateSystemHelper; 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; use skulpin::skia_safe::gpu::SurfaceOrigin;
mod caching_shaper; mod caching_shaper;
mod fps_tracker;
use caching_shaper::CachingShaper; use caching_shaper::CachingShaper;
use fps_tracker::FpsTracker;
use crate::editor::{Editor, CursorShape, Style, Colors}; use crate::editor::{Editor, CursorShape, Style, Colors};
@ -25,8 +23,6 @@ pub struct Renderer {
pub font_width: f32, pub font_width: f32,
pub font_height: f32, pub font_height: f32,
cursor_pos: (f32, f32), cursor_pos: (f32, f32),
fps_tracker: FpsTracker
} }
impl Renderer { impl Renderer {
@ -44,9 +40,7 @@ impl Renderer {
let font_height = metrics.descent - metrics.ascent; let font_height = metrics.descent - metrics.ascent;
let cursor_pos = (0.0, 0.0); let cursor_pos = (0.0, 0.0);
let fps_tracker = FpsTracker::new(); Renderer { editor, surface, paint, font, shaper, font_width, font_height, cursor_pos }
Renderer { editor, surface, paint, font, shaper, font_width, font_height, cursor_pos, fps_tracker }
} }
fn draw_background(&mut self, canvas: &mut Canvas, text: &str, grid_pos: (u64, u64), style: &Style, default_colors: &Colors) { 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) { pub fn draw(&mut self, gpu_canvas: &mut Canvas, coordinate_system_helper: &CoordinateSystemHelper) -> bool {
self.draw_background(canvas, text, grid_pos, style, default_colors); let ((draw_commands, should_clear), default_colors, cursor) = {
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) = {
let mut editor = self.editor.lock().unwrap(); let mut editor = self.editor.lock().unwrap();
( (
editor.build_draw_commands(), editor.build_draw_commands(),
editor.default_colors.clone(), editor.default_colors.clone(),
editor.size.clone(),
editor.cursor.clone() editor.cursor.clone()
) )
}; };
@ -120,25 +108,27 @@ impl Renderer {
for command in draw_commands.iter() { for command in draw_commands.iter() {
self.draw_background(&mut canvas, &command.text, command.grid_position.clone(), &command.style, &default_colors); 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.draw_foreground(&mut canvas, &command.text, command.grid_position.clone(), &command.style, &default_colors);
} }
self.fps_tracker.record_frame(); let image = surface.image_snapshot();
self.draw_text(canvas, &self.fps_tracker.fps.to_string(), (width - 2, height - 1), &Style::new(default_colors.clone()), &default_colors); 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 (cursor_grid_x, cursor_grid_y) = cursor.position;
let target_cursor_x = cursor_grid_x as f32 * self.font_width; 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 target_cursor_y = cursor_grid_y as f32 * self.font_height;
let (previous_cursor_x, previous_cursor_y) = self.cursor_pos; let (previous_cursor_x, previous_cursor_y) = self.cursor_pos;
coordinate_system_helper.use_physical_coordinates(gpu_canvas); let delta_cursor_x = target_cursor_x - previous_cursor_x;
gpu_canvas.draw_image(surface.image_snapshot(), (0, 0), Some(&self.paint)); let delta_cursor_y = target_cursor_y - previous_cursor_y;
self.surface = Some(surface); let cursor_x = delta_cursor_x * 0.5 + previous_cursor_x;
let cursor_y = delta_cursor_y * 0.5 + previous_cursor_y;
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;
self.cursor_pos = (cursor_x, cursor_y); self.cursor_pos = (cursor_x, cursor_y);
if cursor.enabled { if cursor.enabled {
let cursor_width = match cursor.shape { let cursor_width = match cursor.shape {
@ -164,5 +154,7 @@ impl Renderer {
(cursor_x, cursor_y), &self.paint); (cursor_x, cursor_y), &self.paint);
} }
} }
delta_cursor_x.abs() > 0.001 || delta_cursor_y.abs() > 0.001
} }
} }

@ -10,6 +10,8 @@ use crate::editor::Editor;
use crate::keybindings::construct_keybinding_string; use crate::keybindings::construct_keybinding_string;
use crate::renderer::Renderer; use crate::renderer::Renderer;
const EXTRA_LIVE_FRAMES: usize = 10;
pub fn ui_loop(editor: Arc<Mutex<Editor>>, nvim: Neovim, initial_size: (u64, u64)) { pub fn ui_loop(editor: Arc<Mutex<Editor>>, nvim: Neovim, initial_size: (u64, u64)) {
let mut nvim = nvim; let mut nvim = nvim;
let mut renderer = Renderer::new(editor.clone()); let mut renderer = Renderer::new(editor.clone());
@ -21,15 +23,14 @@ pub fn ui_loop(editor: Arc<Mutex<Editor>>, nvim: Neovim, initial_size: (u64, u64
(height as f32 * renderer.font_height + 1.0) as f64 (height as f32 * renderer.font_height + 1.0) as f64
); );
let window = WindowBuilder::new() let window = Arc::new(WindowBuilder::new()
.with_title("Neovide") .with_title("Neovide")
.with_inner_size(logical_size) .with_inner_size(logical_size)
.build(&event_loop) .build(&event_loop)
.expect("Failed to create window"); .expect("Failed to create window"));
let mut skulpin_renderer = RendererBuilder::new() let mut skulpin_renderer = RendererBuilder::new()
.coordinate_system(CoordinateSystem::Logical) .coordinate_system(CoordinateSystem::Logical)
.present_mode_priority(vec![PresentMode::Immediate])
.build(&window) .build(&window)
.expect("Failed to create renderer"); .expect("Failed to create renderer");
@ -38,6 +39,12 @@ pub fn ui_loop(editor: Arc<Mutex<Editor>>, nvim: Neovim, initial_size: (u64, u64
icu::init(); 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| { event_loop.run(move |event, _window_target, control_flow| {
match event { match event {
Event::WindowEvent { Event::WindowEvent {
@ -127,15 +134,23 @@ pub fn ui_loop(editor: Arc<Mutex<Editor>>, nvim: Neovim, initial_size: (u64, u64
} }
Event::EventsCleared => { Event::EventsCleared => {
if live_frames > 0 {
live_frames = live_frames - 1;
window.request_redraw(); window.request_redraw();
*control_flow = ControlFlow::Poll;
} else {
*control_flow = ControlFlow::Wait;
}
}, },
Event::WindowEvent { Event::WindowEvent {
event: WindowEvent::RedrawRequested, event: WindowEvent::RedrawRequested,
.. ..
} => { } => {
if let Err(e) = skulpin_renderer.draw(&window, |canvas, coordinate_system_helper| { if let Err(e) = skulpin_renderer.draw(&window.clone(), |canvas, coordinate_system_helper| {
renderer.draw(canvas, coordinate_system_helper); if renderer.draw(canvas, coordinate_system_helper) {
live_frames = EXTRA_LIVE_FRAMES;
}
}) { }) {
println!("Error during draw: {:?}", e); println!("Error during draw: {:?}", e);
*control_flow = ControlFlow::Exit *control_flow = ControlFlow::Exit

Loading…
Cancel
Save