diff options
| author | 2019-11-03 04:39:11 +0100 | |
|---|---|---|
| committer | 2019-11-03 04:39:11 +0100 | |
| commit | 2c6bfdbc8c2262c3550fa16d4472e29d73077956 (patch) | |
| tree | 4428dea15c7ec8f9baa385927ce96264470d1915 /winit | |
| parent | ef056d84890e745010675e70f734f882f89356c2 (diff) | |
| download | iced-2c6bfdbc8c2262c3550fa16d4472e29d73077956.tar.gz iced-2c6bfdbc8c2262c3550fa16d4472e29d73077956.tar.bz2 iced-2c6bfdbc8c2262c3550fa16d4472e29d73077956.zip | |
Implement debug view and load system fonts
Diffstat (limited to '')
| -rw-r--r-- | winit/Cargo.toml | 3 | ||||
| -rw-r--r-- | winit/src/application.rs | 60 | ||||
| -rw-r--r-- | winit/src/debug/basic.rs | 206 | ||||
| -rw-r--r-- | winit/src/debug/null.rs | 48 | ||||
| -rw-r--r-- | winit/src/lib.rs | 11 | 
5 files changed, 318 insertions, 10 deletions
| diff --git a/winit/Cargo.toml b/winit/Cargo.toml index c8227ac4..2831ba2f 100644 --- a/winit/Cargo.toml +++ b/winit/Cargo.toml @@ -7,6 +7,9 @@ description = "A winit runtime for Iced"  license = "MIT"  repository = "https://github.com/hecrj/iced" +[features] +debug = [] +  [dependencies]  iced_native = { version = "0.1.0-alpha", path = "../native" }  winit = { version = "0.20.0-alpha3", git = "https://github.com/rust-windowing/winit", rev = "709808eb4e69044705fcb214bcc30556db761405"} diff --git a/winit/src/application.rs b/winit/src/application.rs index 8c7d8c37..5d1aae38 100644 --- a/winit/src/application.rs +++ b/winit/src/application.rs @@ -2,13 +2,13 @@ use crate::{      column, conversion,      input::{keyboard, mouse},      renderer::{Target, Windowed}, -    Cache, Column, Element, Event, Length, MouseCursor, UserInterface, +    Cache, Column, Debug, Element, Event, Length, MouseCursor, UserInterface,  };  pub trait Application {      type Renderer: Windowed + column::Renderer; -    type Message; +    type Message: std::fmt::Debug;      fn update(&mut self, message: Self::Message); @@ -24,6 +24,9 @@ pub trait Application {              window::WindowBuilder,          }; +        let mut debug = Debug::new(); + +        debug.startup_started();          let event_loop = EventLoop::new();          // TODO: Ask for window settings and configure this properly @@ -50,16 +53,22 @@ pub trait Application {              &renderer,          ); +        debug.layout_started();          let user_interface = UserInterface::build( -            document(&mut self, size), +            document(&mut self, size, &mut debug),              Cache::default(),              &renderer,          ); +        debug.layout_finished(); +        debug.draw_started();          let mut primitive = user_interface.draw(&mut renderer); +        debug.draw_finished(); +          let mut cache = Some(user_interface.into_cache());          let mut events = Vec::new();          let mut mouse_cursor = MouseCursor::OutOfBounds; +        debug.startup_finished();          window.request_redraw(); @@ -70,17 +79,23 @@ pub trait Application {                  //                  // This will allow us to rebuild it only when a message is                  // handled. +                debug.layout_started();                  let mut user_interface = UserInterface::build( -                    document(&mut self, size), +                    document(&mut self, size, &mut debug),                      cache.take().unwrap(),                      &renderer,                  ); +                debug.layout_finished(); +                debug.event_processing_started();                  let messages =                      user_interface.update(&renderer, events.drain(..)); +                debug.event_processing_finished();                  if messages.is_empty() { +                    debug.draw_started();                      primitive = user_interface.draw(&mut renderer); +                    debug.draw_finished();                      cache = Some(user_interface.into_cache());                  } else { @@ -91,16 +106,24 @@ pub trait Application {                      for message in messages {                          log::debug!("Updating"); +                        debug.log_message(&message); + +                        debug.update_started();                          self.update(message); +                        debug.update_finished();                      } +                    debug.layout_started();                      let user_interface = UserInterface::build( -                        document(&mut self, size), +                        document(&mut self, size, &mut debug),                          temp_cache,                          &renderer,                      ); +                    debug.layout_finished(); +                    debug.draw_started();                      primitive = user_interface.draw(&mut renderer); +                    debug.draw_finished();                      cache = Some(user_interface.into_cache());                  } @@ -108,6 +131,8 @@ pub trait Application {                  window.request_redraw();              }              event::Event::RedrawRequested(_) => { +                debug.render_started(); +                  if let Some(new_size) = new_size.take() {                      target.resize(new_size.width, new_size.height, &renderer); @@ -115,7 +140,9 @@ pub trait Application {                  }                  let new_mouse_cursor = -                    renderer.draw(&primitive, None, &mut target); +                    renderer.draw(&primitive, &debug.overlay(), &mut target); + +                debug.render_finished();                  if new_mouse_cursor != mouse_cursor {                      window.set_cursor_icon(conversion::mouse_cursor( @@ -191,6 +218,14 @@ pub trait Application {                          },                      ..                  } => { +                    match (virtual_keycode, state) { +                        ( +                            winit::event::VirtualKeyCode::F12, +                            winit::event::ElementState::Pressed, +                        ) => debug.toggle(), +                        _ => {} +                    } +                      events.push(Event::Keyboard(keyboard::Event::Input {                          key_code: conversion::key_code(virtual_keycode),                          state: conversion::button_state(state), @@ -229,17 +264,22 @@ impl From<winit::dpi::PhysicalSize> for Size {      }  } -fn document<Application>( -    application: &mut Application, +fn document<'a, Application>( +    application: &'a mut Application,      size: Size, -) -> Element<Application::Message, Application::Renderer> +    debug: &mut Debug, +) -> Element<'a, Application::Message, Application::Renderer>  where      Application: self::Application,      Application::Message: 'static,  { +    debug.view_started(); +    let view = application.view(); +    debug.view_finished(); +      Column::new()          .width(Length::Units(size.width))          .height(Length::Units(size.height)) -        .push(application.view()) +        .push(view)          .into()  } diff --git a/winit/src/debug/basic.rs b/winit/src/debug/basic.rs new file mode 100644 index 00000000..09bb5ae1 --- /dev/null +++ b/winit/src/debug/basic.rs @@ -0,0 +1,206 @@ +use std::collections::VecDeque; +use std::time; + +#[derive(Debug)] +pub struct Debug { +    is_enabled: bool, + +    startup_start: time::Instant, +    startup_duration: time::Duration, + +    update_start: time::Instant, +    update_durations: TimeBuffer, + +    view_start: time::Instant, +    view_durations: TimeBuffer, + +    layout_start: time::Instant, +    layout_durations: TimeBuffer, + +    event_start: time::Instant, +    event_durations: TimeBuffer, + +    draw_start: time::Instant, +    draw_durations: TimeBuffer, + +    render_start: time::Instant, +    render_durations: TimeBuffer, + +    message_count: usize, +    last_messages: VecDeque<String>, +} + +impl Debug { +    pub fn new() -> Self { +        let now = time::Instant::now(); + +        Self { +            is_enabled: false, +            startup_start: now, +            startup_duration: time::Duration::from_secs(0), + +            update_start: now, +            update_durations: TimeBuffer::new(200), + +            view_start: now, +            view_durations: TimeBuffer::new(200), + +            layout_start: now, +            layout_durations: TimeBuffer::new(200), + +            event_start: now, +            event_durations: TimeBuffer::new(200), + +            draw_start: now, +            draw_durations: TimeBuffer::new(200), + +            render_start: now, +            render_durations: TimeBuffer::new(50), + +            message_count: 0, +            last_messages: VecDeque::new(), +        } +    } + +    pub fn toggle(&mut self) { +        self.is_enabled = !self.is_enabled; +    } + +    pub fn startup_started(&mut self) { +        self.startup_start = time::Instant::now(); +    } + +    pub fn startup_finished(&mut self) { +        self.startup_duration = time::Instant::now() - self.startup_start; +    } + +    pub fn update_started(&mut self) { +        self.update_start = time::Instant::now(); +    } + +    pub fn update_finished(&mut self) { +        self.update_durations +            .push(time::Instant::now() - self.update_start); +    } + +    pub fn view_started(&mut self) { +        self.view_start = time::Instant::now(); +    } + +    pub fn view_finished(&mut self) { +        self.view_durations +            .push(time::Instant::now() - self.view_start); +    } + +    pub fn layout_started(&mut self) { +        self.layout_start = time::Instant::now(); +    } + +    pub fn layout_finished(&mut self) { +        self.layout_durations +            .push(time::Instant::now() - self.layout_start); +    } + +    pub fn event_processing_started(&mut self) { +        self.event_start = time::Instant::now(); +    } + +    pub fn event_processing_finished(&mut self) { +        self.event_durations +            .push(time::Instant::now() - self.event_start); +    } + +    pub fn draw_started(&mut self) { +        self.draw_start = time::Instant::now(); +    } + +    pub fn draw_finished(&mut self) { +        self.draw_durations +            .push(time::Instant::now() - self.draw_start); +    } + +    pub fn render_started(&mut self) { +        self.render_start = time::Instant::now(); +    } + +    pub fn render_finished(&mut self) { +        self.render_durations +            .push(time::Instant::now() - self.render_start); +    } + +    pub fn log_message<Message: std::fmt::Debug>(&mut self, message: &Message) { +        self.last_messages.push_back(format!("{:?}", message)); + +        if self.last_messages.len() > 10 { +            let _ = self.last_messages.pop_front(); +        } + +        self.message_count += 1; +    } + +    pub fn overlay(&self) -> Vec<String> { +        if !self.is_enabled { +            return Vec::new(); +        } + +        let mut lines = Vec::new(); + +        fn key_value<T: std::fmt::Debug>(key: &str, value: T) -> String { +            format!("{: <30} {:?}", key, value) +        } + +        lines.push(key_value("Startup:", self.startup_duration)); +        lines.push(key_value("Update:", self.update_durations.average())); +        lines.push(key_value("View:", self.view_durations.average())); +        lines.push(key_value("Layout:", self.layout_durations.average())); +        lines.push(key_value( +            "Event processing:", +            self.event_durations.average(), +        )); +        lines.push(key_value( +            "Primitive generation:", +            self.draw_durations.average(), +        )); +        lines.push(key_value("Render:", self.render_durations.average())); +        lines.push(key_value("Message count:", self.message_count)); +        lines.push(String::from("Last messages:")); +        lines.extend( +            self.last_messages.iter().map(|msg| format!("    {}", msg)), +        ); + +        lines +    } +} + +#[derive(Debug)] +struct TimeBuffer { +    head: usize, +    size: usize, +    contents: Vec<time::Duration>, +} + +impl TimeBuffer { +    fn new(capacity: usize) -> TimeBuffer { +        TimeBuffer { +            head: 0, +            size: 0, +            contents: vec![time::Duration::from_secs(0); capacity], +        } +    } + +    fn push(&mut self, duration: time::Duration) { +        self.head = (self.head + 1) % self.contents.len(); +        self.contents[self.head] = duration; +        self.size = (self.size + 1).min(self.contents.len()); +    } + +    fn average(&self) -> time::Duration { +        let sum: time::Duration = if self.size == self.contents.len() { +            self.contents[..].iter().sum() +        } else { +            self.contents[..self.size].iter().sum() +        }; + +        sum / self.size.max(1) as u32 +    } +} diff --git a/winit/src/debug/null.rs b/winit/src/debug/null.rs new file mode 100644 index 00000000..9c809dd4 --- /dev/null +++ b/winit/src/debug/null.rs @@ -0,0 +1,48 @@ +#[derive(Debug)] +pub struct Debug; + +impl Debug { +    pub fn new() -> Self { +        Self +    } + +    pub fn toggle(&mut self) {} + +    pub fn startup_started(&mut self) {} + +    pub fn startup_finished(&mut self) {} + +    pub fn update_started(&mut self) {} + +    pub fn update_finished(&mut self) {} + +    pub fn view_started(&mut self) {} + +    pub fn view_finished(&mut self) {} + +    pub fn layout_started(&mut self) {} + +    pub fn layout_finished(&mut self) {} + +    pub fn event_processing_started(&mut self) {} + +    pub fn event_processing_finished(&mut self) {} + +    pub fn draw_started(&mut self) {} + +    pub fn draw_finished(&mut self) {} + +    pub fn render_started(&mut self) {} + +    pub fn render_finished(&mut self) {} + +    pub fn log_message<Message: std::fmt::Debug>( +        &mut self, +        _message: &Message, +    ) { +    } + +    pub fn overlay(&self) -> Vec<String> { +        Vec::new() +    } +} diff --git a/winit/src/lib.rs b/winit/src/lib.rs index b08fcb6c..f66c0553 100644 --- a/winit/src/lib.rs +++ b/winit/src/lib.rs @@ -6,3 +6,14 @@ pub mod conversion;  mod application;  pub use application::Application; + +// We disable debug capabilities on release builds unless the `debug` feature +// is explicitly enabled. +#[cfg_attr(any(debug_assertions, feature = "debug"), path = "debug/basic.rs")] +#[cfg_attr( +    not(any(debug_assertions, feature = "debug")), +    path = "debug/null.rs" +)] +mod debug; + +use debug::Debug; | 
