Don't panic on failure to allocate an AtlasTile (#11579)

Conrad Irwin created

Release Notes:

- Fixed a panic in graphics allocation

Change summary

crates/gpui/src/platform/mac/metal_atlas.rs    | 18 ++++++++++++------
crates/gpui/src/platform/mac/metal_renderer.rs |  2 +-
2 files changed, 13 insertions(+), 7 deletions(-)

Detailed changes

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

@@ -2,7 +2,7 @@ use crate::{
     AtlasKey, AtlasTextureId, AtlasTextureKind, AtlasTile, Bounds, DevicePixels, PlatformAtlas,
     Point, Size,
 };
-use anyhow::Result;
+use anyhow::{anyhow, Result};
 use collections::FxHashMap;
 use derive_more::{Deref, DerefMut};
 use etagere::BucketedAtlasAllocator;
@@ -31,7 +31,7 @@ impl MetalAtlas {
         &self,
         size: Size<DevicePixels>,
         texture_kind: AtlasTextureKind,
-    ) -> AtlasTile {
+    ) -> Option<AtlasTile> {
         self.0.lock().allocate(size, texture_kind)
     }
 
@@ -67,7 +67,9 @@ impl PlatformAtlas for MetalAtlas {
             Ok(tile.clone())
         } else {
             let (size, bytes) = build()?;
-            let tile = lock.allocate(size, key.texture_kind());
+            let tile = lock
+                .allocate(size, key.texture_kind())
+                .ok_or_else(|| anyhow!("failed to allocate"))?;
             let texture = lock.texture(tile.texture_id);
             texture.upload(tile.bounds, &bytes);
             lock.tiles_by_key.insert(key.clone(), tile.clone());
@@ -77,7 +79,11 @@ impl PlatformAtlas for MetalAtlas {
 }
 
 impl MetalAtlasState {
-    fn allocate(&mut self, size: Size<DevicePixels>, texture_kind: AtlasTextureKind) -> AtlasTile {
+    fn allocate(
+        &mut self,
+        size: Size<DevicePixels>,
+        texture_kind: AtlasTextureKind,
+    ) -> Option<AtlasTile> {
         let textures = match texture_kind {
             AtlasTextureKind::Monochrome => &mut self.monochrome_textures,
             AtlasTextureKind::Polychrome => &mut self.polychrome_textures,
@@ -88,9 +94,9 @@ impl MetalAtlasState {
             .iter_mut()
             .rev()
             .find_map(|texture| texture.allocate(size))
-            .unwrap_or_else(|| {
+            .or_else(|| {
                 let texture = self.push_texture(size, texture_kind);
-                texture.allocate(size).unwrap()
+                texture.allocate(size)
             })
     }
 

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

@@ -417,7 +417,7 @@ impl MetalRenderer {
 
             let tile = self
                 .sprite_atlas
-                .allocate(clipped_bounds.size.map(Into::into), AtlasTextureKind::Path);
+                .allocate(clipped_bounds.size.map(Into::into), AtlasTextureKind::Path)?;
             vertices_by_texture_id
                 .entry(tile.texture_id)
                 .or_insert(Vec::new())