Insert primitives associated with views from a previous scene

Antonio Scandurra created

Change summary

crates/gpui/src/app/entity_map.rs |   8 +
crates/gpui/src/key_dispatch.rs   |   3 
crates/gpui/src/scene.rs          | 218 +++++++++++++++++++-------------
crates/gpui/src/view.rs           |   2 
crates/gpui/src/window.rs         |  41 +++--
5 files changed, 164 insertions(+), 108 deletions(-)

Detailed changes

crates/gpui/src/app/entity_map.rs 🔗

@@ -2,7 +2,7 @@ use crate::{seal::Sealed, AppContext, Context, Entity, ModelContext};
 use anyhow::{anyhow, Result};
 use derive_more::{Deref, DerefMut};
 use parking_lot::{RwLock, RwLockUpgradableReadGuard};
-use slotmap::{SecondaryMap, SlotMap};
+use slotmap::{KeyData, SecondaryMap, SlotMap};
 use std::{
     any::{type_name, Any, TypeId},
     fmt::{self, Display},
@@ -21,6 +21,12 @@ use collections::HashMap;
 
 slotmap::new_key_type! { pub struct EntityId; }
 
+impl From<u64> for EntityId {
+    fn from(value: u64) -> Self {
+        Self(KeyData::from_ffi(value))
+    }
+}
+
 impl EntityId {
     pub fn as_u64(self) -> u64 {
         self.0.as_ffi()

crates/gpui/src/key_dispatch.rs 🔗

@@ -144,6 +144,8 @@ impl DispatchTree {
                 if source_node.parent != Some(*source_ancestor) {
                     source_stack.pop();
                     self.pop_node();
+                } else {
+                    break;
                 }
             }
 
@@ -159,6 +161,7 @@ impl DispatchTree {
         }
 
         while !source_stack.is_empty() {
+            source_stack.pop();
             self.pop_node();
         }
 

crates/gpui/src/scene.rs 🔗

@@ -1,9 +1,9 @@
 use crate::{
-    point, AtlasTextureId, AtlasTile, Bounds, ContentMask, Corners, Edges, Hsla, Pixels, Point,
-    ScaledPixels, StackingOrder,
+    point, AtlasTextureId, AtlasTile, Bounds, ContentMask, Corners, Edges, EntityId, Hsla, Pixels,
+    Point, ScaledPixels, StackingOrder,
 };
-use collections::BTreeMap;
-use std::{fmt::Debug, iter::Peekable, mem, slice};
+use collections::{BTreeMap, FxHashSet};
+use std::{fmt::Debug, iter::Peekable, slice};
 
 // Exported to metal
 pub(crate) type PointF = Point<f32>;
@@ -14,7 +14,7 @@ pub type LayerId = u32;
 pub type DrawOrder = u32;
 
 #[derive(Default)]
-pub(crate) struct SceneBuilder {
+pub struct Scene {
     layers_by_order: BTreeMap<StackingOrder, LayerId>,
     orders_by_layer: BTreeMap<LayerId, StackingOrder>,
     shadows: Vec<Shadow>,
@@ -26,57 +26,46 @@ pub(crate) struct SceneBuilder {
     surfaces: Vec<Surface>,
 }
 
-impl SceneBuilder {
-    pub fn build(&mut self) -> Scene {
-        let mut orders = vec![0; self.layers_by_order.len()];
-        for (ix, layer_id) in self.layers_by_order.values().enumerate() {
-            orders[*layer_id as usize] = ix as u32;
-        }
+impl Scene {
+    pub fn clear(&mut self) {
         self.layers_by_order.clear();
+        self.orders_by_layer.clear();
+        self.shadows.clear();
+        self.quads.clear();
+        self.paths.clear();
+        self.underlines.clear();
+        self.monochrome_sprites.clear();
+        self.polychrome_sprites.clear();
+        self.surfaces.clear();
+    }
 
-        for shadow in &mut self.shadows {
-            shadow.order = orders[shadow.layer_id as usize];
-        }
-        self.shadows.sort_by_key(|shadow| shadow.order);
-
-        for quad in &mut self.quads {
-            quad.order = orders[quad.layer_id as usize];
-        }
-        self.quads.sort_by_key(|quad| quad.order);
-
-        for path in &mut self.paths {
-            path.order = orders[path.layer_id as usize];
-        }
-        self.paths.sort_by_key(|path| path.order);
-
-        for underline in &mut self.underlines {
-            underline.order = orders[underline.layer_id as usize];
-        }
-        self.underlines.sort_by_key(|underline| underline.order);
-
-        for monochrome_sprite in &mut self.monochrome_sprites {
-            monochrome_sprite.order = orders[monochrome_sprite.layer_id as usize];
-        }
-        self.monochrome_sprites.sort_by_key(|sprite| sprite.order);
-
-        for polychrome_sprite in &mut self.polychrome_sprites {
-            polychrome_sprite.order = orders[polychrome_sprite.layer_id as usize];
-        }
-        self.polychrome_sprites.sort_by_key(|sprite| sprite.order);
-
-        for surface in &mut self.surfaces {
-            surface.order = orders[surface.layer_id as usize];
-        }
-        self.surfaces.sort_by_key(|surface| surface.order);
+    pub fn paths(&self) -> &[Path<ScaledPixels>] {
+        &self.paths
+    }
 
-        Scene {
-            shadows: mem::take(&mut self.shadows),
-            quads: mem::take(&mut self.quads),
-            paths: mem::take(&mut self.paths),
-            underlines: mem::take(&mut self.underlines),
-            monochrome_sprites: mem::take(&mut self.monochrome_sprites),
-            polychrome_sprites: mem::take(&mut self.polychrome_sprites),
-            surfaces: mem::take(&mut self.surfaces),
+    pub(crate) fn batches(&self) -> impl Iterator<Item = PrimitiveBatch> {
+        BatchIterator {
+            shadows: &self.shadows,
+            shadows_start: 0,
+            shadows_iter: self.shadows.iter().peekable(),
+            quads: &self.quads,
+            quads_start: 0,
+            quads_iter: self.quads.iter().peekable(),
+            paths: &self.paths,
+            paths_start: 0,
+            paths_iter: self.paths.iter().peekable(),
+            underlines: &self.underlines,
+            underlines_start: 0,
+            underlines_iter: self.underlines.iter().peekable(),
+            monochrome_sprites: &self.monochrome_sprites,
+            monochrome_sprites_start: 0,
+            monochrome_sprites_iter: self.monochrome_sprites.iter().peekable(),
+            polychrome_sprites: &self.polychrome_sprites,
+            polychrome_sprites_start: 0,
+            polychrome_sprites_iter: self.polychrome_sprites.iter().peekable(),
+            surfaces: &self.surfaces,
+            surfaces_start: 0,
+            surfaces_iter: self.surfaces.iter().peekable(),
         }
     }
 
@@ -135,47 +124,98 @@ impl SceneBuilder {
             next_id
         }
     }
-}
 
-pub struct Scene {
-    pub shadows: Vec<Shadow>,
-    pub quads: Vec<Quad>,
-    pub paths: Vec<Path<ScaledPixels>>,
-    pub underlines: Vec<Underline>,
-    pub monochrome_sprites: Vec<MonochromeSprite>,
-    pub polychrome_sprites: Vec<PolychromeSprite>,
-    pub surfaces: Vec<Surface>,
-}
+    pub fn insert_views_from_scene(&mut self, views: &FxHashSet<EntityId>, prev_scene: &mut Self) {
+        for shadow in prev_scene.shadows.drain(..) {
+            if views.contains(&EntityId::from(shadow.view_id as u64)) {
+                let order = &prev_scene.orders_by_layer[&shadow.layer_id];
+                self.insert(&order, shadow);
+            }
+        }
 
-impl Scene {
-    pub fn paths(&self) -> &[Path<ScaledPixels>] {
-        &self.paths
+        for quad in prev_scene.quads.drain(..) {
+            if views.contains(&EntityId::from(quad.view_id as u64)) {
+                let order = &prev_scene.orders_by_layer[&quad.layer_id];
+                self.insert(&order, quad);
+            }
+        }
+
+        for path in prev_scene.paths.drain(..) {
+            if views.contains(&EntityId::from(path.view_id as u64)) {
+                let order = &prev_scene.orders_by_layer[&path.layer_id];
+                self.insert(&order, path);
+            }
+        }
+
+        for underline in prev_scene.underlines.drain(..) {
+            if views.contains(&EntityId::from(underline.view_id as u64)) {
+                let order = &prev_scene.orders_by_layer[&underline.layer_id];
+                self.insert(&order, underline);
+            }
+        }
+
+        for sprite in prev_scene.monochrome_sprites.drain(..) {
+            if views.contains(&EntityId::from(sprite.view_id as u64)) {
+                let order = &prev_scene.orders_by_layer[&sprite.layer_id];
+                self.insert(&order, sprite);
+            }
+        }
+
+        for sprite in prev_scene.polychrome_sprites.drain(..) {
+            if views.contains(&EntityId::from(sprite.view_id as u64)) {
+                let order = &prev_scene.orders_by_layer[&sprite.layer_id];
+                self.insert(&order, sprite);
+            }
+        }
+
+        for surface in prev_scene.surfaces.drain(..) {
+            if views.contains(&EntityId::from(surface.view_id as u64)) {
+                let order = &prev_scene.orders_by_layer[&surface.layer_id];
+                self.insert(&order, surface);
+            }
+        }
     }
 
-    pub(crate) fn batches(&self) -> impl Iterator<Item = PrimitiveBatch> {
-        BatchIterator {
-            shadows: &self.shadows,
-            shadows_start: 0,
-            shadows_iter: self.shadows.iter().peekable(),
-            quads: &self.quads,
-            quads_start: 0,
-            quads_iter: self.quads.iter().peekable(),
-            paths: &self.paths,
-            paths_start: 0,
-            paths_iter: self.paths.iter().peekable(),
-            underlines: &self.underlines,
-            underlines_start: 0,
-            underlines_iter: self.underlines.iter().peekable(),
-            monochrome_sprites: &self.monochrome_sprites,
-            monochrome_sprites_start: 0,
-            monochrome_sprites_iter: self.monochrome_sprites.iter().peekable(),
-            polychrome_sprites: &self.polychrome_sprites,
-            polychrome_sprites_start: 0,
-            polychrome_sprites_iter: self.polychrome_sprites.iter().peekable(),
-            surfaces: &self.surfaces,
-            surfaces_start: 0,
-            surfaces_iter: self.surfaces.iter().peekable(),
+    pub fn finish(&mut self) {
+        let mut orders = vec![0; self.layers_by_order.len()];
+        for (ix, layer_id) in self.layers_by_order.values().enumerate() {
+            orders[*layer_id as usize] = ix as u32;
+        }
+
+        for shadow in &mut self.shadows {
+            shadow.order = orders[shadow.layer_id as usize];
+        }
+        self.shadows.sort_by_key(|shadow| shadow.order);
+
+        for quad in &mut self.quads {
+            quad.order = orders[quad.layer_id as usize];
+        }
+        self.quads.sort_by_key(|quad| quad.order);
+
+        for path in &mut self.paths {
+            path.order = orders[path.layer_id as usize];
+        }
+        self.paths.sort_by_key(|path| path.order);
+
+        for underline in &mut self.underlines {
+            underline.order = orders[underline.layer_id as usize];
+        }
+        self.underlines.sort_by_key(|underline| underline.order);
+
+        for monochrome_sprite in &mut self.monochrome_sprites {
+            monochrome_sprite.order = orders[monochrome_sprite.layer_id as usize];
         }
+        self.monochrome_sprites.sort_by_key(|sprite| sprite.order);
+
+        for polychrome_sprite in &mut self.polychrome_sprites {
+            polychrome_sprite.order = orders[polychrome_sprite.layer_id as usize];
+        }
+        self.polychrome_sprites.sort_by_key(|sprite| sprite.order);
+
+        for surface in &mut self.surfaces {
+            surface.order = orders[surface.layer_id as usize];
+        }
+        self.surfaces.sort_by_key(|surface| surface.order);
     }
 }
 

crates/gpui/src/view.rs 🔗

@@ -231,7 +231,7 @@ impl AnyView {
         cx.with_absolute_element_offset(origin, |cx| {
             let (layout_id, mut rendered_element) = (self.request_layout)(self, cx);
             cx.compute_layout(layout_id, available_space);
-            rendered_element.paint(cx);
+            cx.with_view_id(self.entity_id(), |cx| rendered_element.paint(cx));
         })
     }
 }

crates/gpui/src/window.rs 🔗

@@ -7,9 +7,9 @@ use crate::{
     Model, ModelContext, Modifiers, MonochromeSprite, MouseButton, MouseMoveEvent, MouseUpEvent,
     Path, Pixels, PlatformAtlas, PlatformDisplay, PlatformInputHandler, PlatformWindow, Point,
     PolychromeSprite, PromptLevel, Quad, Render, RenderGlyphParams, RenderImageParams,
-    RenderSvgParams, ScaledPixels, Scene, SceneBuilder, Shadow, SharedString, Size, Style,
-    SubscriberSet, Subscription, Surface, TaffyLayoutEngine, Task, Underline, UnderlineStyle, View,
-    VisualContext, WeakView, WindowBounds, WindowOptions, SUBPIXEL_VARIANTS,
+    RenderSvgParams, ScaledPixels, Scene, Shadow, SharedString, Size, Style, SubscriberSet,
+    Subscription, Surface, TaffyLayoutEngine, Task, Underline, UnderlineStyle, View, VisualContext,
+    WeakView, WindowBounds, WindowOptions, SUBPIXEL_VARIANTS,
 };
 use anyhow::{anyhow, Context as _, Result};
 use collections::{FxHashMap, FxHashSet};
@@ -289,7 +289,7 @@ pub(crate) struct Frame {
     pub(crate) element_states: FxHashMap<GlobalElementId, ElementStateBox>,
     mouse_listeners: FxHashMap<TypeId, Vec<(StackingOrder, EntityId, AnyMouseListener)>>,
     pub(crate) dispatch_tree: DispatchTree,
-    pub(crate) scene_builder: SceneBuilder,
+    pub(crate) scene: Scene,
     pub(crate) depth_map: Vec<(StackingOrder, Bounds<Pixels>)>,
     pub(crate) z_index_stack: StackingOrder,
     pub(crate) next_stacking_order_id: u32,
@@ -305,7 +305,7 @@ impl Frame {
             element_states: FxHashMap::default(),
             mouse_listeners: FxHashMap::default(),
             dispatch_tree,
-            scene_builder: SceneBuilder::default(),
+            scene: Scene::default(),
             z_index_stack: StackingOrder::default(),
             next_stacking_order_id: 0,
             depth_map: Default::default(),
@@ -322,6 +322,7 @@ impl Frame {
         self.depth_map.clear();
         self.next_stacking_order_id = 0;
         self.reused_views.clear();
+        self.scene.clear();
     }
 
     fn focus_path(&self) -> SmallVec<[FocusId; 8]> {
@@ -1028,7 +1029,7 @@ impl<'a> WindowContext<'a> {
             let mut shadow_bounds = bounds;
             shadow_bounds.origin += shadow.offset;
             shadow_bounds.dilate(shadow.spread_radius);
-            window.next_frame.scene_builder.insert(
+            window.next_frame.scene.insert(
                 &window.next_frame.z_index_stack,
                 Shadow {
                     view_id: view_id.as_u64() as u32,
@@ -1053,7 +1054,7 @@ impl<'a> WindowContext<'a> {
         let view_id = self.active_view_id();
 
         let window = &mut *self.window;
-        window.next_frame.scene_builder.insert(
+        window.next_frame.scene.insert(
             &window.next_frame.z_index_stack,
             Quad {
                 view_id: view_id.as_u64() as u32,
@@ -1081,7 +1082,7 @@ impl<'a> WindowContext<'a> {
         let window = &mut *self.window;
         window
             .next_frame
-            .scene_builder
+            .scene
             .insert(&window.next_frame.z_index_stack, path.scale(scale_factor));
     }
 
@@ -1106,7 +1107,7 @@ impl<'a> WindowContext<'a> {
         let view_id = self.active_view_id();
 
         let window = &mut *self.window;
-        window.next_frame.scene_builder.insert(
+        window.next_frame.scene.insert(
             &window.next_frame.z_index_stack,
             Underline {
                 view_id: view_id.as_u64() as u32,
@@ -1162,7 +1163,7 @@ impl<'a> WindowContext<'a> {
             let content_mask = self.content_mask().scale(scale_factor);
             let view_id = self.active_view_id();
             let window = &mut *self.window;
-            window.next_frame.scene_builder.insert(
+            window.next_frame.scene.insert(
                 &window.next_frame.z_index_stack,
                 MonochromeSprite {
                     view_id: view_id.as_u64() as u32,
@@ -1216,7 +1217,7 @@ impl<'a> WindowContext<'a> {
             let view_id = self.active_view_id();
             let window = &mut *self.window;
 
-            window.next_frame.scene_builder.insert(
+            window.next_frame.scene.insert(
                 &window.next_frame.z_index_stack,
                 PolychromeSprite {
                     view_id: view_id.as_u64() as u32,
@@ -1261,7 +1262,7 @@ impl<'a> WindowContext<'a> {
         let view_id = self.active_view_id();
 
         let window = &mut *self.window;
-        window.next_frame.scene_builder.insert(
+        window.next_frame.scene.insert(
             &window.next_frame.z_index_stack,
             MonochromeSprite {
                 view_id: view_id.as_u64() as u32,
@@ -1300,7 +1301,7 @@ impl<'a> WindowContext<'a> {
         let view_id = self.active_view_id();
 
         let window = &mut *self.window;
-        window.next_frame.scene_builder.insert(
+        window.next_frame.scene.insert(
             &window.next_frame.z_index_stack,
             PolychromeSprite {
                 view_id: view_id.as_u64() as u32,
@@ -1323,7 +1324,7 @@ impl<'a> WindowContext<'a> {
         let content_mask = self.content_mask().scale(scale_factor);
         let view_id = self.active_view_id();
         let window = &mut *self.window;
-        window.next_frame.scene_builder.insert(
+        window.next_frame.scene.insert(
             &window.next_frame.z_index_stack,
             Surface {
                 view_id: view_id.as_u64() as u32,
@@ -1337,6 +1338,7 @@ impl<'a> WindowContext<'a> {
     }
 
     pub(crate) fn reuse_geometry(&mut self) {
+        println!("reusing geometry");
         let view_id = self.active_view_id();
         let window = &mut self.window;
         let grafted_view_ids = window
@@ -1407,6 +1409,11 @@ impl<'a> WindowContext<'a> {
             });
         }
         self.window.dirty_views.clear();
+        self.window.next_frame.scene.insert_views_from_scene(
+            &self.window.next_frame.reused_views,
+            &mut self.window.rendered_frame.scene,
+        );
+        self.window.next_frame.scene.finish();
 
         self.window
             .next_frame
@@ -1454,8 +1461,6 @@ impl<'a> WindowContext<'a> {
                 .retain(&(), |listener| listener(&event, self));
         }
 
-        let scene = self.window.rendered_frame.scene_builder.build();
-
         // Set the cursor only if we're the active window.
         let cursor_style = self
             .window
@@ -1469,7 +1474,9 @@ impl<'a> WindowContext<'a> {
         self.window.drawing = false;
         ELEMENT_ARENA.with_borrow_mut(|element_arena| element_arena.clear());
 
-        self.window.platform_window.draw(&scene);
+        self.window
+            .platform_window
+            .draw(&self.window.rendered_frame.scene);
     }
 
     /// Dispatch a mouse or keyboard event on the window.