diff --git a/src/backends/metal/video.rs b/src/backends/metal/video.rs index 90a8426e..e8e63fff 100644 --- a/src/backends/metal/video.rs +++ b/src/backends/metal/video.rs @@ -923,6 +923,7 @@ impl MetalConnector { if let Some(node) = self.state.root.outputs.get(&self.connector_id) { let buffer = &buffers[self.next_buffer.get() % buffers.len()]; let mut rr = self.render_result.borrow_mut(); + rr.output_id = node.id; let fb = self.prepare_present_fb(&mut rr, buffer, &plane, &node, try_direct_scanout)?; rr.dispatch_frame_requests(); diff --git a/src/ifs/wl_surface.rs b/src/ifs/wl_surface.rs index c319354c..103b1e50 100644 --- a/src/ifs/wl_surface.rs +++ b/src/ifs/wl_surface.rs @@ -63,7 +63,7 @@ use { renderer::Renderer, tree::{ ContainerNode, FindTreeResult, FoundNode, Node, NodeId, NodeVisitor, NodeVisitorBase, - OutputNode, PlaceholderNode, ToplevelNode, + OutputNode, OutputNodeId, PlaceholderNode, ToplevelNode, }, utils::{ cell_ext::CellExt, clonecell::CloneCell, copyhashmap::CopyHashMap, errorfmt::ErrorFmt, @@ -82,7 +82,7 @@ use { xwayland::XWaylandEvent, }, ahash::AHashMap, - isnt::std_1::primitive::IsntSliceExt, + isnt::std_1::{primitive::IsntSliceExt, vec::IsntVecExt}, jay_config::video::Transform, std::{ cell::{Cell, RefCell}, @@ -265,6 +265,7 @@ pub struct WlSurface { pub buffer_abs_pos: Cell, pub need_extents_update: Cell, pub buffer: CloneCell>>, + buffer_presented: Cell, pub shm_texture: CloneCell>>, pub buf_x: NumCell, pub buf_y: NumCell, @@ -536,6 +537,10 @@ impl PendingState { self.buffer_damage.clear(); self.surface_damage.clear(); } + + fn has_damage(&self) -> bool { + self.damage_full || self.buffer_damage.is_not_empty() || self.surface_damage.is_not_empty() + } } #[derive(Default)] @@ -571,6 +576,7 @@ impl WlSurface { buffer_abs_pos: Cell::new(Default::default()), need_extents_update: Default::default(), buffer: Default::default(), + buffer_presented: Default::default(), shm_texture: Default::default(), buf_x: Default::default(), buf_y: Default::default(), @@ -1073,6 +1079,9 @@ impl WlSurface { release, }; self.buffer.set(Some(Rc::new(surface_buffer))); + if pending.has_damage() { + self.buffer_presented.set(false); + } } else { self.shm_texture.take(); self.buf_x.set(0); @@ -1216,6 +1225,14 @@ impl WlSurface { } } self.ext.get().after_apply_commit(); + if self.visible.get() { + if self.buffer_presented.get() { + for fr in self.frame_requests.borrow_mut().drain(..) { + fr.send_done(); + let _ = fr.client.remove_obj(&*fr); + } + } + } self.client.state.damage(); pending.buffer_damage.clear(); pending.surface_damage.clear(); @@ -1328,6 +1345,12 @@ impl WlSurface { self.seat_state.set_visible(self, visible); } + pub fn presented(&self, on: OutputNodeId) { + if on == self.output.get().id { + self.buffer_presented.set(true); + } + } + pub fn detach_node(&self, set_invisible: bool) { for (_, constraint) in &self.constraints { constraint.deactivate(); diff --git a/src/macros.rs b/src/macros.rs index 680d771d..e9327d7b 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -294,6 +294,11 @@ macro_rules! tree_id { pub fn raw(&self) -> u32 { self.0 } + + #[allow(dead_code)] + pub fn none() -> Self { + Self(0) + } } impl std::fmt::Display for $id { diff --git a/src/renderer.rs b/src/renderer.rs index fdd7df9a..7ee9106e 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -17,8 +17,8 @@ use { state::State, theme::Color, tree::{ - ContainerNode, DisplayNode, FloatNode, OutputNode, PlaceholderNode, ToplevelData, - ToplevelNodeBase, WorkspaceNode, + ContainerNode, DisplayNode, FloatNode, OutputNode, OutputNodeId, PlaceholderNode, + ToplevelData, ToplevelNodeBase, WorkspaceNode, }, }, std::{ @@ -31,10 +31,20 @@ use { pub mod renderer_base; -#[derive(Default)] pub struct RenderResult { pub frame_requests: Vec>, pub presentation_feedbacks: Vec>, + pub output_id: OutputNodeId, +} + +impl Default for RenderResult { + fn default() -> Self { + Self { + frame_requests: Default::default(), + presentation_feedbacks: Default::default(), + output_id: OutputNodeId::none(), + } + } } impl RenderResult { @@ -441,6 +451,7 @@ impl Renderer<'_> { let mut fbs = surface.presentation_feedback.borrow_mut(); result.presentation_feedbacks.extend(fbs.drain(..)); } + surface.presented(result.output_id); } }