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 Jun 5, 2020
1 parent 32018c0 commit 45330d1
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 37 deletions.
85 changes: 61 additions & 24 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 @@ -93,9 +94,14 @@ 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 => {
let command = runtime.enter(|| {
let (command, new_damage) = runtime.enter(|| {
state.update(
clipboard.as_ref().map(|c| c as _),
viewport.logical_size(),
Expand All @@ -104,6 +110,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 @@ -142,38 +159,58 @@ 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,
state.primitive(),
&debug.overlay(),
);
let new_mouse_interaction = compositor.draw(
&mut renderer,
&viewport,
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).round())
.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
25 changes: 16 additions & 9 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, Program, Renderer, Size,
UserInterface,
Cache, Clipboard, Command, Damage, Debug, Event, Program, Rectangle,
Renderer, Size, UserInterface,
};

/// The execution state of a [`Program`]. It leverages caching, event
Expand Down Expand Up @@ -92,7 +92,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 @@ -101,9 +102,9 @@ where
bounds: Size,
renderer: &mut P::Renderer,
debug: &mut Debug,
) -> Option<Command<P::Message>> {
) -> (Option<Command<P::Message>>, Option<Vec<Rectangle>>) {
if self.queued_events.is_empty() && self.queued_messages.is_empty() {
return None;
return (None, None);
}

let mut user_interface = build_user_interface(
Expand All @@ -125,12 +126,15 @@ where

if messages.is_empty() {
debug.draw_started();
self.primitive = user_interface.draw(renderer);
let primitive = user_interface.draw(renderer);
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 @@ -156,12 +160,15 @@ where
);

debug.draw_started();
self.primitive = user_interface.draw(renderer);
let primitive = user_interface.draw(renderer);
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 @@ -150,7 +150,7 @@ pub fn run<A, E, C>(

event_loop.run(move |event, _, control_flow| match event {
event::Event::MainEventsCleared => {
let command = runtime.enter(|| {
let (command, _damage) = runtime.enter(|| {
state.update(
clipboard.as_ref().map(|c| c as _),
viewport.logical_size(),
Expand Down

0 comments on commit 45330d1

Please sign in to comment.