Compare commits

...
Sign in to create a new pull request.

15 commits

Author SHA1 Message Date
Junkui Zhang
a4e8d2501a init 2025-08-01 18:00:12 +08:00
Junkui Zhang
3be48a9813 remove unneeded change 2025-08-01 17:32:48 +08:00
Junkui Zhang
7984e05d35 add comments 2025-08-01 16:59:37 +08:00
Junkui Zhang
88b01e5e31 fix raster_bounds 2025-08-01 16:55:12 +08:00
Junkui Zhang
e599352fc2 remove the use of bitmap scaler 2025-08-01 16:48:36 +08:00
Kate
c3f210eb5e
improve rendering (i think) 2025-07-31 17:24:47 +02:00
Junkui Zhang
d84cf7ef03 update rendering quality of small fonts 2025-07-31 21:30:44 +08:00
Junkui Zhang
aa68b3e8ef revert wrong blend state change 2025-07-31 19:46:17 +08:00
Junkui Zhang
fad7aa6643 fix 2025-07-31 18:41:25 +08:00
Junkui Zhang
d50b3e172e cleanup 2025-07-31 18:16:20 +08:00
Junkui Zhang
a8d3e5530b DXGI_ALPHA_MODE_PREMULTIPLIED 2025-07-31 17:53:40 +08:00
Junkui Zhang
fe096ad205 fix monochrome 2025-07-31 17:48:09 +08:00
Junkui Zhang
30f6699b56 checkpoint 2025-07-31 17:27:06 +08:00
Junkui Zhang
a1001079ba properly calculate bounds 2025-07-31 16:20:58 +08:00
Kate
da83011fda Rasterize glyphs without D2D
Co-authored-by: Max Brunsfeld <maxbrunsfeld@gmail.com>
Co-authored-by: Julia <julia@zed.dev>
2025-07-30 17:08:47 -07:00
10 changed files with 713 additions and 284 deletions

View file

@ -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.

View file

@ -198,7 +198,7 @@ impl RenderOnce for CharacterGrid {
"χ", "ψ", "", "а", "в", "Ж", "ж", "З", "з", "К", "к", "л", "м", "Н", "н", "Р", "р",
"У", "у", "ф", "ч", "ь", "ы", "Э", "э", "Я", "я", "ij", "öẋ", ".,", "⣝⣑", "~", "*",
"_", "^", "`", "'", "(", "{", "«", "#", "&", "@", "$", "¢", "%", "|", "?", "", "µ",
"", "<=", "!=", "==", "--", "++", "=>", "->",
"", "<=", "!=", "==", "--", "++", "=>", "->", "🏀", "🎊", "😍", "❤️", "👍", "👎",
];
let columns = 11;

View file

@ -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,

View file

@ -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);
}

File diff suppressed because it is too large Load diff

View file

@ -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;
}

View file

@ -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>,
}
@ -183,7 +183,7 @@ impl DirectXRenderer {
self.resources.viewport[0].Width,
self.resources.viewport[0].Height,
],
..Default::default()
_pad: 0,
}],
)?;
unsafe {
@ -1423,7 +1423,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)]
@ -1436,7 +1436,7 @@ mod shader_resources {
};
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub(super) enum ShaderModule {
pub(crate) enum ShaderModule {
Quad,
Shadow,
Underline,
@ -1444,15 +1444,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)]
@ -1460,7 +1461,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))
@ -1478,7 +1479,7 @@ mod shader_resources {
}
}
pub(super) fn as_bytes(&'t self) -> &'t [u8] {
pub(crate) fn as_bytes(&'t self) -> &'t [u8] {
self.inner
}
@ -1513,6 +1514,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 }
}
@ -1521,6 +1526,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(),
@ -1537,7 +1548,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());
@ -1583,6 +1594,7 @@ mod shader_resources {
ShaderModule::PathSprite => "path_sprite",
ShaderModule::MonochromeSprite => "monochrome_sprite",
ShaderModule::PolychromeSprite => "polychrome_sprite",
ShaderModule::EmojiRasterization => "emoji_rasterization",
}
}
}

View file

@ -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) {

View file

@ -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);
}
/*

View file

@ -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))