wip

Max Brunsfeld created

Change summary

crates/gpui/src/app.rs                      |  8 ++++++
crates/gpui/src/platform.rs                 |  1 
crates/gpui/src/platform/mac/metal_atlas.rs | 29 +++++++++++++++++++++++
crates/gpui/src/platform/test/window.rs     |  7 +++++
crates/theme/src/settings.rs                |  1 
5 files changed, 46 insertions(+)

Detailed changes

crates/gpui/src/app.rs 🔗

@@ -447,6 +447,14 @@ impl App {
         self.pending_effects.push_back(Effect::RefreshWindows);
     }
 
+    /// Clears cache of rasterized glyphs.
+    pub fn clear_glyph_atlases(&mut self) {
+        if let Some(window) = self.windows.values().find_map(|window| window.as_ref()) {
+            let atlas = window.platform_window.sprite_atlas();
+            atlas.clear_glyphs();
+        }
+    }
+
     pub(crate) fn update<R>(&mut self, update: impl FnOnce(&mut Self) -> R) -> R {
         self.start_update();
         let result = update(self);

crates/gpui/src/platform.rs 🔗

@@ -743,6 +743,7 @@ pub(crate) trait PlatformAtlas: Send + Sync {
         build: &mut dyn FnMut() -> Result<Option<(Size<DevicePixels>, Cow<'a, [u8]>)>>,
     ) -> Result<Option<AtlasTile>>;
     fn remove(&self, key: &AtlasKey);
+    fn clear_glyphs(&self);
 }
 
 struct AtlasTextureList<T> {

crates/gpui/src/platform/mac/metal_atlas.rs 🔗

@@ -57,6 +57,35 @@ impl PlatformAtlas for MetalAtlas {
         }
     }
 
+    fn clear_glyphs(&self) {
+        let mut lock = self.0.lock();
+        let mut tile_ids_by_texture = FxHashMap::default();
+        lock.tiles_by_key.retain(|key, tile| {
+            if matches!(key, AtlasKey::Glyph(_)) {
+                tile_ids_by_texture
+                    .entry(tile.texture_id)
+                    .or_insert_with(Vec::new)
+                    .push(tile.tile_id);
+                false
+            } else {
+                true
+            }
+        });
+
+        for (texture_id, tile_ids) in tile_ids_by_texture {
+            let texture_slot = &mut lock.monochrome_textures.textures[texture_id.index as usize];
+            if let Some(texture) = texture_slot {
+                texture.live_atlas_keys -= tile_ids.len() as u32;
+                if texture.is_unreferenced() {
+                    texture_slot.take();
+                    lock.monochrome_textures
+                        .free_list
+                        .push(texture_id.index as usize);
+                }
+            }
+        }
+    }
+
     fn remove(&self, key: &AtlasKey) {
         let mut lock = self.0.lock();
         let Some(id) = lock.tiles_by_key.get(key).map(|v| v.texture_id) else {

crates/gpui/src/platform/test/window.rs 🔗

@@ -359,4 +359,11 @@ impl PlatformAtlas for TestAtlas {
         let mut state = self.0.lock();
         state.tiles.remove(key);
     }
+
+    fn clear_glyphs(&self) {
+        let mut state = self.0.lock();
+        state
+            .tiles
+            .retain(|key, _| !matches!(key, AtlasKey::Glyph(_)))
+    }
 }

crates/theme/src/settings.rs 🔗

@@ -722,6 +722,7 @@ pub fn adjust_buffer_font_size(cx: &mut App, mut f: impl FnMut(&mut Pixels)) {
 
     f(&mut adjusted_size);
     cx.set_global(BufferFontSize(clamp_font_size(adjusted_size)));
+    cx.clear_glyph_atlases();
     cx.refresh_windows();
 }