This commit is contained in:
Antonio Scandurra 2024-01-08 19:31:50 +01:00
parent 84c36066bc
commit c9193b586b
2 changed files with 60 additions and 26 deletions

View File

@ -95,7 +95,7 @@ impl<V: Render> Element for View<V> {
}
fn paint(&mut self, _: Bounds<Pixels>, element: &mut Self::State, cx: &mut WindowContext) {
element.take().unwrap().paint(cx);
cx.with_view_id(self.entity_id(), |cx| element.take().unwrap().paint(cx));
}
}
@ -272,33 +272,36 @@ impl Element for AnyView {
}
fn paint(&mut self, bounds: Bounds<Pixels>, state: &mut Self::State, cx: &mut WindowContext) {
if !self.cache {
state.element.take().unwrap().paint(cx);
return;
}
if let Some(cache_key) = state.cache_key.as_mut() {
if cache_key.bounds == bounds
&& cache_key.content_mask == cx.content_mask()
&& cache_key.stacking_order == *cx.stacking_order()
&& cache_key.text_style == cx.text_style()
{
println!("could reuse geometry for view {}", self.entity_id());
cx.with_view_id(self.entity_id(), |cx| {
if !self.cache {
state.element.take().unwrap().paint(cx);
return;
}
}
let mut element = state
.element
.take()
.unwrap_or_else(|| (self.request_layout)(self, cx).1);
element.draw(bounds.origin, bounds.size.into(), cx);
if let Some(cache_key) = state.cache_key.as_mut() {
if cache_key.bounds == bounds
&& cache_key.content_mask == cx.content_mask()
&& cache_key.stacking_order == *cx.stacking_order()
&& cache_key.text_style == cx.text_style()
&& !cx.window.dirty_views.contains(&self.entity_id())
{
println!("could reuse geometry for view {}", self.entity_id());
}
}
state.cache_key = Some(ViewCacheKey {
bounds,
stacking_order: cx.stacking_order().clone(),
content_mask: cx.content_mask(),
text_style: cx.text_style(),
});
let mut element = state
.element
.take()
.unwrap_or_else(|| (self.request_layout)(self, cx).1);
element.draw(bounds.origin, bounds.size.into(), cx);
state.cache_key = Some(ViewCacheKey {
bounds,
stacking_order: cx.stacking_order().clone(),
content_mask: cx.content_mask(),
text_style: cx.text_style(),
});
})
}
}

View File

@ -12,7 +12,7 @@ use crate::{
VisualContext, WeakView, WindowBounds, WindowOptions, SUBPIXEL_VARIANTS,
};
use anyhow::{anyhow, Context as _, Result};
use collections::FxHashMap;
use collections::{FxHashMap, FxHashSet};
use derive_more::{Deref, DerefMut};
use futures::{
channel::{mpsc, oneshot},
@ -256,6 +256,7 @@ pub struct Window {
pub(crate) element_id_stack: GlobalElementId,
pub(crate) rendered_frame: Frame,
pub(crate) next_frame: Frame,
pub(crate) dirty_views: FxHashSet<EntityId>,
frame_arena: Arena,
pub(crate) focus_handles: Arc<RwLock<SlotMap<FocusId, AtomicUsize>>>,
focus_listeners: SubscriberSet<(), AnyWindowFocusListener>,
@ -295,6 +296,8 @@ pub(crate) struct Frame {
pub(crate) next_stacking_order_id: u32,
content_mask_stack: Vec<ContentMask<Pixels>>,
element_offset_stack: Vec<Point<Pixels>>,
pub(crate) view_parents: FxHashMap<EntityId, EntityId>,
pub(crate) view_stack: Vec<EntityId>,
}
impl Frame {
@ -310,6 +313,8 @@ impl Frame {
depth_map: Default::default(),
content_mask_stack: Vec::new(),
element_offset_stack: Vec::new(),
view_parents: FxHashMap::default(),
view_stack: Vec::new(),
}
}
@ -319,6 +324,8 @@ impl Frame {
self.dispatch_tree.clear();
self.depth_map.clear();
self.next_stacking_order_id = 0;
self.view_parents.clear();
debug_assert!(self.view_stack.is_empty());
}
fn focus_path(&self) -> SmallVec<[FocusId; 8]> {
@ -404,6 +411,7 @@ impl Window {
element_id_stack: GlobalElementId::default(),
rendered_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())),
next_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())),
dirty_views: FxHashSet::default(),
frame_arena: Arena::new(1024 * 1024),
focus_handles: Arc::new(RwLock::new(SlotMap::with_key())),
focus_listeners: SubscriberSet::new(),
@ -1423,6 +1431,7 @@ impl<'a> WindowContext<'a> {
}
self.window.drawing = false;
self.window.dirty_views.clear();
ELEMENT_ARENA.with_borrow_mut(|element_arena| element_arena.clear());
scene
@ -2119,6 +2128,13 @@ pub trait BorrowWindow: BorrowMut<Window> + BorrowMut<AppContext> {
result
}
fn with_view_id<R>(&mut self, view_id: EntityId, f: impl FnOnce(&mut Self) -> R) -> R {
self.window_mut().next_frame.view_stack.push(view_id);
let result = f(self);
self.window_mut().next_frame.view_stack.pop();
result
}
/// Update the global element offset relative to the current offset. This is used to implement
/// scrolling.
fn with_element_offset<R>(
@ -2476,6 +2492,21 @@ impl<'a, V: 'static> ViewContext<'a, V> {
}
pub fn notify(&mut self) {
let mut dirty_view_id = Some(self.view.entity_id());
while let Some(view_id) = dirty_view_id {
if self.window_cx.window.dirty_views.insert(view_id) {
dirty_view_id = self
.window_cx
.window
.rendered_frame
.view_parents
.get(&view_id)
.copied();
} else {
break;
}
}
if !self.window.drawing {
self.window_cx.notify();
self.window_cx.app.push_effect(Effect::Notify {