Skip to content

Commit

Permalink
refactor: Fixes and improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
marc2332 committed Aug 15, 2024
1 parent 88a4975 commit e3271f7
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 85 deletions.
64 changes: 16 additions & 48 deletions crates/common/src/compositor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<NodeId, DirtyTarget>);
pub struct CompositorDirtyNodes(FxHashSet<NodeId>);

impl Deref for CompositorDirtyNodes {
type Target = FxHashMap<NodeId, DirtyTarget>;
type Target = FxHashSet<NodeId>;

fn deref(&self) -> &Self::Target {
&self.0
Expand All @@ -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);
}
}

Expand Down Expand Up @@ -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>(
Expand All @@ -101,8 +90,7 @@ impl Compositor {
dirty_area: &mut CompositorDirtyArea,
layers: &'a Layers,
dirty_layers: &'a mut Layers,
get_area: impl Fn(NodeId) -> Option<Area>,
get_affected: impl Fn(NodeId, bool) -> Vec<NodeId>,
layout: &Torin<NodeId>,
) -> &'a Layers {
if self.full_render {
dirty_nodes.clear();
Expand All @@ -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::<Vec<(NodeId, DirtyTarget)>>(),
)
};

// 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 {
Expand All @@ -166,6 +132,8 @@ impl Compositor {
run_check(*layer, nodes);
}

dirty_nodes.drain();

dirty_layers
}

Expand Down
39 changes: 7 additions & 32 deletions crates/core/src/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ use freya_native_core::{
use freya_node_state::ViewportState;
use itertools::sorted;
use torin::prelude::{
Area,
LayoutNode,
Torin,
};
Expand All @@ -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<Area> = &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(
Expand All @@ -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 {
Expand All @@ -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);
}
}
}
Expand Down
7 changes: 2 additions & 5 deletions crates/state/src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -238,7 +235,7 @@ impl State<CustomAttributeValues> for LayoutState {
compositor_dirty_nodes
.lock()
.unwrap()
.invalidate_with_target(node_view.node_id(), DirtyTarget::ItselfAndNested);
.invalidate(node_view.node_id());
}

*self = layout;
Expand Down

0 comments on commit e3271f7

Please sign in to comment.