diff --git a/crates/common/src/compositor.rs b/crates/common/src/compositor.rs index 4a4ab275f..6b58e7665 100644 --- a/crates/common/src/compositor.rs +++ b/crates/common/src/compositor.rs @@ -5,19 +5,19 @@ use std::ops::{ use freya_native_core::NodeId; use itertools::sorted; -use rustc_hash::{ - FxHashMap, - FxHashSet, +use rustc_hash::FxHashSet; +use torin::prelude::{ + Area, + Torin, }; -use torin::prelude::Area; use crate::Layers; #[derive(Clone, Default)] -pub struct CompositorDirtyNodes(FxHashMap); +pub struct CompositorDirtyNodes(FxHashSet); impl Deref for CompositorDirtyNodes { - type Target = FxHashMap; + type Target = FxHashSet; fn deref(&self) -> &Self::Target { &self.0 @@ -31,14 +31,9 @@ impl DerefMut for CompositorDirtyNodes { } impl CompositorDirtyNodes { - /// Mark a certain node as invalidated. Uses [DirtyTarget::Itself] by default. + /// Mark a certain node as invalidated. pub fn invalidate(&mut self, node_id: NodeId) { - self.0.insert(node_id, DirtyTarget::Itself); - } - - /// Mark a certain node as invalidated with the given [DirtyTarget]. - pub fn invalidate_with_target(&mut self, node_id: NodeId, target: DirtyTarget) { - self.0.insert(node_id, target); + self.0.insert(node_id); } } @@ -87,12 +82,6 @@ pub struct Compositor { full_render: bool, } -#[derive(Clone, Copy, PartialEq)] -pub enum DirtyTarget { - Itself, - ItselfAndNested, -} - impl Compositor { /// Run the compositor to obtain the rendering layers and the dirty area. pub fn run<'a>( @@ -101,8 +90,7 @@ impl Compositor { dirty_area: &mut CompositorDirtyArea, layers: &'a Layers, dirty_layers: &'a mut Layers, - get_area: impl Fn(NodeId) -> Option, - get_affected: impl Fn(NodeId, bool) -> Vec, + layout: &Torin, ) -> &'a Layers { if self.full_render { dirty_nodes.clear(); @@ -111,37 +99,15 @@ impl Compositor { return layers; } - let (mut invalidated_nodes, mut dirty_nodes) = { - ( - FxHashSet::from_iter(dirty_nodes.keys().copied()), - dirty_nodes.drain().collect::>(), - ) - }; - - // Mark children - while let Some((node_id, target)) = dirty_nodes.pop() { - // Mark this node as invalidated - invalidated_nodes.insert(node_id); - - let traverse_children = target == DirtyTarget::ItselfAndNested; - let affected = get_affected(node_id, traverse_children) - .into_iter() - .filter(|id| !invalidated_nodes.contains(id)); - - // Continue searching in the affected nodes - dirty_nodes.extend( - affected - .into_iter() - .map(|id| (id, DirtyTarget::ItselfAndNested)), - ); - } - let mut run_check = |layer: i16, nodes: &[NodeId]| { for node_id in nodes { - let Some(area) = get_area(*node_id) else { + let Some(area) = layout + .get(*node_id) + .map(|layout_node| layout_node.visible_area()) + else { continue; }; - let is_invalidated = invalidated_nodes.contains(node_id); + let is_invalidated = dirty_nodes.contains(node_id); let is_area_invalidated = dirty_area.intersects(&area); if is_invalidated || is_area_invalidated { @@ -166,6 +132,8 @@ impl Compositor { run_check(*layer, nodes); } + dirty_nodes.drain(); + dirty_layers } diff --git a/crates/core/src/render.rs b/crates/core/src/render.rs index 957188ec3..65499bd73 100644 --- a/crates/core/src/render.rs +++ b/crates/core/src/render.rs @@ -17,7 +17,6 @@ use freya_native_core::{ use freya_node_state::ViewportState; use itertools::sorted; use torin::prelude::{ - Area, LayoutNode, Torin, }; @@ -43,42 +42,21 @@ pub fn process_render( let mut dirty_layers = Layers::default(); + // Process what nodes need to be rendered let rendering_layers = compositor.run( &mut compositor_dirty_nodes, &mut compositor_dirty_area, &layers, &mut dirty_layers, - |node| layout.get(node).map(|node| node.area), - |node, try_traverse_children| { - let node = rdom.get(node); - if let Some(node) = node { - let traverse_children = node - .node_type() - .tag() - .map(|tag| !tag.contains_text()) - .unwrap_or_default(); - let mut affected = if traverse_children && try_traverse_children { - node.child_ids() - } else { - Vec::new() - }; - - if !node.node_type().is_visible_element() { - if let Some(parent_id) = node.parent_id() { - affected.push(parent_id); - } - } - affected - } else { - Vec::new() - } - }, + &layout, ); dirty_canvas.save(); - let compositor_dirty_area: &Option = &compositor_dirty_area; - if let Some(dirty_area) = compositor_dirty_area { - // Clear using the configured window background only the dirty + + compositor_dirty_area.round_out(); + + if let Some(dirty_area) = compositor_dirty_area.take() { + // Clear using the the background only, but only the dirty // area in which it will render the intersected nodes again dirty_canvas.clip_rect( Rect::new( @@ -93,8 +71,6 @@ pub fn process_render( dirty_canvas.clear(background); } - let mut painted = Vec::new(); - // Render the layers for (_, nodes) in sorted(rendering_layers.iter()) { 'elements: for node_id in nodes { @@ -114,7 +90,6 @@ pub fn process_render( // Render the element render_fn(fdom, node_id, layout_node, &layout, dirty_canvas); - painted.push(node_id); } } } diff --git a/crates/state/src/layout.rs b/crates/state/src/layout.rs index d2c712138..7ba2cc5db 100644 --- a/crates/state/src/layout.rs +++ b/crates/state/src/layout.rs @@ -3,10 +3,7 @@ use std::sync::{ Mutex, }; -use freya_common::{ - CompositorDirtyNodes, - DirtyTarget, -}; +use freya_common::CompositorDirtyNodes; use freya_native_core::{ attributes::AttributeName, exports::shipyard::Component, @@ -238,7 +235,7 @@ impl State for LayoutState { compositor_dirty_nodes .lock() .unwrap() - .invalidate_with_target(node_view.node_id(), DirtyTarget::ItselfAndNested); + .invalidate(node_view.node_id()); } *self = layout;