mirror of
https://github.com/alacritty/alacritty.git
synced 2024-11-25 14:05:41 -05:00
Eliminate extra renders
Currently has a bug where screen is blank at startup. That aside, Alacritty uses basically 0 CPU now. The input thread is still separate from the render thread, but, given the ability to wake the event loop, it may be possible to merge them again. I'm not sure if that's actually desirable. Performance is seemingly unchanged.
This commit is contained in:
parent
0a94ccfcca
commit
0517f376be
3 changed files with 98 additions and 32 deletions
6
Cargo.lock
generated
6
Cargo.lock
generated
|
@ -7,7 +7,7 @@ dependencies = [
|
|||
"errno 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"font 0.1.0",
|
||||
"gl_generator 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glutin 0.6.1 (git+https://github.com/jwilm/glutin?rev=45092a8e2f6706a7b2c613ff212341754e346c9c)",
|
||||
"glutin 0.6.1 (git+https://github.com/jwilm/glutin?rev=16ed800f68022a37203434bd3b542ff5400c1403)",
|
||||
"libc 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"notify 2.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -285,7 +285,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "glutin"
|
||||
version = "0.6.1"
|
||||
source = "git+https://github.com/jwilm/glutin?rev=45092a8e2f6706a7b2c613ff212341754e346c9c#45092a8e2f6706a7b2c613ff212341754e346c9c"
|
||||
source = "git+https://github.com/jwilm/glutin?rev=16ed800f68022a37203434bd3b542ff5400c1403#16ed800f68022a37203434bd3b542ff5400c1403"
|
||||
dependencies = [
|
||||
"android_glue 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -906,7 +906,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum gdi32-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "65256ec4dc2592e6f05bfc1ca3b956a4e0698aa90b1dff1f5687d55a5a3fd59a"
|
||||
"checksum gl_generator 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1d8edc81c5ae84605a62f5dac661a2313003b26d59839f81d47d46cf0f16a55"
|
||||
"checksum gleam 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "13a363b2a5264b600e530db2f14b3c487098e6dee0655f2810ea779385cbac5a"
|
||||
"checksum glutin 0.6.1 (git+https://github.com/jwilm/glutin?rev=45092a8e2f6706a7b2c613ff212341754e346c9c)" = "<none>"
|
||||
"checksum glutin 0.6.1 (git+https://github.com/jwilm/glutin?rev=16ed800f68022a37203434bd3b542ff5400c1403)" = "<none>"
|
||||
"checksum heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "abb306abb8d398e053cfb1b3e7b72c2f580be048b85745c52652954f8ad1439c"
|
||||
"checksum inotify 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8458c07bdbdaf309c80e2c3304d14c3db64e7465d4f07cf589ccb83fd0ff31a"
|
||||
"checksum itoa 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae3088ea4baeceb0284ee9eea42f591226e6beaecf65373e41b38d95a1b8e7a1"
|
||||
|
|
|
@ -13,7 +13,7 @@ notify = "2.6"
|
|||
bitflags = "*"
|
||||
font = { path = "./font" }
|
||||
errno = "0.1.6"
|
||||
parking_lot = "0.3.1"
|
||||
parking_lot = { version = "0.3.1", features = ["nightly"] }
|
||||
serde = "0.8"
|
||||
serde_yaml = "0.4"
|
||||
serde_macros = "0.8"
|
||||
|
|
122
src/main.rs
122
src/main.rs
|
@ -52,21 +52,45 @@ mod io;
|
|||
mod sync;
|
||||
|
||||
use std::sync::{mpsc, Arc};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
use sync::PriorityMutex;
|
||||
use parking_lot::{Condvar, Mutex};
|
||||
|
||||
use config::Config;
|
||||
use io::{Utf8Chars, Utf8CharsError};
|
||||
use meter::Meter;
|
||||
use renderer::{QuadRenderer, GlyphCache};
|
||||
use sync::PriorityMutex;
|
||||
use term::Term;
|
||||
use tty::process_should_exit;
|
||||
use util::thread;
|
||||
|
||||
use io::{Utf8Chars, Utf8CharsError};
|
||||
|
||||
/// Channel used by resize handling on mac
|
||||
static mut resize_sender: Option<mpsc::Sender<(u32, u32)>> = None;
|
||||
|
||||
struct Waiter {
|
||||
mutex: Mutex<bool>,
|
||||
cond: Condvar,
|
||||
}
|
||||
|
||||
impl Waiter {
|
||||
pub fn new() -> Waiter {
|
||||
Waiter {
|
||||
mutex: Mutex::new(false),
|
||||
cond: Condvar::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn notify(&self) {
|
||||
self.cond.notify_one();
|
||||
}
|
||||
|
||||
pub fn wait(&self) {
|
||||
let mut guard = self.mutex.lock();
|
||||
self.cond.wait(&mut guard);
|
||||
}
|
||||
}
|
||||
|
||||
/// Resize handling for Mac
|
||||
fn window_resize_handler(width: u32, height: u32) {
|
||||
unsafe {
|
||||
|
@ -126,6 +150,9 @@ fn main() {
|
|||
|
||||
let rasterizer = font::Rasterizer::new(dpi.x(), dpi.y(), dpr);
|
||||
|
||||
let waiter = Arc::new(Waiter::new());
|
||||
let dirty = Arc::new(AtomicBool::new(false));
|
||||
|
||||
// Create renderer
|
||||
let mut renderer = QuadRenderer::new(width, height);
|
||||
|
||||
|
@ -163,7 +190,11 @@ fn main() {
|
|||
|
||||
let terminal = Arc::new(PriorityMutex::new(terminal));
|
||||
|
||||
let pty_reader_thread = spawn_pty_reader(terminal.clone(), reader);
|
||||
let pty_reader_thread = spawn_pty_reader(terminal.clone(),
|
||||
reader,
|
||||
waiter.clone(),
|
||||
dirty.clone(),
|
||||
window.create_window_proxy());
|
||||
|
||||
let window = Arc::new(window);
|
||||
|
||||
|
@ -173,11 +204,15 @@ fn main() {
|
|||
renderer,
|
||||
glyph_cache,
|
||||
render_timer,
|
||||
rx);
|
||||
rx,
|
||||
waiter.clone(),
|
||||
dirty);
|
||||
|
||||
handle_window_events(&mut writer, terminal, window);
|
||||
|
||||
pty_reader_thread.join().ok();
|
||||
|
||||
waiter.notify();
|
||||
render_thread.join().ok();
|
||||
println!("Goodbye");
|
||||
}
|
||||
|
@ -219,12 +254,23 @@ fn handle_window_events<W>(writer: &mut W,
|
|||
&mut input::WriteNotifier(writer),
|
||||
*terminal.mode())
|
||||
},
|
||||
glutin::Event::Awakened => {
|
||||
if process_should_exit() {
|
||||
println!("input thread exitting");
|
||||
break;
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fn spawn_pty_reader<R>(terminal: Arc<PriorityMutex<Term>>, mut pty: R) -> std::thread::JoinHandle<()>
|
||||
fn spawn_pty_reader<R>(terminal: Arc<PriorityMutex<Term>>,
|
||||
mut pty: R,
|
||||
waiter: Arc<Waiter>,
|
||||
dirty: Arc<AtomicBool>,
|
||||
proxy: ::glutin::WindowProxy) -> std::thread::JoinHandle<()>
|
||||
where R: std::io::Read + Send + 'static,
|
||||
{
|
||||
thread::spawn_named("pty reader", move || {
|
||||
|
@ -233,40 +279,51 @@ fn spawn_pty_reader<R>(terminal: Arc<PriorityMutex<Term>>, mut pty: R) -> std::t
|
|||
let mut pty_parser = ansi::Parser::new();
|
||||
|
||||
loop {
|
||||
let got = pty.read(&mut buf[start..]).expect("pty fd active");
|
||||
let mut remain = 0;
|
||||
if let Ok(got) = pty.read(&mut buf[start..]) {
|
||||
let mut remain = 0;
|
||||
|
||||
// if `start` is nonzero, then actual bytes in buffer is > `got` by `start` bytes.
|
||||
let end = start + got;
|
||||
let mut terminal = terminal.lock_low();
|
||||
for c in Utf8Chars::new(&buf[..end]) {
|
||||
match c {
|
||||
Ok(c) => pty_parser.advance(&mut *terminal, c),
|
||||
Err(err) => match err {
|
||||
Utf8CharsError::IncompleteUtf8(unused) => {
|
||||
remain = unused;
|
||||
break;
|
||||
},
|
||||
_ => panic!("{}", err),
|
||||
// if `start` is nonzero, then actual bytes in buffer is > `got` by `start` bytes.
|
||||
let end = start + got;
|
||||
{
|
||||
let mut terminal = terminal.lock_low();
|
||||
for c in Utf8Chars::new(&buf[..end]) {
|
||||
match c {
|
||||
Ok(c) => pty_parser.advance(&mut *terminal, c),
|
||||
Err(err) => match err {
|
||||
Utf8CharsError::IncompleteUtf8(unused) => {
|
||||
remain = unused;
|
||||
break;
|
||||
},
|
||||
_ => panic!("{}", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Move any leftover bytes to front of buffer
|
||||
for i in 0..remain {
|
||||
buf[i] = buf[end - (remain - i)];
|
||||
dirty.store(true, Ordering::Release);
|
||||
waiter.notify();
|
||||
|
||||
// Move any leftover bytes to front of buffer
|
||||
for i in 0..remain {
|
||||
buf[i] = buf[end - (remain - i)];
|
||||
}
|
||||
start = remain;
|
||||
} else {
|
||||
proxy.wakeup_event_loop();
|
||||
break;
|
||||
}
|
||||
start = remain;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn spawn_renderer(window: Arc<glutin::Window>,
|
||||
terminal: Arc<PriorityMutex<Term>>,
|
||||
terminal_mutex: Arc<PriorityMutex<Term>>,
|
||||
mut renderer: QuadRenderer,
|
||||
mut glyph_cache: GlyphCache,
|
||||
render_timer: bool,
|
||||
rx: mpsc::Receiver<(u32, u32)>) -> std::thread::JoinHandle<()> {
|
||||
rx: mpsc::Receiver<(u32, u32)>,
|
||||
waiter: Arc<Waiter>,
|
||||
dirty: Arc<AtomicBool>) -> std::thread::JoinHandle<()> {
|
||||
thread::spawn_named("render", move || {
|
||||
unsafe {
|
||||
let _ = window.make_current();
|
||||
|
@ -277,7 +334,15 @@ fn spawn_renderer(window: Arc<glutin::Window>,
|
|||
// Scope ensures terminal lock isn't held when calling swap_buffers
|
||||
{
|
||||
// Acquire term lock
|
||||
let mut terminal = terminal.lock_high();
|
||||
let mut terminal = terminal_mutex.lock_high();
|
||||
|
||||
if !dirty.load(Ordering::Acquire) {
|
||||
drop(terminal);
|
||||
waiter.wait();
|
||||
terminal = terminal_mutex.lock_high();
|
||||
}
|
||||
|
||||
dirty.store(false, Ordering::Release);
|
||||
|
||||
// Resize events new_size and are handled outside the poll_events
|
||||
// iterator. This has the effect of coalescing multiple resize
|
||||
|
@ -328,6 +393,7 @@ fn spawn_renderer(window: Arc<glutin::Window>,
|
|||
|
||||
if process_should_exit() {
|
||||
break;
|
||||
} else {
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue