Skip to content

Commit

Permalink
[WIP] Implement damage tracking in iced_glutin
Browse files Browse the repository at this point in the history
  • Loading branch information
valpackett committed Jul 19, 2020
1 parent cc1577d commit b7025dd
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 37 deletions.
87 changes: 62 additions & 25 deletions glutin/src/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
use crate::{mouse, Executor, Runtime, Size};
use iced_graphics::window;
use iced_graphics::Viewport;
use iced_native::Damage;
use iced_winit::application;
use iced_winit::conversion;
use iced_winit::{Clipboard, Debug, Proxy, Settings};
Expand Down Expand Up @@ -97,13 +98,18 @@ pub fn run<A, E, C>(
);
debug.startup_finished();

let mut damage = <<A as iced_native::program::Program>::Renderer
as iced_native::Renderer>::Output::default().damage(&state.primitive());

let mut first = true;

event_loop.run(move |event, _, control_flow| match event {
event::Event::MainEventsCleared => {
if state.is_queue_empty() {
return;
}

let command = runtime.enter(|| {
let (command, new_damage) = runtime.enter(|| {
state.update(
viewport.logical_size(),
conversion::cursor_position(
Expand All @@ -116,6 +122,17 @@ pub fn run<A, E, C>(
)
});

eprintln!("{:?}", new_damage);
if !first {
damage = None;
if let Some(dmg) = new_damage {
if dmg.len() > 0 {
damage = Some(dmg);
}
}
}
first = false;

// If the application was updated
if let Some(command) = command {
runtime.spawn(command);
Expand Down Expand Up @@ -187,39 +204,59 @@ pub fn run<A, E, C>(
state.queue_message(message);
}
event::Event::RedrawRequested(_) => {
debug.render_started();

if resized {
if let Some(damage) = damage.take() {
debug.render_started();
let physical_size = viewport.physical_size();

context.resize(glutin::dpi::PhysicalSize::new(
physical_size.width,
physical_size.height,
));
if resized {
context.resize(glutin::dpi::PhysicalSize::new(
physical_size.width,
physical_size.height,
));

compositor.resize_viewport(physical_size);
compositor.resize_viewport(physical_size);

resized = false;
}
resized = false;
}

let new_mouse_interaction = compositor.draw(
&mut renderer,
&viewport,
background_color,
state.primitive(),
&debug.overlay(),
);
let new_mouse_interaction = compositor.draw(
&mut renderer,
&viewport,
background_color,
state.primitive(),
&debug.overlay(),
);

context.swap_buffers().expect("Swap buffers");
if context.swap_buffers_with_damage_supported() {
let scale = viewport.scale_factor() as f32;
let rects = damage
.iter()
.map(|dmg| (*dmg * scale).snap())
.map(|dmg| glutin::Rect {
x: dmg.x,
y: physical_size
.height
.saturating_sub(dmg.y + dmg.height),
width: dmg.width.min(physical_size.width),
height: dmg.height.min(physical_size.height),
})
.collect::<Vec<_>>();
context
.swap_buffers_with_damage(&rects[..])
.expect("Swap buffers with damage");
} else {
context.swap_buffers().expect("Swap buffers");
}

debug.render_finished();
debug.render_finished();

if new_mouse_interaction != mouse_interaction {
context.window().set_cursor_icon(
conversion::mouse_interaction(new_mouse_interaction),
);
if new_mouse_interaction != mouse_interaction {
context.window().set_cursor_icon(
conversion::mouse_interaction(new_mouse_interaction),
);

mouse_interaction = new_mouse_interaction;
mouse_interaction = new_mouse_interaction;
}
}

// TODO: Handle animations!
Expand Down
23 changes: 15 additions & 8 deletions native/src/program/state.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
Cache, Clipboard, Command, Debug, Event, Point, Program, Renderer, Size,
UserInterface,
Cache, Clipboard, Command, Damage, Debug, Event, Point, Program, Rectangle,
Renderer, Size, UserInterface,
};

/// The execution state of a [`Program`]. It leverages caching, event
Expand Down Expand Up @@ -100,7 +100,8 @@ where
/// the widgets of the linked [`Program`] if necessary.
///
/// Returns the [`Command`] obtained from [`Program`] after updating it,
/// only if an update was necessary.
/// only if an update was necessary; and a damage rectangle if any pixels
/// changed from the previous frame.
///
/// [`Program`]: trait.Program.html
pub fn update(
Expand All @@ -110,7 +111,7 @@ where
clipboard: Option<&dyn Clipboard>,
renderer: &mut P::Renderer,
debug: &mut Debug,
) -> Option<Command<P::Message>> {
) -> (Option<Command<P::Message>>, Option<Vec<Rectangle>>) {
let mut user_interface = build_user_interface(
&mut self.program,
self.cache.take().unwrap(),
Expand All @@ -133,12 +134,15 @@ where

if messages.is_empty() {
debug.draw_started();
self.primitive = user_interface.draw(renderer, cursor_position);
let primitive = user_interface.draw(renderer, cursor_position);
debug.draw_finished();

self.cache = Some(user_interface.into_cache());

None
let damage = self.primitive.damage(&primitive);
self.primitive = primitive;

(None, damage)
} else {
// When there are messages, we are forced to rebuild twice
// for now :^)
Expand All @@ -164,12 +168,15 @@ where
);

debug.draw_started();
self.primitive = user_interface.draw(renderer, cursor_position);
let primitive = user_interface.draw(renderer, cursor_position);
debug.draw_finished();

self.cache = Some(user_interface.into_cache());

Some(commands)
let damage = self.primitive.damage(&primitive);
self.primitive = primitive;

(Some(commands), damage)
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions native/src/renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ use crate::{layout, Element, Rectangle};
/// updated between two frames.
pub trait Damage {
/// Calculates damage between two frames
fn damage(&self, other: &Self) -> Option<Rectangle>;
fn damage(&self, other: &Self) -> Option<Vec<Rectangle>>;
}

impl Damage for () {
fn damage(&self, _other: &Self) -> Option<Rectangle> {
fn damage(&self, _other: &Self) -> Option<Vec<Rectangle>> {
None
}
}
Expand All @@ -44,7 +44,7 @@ impl<T, U> Damage for (T, U)
where
T: Damage,
{
fn damage(&self, other: &Self) -> Option<Rectangle> {
fn damage(&self, other: &Self) -> Option<Vec<Rectangle>> {
self.0.damage(&other.0)
}
}
Expand Down
2 changes: 1 addition & 1 deletion winit/src/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ pub fn run<A, E, C>(
return;
}

let command = runtime.enter(|| {
let (command, _damage) = runtime.enter(|| {
state.update(
viewport.logical_size(),
conversion::cursor_position(
Expand Down

0 comments on commit b7025dd

Please sign in to comment.