apply #19772

Junkui Zhang created

Change summary

crates/gpui/src/platform/windows/directx_atlas.rs | 140 ++++++++--------
1 file changed, 74 insertions(+), 66 deletions(-)

Detailed changes

crates/gpui/src/platform/windows/directx_atlas.rs 🔗

@@ -3,25 +3,25 @@ use etagere::BucketedAtlasAllocator;
 use parking_lot::Mutex;
 use windows::Win32::Graphics::{
     Direct3D11::{
-        D3D11_BIND_RENDER_TARGET, D3D11_BIND_SHADER_RESOURCE, D3D11_BOX, D3D11_CPU_ACCESS_WRITE,
-        D3D11_TEXTURE2D_DESC, D3D11_USAGE_DEFAULT, ID3D11Device, ID3D11DeviceContext,
-        ID3D11RenderTargetView, ID3D11ShaderResourceView, ID3D11Texture2D,
-    },
-    Dxgi::Common::{
-        DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_R16_FLOAT, DXGI_SAMPLE_DESC,
+        D3D11_BIND_SHADER_RESOURCE, D3D11_BOX, D3D11_CPU_ACCESS_WRITE, D3D11_TEXTURE2D_DESC,
+        D3D11_USAGE_DEFAULT, ID3D11Device, ID3D11DeviceContext, ID3D11ShaderResourceView,
+        ID3D11Texture2D,
     },
+    Dxgi::Common::{DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_SAMPLE_DESC},
 };
 
-use crate::*;
+use crate::{
+    AtlasKey, AtlasTextureId, AtlasTextureKind, AtlasTile, Bounds, DevicePixels, PlatformAtlas,
+    Size, platform::AtlasTextureList,
+};
 
 pub(crate) struct DirectXAtlas(Mutex<DirectXAtlasState>);
 
 struct DirectXAtlasState {
     device: ID3D11Device,
     device_context: ID3D11DeviceContext,
-    monochrome_textures: Vec<DirectXAtlasTexture>,
-    polychrome_textures: Vec<DirectXAtlasTexture>,
-    // path_textures: Vec<DirectXAtlasTexture>,
+    monochrome_textures: AtlasTextureList<DirectXAtlasTexture>,
+    polychrome_textures: AtlasTextureList<DirectXAtlasTexture>,
     tiles_by_key: FxHashMap<AtlasKey, AtlasTile>,
 }
 
@@ -30,8 +30,8 @@ struct DirectXAtlasTexture {
     bytes_per_pixel: u32,
     allocator: BucketedAtlasAllocator,
     texture: ID3D11Texture2D,
-    rtv: [Option<ID3D11RenderTargetView>; 1],
     view: [Option<ID3D11ShaderResourceView>; 1],
+    live_atlas_keys: u32,
 }
 
 impl DirectXAtlas {
@@ -41,27 +41,10 @@ impl DirectXAtlas {
             device_context,
             monochrome_textures: Default::default(),
             polychrome_textures: Default::default(),
-            // path_textures: Default::default(),
             tiles_by_key: Default::default(),
         }))
     }
 
-    pub(crate) fn get_texture_drawing_info(
-        &self,
-        id: AtlasTextureId,
-    ) -> (Size<f32>, [Option<ID3D11RenderTargetView>; 1]) {
-        let lock = self.0.lock();
-        let tex = lock.texture(id);
-        let size = tex.allocator.size();
-        (
-            Size {
-                width: size.width as f32,
-                height: size.height as f32,
-            },
-            tex.rtv.clone(),
-        )
-    }
-
     pub(crate) fn get_texture_view(
         &self,
         id: AtlasTextureId,
@@ -84,9 +67,8 @@ impl DirectXAtlas {
         let textures = match texture_kind {
             AtlasTextureKind::Monochrome => &mut lock.monochrome_textures,
             AtlasTextureKind::Polychrome => &mut lock.polychrome_textures,
-            // AtlasTextureKind::Path => &mut lock.path_textures,
         };
-        for texture in textures {
+        for texture in textures.iter_mut() {
             texture.clear();
         }
     }
@@ -118,7 +100,30 @@ impl PlatformAtlas for DirectXAtlas {
     }
 
     fn remove(&self, key: &AtlasKey) {
-        todo!()
+        let mut lock = self.0.lock();
+
+        let Some(id) = lock.tiles_by_key.remove(key).map(|tile| tile.texture_id) else {
+            return;
+        };
+
+        let textures = match id.kind {
+            AtlasTextureKind::Monochrome => &mut lock.monochrome_textures,
+            AtlasTextureKind::Polychrome => &mut lock.polychrome_textures,
+        };
+
+        let Some(texture_slot) = textures.textures.get_mut(id.index as usize) else {
+            return;
+        };
+
+        if let Some(mut texture) = texture_slot.take() {
+            texture.decrement_ref_count();
+            if texture.is_unreferenced() {
+                textures.free_list.push(texture.id.index as usize);
+                lock.tiles_by_key.remove(key);
+            } else {
+                *texture_slot = Some(texture);
+            }
+        }
     }
 }
 
@@ -128,20 +133,23 @@ impl DirectXAtlasState {
         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,
-            // AtlasTextureKind::Path => &mut self.path_textures,
-        };
+        {
+            let textures = match texture_kind {
+                AtlasTextureKind::Monochrome => &mut self.monochrome_textures,
+                AtlasTextureKind::Polychrome => &mut self.polychrome_textures,
+            };
 
-        textures
-            .iter_mut()
-            .rev()
-            .find_map(|texture| texture.allocate(size))
-            .or_else(|| {
-                let texture = self.push_texture(size, texture_kind);
-                texture.allocate(size)
-            })
+            if let Some(tile) = textures
+                .iter_mut()
+                .rev()
+                .find_map(|texture| texture.allocate(size))
+            {
+                return Some(tile);
+            }
+        }
+
+        let texture = self.push_texture(size, texture_kind);
+        texture.allocate(size)
     }
 
     fn push_texture(
@@ -173,11 +181,7 @@ impl DirectXAtlasState {
                 pixel_format = DXGI_FORMAT_B8G8R8A8_UNORM;
                 bind_flag = D3D11_BIND_SHADER_RESOURCE;
                 bytes_per_pixel = 4;
-            } // AtlasTextureKind::Path => {
-              //     pixel_format = DXGI_FORMAT_R16_FLOAT;
-              //     bind_flag = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
-              //     bytes_per_pixel = 2;
-              // }
+            }
         }
         let texture_desc = D3D11_TEXTURE2D_DESC {
             Width: size.width.0 as u32,
@@ -202,21 +206,11 @@ impl DirectXAtlasState {
         }
         let texture = texture.unwrap();
 
-        let textures = match kind {
+        let texture_list = match kind {
             AtlasTextureKind::Monochrome => &mut self.monochrome_textures,
             AtlasTextureKind::Polychrome => &mut self.polychrome_textures,
-            // AtlasTextureKind::Path => &mut self.path_textures,
-        };
-        let rtv = match kind {
-            // AtlasTextureKind::Path => unsafe {
-            //     let mut view: Option<ID3D11RenderTargetView> = None;
-            //     self.device
-            //         .CreateRenderTargetView(&texture, None, Some(&mut view))
-            //         .unwrap();
-            //     [view]
-            // },
-            _ => [None],
         };
+        let index = texture_list.free_list.pop();
         let view = unsafe {
             let mut view = None;
             self.device
@@ -226,17 +220,22 @@ impl DirectXAtlasState {
         };
         let atlas_texture = DirectXAtlasTexture {
             id: AtlasTextureId {
-                index: textures.len() as u32,
+                index: index.unwrap_or(texture_list.textures.len()) as u32,
                 kind,
             },
             bytes_per_pixel,
             allocator: etagere::BucketedAtlasAllocator::new(size.into()),
             texture,
-            rtv,
             view,
+            live_atlas_keys: 0,
         };
-        textures.push(atlas_texture);
-        textures.last_mut().unwrap()
+        if let Some(ix) = index {
+            texture_list.textures[ix] = Some(atlas_texture);
+            texture_list.textures.get_mut(ix).unwrap().as_mut().unwrap()
+        } else {
+            texture_list.textures.push(Some(atlas_texture));
+            texture_list.textures.last_mut().unwrap().as_mut().unwrap()
+        }
     }
 
     fn texture(&self, id: AtlasTextureId) -> &DirectXAtlasTexture {
@@ -245,7 +244,7 @@ impl DirectXAtlasState {
             crate::AtlasTextureKind::Polychrome => &self.polychrome_textures,
             // crate::AtlasTextureKind::Path => &self.path_textures,
         };
-        &textures[id.index as usize]
+        textures[id.index as usize].as_ref().unwrap()
     }
 }
 
@@ -265,6 +264,7 @@ impl DirectXAtlasTexture {
             },
             padding: 0,
         };
+        self.live_atlas_keys += 1;
         Some(tile)
     }
 
@@ -292,4 +292,12 @@ impl DirectXAtlasTexture {
             );
         }
     }
+
+    fn decrement_ref_count(&mut self) {
+        self.live_atlas_keys -= 1;
+    }
+
+    fn is_unreferenced(&mut self) -> bool {
+        self.live_atlas_keys == 0
+    }
 }