wip

Junkui Zhang created

Change summary

crates/gpui/src/platform/windows/directx_atlas.rs    |  33 
crates/gpui/src/platform/windows/directx_renderer.rs | 381 +++---
crates/gpui/src/platform/windows/events.rs           |   8 
crates/gpui/src/platform/windows/platform.rs         |  10 
crates/gpui/src/platform/windows/shaders.hlsl        | 676 ++++++++++++++
crates/gpui/src/platform/windows/window.rs           |  28 
6 files changed, 910 insertions(+), 226 deletions(-)

Detailed changes

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

@@ -84,7 +84,7 @@ 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,
+            // AtlasTextureKind::Path => &mut lock.path_textures,
         };
         for texture in textures {
             texture.clear();
@@ -131,7 +131,7 @@ impl DirectXAtlasState {
         let textures = match texture_kind {
             AtlasTextureKind::Monochrome => &mut self.monochrome_textures,
             AtlasTextureKind::Polychrome => &mut self.polychrome_textures,
-            AtlasTextureKind::Path => &mut self.path_textures,
+            // AtlasTextureKind::Path => &mut self.path_textures,
         };
 
         textures
@@ -173,12 +173,11 @@ 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;
-            }
+            } // 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,
@@ -206,16 +205,16 @@ impl DirectXAtlasState {
         let textures = match kind {
             AtlasTextureKind::Monochrome => &mut self.monochrome_textures,
             AtlasTextureKind::Polychrome => &mut self.polychrome_textures,
-            AtlasTextureKind::Path => &mut self.path_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]
-            },
+            // AtlasTextureKind::Path => unsafe {
+            //     let mut view: Option<ID3D11RenderTargetView> = None;
+            //     self.device
+            //         .CreateRenderTargetView(&texture, None, Some(&mut view))
+            //         .unwrap();
+            //     [view]
+            // },
             _ => [None],
         };
         let view = unsafe {
@@ -244,7 +243,7 @@ impl DirectXAtlasState {
         let textures = match id.kind {
             crate::AtlasTextureKind::Monochrome => &self.monochrome_textures,
             crate::AtlasTextureKind::Polychrome => &self.polychrome_textures,
-            crate::AtlasTextureKind::Path => &self.path_textures,
+            // crate::AtlasTextureKind::Path => &self.path_textures,
         };
         &textures[id.index as usize]
     }

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

@@ -3,11 +3,11 @@ use std::{collections::HashMap, hash::BuildHasherDefault, sync::Arc};
 use ::util::ResultExt;
 use anyhow::{Context, Result};
 use collections::FxHasher;
-#[cfg(not(feature = "enable-renderdoc"))]
-use windows::Win32::Graphics::DirectComposition::*;
+// #[cfg(not(feature = "enable-renderdoc"))]
+// use windows::Win32::Graphics::DirectComposition::*;
 use windows::{
     Win32::{
-        Foundation::HWND,
+        Foundation::{HMODULE, HWND},
         Graphics::{
             Direct3D::*,
             Direct3D11::*,
@@ -41,8 +41,8 @@ struct DirectXContext {
     swap_chain: IDXGISwapChain1,
     back_buffer: [Option<ID3D11RenderTargetView>; 1],
     viewport: [D3D11_VIEWPORT; 1],
-    #[cfg(not(feature = "enable-renderdoc"))]
-    direct_composition: DirectComposition,
+    // #[cfg(not(feature = "enable-renderdoc"))]
+    // direct_composition: DirectComposition,
 }
 
 struct DirectXRenderPipelines {
@@ -62,12 +62,12 @@ struct DirectXGlobalElements {
     blend_state_for_pr: ID3D11BlendState,
 }
 
-#[cfg(not(feature = "enable-renderdoc"))]
-struct DirectComposition {
-    comp_device: IDCompositionDevice,
-    comp_target: IDCompositionTarget,
-    comp_visual: IDCompositionVisual,
-}
+// #[cfg(not(feature = "enable-renderdoc"))]
+// struct DirectComposition {
+//     comp_device: IDCompositionDevice,
+//     comp_target: IDCompositionTarget,
+//     comp_visual: IDCompositionVisual,
+// }
 
 impl DirectXDevices {
     pub(crate) fn new() -> Result<Self> {
@@ -91,17 +91,17 @@ impl DirectXDevices {
 }
 
 impl DirectXRenderer {
-    pub(crate) fn new(devices: DirectXDevices, hwnd: HWND, transparent: bool) -> Result<Self> {
+    pub(crate) fn new(devices: &DirectXDevices, hwnd: HWND, transparent: bool) -> Result<Self> {
         let atlas = Arc::new(DirectXAtlas::new(
             devices.device.clone(),
             devices.device_context.clone(),
         ));
-        let context = DirectXContext::new(&devices, hwnd, transparent)?;
+        let context = DirectXContext::new(devices, hwnd, transparent)?;
         let globals = DirectXGlobalElements::new(&devices.device)?;
         let pipelines = DirectXRenderPipelines::new(&devices.device)?;
         Ok(DirectXRenderer {
             atlas,
-            devices,
+            devices: devices.clone(),
             context,
             globals,
             pipelines,
@@ -110,7 +110,7 @@ impl DirectXRenderer {
         })
     }
 
-    pub(crate) fn spirite_atlas(&self) -> Arc<dyn PlatformAtlas> {
+    pub(crate) fn sprite_atlas(&self) -> Arc<dyn PlatformAtlas> {
         self.atlas.clone()
     }
 
@@ -153,7 +153,7 @@ impl DirectXRenderer {
                     scene.polychrome_sprites.len(),
                     scene.surfaces.len(),))?;
         }
-        unsafe { self.context.swap_chain.Present(0, 0) }.ok()?;
+        unsafe { self.context.swap_chain.Present(0, DXGI_PRESENT(0)) }.ok()?;
         Ok(())
     }
 
@@ -166,7 +166,7 @@ impl DirectXRenderer {
                 new_size.width.0 as u32,
                 new_size.height.0 as u32,
                 DXGI_FORMAT_B8G8R8A8_UNORM,
-                0,
+                DXGI_SWAP_CHAIN_FLAG(0),
             )?;
         }
         let backbuffer = set_render_target_view(
@@ -183,32 +183,32 @@ impl DirectXRenderer {
         Ok(())
     }
 
-    #[cfg(not(feature = "enable-renderdoc"))]
-    pub(crate) fn update_transparency(
-        &mut self,
-        background_appearance: WindowBackgroundAppearance,
-    ) -> Result<()> {
-        // We only support setting `Transparent` and `Opaque` for now.
-        match background_appearance {
-            WindowBackgroundAppearance::Opaque => {
-                if self.transparent {
-                    return Err(anyhow::anyhow!(
-                        "Set opaque backgroud from transparent background, a restart is required. Or, you can open a new window."
-                    ));
-                }
-            }
-            WindowBackgroundAppearance::Transparent | WindowBackgroundAppearance::Blurred => {
-                if !self.transparent {
-                    return Err(anyhow::anyhow!(
-                        "Set transparent backgroud from opaque background, a restart is required. Or, you can open a new window."
-                    ));
-                }
-            }
-        }
-        Ok(())
-    }
-
-    #[cfg(feature = "enable-renderdoc")]
+    // #[cfg(not(feature = "enable-renderdoc"))]
+    // pub(crate) fn update_transparency(
+    //     &mut self,
+    //     background_appearance: WindowBackgroundAppearance,
+    // ) -> Result<()> {
+    //     // We only support setting `Transparent` and `Opaque` for now.
+    //     match background_appearance {
+    //         WindowBackgroundAppearance::Opaque => {
+    //             if self.transparent {
+    //                 return Err(anyhow::anyhow!(
+    //                     "Set opaque backgroud from transparent background, a restart is required. Or, you can open a new window."
+    //                 ));
+    //             }
+    //         }
+    //         WindowBackgroundAppearance::Transparent | WindowBackgroundAppearance::Blurred => {
+    //             if !self.transparent {
+    //                 return Err(anyhow::anyhow!(
+    //                     "Set transparent backgroud from opaque background, a restart is required. Or, you can open a new window."
+    //                 ));
+    //             }
+    //         }
+    //     }
+    //     Ok(())
+    // }
+
+    // #[cfg(feature = "enable-renderdoc")]
     pub(crate) fn update_transparency(
         &mut self,
         background_appearance: WindowBackgroundAppearance,
@@ -280,77 +280,78 @@ impl DirectXRenderer {
         &mut self,
         paths: &[Path<ScaledPixels>],
     ) -> Option<HashMap<PathId, AtlasTile>> {
-        self.atlas.clear_textures(AtlasTextureKind::Path);
-
-        let mut tiles = HashMap::default();
-        let mut vertices_by_texture_id: HashMap<
-            AtlasTextureId,
-            Vec<PathVertex<ScaledPixels>>,
-            BuildHasherDefault<FxHasher>,
-        > = HashMap::default();
-        for path in paths {
-            let clipped_bounds = path.bounds.intersect(&path.content_mask.bounds);
-
-            let tile = self
-                .atlas
-                .allocate(clipped_bounds.size.map(Into::into), AtlasTextureKind::Path)?;
-            vertices_by_texture_id
-                .entry(tile.texture_id)
-                .or_insert(Vec::new())
-                .extend(path.vertices.iter().map(|vertex| PathVertex {
-                    xy_position: vertex.xy_position - clipped_bounds.origin
-                        + tile.bounds.origin.map(Into::into),
-                    content_mask: ContentMask {
-                        bounds: tile.bounds.map(Into::into),
-                    },
-                }));
-            tiles.insert(path.id, tile);
-        }
-
-        for (texture_id, vertices) in vertices_by_texture_id {
-            let (texture_size, rtv) = self.atlas.get_texture_drawing_info(texture_id);
-            let viewport = [D3D11_VIEWPORT {
-                TopLeftX: 0.0,
-                TopLeftY: 0.0,
-                Width: texture_size.width,
-                Height: texture_size.height,
-                MinDepth: 0.0,
-                MaxDepth: 1.0,
-            }];
-            pre_draw(
-                &self.devices.device_context,
-                &self.globals.global_params_buffer,
-                &viewport,
-                &rtv,
-                [0.0, 0.0, 0.0, 1.0],
-                &self.globals.blend_state_for_pr,
-            )
-            .log_err()?;
-            update_buffer_capacity(
-                &self.pipelines.path_raster_pipeline,
-                std::mem::size_of::<PathVertex<ScaledPixels>>(),
-                vertices.len(),
-                &self.devices.device,
-            )
-            .map(|input| update_pipeline(&mut self.pipelines.path_raster_pipeline, input));
-            update_buffer(
-                &self.devices.device_context,
-                &self.pipelines.path_raster_pipeline.buffer,
-                &vertices,
-            )
-            .log_err()?;
-            draw_normal(
-                &self.devices.device_context,
-                &self.pipelines.path_raster_pipeline,
-                &viewport,
-                &self.globals.global_params_buffer,
-                D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST,
-                vertices.len() as u32,
-                1,
-            )
-            .log_err()?;
-        }
-        Some(tiles)
+        // self.atlas.clear_textures(AtlasTextureKind::Path);
+
+        // let mut tiles = HashMap::default();
+        // let mut vertices_by_texture_id: HashMap<
+        //     AtlasTextureId,
+        //     Vec<PathVertex<ScaledPixels>>,
+        //     BuildHasherDefault<FxHasher>,
+        // > = HashMap::default();
+        // for path in paths {
+        //     let clipped_bounds = path.bounds.intersect(&path.content_mask.bounds);
+
+        //     let tile = self
+        //         .atlas
+        //         .allocate(clipped_bounds.size.map(Into::into), AtlasTextureKind::Path)?;
+        //     vertices_by_texture_id
+        //         .entry(tile.texture_id)
+        //         .or_insert(Vec::new())
+        //         .extend(path.vertices.iter().map(|vertex| PathVertex {
+        //             xy_position: vertex.xy_position - clipped_bounds.origin
+        //                 + tile.bounds.origin.map(Into::into),
+        //             content_mask: ContentMask {
+        //                 bounds: tile.bounds.map(Into::into),
+        //             },
+        //         }));
+        //     tiles.insert(path.id, tile);
+        // }
+
+        // for (texture_id, vertices) in vertices_by_texture_id {
+        //     let (texture_size, rtv) = self.atlas.get_texture_drawing_info(texture_id);
+        //     let viewport = [D3D11_VIEWPORT {
+        //         TopLeftX: 0.0,
+        //         TopLeftY: 0.0,
+        //         Width: texture_size.width,
+        //         Height: texture_size.height,
+        //         MinDepth: 0.0,
+        //         MaxDepth: 1.0,
+        //     }];
+        //     pre_draw(
+        //         &self.devices.device_context,
+        //         &self.globals.global_params_buffer,
+        //         &viewport,
+        //         &rtv,
+        //         [0.0, 0.0, 0.0, 1.0],
+        //         &self.globals.blend_state_for_pr,
+        //     )
+        //     .log_err()?;
+        //     update_buffer_capacity(
+        //         &self.pipelines.path_raster_pipeline,
+        //         std::mem::size_of::<PathVertex<ScaledPixels>>(),
+        //         vertices.len(),
+        //         &self.devices.device,
+        //     )
+        //     .map(|input| update_pipeline(&mut self.pipelines.path_raster_pipeline, input));
+        //     update_buffer(
+        //         &self.devices.device_context,
+        //         &self.pipelines.path_raster_pipeline.buffer,
+        //         &vertices,
+        //     )
+        //     .log_err()?;
+        //     draw_normal(
+        //         &self.devices.device_context,
+        //         &self.pipelines.path_raster_pipeline,
+        //         &viewport,
+        //         &self.globals.global_params_buffer,
+        //         D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST,
+        //         vertices.len() as u32,
+        //         1,
+        //     )
+        //     .log_err()?;
+        // }
+        // Some(tiles)
+        None
     }
 
     fn draw_paths(
@@ -358,43 +359,43 @@ impl DirectXRenderer {
         paths: &[Path<ScaledPixels>],
         path_tiles: &HashMap<PathId, AtlasTile>,
     ) -> Result<()> {
-        if paths.is_empty() {
-            return Ok(());
-        }
-        for path in paths {
-            let tile = &path_tiles[&path.id];
-            let texture_view = self.atlas.get_texture_view(tile.texture_id);
-            let origin = path.bounds.intersect(&path.content_mask.bounds).origin;
-            let sprites = [PathSprite {
-                bounds: Bounds {
-                    origin: origin.map(|p| p.floor()),
-                    size: tile.bounds.size.map(Into::into),
-                },
-                color: path.color,
-                tile: (*tile).clone(),
-            }];
-            update_buffer_capacity(
-                &self.pipelines.paths_pipeline,
-                std::mem::size_of::<PathSprite>(),
-                1,
-                &self.devices.device,
-            )
-            .map(|input| update_pipeline(&mut self.pipelines.paths_pipeline, input));
-            update_buffer(
-                &self.devices.device_context,
-                &self.pipelines.paths_pipeline.buffer,
-                &sprites,
-            )?;
-            draw_with_texture(
-                &self.devices.device_context,
-                &self.pipelines.paths_pipeline,
-                &texture_view,
-                &self.context.viewport,
-                &self.globals.global_params_buffer,
-                &self.globals.sampler,
-                1,
-            )?;
-        }
+        // if paths.is_empty() {
+        //     return Ok(());
+        // }
+        // for path in paths {
+        //     let tile = &path_tiles[&path.id];
+        //     let texture_view = self.atlas.get_texture_view(tile.texture_id);
+        //     let origin = path.bounds.intersect(&path.content_mask.bounds).origin;
+        //     let sprites = [PathSprite {
+        //         bounds: Bounds {
+        //             origin: origin.map(|p| p.floor()),
+        //             size: tile.bounds.size.map(Into::into),
+        //         },
+        //         color: path.color,
+        //         tile: (*tile).clone(),
+        //     }];
+        //     update_buffer_capacity(
+        //         &self.pipelines.paths_pipeline,
+        //         std::mem::size_of::<PathSprite>(),
+        //         1,
+        //         &self.devices.device,
+        //     )
+        //     .map(|input| update_pipeline(&mut self.pipelines.paths_pipeline, input));
+        //     update_buffer(
+        //         &self.devices.device_context,
+        //         &self.pipelines.paths_pipeline.buffer,
+        //         &sprites,
+        //     )?;
+        //     draw_with_texture(
+        //         &self.devices.device_context,
+        //         &self.pipelines.paths_pipeline,
+        //         &texture_view,
+        //         &self.context.viewport,
+        //         &self.globals.global_params_buffer,
+        //         &self.globals.sampler,
+        //         1,
+        //     )?;
+        // }
         Ok(())
     }
 
@@ -489,7 +490,7 @@ impl DirectXRenderer {
         )
     }
 
-    fn draw_surfaces(&mut self, surfaces: &[Surface]) -> Result<()> {
+    fn draw_surfaces(&mut self, surfaces: &[PaintSurface]) -> Result<()> {
         if surfaces.is_empty() {
             return Ok(());
         }
@@ -499,15 +500,15 @@ impl DirectXRenderer {
 
 impl DirectXContext {
     pub fn new(devices: &DirectXDevices, hwnd: HWND, transparent: bool) -> Result<Self> {
-        #[cfg(not(feature = "enable-renderdoc"))]
-        let swap_chain = create_swap_chain(&devices.dxgi_factory, &devices.device, transparent)?;
-        #[cfg(feature = "enable-renderdoc")]
+        // #[cfg(not(feature = "enable-renderdoc"))]
+        // let swap_chain = create_swap_chain(&devices.dxgi_factory, &devices.device, transparent)?;
+        // #[cfg(feature = "enable-renderdoc")]
         let swap_chain =
             create_swap_chain_default(&devices.dxgi_factory, &devices.device, hwnd, transparent)?;
-        #[cfg(not(feature = "enable-renderdoc"))]
-        let direct_composition = DirectComposition::new(&devices.dxgi_device, hwnd)?;
-        #[cfg(not(feature = "enable-renderdoc"))]
-        direct_composition.set_swap_chain(&swap_chain)?;
+        // #[cfg(not(feature = "enable-renderdoc"))]
+        // let direct_composition = DirectComposition::new(&devices.dxgi_device, hwnd)?;
+        // #[cfg(not(feature = "enable-renderdoc"))]
+        // direct_composition.set_swap_chain(&swap_chain)?;
         let back_buffer = [Some(set_render_target_view(
             &swap_chain,
             &devices.device,
@@ -520,8 +521,8 @@ impl DirectXContext {
             swap_chain,
             back_buffer,
             viewport,
-            #[cfg(not(feature = "enable-renderdoc"))]
-            direct_composition,
+            // #[cfg(not(feature = "enable-renderdoc"))]
+            // direct_composition,
         })
     }
 }
@@ -590,29 +591,29 @@ impl DirectXRenderPipelines {
     }
 }
 
-#[cfg(not(feature = "enable-renderdoc"))]
-impl DirectComposition {
-    pub fn new(dxgi_device: &IDXGIDevice, hwnd: HWND) -> Result<Self> {
-        let comp_device = get_comp_device(&dxgi_device)?;
-        let comp_target = unsafe { comp_device.CreateTargetForHwnd(hwnd, true) }?;
-        let comp_visual = unsafe { comp_device.CreateVisual() }?;
-
-        Ok(Self {
-            comp_device,
-            comp_target,
-            comp_visual,
-        })
-    }
-
-    pub fn set_swap_chain(&self, swap_chain: &IDXGISwapChain1) -> Result<()> {
-        unsafe {
-            self.comp_visual.SetContent(swap_chain)?;
-            self.comp_target.SetRoot(&self.comp_visual)?;
-            self.comp_device.Commit()?;
-        }
-        Ok(())
-    }
-}
+// #[cfg(not(feature = "enable-renderdoc"))]
+// impl DirectComposition {
+//     pub fn new(dxgi_device: &IDXGIDevice, hwnd: HWND) -> Result<Self> {
+//         let comp_device = get_comp_device(&dxgi_device)?;
+//         let comp_target = unsafe { comp_device.CreateTargetForHwnd(hwnd, true) }?;
+//         let comp_visual = unsafe { comp_device.CreateVisual() }?;
+
+//         Ok(Self {
+//             comp_device,
+//             comp_target,
+//             comp_visual,
+//         })
+//     }
+
+//     pub fn set_swap_chain(&self, swap_chain: &IDXGISwapChain1) -> Result<()> {
+//         unsafe {
+//             self.comp_visual.SetContent(swap_chain)?;
+//             self.comp_target.SetRoot(&self.comp_visual)?;
+//             self.comp_device.Commit()?;
+//         }
+//         Ok(())
+//     }
+// }
 
 impl DirectXGlobalElements {
     pub fn new(device: &ID3D11Device) -> Result<Self> {
@@ -726,7 +727,7 @@ fn get_device(
         D3D11CreateDevice(
             adapter,
             D3D_DRIVER_TYPE_UNKNOWN,
-            None,
+            HMODULE::default(),
             device_flags,
             Some(&[D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_11_1]),
             D3D11_SDK_VERSION,
@@ -737,10 +738,10 @@ fn get_device(
     })
 }
 
-#[cfg(not(feature = "enable-renderdoc"))]
-fn get_comp_device(dxgi_device: &IDXGIDevice) -> Result<IDCompositionDevice> {
-    Ok(unsafe { DCompositionCreateDevice(dxgi_device)? })
-}
+// #[cfg(not(feature = "enable-renderdoc"))]
+// fn get_comp_device(dxgi_device: &IDXGIDevice) -> Result<IDCompositionDevice> {
+//     Ok(unsafe { DCompositionCreateDevice(dxgi_device)? })
+// }
 
 fn create_swap_chain(
     dxgi_factory: &IDXGIFactory6,
@@ -772,7 +773,7 @@ fn create_swap_chain(
     Ok(unsafe { dxgi_factory.CreateSwapChainForComposition(device, &desc, None)? })
 }
 
-#[cfg(feature = "enable-renderdoc")]
+// #[cfg(feature = "enable-renderdoc")]
 fn create_swap_chain_default(
     dxgi_factory: &IDXGIFactory6,
     device: &ID3D11Device,

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

@@ -181,11 +181,13 @@ fn handle_size_msg(
     let new_size = size(DevicePixels(width), DevicePixels(height));
     let scale_factor = lock.scale_factor;
     if lock.restore_from_minimized.is_some() {
-        lock.renderer
-            .update_drawable_size_even_if_unchanged(new_size);
+        // lock.renderer
+        //     .update_drawable_size_even_if_unchanged(new_size);
+        lock.renderer.resize(new_size).log_err();
         lock.callbacks.request_frame = lock.restore_from_minimized.take();
     } else {
-        lock.renderer.update_drawable_size(new_size);
+        // lock.renderer.update_drawable_size(new_size);
+        lock.renderer.resize(new_size).log_err();
     }
     let new_size = new_size.to_pixels(scale_factor);
     lock.logical_size = new_size;

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

@@ -34,7 +34,8 @@ pub(crate) struct WindowsPlatform {
     state: RefCell<WindowsPlatformState>,
     raw_window_handles: RwLock<SmallVec<[HWND; 4]>>,
     // The below members will never change throughout the entire lifecycle of the app.
-    gpu_context: BladeContext,
+    // gpu_context: BladeContext,
+    directx_devices: DirectXDevices,
     icon: HICON,
     main_receiver: flume::Receiver<Runnable>,
     background_executor: BackgroundExecutor,
@@ -111,13 +112,14 @@ impl WindowsPlatform {
         let icon = load_icon().unwrap_or_default();
         let state = RefCell::new(WindowsPlatformState::new());
         let raw_window_handles = RwLock::new(SmallVec::new());
-        let gpu_context = BladeContext::new().context("Unable to init GPU context")?;
+        // let gpu_context = BladeContext::new().context("Unable to init GPU context")?;
+        let directx_devices = DirectXDevices::new().context("Unable to init directx devices.")?;
         let windows_version = WindowsVersion::new().context("Error retrieve windows version")?;
 
         Ok(Self {
             state,
             raw_window_handles,
-            gpu_context,
+            directx_devices,
             icon,
             main_receiver,
             background_executor,
@@ -459,7 +461,7 @@ impl Platform for WindowsPlatform {
             handle,
             options,
             self.generate_creation_info(),
-            &self.gpu_context,
+            &self.directx_devices,
         )?;
         let handle = window.get_raw_handle();
         self.raw_window_handles.write().push(handle);

crates/gpui/src/platform/windows/shaders.hlsl 🔗

@@ -0,0 +1,676 @@
+cbuffer GlobalParams: register(b0) {
+    float2 global_viewport_size;
+    uint2 _global_pad;
+};
+
+Texture2D<float4> t_sprite: register(t0);
+SamplerState s_sprite: register(s0);
+
+struct Bounds {
+    float2 origin;
+    float2 size;
+};
+
+struct Corners {
+    float top_left;
+    float top_right;
+    float bottom_right;
+    float bottom_left;
+};
+
+struct Edges {
+    float top;
+    float right;
+    float bottom;
+    float left;
+};
+
+struct Hsla {
+    float h;
+    float s;
+    float l;
+    float a;
+};
+
+struct AtlasTextureId {
+    uint index;
+    uint kind;
+};
+
+struct AtlasBounds {
+    int2 origin;
+    int2 size;
+};
+
+struct AtlasTile {
+    AtlasTextureId texture_id;
+    uint tile_id;
+    uint padding;
+    AtlasBounds bounds;
+};
+
+struct TransformationMatrix {
+    float2x2 rotation_scale;
+    float2 translation;
+};
+
+static const float M_PI_F = 3.141592653f;
+static const float3 GRAYSCALE_FACTORS = float3(0.2126f, 0.7152f, 0.0722f);
+
+float4 to_device_position(float2 unit_vertex, Bounds bounds) {
+    float2 position = unit_vertex * bounds.size + bounds.origin;
+    float2 device_position = position / global_viewport_size * float2(2.0, -2.0) + float2(-1.0, 1.0);
+    return float4(device_position, 0., 1.);
+}
+
+float4 distance_from_clip_rect(float2 unit_vertex, Bounds bounds, Bounds clip_bounds) {
+    float2 position = unit_vertex * bounds.size + bounds.origin;
+    return float4(position.x - clip_bounds.origin.x,
+                    clip_bounds.origin.x + clip_bounds.size.x - position.x,
+                    position.y - clip_bounds.origin.y,
+                    clip_bounds.origin.y + clip_bounds.size.y - position.y);
+}
+
+float4 hsla_to_rgba(Hsla hsla) {
+    float h = hsla.h * 6.0; // Now, it's an angle but scaled in [0, 6) range
+    float s = hsla.s;
+    float l = hsla.l;
+    float a = hsla.a;
+
+    float c = (1.0 - abs(2.0 * l - 1.0)) * s;
+    float x = c * (1.0 - abs(fmod(h, 2.0) - 1.0));
+    float m = l - c / 2.0;
+
+    float r = 0.0;
+    float g = 0.0;
+    float b = 0.0;
+
+    if (h >= 0.0 && h < 1.0) {
+        r = c;
+        g = x;
+        b = 0.0;
+    } else if (h >= 1.0 && h < 2.0) {
+        r = x;
+        g = c;
+        b = 0.0;
+    } else if (h >= 2.0 && h < 3.0) {
+        r = 0.0;
+        g = c;
+        b = x;
+    } else if (h >= 3.0 && h < 4.0) {
+        r = 0.0;
+        g = x;
+        b = c;
+    } else if (h >= 4.0 && h < 5.0) {
+        r = x;
+        g = 0.0;
+        b = c;
+    } else {
+        r = c;
+        g = 0.0;
+        b = x;
+    }
+
+    float4 rgba;
+    rgba.x = (r + m);
+    rgba.y = (g + m);
+    rgba.z = (b + m);
+    rgba.w = a;
+    return rgba;
+}
+
+// This approximates the error function, needed for the gaussian integral
+float2 erf(float2 x) {
+    float2 s = sign(x);
+    float2 a = abs(x);
+    x = 1. + (0.278393 + (0.230389 + 0.078108 * (a * a)) * a) * a;
+    x *= x;
+    return s - s / (x * x);
+}
+
+float blur_along_x(float x, float y, float sigma, float corner, float2 half_size) {
+    float delta = min(half_size.y - corner - abs(y), 0.);
+    float curved = half_size.x - corner + sqrt(max(0., corner * corner - delta * delta));
+    float2 integral = 0.5 + 0.5 * erf((x + float2(-curved, curved)) * (sqrt(0.5) / sigma));
+    return integral.y - integral.x;
+}
+
+// A standard gaussian function, used for weighting samples
+float gaussian(float x, float sigma) {
+    return exp(-(x * x) / (2. * sigma * sigma)) / (sqrt(2. * M_PI_F) * sigma);
+}
+
+float4 over(float4 below, float4 above) {
+    float4 result;
+    float alpha = above.a + below.a * (1.0 - above.a);
+    result.rgb = (above.rgb * above.a + below.rgb * below.a * (1.0 - above.a)) / alpha;
+    result.a = alpha;
+    return result;
+}
+
+float2 to_tile_position(float2 unit_vertex, AtlasTile tile) {
+    float2 atlas_size;
+    t_sprite.GetDimensions(atlas_size.x, atlas_size.y);
+    return (float2(tile.bounds.origin) + unit_vertex * float2(tile.bounds.size)) / atlas_size;
+}
+
+float4 to_device_position_transformed(float2 unit_vertex, Bounds bounds, 
+                                      TransformationMatrix transformation) {
+    float2 position = unit_vertex * bounds.size + bounds.origin;
+    float2 transformed = mul(position, transformation.rotation_scale) + transformation.translation;
+    float2 device_position = transformed / global_viewport_size * float2(2.0, -2.0) + float2(-1.0, 1.0);
+    return float4(device_position, 0.0, 1.0);
+}
+
+float quad_sdf(float2 pt, Bounds bounds, Corners corner_radii) {
+    float2 half_size = bounds.size / 2.;
+    float2 center = bounds.origin + half_size;
+    float2 center_to_point = pt - center;
+    float corner_radius;
+    if (center_to_point.x < 0.) {
+        if (center_to_point.y < 0.) {
+            corner_radius = corner_radii.top_left;
+        } else {
+            corner_radius = corner_radii.bottom_left;
+        }
+    } else {
+        if (center_to_point.y < 0.) {
+            corner_radius = corner_radii.top_right;
+        } else {
+            corner_radius = corner_radii.bottom_right;
+        }
+    }
+
+    float2 rounded_edge_to_point = abs(center_to_point) - half_size + corner_radius;
+    float distance =
+        length(max(0., rounded_edge_to_point)) +
+        min(0., max(rounded_edge_to_point.x, rounded_edge_to_point.y)) -
+        corner_radius;
+
+    return distance;
+}
+
+/*
+**
+**              Shadows
+**
+*/
+
+struct ShadowVertexOutput {
+    float4 position: SV_Position;
+    float4 color: COLOR;
+    uint shadow_id: FLAT;
+    float4 clip_distance: SV_ClipDistance;
+};
+
+struct ShadowFragmentInput {
+  float4 position: SV_Position;
+  float4 color: COLOR;
+  uint shadow_id: FLAT;
+};
+
+struct Shadow {
+    uint order;
+    float blur_radius;
+    Bounds bounds;
+    Corners corner_radii;
+    Bounds content_mask;
+    Hsla color;
+};
+
+StructuredBuffer<Shadow> shadows: register(t1);
+
+ShadowVertexOutput shadow_vertex(uint vertex_id: SV_VertexID, uint shadow_id: SV_InstanceID) {
+    float2 unit_vertex = float2(float(vertex_id & 1u), 0.5 * float(vertex_id & 2u));
+    Shadow shadow = shadows[shadow_id];
+
+    float margin = 3.0 * shadow.blur_radius;
+    Bounds bounds = shadow.bounds;
+    bounds.origin -= margin;
+    bounds.size += 2.0 * margin;
+
+    float4 device_position = to_device_position(unit_vertex, bounds);
+    float4 clip_distance = distance_from_clip_rect(unit_vertex, bounds, shadow.content_mask);
+    float4 color = hsla_to_rgba(shadow.color);
+
+    ShadowVertexOutput output;
+    output.position = device_position;
+    output.color = color;
+    output.shadow_id = shadow_id;
+    output.clip_distance = clip_distance;
+
+    return output;
+}
+
+float4 shadow_fragment(ShadowFragmentInput input): SV_TARGET {
+    Shadow shadow = shadows[input.shadow_id];
+
+    float2 half_size = shadow.bounds.size / 2.;
+    float2 center = shadow.bounds.origin + half_size;
+    float2 point0 = input.position.xy - center;
+    float corner_radius;
+    if (point0.x < 0.) {
+        if (point0.y < 0.) {
+            corner_radius = shadow.corner_radii.top_left;
+        } else {
+            corner_radius = shadow.corner_radii.bottom_left;
+        }
+    } else {
+        if (point0.y < 0.) {
+            corner_radius = shadow.corner_radii.top_right;
+        } else {
+            corner_radius = shadow.corner_radii.bottom_right;
+        }
+    }
+
+    // The signal is only non-zero in a limited range, so don't waste samples
+    float low = point0.y - half_size.y;
+    float high = point0.y + half_size.y;
+    float start = clamp(-3. * shadow.blur_radius, low, high);
+    float end = clamp(3. * shadow.blur_radius, low, high);
+
+    // Accumulate samples (we can get away with surprisingly few samples)
+    float step = (end - start) / 4.;
+    float y = start + step * 0.5;
+    float alpha = 0.;
+    for (int i = 0; i < 4; i++) {
+        alpha += blur_along_x(point0.x, point0.y - y, shadow.blur_radius,
+                            corner_radius, half_size) *
+                gaussian(y, shadow.blur_radius) * step;
+        y += step;
+    }
+
+    return input.color * float4(1., 1., 1., alpha);
+}
+
+/*
+**
+**              Quads
+**
+*/
+
+struct Quad {
+    uint order;
+    uint pad;
+    Bounds bounds;
+    Bounds content_mask;
+    Hsla background;
+    Hsla border_color;
+    Corners corner_radii;
+    Edges border_widths;
+};
+
+struct QuadVertexOutput {
+    float4 position: SV_Position;
+    float4 background_color: COLOR0;
+    float4 border_color: COLOR1;
+    uint quad_id: FLAT;
+    float4 clip_distance: SV_ClipDistance;
+};
+
+struct QuadFragmentInput {
+    float4 position: SV_Position;
+    float4 background_color: COLOR0;
+    float4 border_color: COLOR1;
+    uint quad_id: FLAT;
+};
+
+StructuredBuffer<Quad> quads: register(t1);
+
+QuadVertexOutput quad_vertex(uint vertex_id: SV_VertexID, uint quad_id: SV_InstanceID) {
+    float2 unit_vertex = float2(float(vertex_id & 1u), 0.5 * float(vertex_id & 2u));
+    Quad quad = quads[quad_id];
+    float4 device_position = to_device_position(unit_vertex, quad.bounds);
+    float4 clip_distance = distance_from_clip_rect(unit_vertex, quad.bounds, quad.content_mask);
+    float4 background_color = hsla_to_rgba(quad.background);
+    float4 border_color = hsla_to_rgba(quad.border_color);
+
+    QuadVertexOutput output;
+    output.position = device_position;
+    output.background_color = background_color;
+    output.border_color = border_color;
+    output.quad_id = quad_id;
+    output.clip_distance = clip_distance;
+    return output;
+}
+
+float4 quad_fragment(QuadFragmentInput input): SV_Target {
+    Quad quad = quads[input.quad_id];
+
+    // Fast path when the quad is not rounded and doesn't have any border.
+    if (quad.corner_radii.top_left == 0. && quad.corner_radii.bottom_left == 0. &&
+        quad.corner_radii.top_right == 0. &&
+        quad.corner_radii.bottom_right == 0. && quad.border_widths.top == 0. &&
+        quad.border_widths.left == 0. && quad.border_widths.right == 0. &&
+        quad.border_widths.bottom == 0.) {
+        return input.background_color;
+    }
+
+    float2 half_size = quad.bounds.size / 2.;
+    float2 center = quad.bounds.origin + half_size;
+    float2 center_to_point = input.position.xy - center;
+    float corner_radius;
+    if (center_to_point.x < 0.) {
+        if (center_to_point.y < 0.) {
+            corner_radius = quad.corner_radii.top_left;
+        } else {
+            corner_radius = quad.corner_radii.bottom_left;
+        }
+    } else {
+        if (center_to_point.y < 0.) {
+            corner_radius = quad.corner_radii.top_right;
+        } else {
+            corner_radius = quad.corner_radii.bottom_right;
+        }
+    }
+
+    float2 rounded_edge_to_point = abs(center_to_point) - half_size + corner_radius;
+    float distance =
+        length(max(0., rounded_edge_to_point)) +
+        min(0., max(rounded_edge_to_point.x, rounded_edge_to_point.y)) -
+        corner_radius;
+
+    float vertical_border = center_to_point.x <= 0. ? quad.border_widths.left
+                                                    : quad.border_widths.right;
+    float horizontal_border = center_to_point.y <= 0. ? quad.border_widths.top
+                                                        : quad.border_widths.bottom;
+    float2 inset_size = half_size - corner_radius - float2(vertical_border, horizontal_border);
+    float2 point_to_inset_corner = abs(center_to_point) - inset_size;
+    float border_width;
+    if (point_to_inset_corner.x < 0. && point_to_inset_corner.y < 0.) {
+        border_width = 0.;
+    } else if (point_to_inset_corner.y > point_to_inset_corner.x) {
+        border_width = horizontal_border;
+    } else {
+        border_width = vertical_border;
+    }
+
+    float4 color;
+    if (border_width == 0.) {
+        color = input.background_color;
+    } else {
+        float inset_distance = distance + border_width;
+        // Blend the border on top of the background and then linearly interpolate
+        // between the two as we slide inside the background.
+        float4 blended_border = over(input.background_color, input.border_color);
+        color = lerp(blended_border, input.background_color,
+                    saturate(0.5 - inset_distance));
+    }
+
+    return color * float4(1., 1., 1., saturate(0.5 - distance));
+}
+
+/*
+**
+**              Path raster
+**
+*/
+
+struct PathVertex {
+    float2 xy_position;
+    float2 st_position;
+    Bounds content_mask;
+};
+
+struct PathRasterizationOutput {
+    float4 position: SV_Position;
+    float2 st_position: TEXCOORD0;
+    float4 clip_distances: SV_ClipDistance;
+};
+
+struct PathRasterizationInput {
+    float4 position: SV_Position;
+    float2 st_position: TEXCOORD0;
+};
+
+StructuredBuffer<PathVertex> path_vertices: register(t1);
+
+PathRasterizationOutput path_rasterization_vertex(uint vertex_id: SV_VertexID) {
+    PathVertex vertex = path_vertices[vertex_id];
+    PathRasterizationOutput output;
+    float2 device_position = vertex.xy_position / global_viewport_size * float2(2.0, -2.0) + float2(-1.0, 1.0);
+    float2 tl = vertex.xy_position - vertex.content_mask.origin;
+    float2 br = vertex.content_mask.origin + vertex.content_mask.size - vertex.xy_position;
+
+    output.position = float4(device_position, 0.0, 1.0);
+    output.st_position = vertex.st_position;
+    output.clip_distances = float4(tl.x, br.x, tl.y, br.y);
+    return output;
+}
+
+float4 path_rasterization_fragment(PathRasterizationInput input): SV_Target {
+    float2 dx = ddx(input.st_position);
+    float2 dy = ddy(input.st_position);
+    float2 gradient = float2((2. * input.st_position.x) * dx.x - dx.y,
+                            (2. * input.st_position.x) * dy.x - dy.y);
+    float f = (input.st_position.x * input.st_position.x) - input.st_position.y;
+    float distance = f / length(gradient);
+    float alpha = saturate(0.5 - distance);
+    return float4(alpha, 0., 0., 1.);
+}
+
+/*
+**
+**              Paths
+**
+*/
+
+struct PathSprite {
+    Bounds bounds;
+    Hsla color;
+    AtlasTile tile;
+};
+
+struct PathVertexOutput {
+    float4 position: SV_Position;
+    float2 tile_position: POSITION1;
+    float4 color: COLOR;
+};
+
+StructuredBuffer<PathSprite> path_sprites: register(t1);
+
+PathVertexOutput paths_vertex(uint vertex_id: SV_VertexID, uint instance_id: SV_InstanceID) {
+    float2 unit_vertex = float2(float(vertex_id & 1u), 0.5 * float(vertex_id & 2u));
+    PathSprite sprite = path_sprites[instance_id];
+    // Don't apply content mask because it was already accounted for when rasterizing the path.
+
+    PathVertexOutput output;
+    output.position = to_device_position(unit_vertex, sprite.bounds);
+    output.tile_position = to_tile_position(unit_vertex, sprite.tile);
+    output.color = hsla_to_rgba(sprite.color);
+    return output;
+}
+
+float4 paths_fragment(PathVertexOutput input): SV_Target {
+    float sample = t_sprite.Sample(s_sprite, input.tile_position).r;
+    float mask = 1.0 - abs(1.0 - sample % 2.0);
+    float4 color = input.color;
+    color.a *= mask;
+    return color;
+}
+
+/*
+**
+**              Underlines
+**
+*/
+
+struct Underline {
+    uint order;
+    uint pad;
+    Bounds bounds;
+    Bounds content_mask;
+    Hsla color;
+    float thickness;
+    uint wavy;
+};
+
+struct UnderlineVertexOutput {
+  float4 position: SV_Position;
+  float4 color: COLOR;
+  uint underline_id: FLAT;
+  float4 clip_distance: SV_ClipDistance;
+};
+
+struct UnderlineFragmentInput {
+  float4 position: SV_Position;
+  float4 color: COLOR;
+  uint underline_id: FLAT;
+};
+
+StructuredBuffer<Underline> underlines: register(t1);
+
+UnderlineVertexOutput underline_vertex(uint vertex_id: SV_VertexID, uint underline_id: SV_InstanceID) {
+    float2 unit_vertex = float2(float(vertex_id & 1u), 0.5 * float(vertex_id & 2u));
+    Underline underline = underlines[underline_id];
+    float4 device_position = to_device_position(unit_vertex, underline.bounds);
+    float4 clip_distance = distance_from_clip_rect(unit_vertex, underline.bounds, 
+                                                    underline.content_mask);
+    float4 color = hsla_to_rgba(underline.color);
+
+    UnderlineVertexOutput output;
+    output.position = device_position;
+    output.color = color;
+    output.underline_id = underline_id;
+    output.clip_distance = clip_distance;
+    return output;
+}
+
+float4 underline_fragment(UnderlineFragmentInput input): SV_Target {
+    Underline underline = underlines[input.underline_id];
+    if (underline.wavy) {
+        float half_thickness = underline.thickness * 0.5;
+        float2 origin =
+            float2(underline.bounds.origin.x, underline.bounds.origin.y);
+        float2 st = ((input.position.xy - origin) / underline.bounds.size.y) -
+                    float2(0., 0.5);
+        float frequency = (M_PI_F * (3. * underline.thickness)) / 8.;
+        float amplitude = 1. / (2. * underline.thickness);
+        float sine = sin(st.x * frequency) * amplitude;
+        float dSine = cos(st.x * frequency) * amplitude * frequency;
+        float distance = (st.y - sine) / sqrt(1. + dSine * dSine);
+        float distance_in_pixels = distance * underline.bounds.size.y;
+        float distance_from_top_border = distance_in_pixels - half_thickness;
+        float distance_from_bottom_border = distance_in_pixels + half_thickness;
+        float alpha = saturate(
+            0.5 - max(-distance_from_bottom_border, distance_from_top_border));
+        return input.color * float4(1., 1., 1., alpha);
+    } else {
+        return input.color;
+    }
+}
+
+/*
+**
+**              Monochrome sprites
+**
+*/
+
+struct MonochromeSprite {
+    uint order;
+    uint pad;
+    Bounds bounds;
+    Bounds content_mask;
+    Hsla color;
+    AtlasTile tile;
+    TransformationMatrix transformation;
+};
+
+struct MonochromeSpriteVertexOutput {
+    float4 position: SV_Position;
+    float2 tile_position: POSITION;
+    float4 color: COLOR;
+    float4 clip_distance: SV_ClipDistance;
+};
+
+struct MonochromeSpriteFragmentInput {
+    float4 position: SV_Position;
+    float2 tile_position: POSITION;
+    float4 color: COLOR;
+};
+
+StructuredBuffer<MonochromeSprite> mono_sprites: register(t1);
+
+MonochromeSpriteVertexOutput monochrome_sprite_vertex(uint vertex_id: SV_VertexID, uint sprite_id: SV_InstanceID) {
+    float2 unit_vertex = float2(float(vertex_id & 1u), 0.5 * float(vertex_id & 2u));
+    MonochromeSprite sprite = mono_sprites[sprite_id];
+    float4 device_position =
+        to_device_position_transformed(unit_vertex, sprite.bounds, sprite.transformation);
+    float4 clip_distance = distance_from_clip_rect(unit_vertex, sprite.bounds, sprite.content_mask);
+    float2 tile_position = to_tile_position(unit_vertex, sprite.tile);
+    float4 color = hsla_to_rgba(sprite.color);
+
+    MonochromeSpriteVertexOutput output;
+    output.position = device_position;
+    output.tile_position = tile_position;
+    output.color = color;
+    output.clip_distance = clip_distance;
+    return output;
+}
+
+float4 monochrome_sprite_fragment(MonochromeSpriteFragmentInput input): SV_Target {
+    float4 sample = t_sprite.Sample(s_sprite, input.tile_position);
+    float4 color = input.color;
+    color.a *= sample.a;
+    return color;
+}
+
+/*
+**
+**              Polychrome sprites
+**
+*/
+
+struct PolychromeSprite {
+    uint order;
+    uint grayscale;
+    Bounds bounds;
+    Bounds content_mask;
+    Corners corner_radii;
+    AtlasTile tile;
+};
+
+struct PolychromeSpriteVertexOutput {
+    float4 position: SV_Position;
+    float2 tile_position: POSITION;
+    uint sprite_id: FLAT;
+    float4 clip_distance: SV_ClipDistance;
+};
+
+struct PolychromeSpriteFragmentInput {
+    float4 position: SV_Position;
+    float2 tile_position: POSITION;
+    uint sprite_id: FLAT;
+};
+
+StructuredBuffer<PolychromeSprite> poly_sprites: register(t1);
+
+PolychromeSpriteVertexOutput polychrome_sprite_vertex(uint vertex_id: SV_VertexID, uint sprite_id: SV_InstanceID) {
+    float2 unit_vertex = float2(float(vertex_id & 1u), 0.5 * float(vertex_id & 2u));
+    PolychromeSprite sprite = poly_sprites[sprite_id];
+    float4 device_position = to_device_position(unit_vertex, sprite.bounds);
+    float4 clip_distance = distance_from_clip_rect(unit_vertex, sprite.bounds,
+                                                    sprite.content_mask);
+    float2 tile_position = to_tile_position(unit_vertex, sprite.tile);
+
+    PolychromeSpriteVertexOutput output;
+    output.position = device_position;
+    output.tile_position = tile_position;
+    output.sprite_id = sprite_id;
+    output.clip_distance = clip_distance;
+    return output;
+}
+
+float4 polychrome_sprite_fragment(PolychromeSpriteFragmentInput input): SV_Target {
+    PolychromeSprite sprite = poly_sprites[input.sprite_id];
+    float4 sample = t_sprite.Sample(s_sprite, input.tile_position);
+    float distance = quad_sdf(input.position.xy, sprite.bounds, sprite.corner_radii);
+
+    float4 color = sample;
+    if ((sprite.grayscale & 0xFFu) != 0u) {
+        float3 grayscale = dot(color.rgb, GRAYSCALE_FACTORS);
+        color = float4(grayscale, sample.a);
+    }
+    color.a *= saturate(0.5 - distance);
+    return color;
+}

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

@@ -49,7 +49,7 @@ pub struct WindowsWindowState {
     pub system_key_handled: bool,
     pub hovered: bool,
 
-    pub renderer: BladeRenderer,
+    pub renderer: DirectXRenderer,
 
     pub click_state: ClickState,
     pub system_settings: WindowsSystemSettings,
@@ -84,7 +84,7 @@ impl WindowsWindowState {
         cs: &CREATESTRUCTW,
         current_cursor: Option<HCURSOR>,
         display: WindowsDisplay,
-        gpu_context: &BladeContext,
+        gpu_context: &DirectXDevices,
         min_size: Option<Size<Pixels>>,
         appearance: WindowAppearance,
     ) -> Result<Self> {
@@ -103,7 +103,8 @@ impl WindowsWindowState {
         };
         let border_offset = WindowBorderOffset::default();
         let restore_from_minimized = None;
-        let renderer = windows_renderer::init(gpu_context, hwnd, transparent)?;
+        // let renderer = windows_renderer::init(gpu_context, hwnd, transparent)?;
+        let renderer = DirectXRenderer::new(gpu_context, hwnd, transparent)?;
         let callbacks = Callbacks::default();
         let input_handler = None;
         let pending_surrogate = None;
@@ -343,7 +344,7 @@ struct WindowCreateContext<'a> {
     drop_target_helper: IDropTargetHelper,
     validation_number: usize,
     main_receiver: flume::Receiver<Runnable>,
-    gpu_context: &'a BladeContext,
+    gpu_context: &'a DirectXDevices,
     main_thread_id_win32: u32,
     appearance: WindowAppearance,
 }
@@ -353,7 +354,7 @@ impl WindowsWindow {
         handle: AnyWindowHandle,
         params: WindowParams,
         creation_info: WindowCreationInfo,
-        gpu_context: &BladeContext,
+        gpu_context: &DirectXDevices,
     ) -> Result<Self> {
         let WindowCreationInfo {
             icon,
@@ -485,7 +486,7 @@ impl rwh::HasDisplayHandle for WindowsWindow {
 
 impl Drop for WindowsWindow {
     fn drop(&mut self) {
-        self.0.state.borrow_mut().renderer.destroy();
+        // self.0.state.borrow_mut().renderer.destroy();
         // clone this `Rc` to prevent early release of the pointer
         let this = self.0.clone();
         self.0
@@ -706,9 +707,10 @@ impl PlatformWindow for WindowsWindow {
 
     fn set_background_appearance(&self, background_appearance: WindowBackgroundAppearance) {
         let mut window_state = self.0.state.borrow_mut();
-        window_state
-            .renderer
-            .update_transparency(background_appearance != WindowBackgroundAppearance::Opaque);
+        // todo(zjk)
+        // window_state
+        //     .renderer
+        //     .update_transparency(background_appearance != WindowBackgroundAppearance::Opaque);
 
         match background_appearance {
             WindowBackgroundAppearance::Opaque => {
@@ -794,11 +796,11 @@ impl PlatformWindow for WindowsWindow {
     }
 
     fn draw(&self, scene: &Scene) {
-        self.0.state.borrow_mut().renderer.draw(scene)
+        self.0.state.borrow_mut().renderer.draw(scene).log_err();
     }
 
     fn sprite_atlas(&self) -> Arc<dyn PlatformAtlas> {
-        self.0.state.borrow().renderer.sprite_atlas().clone()
+        self.0.state.borrow().renderer.sprite_atlas()
     }
 
     fn get_raw_handle(&self) -> HWND {
@@ -806,7 +808,9 @@ impl PlatformWindow for WindowsWindow {
     }
 
     fn gpu_specs(&self) -> Option<GpuSpecs> {
-        Some(self.0.state.borrow().renderer.gpu_specs())
+        // todo(zjk)
+        // Some(self.0.state.borrow().renderer.gpu_specs())
+        None
     }
 
     fn update_ime_position(&self, _bounds: Bounds<ScaledPixels>) {