diff options
author | Joe Wilm <joe@jwilm.com> | 2016-12-10 22:44:13 -0800 |
---|---|---|
committer | Joe Wilm <joe@jwilm.com> | 2016-12-11 20:23:41 -0800 |
commit | ed0b1cfff04903fe26f586340e036c38bbf30b33 (patch) | |
tree | eb4eb3545bee57ed401cb7727c9dc3f106fabe3b /src/window.rs | |
parent | bbd8ddbfc055e85f8810285e71fd227cdd418221 (diff) | |
download | alacritty-ed0b1cfff04903fe26f586340e036c38bbf30b33.tar.gz alacritty-ed0b1cfff04903fe26f586340e036c38bbf30b33.zip |
Display manages window, renderer, rasterizer
This is part of an ongoing decoupling effort across the codebase and
tidying effort in main.rs. Everything to do with showing the window with
a grid of characters is now managed by the `Display` type. It owns the
window, the font rasterizer, and the renderer. The only info needed from
it are dimensions of characters and the window itself for sizing the
terminal properly. Additionally, the I/O loop has access to wake it up
when new data arrives.
Diffstat (limited to 'src/window.rs')
-rw-r--r-- | src/window.rs | 79 |
1 files changed, 72 insertions, 7 deletions
diff --git a/src/window.rs b/src/window.rs index 4d8a0c02..f9f2050c 100644 --- a/src/window.rs +++ b/src/window.rs @@ -11,6 +11,8 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +use std::sync::Arc; +use std::sync::atomic::{AtomicBool, Ordering}; use std::convert::From; use std::fmt::{self, Display}; use std::ops::Deref; @@ -55,10 +57,17 @@ type Result<T> = ::std::result::Result<T, Error>; /// Wraps the underlying windowing library to provide a stable API in Alacritty pub struct Window { glutin_window: glutin::Window, + + /// This flag allows calls to wakeup_event_loop to be coalesced. Waking the + /// event loop is potentially very slow (and indeed is on X11). + flag: Flag } /// Threadsafe APIs for the window -pub struct Proxy(glutin::WindowProxy); +pub struct Proxy { + inner: glutin::WindowProxy, + flag: Flag, +} /// Information about where the window is being displayed /// @@ -89,6 +98,46 @@ pub struct Pixels<T>(pub T); #[derive(Debug, Copy, Clone)] pub struct Points<T>(pub T); +/// A wrapper around glutin's WaitEventsIterator that clears the wakeup +/// optimization flag on drop. +pub struct WaitEventsIterator<'a> { + inner: glutin::WaitEventsIterator<'a>, + flag: Flag +} + +impl<'a> Iterator for WaitEventsIterator<'a> { + type Item = glutin::Event; + + #[inline] + fn next(&mut self) -> Option<Self::Item> { + self.inner.next() + } +} + +impl<'a> Drop for WaitEventsIterator<'a> { + fn drop(&mut self) { + self.flag.set(false); + } +} + +#[derive(Clone)] +pub struct Flag(pub Arc<AtomicBool>); +impl Flag { + pub fn new(initial_value: bool) -> Flag { + Flag(Arc::new(AtomicBool::new(initial_value))) + } + + #[inline] + pub fn get(&self) -> bool { + self.0.load(Ordering::Acquire) + } + + #[inline] + pub fn set(&self, value: bool) { + self.0.store(value, Ordering::Release) + } +} + pub trait ToPoints { fn to_points(&self, scale: f32) -> Size<Points<u32>>; } @@ -216,6 +265,7 @@ impl Window { Ok(Window { glutin_window: window, + flag: Flag::new(false), }) } @@ -256,7 +306,10 @@ impl Window { #[inline] pub fn create_window_proxy(&self) -> Proxy { - Proxy(self.glutin_window.create_window_proxy()) + Proxy { + inner: self.glutin_window.create_window_proxy(), + flag: self.flag.clone(), + } } #[inline] @@ -267,11 +320,17 @@ impl Window { } /// Block waiting for events - /// - /// FIXME should return our own type #[inline] - pub fn wait_events(&self) -> glutin::WaitEventsIterator { - self.glutin_window.wait_events() + pub fn wait_events(&self) -> WaitEventsIterator { + WaitEventsIterator { + inner: self.glutin_window.wait_events(), + flag: self.flag.clone() + } + } + + /// Clear the wakeup optimization flag + pub fn clear_wakeup_flag(&self) { + self.flag.set(false); } /// Block waiting for events @@ -289,7 +348,13 @@ impl Proxy { /// This is useful for triggering a draw when the renderer would otherwise /// be waiting on user input. pub fn wakeup_event_loop(&self) { - self.0.wakeup_event_loop(); + // Only wake up the window event loop if it hasn't already been + // signaled. This is a really important optimization because waking up + // the event loop redundantly burns *a lot* of cycles. + if !self.flag.get() { + self.inner.wakeup_event_loop(); + self.flag.set(true); + } } } |