progressive rendering done

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

@ -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<Vec<GridCell>>,
pub dirty: Vec<Vec<bool>>,
pub should_clear: bool,
pub window: Option<Arc<Window>>,
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<DrawCommand>, bool) {

@ -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<Vec<RedrawEvent>> {
"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)?),

@ -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
}
}

@ -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<Mutex<Editor>>, 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<Mutex<Editor>>, 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<Mutex<Editor>>, 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<Mutex<Editor>>, 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

Loading…
Cancel
Save