diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index 759d33563e..668c2670b9 100644 --- a/crates/gpui/src/app.rs +++ b/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(&mut self, update: impl FnOnce(&mut Self) -> R) -> R { self.start_update(); let result = update(self); diff --git a/crates/gpui/src/platform.rs b/crates/gpui/src/platform.rs index 1e72d23868..67eac60edb 100644 --- a/crates/gpui/src/platform.rs +++ b/crates/gpui/src/platform.rs @@ -743,6 +743,7 @@ pub(crate) trait PlatformAtlas: Send + Sync { build: &mut dyn FnMut() -> Result, Cow<'a, [u8]>)>>, ) -> Result>; fn remove(&self, key: &AtlasKey); + fn clear_glyphs(&self); } struct AtlasTextureList { diff --git a/crates/gpui/src/platform/mac/metal_atlas.rs b/crates/gpui/src/platform/mac/metal_atlas.rs index 5d2d8e63e0..69de3f8053 100644 --- a/crates/gpui/src/platform/mac/metal_atlas.rs +++ b/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 { diff --git a/crates/gpui/src/platform/test/window.rs b/crates/gpui/src/platform/test/window.rs index e15bd7aeec..2d7af08f10 100644 --- a/crates/gpui/src/platform/test/window.rs +++ b/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(_))) + } } diff --git a/crates/theme/src/settings.rs b/crates/theme/src/settings.rs index 1c4c90a475..33bb431d33 100644 --- a/crates/theme/src/settings.rs +++ b/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(); }