Rasterize glyphs without D2D (#35376)

Max Brunsfeld , Kate , Julia , and Junkui Zhang created

This allows debugging Zed with Renderdoc, and also fixes an issue where
glyphs' bounds were miscalculated for certain sizes and scale factors.

Release Notes:

- N/A

---------

Co-authored-by: Kate <kate@zed.dev>
Co-authored-by: Julia <julia@zed.dev>
Co-authored-by: Junkui Zhang <364772080@qq.com>

Change summary

Cargo.toml                                              |   3 
crates/gpui/build.rs                                    |  12 
crates/gpui/examples/text.rs                            |   2 
crates/gpui/src/color.rs                                |   1 
crates/gpui/src/platform/windows/color_text_raster.hlsl |  39 
crates/gpui/src/platform/windows/direct_write.rs        | 876 +++++++---
crates/gpui/src/platform/windows/directx_atlas.rs       |   4 
crates/gpui/src/platform/windows/directx_renderer.rs    |  32 
crates/gpui/src/platform/windows/platform.rs            |  10 
crates/gpui/src/platform/windows/shaders.hlsl           |   9 
crates/gpui/src/platform/windows/window.rs              |   3 
11 files changed, 701 insertions(+), 290 deletions(-)

Detailed changes

Cargo.toml ๐Ÿ”—

@@ -678,8 +678,6 @@ features = [
     "UI_ViewManagement",
     "Wdk_System_SystemServices",
     "Win32_Globalization",
-    "Win32_Graphics_Direct2D",
-    "Win32_Graphics_Direct2D_Common",
     "Win32_Graphics_Direct3D",
     "Win32_Graphics_Direct3D11",
     "Win32_Graphics_Direct3D_Fxc",
@@ -690,7 +688,6 @@ features = [
     "Win32_Graphics_Dxgi_Common",
     "Win32_Graphics_Gdi",
     "Win32_Graphics_Imaging",
-    "Win32_Graphics_Imaging_D2D",
     "Win32_Networking_WinSock",
     "Win32_Security",
     "Win32_Security_Credentials",

crates/gpui/build.rs ๐Ÿ”—

@@ -310,6 +310,18 @@ mod windows {
                 &rust_binding_path,
             );
         }
+
+        {
+            let shader_path = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap())
+                .join("src/platform/windows/color_text_raster.hlsl");
+            compile_shader_for_module(
+                "emoji_rasterization",
+                &out_dir,
+                &fxc_path,
+                shader_path.to_str().unwrap(),
+                &rust_binding_path,
+            );
+        }
     }
 
     /// You can set the `GPUI_FXC_PATH` environment variable to specify the path to the fxc.exe compiler.

crates/gpui/examples/text.rs ๐Ÿ”—

@@ -198,7 +198,7 @@ impl RenderOnce for CharacterGrid {
             "ฯ‡", "ฯˆ", "โˆ‚", "ะฐ", "ะฒ", "ะ–", "ะถ", "ะ—", "ะท", "ะš", "ะบ", "ะป", "ะผ", "ะ", "ะฝ", "ะ ", "ั€",
             "ะฃ", "ัƒ", "ั„", "ั‡", "ัŒ", "ั‹", "ะญ", "ั", "ะฏ", "ั", "ij", "รถแบ‹", ".,", "โฃโฃ‘", "~", "*",
             "_", "^", "`", "'", "(", "{", "ยซ", "#", "&", "@", "$", "ยข", "%", "|", "?", "ยถ", "ยต",
-            "โฎ", "<=", "!=", "==", "--", "++", "=>", "->",
+            "โฎ", "<=", "!=", "==", "--", "++", "=>", "->", "๐Ÿ€", "๐ŸŽŠ", "๐Ÿ˜", "โค๏ธ", "๐Ÿ‘", "๐Ÿ‘Ž",
         ];
 
         let columns = 11;

crates/gpui/src/color.rs ๐Ÿ”—

@@ -35,6 +35,7 @@ pub(crate) fn swap_rgba_pa_to_bgra(color: &mut [u8]) {
 
 /// An RGBA color
 #[derive(PartialEq, Clone, Copy, Default)]
+#[repr(C)]
 pub struct Rgba {
     /// The red component of the color, in the range 0.0 to 1.0
     pub r: f32,

crates/gpui/src/platform/windows/color_text_raster.hlsl ๐Ÿ”—

@@ -0,0 +1,39 @@
+struct RasterVertexOutput {
+    float4 position : SV_Position;
+    float2 texcoord : TEXCOORD0;
+};
+
+RasterVertexOutput emoji_rasterization_vertex(uint vertexID : SV_VERTEXID)
+{
+    RasterVertexOutput output;
+    output.texcoord = float2((vertexID << 1) & 2, vertexID & 2);
+    output.position = float4(output.texcoord * 2.0f - 1.0f, 0.0f, 1.0f);
+    output.position.y = -output.position.y;
+
+    return output;
+}
+
+struct PixelInput {
+    float4 position: SV_Position;
+    float2 texcoord : TEXCOORD0;
+};
+
+struct Bounds {
+    int2 origin;
+    int2 size;
+};
+
+Texture2D<float4> t_layer : register(t0);
+SamplerState s_layer : register(s0);
+
+cbuffer GlyphLayerTextureParams : register(b0) {
+    Bounds bounds;
+    float4 run_color;
+};
+
+float4 emoji_rasterization_fragment(PixelInput input): SV_Target {
+    float3 sampled = t_layer.Sample(s_layer, input.texcoord.xy).rgb;
+    float alpha = (sampled.r + sampled.g + sampled.b) / 3;
+
+    return float4(run_color.rgb, alpha);
+}

crates/gpui/src/platform/windows/direct_write.rs ๐Ÿ”—

@@ -10,10 +10,11 @@ use windows::{
         Foundation::*,
         Globalization::GetUserDefaultLocaleName,
         Graphics::{
-            Direct2D::{Common::*, *},
+            Direct3D::D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP,
+            Direct3D11::*,
             DirectWrite::*,
             Dxgi::Common::*,
-            Gdi::LOGFONTW,
+            Gdi::{IsRectEmpty, LOGFONTW},
             Imaging::*,
         },
         System::SystemServices::LOCALE_NAME_MAX_LENGTH,
@@ -40,16 +41,21 @@ struct DirectWriteComponent {
     locale: String,
     factory: IDWriteFactory5,
     bitmap_factory: AgileReference<IWICImagingFactory>,
-    d2d1_factory: ID2D1Factory,
     in_memory_loader: IDWriteInMemoryFontFileLoader,
     builder: IDWriteFontSetBuilder1,
     text_renderer: Arc<TextRendererWrapper>,
-    render_context: GlyphRenderContext,
+
+    render_params: IDWriteRenderingParams3,
+    gpu_state: GPUState,
 }
 
-struct GlyphRenderContext {
-    params: IDWriteRenderingParams3,
-    dc_target: ID2D1DeviceContext4,
+struct GPUState {
+    device: ID3D11Device,
+    device_context: ID3D11DeviceContext,
+    sampler: [Option<ID3D11SamplerState>; 1],
+    blend_state: ID3D11BlendState,
+    vertex_shader: ID3D11VertexShader,
+    pixel_shader: ID3D11PixelShader,
 }
 
 struct DirectWriteState {
@@ -70,12 +76,11 @@ struct FontIdentifier {
 }
 
 impl DirectWriteComponent {
-    pub fn new(bitmap_factory: &IWICImagingFactory) -> Result<Self> {
+    pub fn new(bitmap_factory: &IWICImagingFactory, gpu_context: &DirectXDevices) -> Result<Self> {
+        // todo: ideally this would not be a large unsafe block but smaller isolated ones for easier auditing
         unsafe {
             let factory: IDWriteFactory5 = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED)?;
             let bitmap_factory = AgileReference::new(bitmap_factory)?;
-            let d2d1_factory: ID2D1Factory =
-                D2D1CreateFactory(D2D1_FACTORY_TYPE_MULTI_THREADED, None)?;
             // The `IDWriteInMemoryFontFileLoader` here is supported starting from
             // Windows 10 Creators Update, which consequently requires the entire
             // `DirectWriteTextSystem` to run on `win10 1703`+.
@@ -86,60 +91,132 @@ impl DirectWriteComponent {
             GetUserDefaultLocaleName(&mut locale_vec);
             let locale = String::from_utf16_lossy(&locale_vec);
             let text_renderer = Arc::new(TextRendererWrapper::new(&locale));
-            let render_context = GlyphRenderContext::new(&factory, &d2d1_factory)?;
+
+            let render_params = {
+                let default_params: IDWriteRenderingParams3 =
+                    factory.CreateRenderingParams()?.cast()?;
+                let gamma = default_params.GetGamma();
+                let enhanced_contrast = default_params.GetEnhancedContrast();
+                let gray_contrast = default_params.GetGrayscaleEnhancedContrast();
+                let cleartype_level = default_params.GetClearTypeLevel();
+                let grid_fit_mode = default_params.GetGridFitMode();
+
+                factory.CreateCustomRenderingParams(
+                    gamma,
+                    enhanced_contrast,
+                    gray_contrast,
+                    cleartype_level,
+                    DWRITE_PIXEL_GEOMETRY_RGB,
+                    DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC,
+                    grid_fit_mode,
+                )?
+            };
+
+            let gpu_state = GPUState::new(gpu_context)?;
 
             Ok(DirectWriteComponent {
                 locale,
                 factory,
                 bitmap_factory,
-                d2d1_factory,
                 in_memory_loader,
                 builder,
                 text_renderer,
-                render_context,
+                render_params,
+                gpu_state,
             })
         }
     }
 }
 
-impl GlyphRenderContext {
-    pub fn new(factory: &IDWriteFactory5, d2d1_factory: &ID2D1Factory) -> Result<Self> {
-        unsafe {
-            let default_params: IDWriteRenderingParams3 =
-                factory.CreateRenderingParams()?.cast()?;
-            let gamma = default_params.GetGamma();
-            let enhanced_contrast = default_params.GetEnhancedContrast();
-            let gray_contrast = default_params.GetGrayscaleEnhancedContrast();
-            let cleartype_level = default_params.GetClearTypeLevel();
-            let grid_fit_mode = default_params.GetGridFitMode();
-
-            let params = factory.CreateCustomRenderingParams(
-                gamma,
-                enhanced_contrast,
-                gray_contrast,
-                cleartype_level,
-                DWRITE_PIXEL_GEOMETRY_RGB,
-                DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC,
-                grid_fit_mode,
-            )?;
-            let dc_target = {
-                let target = d2d1_factory.CreateDCRenderTarget(&get_render_target_property(
-                    DXGI_FORMAT_B8G8R8A8_UNORM,
-                    D2D1_ALPHA_MODE_PREMULTIPLIED,
-                ))?;
-                let target = target.cast::<ID2D1DeviceContext4>()?;
-                target.SetTextRenderingParams(&params);
-                target
+impl GPUState {
+    fn new(gpu_context: &DirectXDevices) -> Result<Self> {
+        let device = gpu_context.device.clone();
+        let device_context = gpu_context.device_context.clone();
+
+        let blend_state = {
+            let mut blend_state = None;
+            let desc = D3D11_BLEND_DESC {
+                AlphaToCoverageEnable: false.into(),
+                IndependentBlendEnable: false.into(),
+                RenderTarget: [
+                    D3D11_RENDER_TARGET_BLEND_DESC {
+                        BlendEnable: true.into(),
+                        SrcBlend: D3D11_BLEND_SRC_ALPHA,
+                        DestBlend: D3D11_BLEND_INV_SRC_ALPHA,
+                        BlendOp: D3D11_BLEND_OP_ADD,
+                        SrcBlendAlpha: D3D11_BLEND_SRC_ALPHA,
+                        DestBlendAlpha: D3D11_BLEND_INV_SRC_ALPHA,
+                        BlendOpAlpha: D3D11_BLEND_OP_ADD,
+                        RenderTargetWriteMask: D3D11_COLOR_WRITE_ENABLE_ALL.0 as u8,
+                    },
+                    Default::default(),
+                    Default::default(),
+                    Default::default(),
+                    Default::default(),
+                    Default::default(),
+                    Default::default(),
+                    Default::default(),
+                ],
             };
+            unsafe { device.CreateBlendState(&desc, Some(&mut blend_state)) }?;
+            blend_state.unwrap()
+        };
 
-            Ok(Self { params, dc_target })
-        }
+        let sampler = {
+            let mut sampler = None;
+            let desc = D3D11_SAMPLER_DESC {
+                Filter: D3D11_FILTER_MIN_MAG_MIP_POINT,
+                AddressU: D3D11_TEXTURE_ADDRESS_BORDER,
+                AddressV: D3D11_TEXTURE_ADDRESS_BORDER,
+                AddressW: D3D11_TEXTURE_ADDRESS_BORDER,
+                MipLODBias: 0.0,
+                MaxAnisotropy: 1,
+                ComparisonFunc: D3D11_COMPARISON_ALWAYS,
+                BorderColor: [0.0, 0.0, 0.0, 0.0],
+                MinLOD: 0.0,
+                MaxLOD: 0.0,
+            };
+            unsafe { device.CreateSamplerState(&desc, Some(&mut sampler)) }?;
+            [sampler]
+        };
+
+        let vertex_shader = {
+            let source = shader_resources::RawShaderBytes::new(
+                shader_resources::ShaderModule::EmojiRasterization,
+                shader_resources::ShaderTarget::Vertex,
+            )?;
+            let mut shader = None;
+            unsafe { device.CreateVertexShader(source.as_bytes(), None, Some(&mut shader)) }?;
+            shader.unwrap()
+        };
+
+        let pixel_shader = {
+            let source = shader_resources::RawShaderBytes::new(
+                shader_resources::ShaderModule::EmojiRasterization,
+                shader_resources::ShaderTarget::Fragment,
+            )?;
+            let mut shader = None;
+            unsafe { device.CreatePixelShader(source.as_bytes(), None, Some(&mut shader)) }?;
+            shader.unwrap()
+        };
+
+        Ok(Self {
+            device,
+            device_context,
+            sampler,
+            blend_state,
+            vertex_shader,
+            pixel_shader,
+        })
     }
 }
 
 impl DirectWriteTextSystem {
-    pub(crate) fn new(bitmap_factory: &IWICImagingFactory) -> Result<Self> {
-        let components = DirectWriteComponent::new(bitmap_factory)?;
+    pub(crate) fn new(
+        gpu_context: &DirectXDevices,
+        bitmap_factory: &IWICImagingFactory,
+    ) -> Result<Self> {
+        let components = DirectWriteComponent::new(bitmap_factory, gpu_context)?;
         let system_font_collection = unsafe {
             let mut result = std::mem::zeroed();
             components
@@ -648,15 +725,13 @@ impl DirectWriteState {
         }
     }
 
-    fn raster_bounds(&self, params: &RenderGlyphParams) -> Result<Bounds<DevicePixels>> {
-        let render_target = &self.components.render_context.dc_target;
-        unsafe {
-            render_target.SetUnitMode(D2D1_UNIT_MODE_DIPS);
-            render_target.SetDpi(96.0 * params.scale_factor, 96.0 * params.scale_factor);
-        }
+    fn create_glyph_run_analysis(
+        &self,
+        params: &RenderGlyphParams,
+    ) -> Result<IDWriteGlyphRunAnalysis> {
         let font = &self.fonts[params.font_id.0];
         let glyph_id = [params.glyph_id.0 as u16];
-        let advance = [0.0f32];
+        let advance = [0.0];
         let offset = [DWRITE_GLYPH_OFFSET::default()];
         let glyph_run = DWRITE_GLYPH_RUN {
             fontFace: unsafe { std::mem::transmute_copy(&font.font_face) },
@@ -668,44 +743,87 @@ impl DirectWriteState {
             isSideways: BOOL(0),
             bidiLevel: 0,
         };
-        let bounds = unsafe {
-            render_target.GetGlyphRunWorldBounds(
-                Vector2 { X: 0.0, Y: 0.0 },
-                &glyph_run,
-                DWRITE_MEASURING_MODE_NATURAL,
-            )?
+        let transform = DWRITE_MATRIX {
+            m11: params.scale_factor,
+            m12: 0.0,
+            m21: 0.0,
+            m22: params.scale_factor,
+            dx: 0.0,
+            dy: 0.0,
         };
-        // todo(windows)
-        // This is a walkaround, deleted when figured out.
-        let y_offset;
-        let extra_height;
-        if params.is_emoji {
-            y_offset = 0;
-            extra_height = 0;
-        } else {
-            // make some room for scaler.
-            y_offset = -1;
-            extra_height = 2;
+        let subpixel_shift = params
+            .subpixel_variant
+            .map(|v| v as f32 / SUBPIXEL_VARIANTS as f32);
+        let baseline_origin_x = subpixel_shift.x / params.scale_factor;
+        let baseline_origin_y = subpixel_shift.y / params.scale_factor;
+
+        let mut rendering_mode = DWRITE_RENDERING_MODE1::default();
+        let mut grid_fit_mode = DWRITE_GRID_FIT_MODE::default();
+        unsafe {
+            font.font_face.GetRecommendedRenderingMode(
+                params.font_size.0,
+                // The dpi here seems that it has the same effect with `Some(&transform)`
+                1.0,
+                1.0,
+                Some(&transform),
+                false,
+                DWRITE_OUTLINE_THRESHOLD_ANTIALIASED,
+                DWRITE_MEASURING_MODE_NATURAL,
+                &self.components.render_params,
+                &mut rendering_mode,
+                &mut grid_fit_mode,
+            )?;
         }
 
-        if bounds.right < bounds.left {
-            Ok(Bounds {
-                origin: point(0.into(), 0.into()),
-                size: size(0.into(), 0.into()),
-            })
-        } else {
+        let glyph_analysis = unsafe {
+            self.components.factory.CreateGlyphRunAnalysis(
+                &glyph_run,
+                Some(&transform),
+                rendering_mode,
+                DWRITE_MEASURING_MODE_NATURAL,
+                grid_fit_mode,
+                // We're using cleartype not grayscale for monochrome is because it provides better quality
+                DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE,
+                baseline_origin_x,
+                baseline_origin_y,
+            )
+        }?;
+        Ok(glyph_analysis)
+    }
+
+    fn raster_bounds(&self, params: &RenderGlyphParams) -> Result<Bounds<DevicePixels>> {
+        let glyph_analysis = self.create_glyph_run_analysis(params)?;
+
+        let bounds = unsafe { glyph_analysis.GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1)? };
+        // Some glyphs cannot be drawn with ClearType, such as bitmap fonts. In that case
+        // GetAlphaTextureBounds() supposedly returns an empty RECT, but I haven't tested that yet.
+        if !unsafe { IsRectEmpty(&bounds) }.as_bool() {
             Ok(Bounds {
-                origin: point(
-                    ((bounds.left * params.scale_factor).ceil() as i32).into(),
-                    ((bounds.top * params.scale_factor).ceil() as i32 + y_offset).into(),
-                ),
+                origin: point(bounds.left.into(), bounds.top.into()),
                 size: size(
-                    (((bounds.right - bounds.left) * params.scale_factor).ceil() as i32).into(),
-                    (((bounds.bottom - bounds.top) * params.scale_factor).ceil() as i32
-                        + extra_height)
-                        .into(),
+                    (bounds.right - bounds.left).into(),
+                    (bounds.bottom - bounds.top).into(),
                 ),
             })
+        } else {
+            // If it's empty, retry with grayscale AA.
+            let bounds =
+                unsafe { glyph_analysis.GetAlphaTextureBounds(DWRITE_TEXTURE_ALIASED_1x1)? };
+
+            if bounds.right < bounds.left {
+                Ok(Bounds {
+                    origin: point(0.into(), 0.into()),
+                    size: size(0.into(), 0.into()),
+                })
+            } else {
+                Ok(Bounds {
+                    origin: point(bounds.left.into(), bounds.top.into()),
+                    size: size(
+                        (bounds.right - bounds.left).into(),
+                        (bounds.bottom - bounds.top).into(),
+                    ),
+                })
+            }
         }
     }
 
@@ -731,7 +849,95 @@ impl DirectWriteState {
             anyhow::bail!("glyph bounds are empty");
         }
 
-        let font_info = &self.fonts[params.font_id.0];
+        let bitmap_data = if params.is_emoji {
+            if let Ok(color) = self.rasterize_color(&params, glyph_bounds) {
+                color
+            } else {
+                let monochrome = self.rasterize_monochrome(params, glyph_bounds)?;
+                monochrome
+                    .into_iter()
+                    .flat_map(|pixel| [0, 0, 0, pixel])
+                    .collect::<Vec<_>>()
+            }
+        } else {
+            self.rasterize_monochrome(params, glyph_bounds)?
+        };
+
+        Ok((glyph_bounds.size, bitmap_data))
+    }
+
+    fn rasterize_monochrome(
+        &self,
+        params: &RenderGlyphParams,
+        glyph_bounds: Bounds<DevicePixels>,
+    ) -> Result<Vec<u8>> {
+        let mut bitmap_data =
+            vec![0u8; glyph_bounds.size.width.0 as usize * glyph_bounds.size.height.0 as usize * 3];
+
+        let glyph_analysis = self.create_glyph_run_analysis(params)?;
+        unsafe {
+            glyph_analysis.CreateAlphaTexture(
+                // We're using cleartype not grayscale for monochrome is because it provides better quality
+                DWRITE_TEXTURE_CLEARTYPE_3x1,
+                &RECT {
+                    left: glyph_bounds.origin.x.0,
+                    top: glyph_bounds.origin.y.0,
+                    right: glyph_bounds.size.width.0 + glyph_bounds.origin.x.0,
+                    bottom: glyph_bounds.size.height.0 + glyph_bounds.origin.y.0,
+                },
+                &mut bitmap_data,
+            )?;
+        }
+
+        let bitmap_factory = self.components.bitmap_factory.resolve()?;
+        let bitmap = unsafe {
+            bitmap_factory.CreateBitmapFromMemory(
+                glyph_bounds.size.width.0 as u32,
+                glyph_bounds.size.height.0 as u32,
+                &GUID_WICPixelFormat24bppRGB,
+                glyph_bounds.size.width.0 as u32 * 3,
+                &bitmap_data,
+            )
+        }?;
+
+        let grayscale_bitmap =
+            unsafe { WICConvertBitmapSource(&GUID_WICPixelFormat8bppGray, &bitmap) }?;
+
+        let mut bitmap_data =
+            vec![0u8; glyph_bounds.size.width.0 as usize * glyph_bounds.size.height.0 as usize];
+        unsafe {
+            grayscale_bitmap.CopyPixels(
+                std::ptr::null() as _,
+                glyph_bounds.size.width.0 as u32,
+                &mut bitmap_data,
+            )
+        }?;
+
+        Ok(bitmap_data)
+    }
+
+    fn rasterize_color(
+        &self,
+        params: &RenderGlyphParams,
+        glyph_bounds: Bounds<DevicePixels>,
+    ) -> Result<Vec<u8>> {
+        let bitmap_size = glyph_bounds.size;
+        let subpixel_shift = params
+            .subpixel_variant
+            .map(|v| v as f32 / SUBPIXEL_VARIANTS as f32);
+        let baseline_origin_x = subpixel_shift.x / params.scale_factor;
+        let baseline_origin_y = subpixel_shift.y / params.scale_factor;
+
+        let transform = DWRITE_MATRIX {
+            m11: params.scale_factor,
+            m12: 0.0,
+            m21: 0.0,
+            m22: params.scale_factor,
+            dx: 0.0,
+            dy: 0.0,
+        };
+
+        let font = &self.fonts[params.font_id.0];
         let glyph_id = [params.glyph_id.0 as u16];
         let advance = [glyph_bounds.size.width.0 as f32];
         let offset = [DWRITE_GLYPH_OFFSET {
@@ -739,7 +945,7 @@ impl DirectWriteState {
             ascenderOffset: glyph_bounds.origin.y.0 as f32 / params.scale_factor,
         }];
         let glyph_run = DWRITE_GLYPH_RUN {
-            fontFace: unsafe { std::mem::transmute_copy(&font_info.font_face) },
+            fontFace: unsafe { std::mem::transmute_copy(&font.font_face) },
             fontEmSize: params.font_size.0,
             glyphCount: 1,
             glyphIndices: glyph_id.as_ptr(),
@@ -749,160 +955,254 @@ impl DirectWriteState {
             bidiLevel: 0,
         };
 
-        // Add an extra pixel when the subpixel variant isn't zero to make room for anti-aliasing.
-        let mut bitmap_size = glyph_bounds.size;
-        if params.subpixel_variant.x > 0 {
-            bitmap_size.width += DevicePixels(1);
-        }
-        if params.subpixel_variant.y > 0 {
-            bitmap_size.height += DevicePixels(1);
-        }
-        let bitmap_size = bitmap_size;
-
-        let total_bytes;
-        let bitmap_format;
-        let render_target_property;
-        let bitmap_width;
-        let bitmap_height;
-        let bitmap_stride;
-        let bitmap_dpi;
-        if params.is_emoji {
-            total_bytes = bitmap_size.height.0 as usize * bitmap_size.width.0 as usize * 4;
-            bitmap_format = &GUID_WICPixelFormat32bppPBGRA;
-            render_target_property = get_render_target_property(
-                DXGI_FORMAT_B8G8R8A8_UNORM,
-                D2D1_ALPHA_MODE_PREMULTIPLIED,
-            );
-            bitmap_width = bitmap_size.width.0 as u32;
-            bitmap_height = bitmap_size.height.0 as u32;
-            bitmap_stride = bitmap_size.width.0 as u32 * 4;
-            bitmap_dpi = 96.0;
-        } else {
-            total_bytes = bitmap_size.height.0 as usize * bitmap_size.width.0 as usize;
-            bitmap_format = &GUID_WICPixelFormat8bppAlpha;
-            render_target_property =
-                get_render_target_property(DXGI_FORMAT_A8_UNORM, D2D1_ALPHA_MODE_STRAIGHT);
-            bitmap_width = bitmap_size.width.0 as u32 * 2;
-            bitmap_height = bitmap_size.height.0 as u32 * 2;
-            bitmap_stride = bitmap_size.width.0 as u32;
-            bitmap_dpi = 192.0;
-        }
+        // todo: support formats other than COLR
+        let color_enumerator = unsafe {
+            self.components.factory.TranslateColorGlyphRun(
+                Vector2::new(baseline_origin_x, baseline_origin_y),
+                &glyph_run,
+                None,
+                DWRITE_GLYPH_IMAGE_FORMATS_COLR,
+                DWRITE_MEASURING_MODE_NATURAL,
+                Some(&transform),
+                0,
+            )
+        }?;
+
+        let mut glyph_layers = Vec::new();
+        loop {
+            let color_run = unsafe { color_enumerator.GetCurrentRun() }?;
+            let color_run = unsafe { &*color_run };
+            let image_format = color_run.glyphImageFormat & !DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE;
+            if image_format == DWRITE_GLYPH_IMAGE_FORMATS_COLR {
+                let color_analysis = unsafe {
+                    self.components.factory.CreateGlyphRunAnalysis(
+                        &color_run.Base.glyphRun as *const _,
+                        Some(&transform),
+                        DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC,
+                        DWRITE_MEASURING_MODE_NATURAL,
+                        DWRITE_GRID_FIT_MODE_DEFAULT,
+                        DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE,
+                        baseline_origin_x,
+                        baseline_origin_y,
+                    )
+                }?;
 
-        let bitmap_factory = self.components.bitmap_factory.resolve()?;
-        unsafe {
-            let bitmap = bitmap_factory.CreateBitmap(
-                bitmap_width,
-                bitmap_height,
-                bitmap_format,
-                WICBitmapCacheOnLoad,
-            )?;
-            let render_target = self
-                .components
-                .d2d1_factory
-                .CreateWicBitmapRenderTarget(&bitmap, &render_target_property)?;
-            let brush = render_target.CreateSolidColorBrush(&BRUSH_COLOR, None)?;
-            let subpixel_shift = params
-                .subpixel_variant
-                .map(|v| v as f32 / SUBPIXEL_VARIANTS as f32);
-            let baseline_origin = Vector2 {
-                X: subpixel_shift.x / params.scale_factor,
-                Y: subpixel_shift.y / params.scale_factor,
-            };
+                let color_bounds =
+                    unsafe { color_analysis.GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1) }?;
 
-            // This `cast()` action here should never fail since we are running on Win10+, and
-            // ID2D1DeviceContext4 requires Win8+
-            let render_target = render_target.cast::<ID2D1DeviceContext4>().unwrap();
-            render_target.SetUnitMode(D2D1_UNIT_MODE_DIPS);
-            render_target.SetDpi(
-                bitmap_dpi * params.scale_factor,
-                bitmap_dpi * params.scale_factor,
-            );
-            render_target.SetTextRenderingParams(&self.components.render_context.params);
-            render_target.BeginDraw();
-
-            if params.is_emoji {
-                // WARN: only DWRITE_GLYPH_IMAGE_FORMATS_COLR has been tested
-                let enumerator = self.components.factory.TranslateColorGlyphRun(
-                    baseline_origin,
-                    &glyph_run as _,
-                    None,
-                    DWRITE_GLYPH_IMAGE_FORMATS_COLR
-                        | DWRITE_GLYPH_IMAGE_FORMATS_SVG
-                        | DWRITE_GLYPH_IMAGE_FORMATS_PNG
-                        | DWRITE_GLYPH_IMAGE_FORMATS_JPEG
-                        | DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8,
-                    DWRITE_MEASURING_MODE_NATURAL,
-                    None,
-                    0,
-                )?;
-                while enumerator.MoveNext().is_ok() {
-                    let Ok(color_glyph) = enumerator.GetCurrentRun() else {
-                        break;
+                let color_size = size(
+                    color_bounds.right - color_bounds.left,
+                    color_bounds.bottom - color_bounds.top,
+                );
+                if color_size.width > 0 && color_size.height > 0 {
+                    let mut alpha_data =
+                        vec![0u8; (color_size.width * color_size.height * 3) as usize];
+                    unsafe {
+                        color_analysis.CreateAlphaTexture(
+                            DWRITE_TEXTURE_CLEARTYPE_3x1,
+                            &color_bounds,
+                            &mut alpha_data,
+                        )
+                    }?;
+
+                    let run_color = {
+                        let run_color = color_run.Base.runColor;
+                        Rgba {
+                            r: run_color.r,
+                            g: run_color.g,
+                            b: run_color.b,
+                            a: run_color.a,
+                        }
                     };
-                    let color_glyph = &*color_glyph;
-                    let brush_color = translate_color(&color_glyph.Base.runColor);
-                    brush.SetColor(&brush_color);
-                    match color_glyph.glyphImageFormat {
-                        DWRITE_GLYPH_IMAGE_FORMATS_PNG
-                        | DWRITE_GLYPH_IMAGE_FORMATS_JPEG
-                        | DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8 => render_target
-                            .DrawColorBitmapGlyphRun(
-                                color_glyph.glyphImageFormat,
-                                baseline_origin,
-                                &color_glyph.Base.glyphRun,
-                                color_glyph.measuringMode,
-                                D2D1_COLOR_BITMAP_GLYPH_SNAP_OPTION_DEFAULT,
-                            ),
-                        DWRITE_GLYPH_IMAGE_FORMATS_SVG => render_target.DrawSvgGlyphRun(
-                            baseline_origin,
-                            &color_glyph.Base.glyphRun,
-                            &brush,
-                            None,
-                            color_glyph.Base.paletteIndex as u32,
-                            color_glyph.measuringMode,
-                        ),
-                        _ => render_target.DrawGlyphRun(
-                            baseline_origin,
-                            &color_glyph.Base.glyphRun,
-                            Some(color_glyph.Base.glyphRunDescription as *const _),
-                            &brush,
-                            color_glyph.measuringMode,
-                        ),
-                    }
+                    let bounds = bounds(point(color_bounds.left, color_bounds.top), color_size);
+                    let alpha_data = alpha_data
+                        .chunks_exact(3)
+                        .flat_map(|chunk| [chunk[0], chunk[1], chunk[2], 255])
+                        .collect::<Vec<_>>();
+                    glyph_layers.push(GlyphLayerTexture::new(
+                        &self.components.gpu_state,
+                        run_color,
+                        bounds,
+                        &alpha_data,
+                    )?);
                 }
-            } else {
-                render_target.DrawGlyphRun(
-                    baseline_origin,
-                    &glyph_run,
-                    None,
-                    &brush,
-                    DWRITE_MEASURING_MODE_NATURAL,
-                );
             }
-            render_target.EndDraw(None, None)?;
-
-            let mut raw_data = vec![0u8; total_bytes];
-            if params.is_emoji {
-                bitmap.CopyPixels(std::ptr::null() as _, bitmap_stride, &mut raw_data)?;
-                // Convert from BGRA with premultiplied alpha to BGRA with straight alpha.
-                for pixel in raw_data.chunks_exact_mut(4) {
-                    let a = pixel[3] as f32 / 255.;
-                    pixel[0] = (pixel[0] as f32 / a) as u8;
-                    pixel[1] = (pixel[1] as f32 / a) as u8;
-                    pixel[2] = (pixel[2] as f32 / a) as u8;
-                }
-            } else {
-                let scaler = bitmap_factory.CreateBitmapScaler()?;
-                scaler.Initialize(
-                    &bitmap,
-                    bitmap_size.width.0 as u32,
-                    bitmap_size.height.0 as u32,
-                    WICBitmapInterpolationModeHighQualityCubic,
-                )?;
-                scaler.CopyPixels(std::ptr::null() as _, bitmap_stride, &mut raw_data)?;
+
+            let has_next = unsafe { color_enumerator.MoveNext() }
+                .map(|e| e.as_bool())
+                .unwrap_or(false);
+            if !has_next {
+                break;
             }
-            Ok((bitmap_size, raw_data))
         }
+
+        let gpu_state = &self.components.gpu_state;
+        let params_buffer = {
+            let desc = D3D11_BUFFER_DESC {
+                ByteWidth: std::mem::size_of::<GlyphLayerTextureParams>() as u32,
+                Usage: D3D11_USAGE_DYNAMIC,
+                BindFlags: D3D11_BIND_CONSTANT_BUFFER.0 as u32,
+                CPUAccessFlags: D3D11_CPU_ACCESS_WRITE.0 as u32,
+                MiscFlags: 0,
+                StructureByteStride: 0,
+            };
+
+            let mut buffer = None;
+            unsafe {
+                gpu_state
+                    .device
+                    .CreateBuffer(&desc, None, Some(&mut buffer))
+            }?;
+            [buffer]
+        };
+
+        let render_target_texture = {
+            let mut texture = None;
+            let desc = D3D11_TEXTURE2D_DESC {
+                Width: bitmap_size.width.0 as u32,
+                Height: bitmap_size.height.0 as u32,
+                MipLevels: 1,
+                ArraySize: 1,
+                Format: DXGI_FORMAT_B8G8R8A8_UNORM,
+                SampleDesc: DXGI_SAMPLE_DESC {
+                    Count: 1,
+                    Quality: 0,
+                },
+                Usage: D3D11_USAGE_DEFAULT,
+                BindFlags: D3D11_BIND_RENDER_TARGET.0 as u32,
+                CPUAccessFlags: 0,
+                MiscFlags: 0,
+            };
+            unsafe {
+                gpu_state
+                    .device
+                    .CreateTexture2D(&desc, None, Some(&mut texture))
+            }?;
+            texture.unwrap()
+        };
+
+        let render_target_view = {
+            let desc = D3D11_RENDER_TARGET_VIEW_DESC {
+                Format: DXGI_FORMAT_B8G8R8A8_UNORM,
+                ViewDimension: D3D11_RTV_DIMENSION_TEXTURE2D,
+                Anonymous: D3D11_RENDER_TARGET_VIEW_DESC_0 {
+                    Texture2D: D3D11_TEX2D_RTV { MipSlice: 0 },
+                },
+            };
+            let mut rtv = None;
+            unsafe {
+                gpu_state.device.CreateRenderTargetView(
+                    &render_target_texture,
+                    Some(&desc),
+                    Some(&mut rtv),
+                )
+            }?;
+            [rtv]
+        };
+
+        let staging_texture = {
+            let mut texture = None;
+            let desc = D3D11_TEXTURE2D_DESC {
+                Width: bitmap_size.width.0 as u32,
+                Height: bitmap_size.height.0 as u32,
+                MipLevels: 1,
+                ArraySize: 1,
+                Format: DXGI_FORMAT_B8G8R8A8_UNORM,
+                SampleDesc: DXGI_SAMPLE_DESC {
+                    Count: 1,
+                    Quality: 0,
+                },
+                Usage: D3D11_USAGE_STAGING,
+                BindFlags: 0,
+                CPUAccessFlags: D3D11_CPU_ACCESS_READ.0 as u32,
+                MiscFlags: 0,
+            };
+            unsafe {
+                gpu_state
+                    .device
+                    .CreateTexture2D(&desc, None, Some(&mut texture))
+            }?;
+            texture.unwrap()
+        };
+
+        let device_context = &gpu_state.device_context;
+        unsafe { device_context.IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP) };
+        unsafe { device_context.VSSetShader(&gpu_state.vertex_shader, None) };
+        unsafe { device_context.PSSetShader(&gpu_state.pixel_shader, None) };
+        unsafe { device_context.VSSetConstantBuffers(0, Some(&params_buffer)) };
+        unsafe { device_context.PSSetConstantBuffers(0, Some(&params_buffer)) };
+        unsafe { device_context.OMSetRenderTargets(Some(&render_target_view), None) };
+        unsafe { device_context.PSSetSamplers(0, Some(&gpu_state.sampler)) };
+        unsafe { device_context.OMSetBlendState(&gpu_state.blend_state, None, 0xffffffff) };
+
+        for layer in glyph_layers {
+            let params = GlyphLayerTextureParams {
+                run_color: layer.run_color,
+                bounds: layer.bounds,
+            };
+            unsafe {
+                let mut dest = std::mem::zeroed();
+                gpu_state.device_context.Map(
+                    params_buffer[0].as_ref().unwrap(),
+                    0,
+                    D3D11_MAP_WRITE_DISCARD,
+                    0,
+                    Some(&mut dest),
+                )?;
+                std::ptr::copy_nonoverlapping(&params as *const _, dest.pData as *mut _, 1);
+                gpu_state
+                    .device_context
+                    .Unmap(params_buffer[0].as_ref().unwrap(), 0);
+            };
+
+            let texture = [Some(layer.texture_view)];
+            unsafe { device_context.PSSetShaderResources(0, Some(&texture)) };
+
+            let viewport = [D3D11_VIEWPORT {
+                TopLeftX: layer.bounds.origin.x as f32,
+                TopLeftY: layer.bounds.origin.y as f32,
+                Width: layer.bounds.size.width as f32,
+                Height: layer.bounds.size.height as f32,
+                MinDepth: 0.0,
+                MaxDepth: 1.0,
+            }];
+            unsafe { device_context.RSSetViewports(Some(&viewport)) };
+
+            unsafe { device_context.Draw(4, 0) };
+        }
+
+        unsafe { device_context.CopyResource(&staging_texture, &render_target_texture) };
+
+        let mapped_data = {
+            let mut mapped_data = D3D11_MAPPED_SUBRESOURCE::default();
+            unsafe {
+                device_context.Map(
+                    &staging_texture,
+                    0,
+                    D3D11_MAP_READ,
+                    0,
+                    Some(&mut mapped_data),
+                )
+            }?;
+            mapped_data
+        };
+        let mut rasterized =
+            vec![0u8; (bitmap_size.width.0 as u32 * bitmap_size.height.0 as u32 * 4) as usize];
+
+        for y in 0..bitmap_size.height.0 as usize {
+            let width = bitmap_size.width.0 as usize;
+            unsafe {
+                std::ptr::copy_nonoverlapping::<u8>(
+                    (mapped_data.pData as *const u8).byte_add(mapped_data.RowPitch as usize * y),
+                    rasterized
+                        .as_mut_ptr()
+                        .byte_add(width * y * std::mem::size_of::<u32>()),
+                    width * std::mem::size_of::<u32>(),
+                )
+            };
+        }
+
+        Ok(rasterized)
     }
 
     fn get_typographic_bounds(&self, font_id: FontId, glyph_id: GlyphId) -> Result<Bounds<f32>> {
@@ -976,6 +1276,84 @@ impl Drop for DirectWriteState {
     }
 }
 
+struct GlyphLayerTexture {
+    run_color: Rgba,
+    bounds: Bounds<i32>,
+    texture_view: ID3D11ShaderResourceView,
+    // holding on to the texture to not RAII drop it
+    _texture: ID3D11Texture2D,
+}
+
+impl GlyphLayerTexture {
+    pub fn new(
+        gpu_state: &GPUState,
+        run_color: Rgba,
+        bounds: Bounds<i32>,
+        alpha_data: &[u8],
+    ) -> Result<Self> {
+        let texture_size = bounds.size;
+
+        let desc = D3D11_TEXTURE2D_DESC {
+            Width: texture_size.width as u32,
+            Height: texture_size.height as u32,
+            MipLevels: 1,
+            ArraySize: 1,
+            Format: DXGI_FORMAT_R8G8B8A8_UNORM,
+            SampleDesc: DXGI_SAMPLE_DESC {
+                Count: 1,
+                Quality: 0,
+            },
+            Usage: D3D11_USAGE_DEFAULT,
+            BindFlags: D3D11_BIND_SHADER_RESOURCE.0 as u32,
+            CPUAccessFlags: D3D11_CPU_ACCESS_WRITE.0 as u32,
+            MiscFlags: 0,
+        };
+
+        let texture = {
+            let mut texture: Option<ID3D11Texture2D> = None;
+            unsafe {
+                gpu_state
+                    .device
+                    .CreateTexture2D(&desc, None, Some(&mut texture))?
+            };
+            texture.unwrap()
+        };
+        let texture_view = {
+            let mut view: Option<ID3D11ShaderResourceView> = None;
+            unsafe {
+                gpu_state
+                    .device
+                    .CreateShaderResourceView(&texture, None, Some(&mut view))?
+            };
+            view.unwrap()
+        };
+
+        unsafe {
+            gpu_state.device_context.UpdateSubresource(
+                &texture,
+                0,
+                None,
+                alpha_data.as_ptr() as _,
+                (texture_size.width * 4) as u32,
+                0,
+            )
+        };
+
+        Ok(GlyphLayerTexture {
+            run_color,
+            bounds,
+            texture_view,
+            _texture: texture,
+        })
+    }
+}
+
+#[repr(C)]
+struct GlyphLayerTextureParams {
+    bounds: Bounds<i32>,
+    run_color: Rgba,
+}
+
 struct TextRendererWrapper(pub IDWriteTextRenderer);
 
 impl TextRendererWrapper {
@@ -1470,16 +1848,6 @@ fn get_name(string: IDWriteLocalizedStrings, locale: &str) -> Result<String> {
     Ok(String::from_utf16_lossy(&name_vec[..name_length]))
 }
 
-#[inline]
-fn translate_color(color: &DWRITE_COLOR_F) -> D2D1_COLOR_F {
-    D2D1_COLOR_F {
-        r: color.r,
-        g: color.g,
-        b: color.b,
-        a: color.a,
-    }
-}
-
 fn get_system_ui_font_name() -> SharedString {
     unsafe {
         let mut info: LOGFONTW = std::mem::zeroed();
@@ -1504,24 +1872,6 @@ fn get_system_ui_font_name() -> SharedString {
     }
 }
 
-#[inline]
-fn get_render_target_property(
-    pixel_format: DXGI_FORMAT,
-    alpha_mode: D2D1_ALPHA_MODE,
-) -> D2D1_RENDER_TARGET_PROPERTIES {
-    D2D1_RENDER_TARGET_PROPERTIES {
-        r#type: D2D1_RENDER_TARGET_TYPE_DEFAULT,
-        pixelFormat: D2D1_PIXEL_FORMAT {
-            format: pixel_format,
-            alphaMode: alpha_mode,
-        },
-        dpiX: 96.0,
-        dpiY: 96.0,
-        usage: D2D1_RENDER_TARGET_USAGE_NONE,
-        minLevel: D2D1_FEATURE_LEVEL_DEFAULT,
-    }
-}
-
 // One would think that with newer DirectWrite method: IDWriteFontFace4::GetGlyphImageFormats
 // but that doesn't seem to work for some glyphs, say โค
 fn is_color_glyph(
@@ -1561,12 +1911,6 @@ fn is_color_glyph(
 }
 
 const DEFAULT_LOCALE_NAME: PCWSTR = windows::core::w!("en-US");
-const BRUSH_COLOR: D2D1_COLOR_F = D2D1_COLOR_F {
-    r: 1.0,
-    g: 1.0,
-    b: 1.0,
-    a: 1.0,
-};
 
 #[cfg(test)]
 mod tests {

crates/gpui/src/platform/windows/directx_atlas.rs ๐Ÿ”—

@@ -7,7 +7,7 @@ use windows::Win32::Graphics::{
         D3D11_USAGE_DEFAULT, ID3D11Device, ID3D11DeviceContext, ID3D11ShaderResourceView,
         ID3D11Texture2D,
     },
-    Dxgi::Common::{DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_SAMPLE_DESC},
+    Dxgi::Common::*,
 };
 
 use crate::{
@@ -167,7 +167,7 @@ impl DirectXAtlasState {
         let bytes_per_pixel;
         match kind {
             AtlasTextureKind::Monochrome => {
-                pixel_format = DXGI_FORMAT_A8_UNORM;
+                pixel_format = DXGI_FORMAT_R8_UNORM;
                 bind_flag = D3D11_BIND_SHADER_RESOURCE;
                 bytes_per_pixel = 1;
             }

crates/gpui/src/platform/windows/directx_renderer.rs ๐Ÿ”—

@@ -42,8 +42,8 @@ pub(crate) struct DirectXRenderer {
 pub(crate) struct DirectXDevices {
     adapter: IDXGIAdapter1,
     dxgi_factory: IDXGIFactory6,
-    device: ID3D11Device,
-    device_context: ID3D11DeviceContext,
+    pub(crate) device: ID3D11Device,
+    pub(crate) device_context: ID3D11DeviceContext,
     dxgi_device: Option<IDXGIDevice>,
 }
 
@@ -187,7 +187,7 @@ impl DirectXRenderer {
                     self.resources.viewport[0].Width,
                     self.resources.viewport[0].Height,
                 ],
-                ..Default::default()
+                _pad: 0,
             }],
         )?;
         unsafe {
@@ -1441,7 +1441,7 @@ fn report_live_objects(device: &ID3D11Device) -> Result<()> {
 
 const BUFFER_COUNT: usize = 3;
 
-mod shader_resources {
+pub(crate) mod shader_resources {
     use anyhow::Result;
 
     #[cfg(debug_assertions)]
@@ -1454,7 +1454,7 @@ mod shader_resources {
     };
 
     #[derive(Copy, Clone, Debug, Eq, PartialEq)]
-    pub(super) enum ShaderModule {
+    pub(crate) enum ShaderModule {
         Quad,
         Shadow,
         Underline,
@@ -1462,15 +1462,16 @@ mod shader_resources {
         PathSprite,
         MonochromeSprite,
         PolychromeSprite,
+        EmojiRasterization,
     }
 
     #[derive(Copy, Clone, Debug, Eq, PartialEq)]
-    pub(super) enum ShaderTarget {
+    pub(crate) enum ShaderTarget {
         Vertex,
         Fragment,
     }
 
-    pub(super) struct RawShaderBytes<'t> {
+    pub(crate) struct RawShaderBytes<'t> {
         inner: &'t [u8],
 
         #[cfg(debug_assertions)]
@@ -1478,7 +1479,7 @@ mod shader_resources {
     }
 
     impl<'t> RawShaderBytes<'t> {
-        pub(super) fn new(module: ShaderModule, target: ShaderTarget) -> Result<Self> {
+        pub(crate) fn new(module: ShaderModule, target: ShaderTarget) -> Result<Self> {
             #[cfg(not(debug_assertions))]
             {
                 Ok(Self::from_bytes(module, target))
@@ -1496,7 +1497,7 @@ mod shader_resources {
             }
         }
 
-        pub(super) fn as_bytes(&'t self) -> &'t [u8] {
+        pub(crate) fn as_bytes(&'t self) -> &'t [u8] {
             self.inner
         }
 
@@ -1531,6 +1532,10 @@ mod shader_resources {
                     ShaderTarget::Vertex => POLYCHROME_SPRITE_VERTEX_BYTES,
                     ShaderTarget::Fragment => POLYCHROME_SPRITE_FRAGMENT_BYTES,
                 },
+                ShaderModule::EmojiRasterization => match target {
+                    ShaderTarget::Vertex => EMOJI_RASTERIZATION_VERTEX_BYTES,
+                    ShaderTarget::Fragment => EMOJI_RASTERIZATION_FRAGMENT_BYTES,
+                },
             };
             Self { inner: bytes }
         }
@@ -1539,6 +1544,12 @@ mod shader_resources {
     #[cfg(debug_assertions)]
     pub(super) fn build_shader_blob(entry: ShaderModule, target: ShaderTarget) -> Result<ID3DBlob> {
         unsafe {
+            let shader_name = if matches!(entry, ShaderModule::EmojiRasterization) {
+                "color_text_raster.hlsl"
+            } else {
+                "shaders.hlsl"
+            };
+
             let entry = format!(
                 "{}_{}\0",
                 entry.as_str(),
@@ -1555,7 +1566,7 @@ mod shader_resources {
             let mut compile_blob = None;
             let mut error_blob = None;
             let shader_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
-                .join("src/platform/windows/shaders.hlsl")
+                .join(&format!("src/platform/windows/{}", shader_name))
                 .canonicalize()?;
 
             let entry_point = PCSTR::from_raw(entry.as_ptr());
@@ -1601,6 +1612,7 @@ mod shader_resources {
                 ShaderModule::PathSprite => "path_sprite",
                 ShaderModule::MonochromeSprite => "monochrome_sprite",
                 ShaderModule::PolychromeSprite => "polychrome_sprite",
+                ShaderModule::EmojiRasterization => "emoji_rasterization",
             }
         }
     }

crates/gpui/src/platform/windows/platform.rs ๐Ÿ”—

@@ -44,6 +44,7 @@ pub(crate) struct WindowsPlatform {
     drop_target_helper: IDropTargetHelper,
     validation_number: usize,
     main_thread_id_win32: u32,
+    disable_direct_composition: bool,
 }
 
 pub(crate) struct WindowsPlatformState {
@@ -93,14 +94,18 @@ impl WindowsPlatform {
             main_thread_id_win32,
             validation_number,
         ));
+        let disable_direct_composition = std::env::var(DISABLE_DIRECT_COMPOSITION)
+            .is_ok_and(|value| value == "true" || value == "1");
         let background_executor = BackgroundExecutor::new(dispatcher.clone());
         let foreground_executor = ForegroundExecutor::new(dispatcher);
+        let directx_devices = DirectXDevices::new(disable_direct_composition)
+            .context("Unable to init directx devices.")?;
         let bitmap_factory = ManuallyDrop::new(unsafe {
             CoCreateInstance(&CLSID_WICImagingFactory, None, CLSCTX_INPROC_SERVER)
                 .context("Error creating bitmap factory.")?
         });
         let text_system = Arc::new(
-            DirectWriteTextSystem::new(&bitmap_factory)
+            DirectWriteTextSystem::new(&directx_devices, &bitmap_factory)
                 .context("Error creating DirectWriteTextSystem")?,
         );
         let drop_target_helper: IDropTargetHelper = unsafe {
@@ -120,6 +125,7 @@ impl WindowsPlatform {
             background_executor,
             foreground_executor,
             text_system,
+            disable_direct_composition,
             windows_version,
             bitmap_factory,
             drop_target_helper,
@@ -184,6 +190,7 @@ impl WindowsPlatform {
             validation_number: self.validation_number,
             main_receiver: self.main_receiver.clone(),
             main_thread_id_win32: self.main_thread_id_win32,
+            disable_direct_composition: self.disable_direct_composition,
         }
     }
 
@@ -715,6 +722,7 @@ pub(crate) struct WindowCreationInfo {
     pub(crate) validation_number: usize,
     pub(crate) main_receiver: flume::Receiver<Runnable>,
     pub(crate) main_thread_id_win32: u32,
+    pub(crate) disable_direct_composition: bool,
 }
 
 fn open_target(target: &str) {

crates/gpui/src/platform/windows/shaders.hlsl ๐Ÿ”—

@@ -1,6 +1,6 @@
 cbuffer GlobalParams: register(b0) {
     float2 global_viewport_size;
-    uint2 _global_pad;
+    uint2 _pad;
 };
 
 Texture2D<float4> t_sprite: register(t0);
@@ -1069,6 +1069,7 @@ struct MonochromeSpriteFragmentInput {
     float4 position: SV_Position;
     float2 tile_position: POSITION;
     nointerpolation float4 color: COLOR;
+    float4 clip_distance: SV_ClipDistance;
 };
 
 StructuredBuffer<MonochromeSprite> mono_sprites: register(t1);
@@ -1091,10 +1092,8 @@ MonochromeSpriteVertexOutput monochrome_sprite_vertex(uint vertex_id: SV_VertexI
 }
 
 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;
+    float sample = t_sprite.Sample(s_sprite, input.tile_position).r;
+    return float4(input.color.rgb, input.color.a * sample);
 }
 
 /*

crates/gpui/src/platform/windows/window.rs ๐Ÿ”—

@@ -360,6 +360,7 @@ impl WindowsWindow {
             validation_number,
             main_receiver,
             main_thread_id_win32,
+            disable_direct_composition,
         } = creation_info;
         let classname = register_wnd_class(icon);
         let hide_title_bar = params
@@ -375,8 +376,6 @@ impl WindowsWindow {
                 .map(|title| title.as_ref())
                 .unwrap_or(""),
         );
-        let disable_direct_composition = std::env::var(DISABLE_DIRECT_COMPOSITION)
-            .is_ok_and(|value| value == "true" || value == "1");
 
         let (mut dwexstyle, dwstyle) = if params.kind == WindowKind::PopUp {
             (WS_EX_TOOLWINDOW, WINDOW_STYLE(0x0))