fix: submit tracked nested output damage
This commit is contained in:
1 parent
bcd841ca23
commit
0a98bead56
1 file changed
+119
-23
+119
-23
@@ -61,6 +61,9 @@ type MemoryRenderElement = CropRenderElement<
|
|||||||
RelocateRenderElement<RescaleRenderElement<MemoryRenderBufferRenderElement<GlesRenderer>>>,
|
RelocateRenderElement<RescaleRenderElement<MemoryRenderBufferRenderElement<GlesRenderer>>>,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
type PhysicalDamage = Vec<Rectangle<i32, Physical>>;
|
||||||
|
type DamageRenderResult = Result<Option<PhysicalDamage>, Box<dyn Error>>;
|
||||||
|
|
||||||
render_elements! {
|
render_elements! {
|
||||||
pub(crate) AnimatedWindowRenderElement<=GlesRenderer>;
|
pub(crate) AnimatedWindowRenderElement<=GlesRenderer>;
|
||||||
Window=WindowRenderElement,
|
Window=WindowRenderElement,
|
||||||
@@ -403,31 +406,16 @@ pub fn init(event_loop: &mut EventLoop<Ferese>, state: &mut Ferese) -> Result<()
|
|||||||
WinitEvent::Input(event) => state.process_input_event(event),
|
WinitEvent::Input(event) => state.process_input_event(event),
|
||||||
WinitEvent::Redraw => {
|
WinitEvent::Redraw => {
|
||||||
state.advance_animations(Instant::now());
|
state.advance_animations(Instant::now());
|
||||||
let damage = Rectangle::from_size(backend.window_size());
|
let age = backend.buffer_age().unwrap_or(0);
|
||||||
let mut presentation = OutputPresentationFeedback::new(&output);
|
let rendered = (|| -> DamageRenderResult {
|
||||||
state.space.elements().for_each(|window| {
|
|
||||||
window.take_presentation_feedback(
|
|
||||||
&mut presentation,
|
|
||||||
|_, _| Some(output.clone()),
|
|
||||||
|_, _| PresentationKind::Vsync,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
layer_surfaces(&output).iter().for_each(|layer| {
|
|
||||||
layer.take_presentation_feedback(
|
|
||||||
&mut presentation,
|
|
||||||
|_, _| Some(output.clone()),
|
|
||||||
|_, _| PresentationKind::Vsync,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
let rendered = (|| -> Result<(), Box<dyn Error>> {
|
|
||||||
{
|
{
|
||||||
let (renderer, mut framebuffer) = backend.bind()?;
|
let (renderer, mut framebuffer) = backend.bind()?;
|
||||||
state.process_dmabuf_imports(renderer);
|
state.process_dmabuf_imports(renderer);
|
||||||
let elements = animated_window_elements(state, renderer, &output);
|
let elements = animated_window_elements(state, renderer, &output);
|
||||||
damage_tracker.render_output(
|
let result = damage_tracker.render_output(
|
||||||
renderer,
|
renderer,
|
||||||
&mut framebuffer,
|
&mut framebuffer,
|
||||||
0,
|
age,
|
||||||
&elements,
|
&elements,
|
||||||
[0.035, 0.04, 0.055, 1.0],
|
[0.035, 0.04, 0.055, 1.0],
|
||||||
)?;
|
)?;
|
||||||
@@ -455,15 +443,49 @@ pub fn init(event_loop: &mut EventLoop<Ferese>, state: &mut Ferese) -> Result<()
|
|||||||
)?
|
)?
|
||||||
.finish()?;
|
.finish()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(result.damage.cloned())
|
||||||
}
|
}
|
||||||
backend.submit(Some(&[damage]))?;
|
|
||||||
Ok(())
|
|
||||||
})();
|
})();
|
||||||
if let Err(error) = rendered {
|
let damage = match rendered {
|
||||||
|
Ok(Some(damage)) => damage,
|
||||||
|
Ok(None) => {
|
||||||
|
state.space.refresh();
|
||||||
|
state.popups.cleanup();
|
||||||
|
layer_map_for_output(&output).cleanup();
|
||||||
|
if let Err(error) = state.display_handle.flush_clients() {
|
||||||
|
tracing::debug!(%error, "failed to flush clients");
|
||||||
|
}
|
||||||
|
backend.window().request_redraw();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Err(error) => {
|
||||||
tracing::error!(%error, "nested renderer failed");
|
tracing::error!(%error, "nested renderer failed");
|
||||||
state.loop_signal.stop();
|
state.loop_signal.stop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
if let Err(error) = backend.submit(Some(&damage)) {
|
||||||
|
tracing::error!(%error, "nested buffer submission failed");
|
||||||
|
state.loop_signal.stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut presentation = OutputPresentationFeedback::new(&output);
|
||||||
|
state.space.elements().for_each(|window| {
|
||||||
|
window.take_presentation_feedback(
|
||||||
|
&mut presentation,
|
||||||
|
|_, _| Some(output.clone()),
|
||||||
|
|_, _| PresentationKind::Vsync,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
layer_surfaces(&output).iter().for_each(|layer| {
|
||||||
|
layer.take_presentation_feedback(
|
||||||
|
&mut presentation,
|
||||||
|
|_, _| Some(output.clone()),
|
||||||
|
|_, _| PresentationKind::Vsync,
|
||||||
|
);
|
||||||
|
});
|
||||||
sequence = sequence.wrapping_add(1);
|
sequence = sequence.wrapping_add(1);
|
||||||
presentation.presented(
|
presentation.presented(
|
||||||
clock.now(),
|
clock.now(),
|
||||||
@@ -1173,13 +1195,58 @@ fn normalized_scale(scale: f64) -> f64 {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use smithay::utils::{Logical, Physical, Rectangle, Transform};
|
use smithay::{
|
||||||
|
backend::renderer::{
|
||||||
|
damage::OutputDamageTracker,
|
||||||
|
element::{Element, Id},
|
||||||
|
utils::CommitCounter,
|
||||||
|
},
|
||||||
|
utils::{Buffer, Logical, Physical, Rectangle, Scale, Transform},
|
||||||
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
color_with_alpha, framebuffer_clip_rect, normalized_scale, rounded_visual_rect,
|
color_with_alpha, framebuffer_clip_rect, normalized_scale, rounded_visual_rect,
|
||||||
scaled_visual_rect, shadow_bounds,
|
scaled_visual_rect, shadow_bounds,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct DamageElement {
|
||||||
|
id: Id,
|
||||||
|
geometry: Rectangle<i32, Logical>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DamageElement {
|
||||||
|
fn new(geometry: Rectangle<i32, Logical>) -> Self {
|
||||||
|
Self {
|
||||||
|
id: Id::new(),
|
||||||
|
geometry,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Element for DamageElement {
|
||||||
|
fn id(&self) -> &Id {
|
||||||
|
&self.id
|
||||||
|
}
|
||||||
|
|
||||||
|
fn current_commit(&self) -> CommitCounter {
|
||||||
|
CommitCounter::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn src(&self) -> Rectangle<f64, Buffer> {
|
||||||
|
Rectangle::from_size(
|
||||||
|
self.geometry
|
||||||
|
.size
|
||||||
|
.to_f64()
|
||||||
|
.to_buffer(1.0, Transform::Normal),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn geometry(&self, scale: Scale<f64>) -> Rectangle<i32, Physical> {
|
||||||
|
self.geometry.to_physical_precise_round(scale)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn accepts_positive_finite_scale() {
|
fn accepts_positive_finite_scale() {
|
||||||
assert_eq!(normalized_scale(1.25), 1.25);
|
assert_eq!(normalized_scale(1.25), 1.25);
|
||||||
@@ -1230,6 +1297,35 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn damage_tracks_old_and_new_expanded_shadow_bounds() {
|
||||||
|
let old_window = Rectangle::<i32, Logical>::new((100, 80).into(), (400, 300).into());
|
||||||
|
let new_window = Rectangle::<i32, Logical>::new((300, 180).into(), (400, 300).into());
|
||||||
|
let mut shadow = DamageElement::new(shadow_bounds(old_window, 4.0, 18.0));
|
||||||
|
let mut tracker =
|
||||||
|
OutputDamageTracker::new((1_000, 800), Scale::from(1.0), Transform::Normal);
|
||||||
|
|
||||||
|
tracker.damage_output(0, &[&shadow]).unwrap();
|
||||||
|
shadow.geometry = shadow_bounds(new_window, 4.0, 18.0);
|
||||||
|
let damage = tracker
|
||||||
|
.damage_output(1, &[&shadow])
|
||||||
|
.unwrap()
|
||||||
|
.0
|
||||||
|
.cloned()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert!(damage.iter().any(|rect| rect.contains((64, 48))));
|
||||||
|
assert!(damage.iter().any(|rect| rect.contains((735, 519))));
|
||||||
|
|
||||||
|
let removal_damage = tracker
|
||||||
|
.damage_output::<&DamageElement>(1, &[])
|
||||||
|
.unwrap()
|
||||||
|
.0
|
||||||
|
.cloned()
|
||||||
|
.unwrap();
|
||||||
|
assert!(removal_damage.iter().any(|rect| rect.contains((300, 180))));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn close_transform_scales_about_the_window_center() {
|
fn close_transform_scales_about_the_window_center() {
|
||||||
let rect = ferese_layout::Rect::new(100.0, 50.0, 400.0, 300.0);
|
let rect = ferese_layout::Rect::new(100.0, 50.0, 400.0, 300.0);
|
||||||
|
|||||||
Reference in new issue
Block a user