diff --git a/crates/gpui/src/platform/windows/color_text_raster.hlsl b/crates/gpui/src/platform/windows/color_text_raster.hlsl index b19bc05ac9..b0307aee42 100644 --- a/crates/gpui/src/platform/windows/color_text_raster.hlsl +++ b/crates/gpui/src/platform/windows/color_text_raster.hlsl @@ -1,22 +1,39 @@ - -struct RasterVertexInput { - float2 position : POSITION; -}; - struct RasterVertexOutput { float4 position : SV_Position; + float2 texcoord : TEXCOORD0; }; -RasterVertexOutput vertex(RasterVertexInput input) { +RasterVertexOutput vertex(uint vertexID : SV_VERTEXID) +{ RasterVertexOutput output; - output.position = float4(input.position, 0.0, 1.0); + 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 t_layer : register(t0); +SamplerState s_layer : register(s0); + +cbuffer GlyphLayerTextureParams : register(b0) { + Bounds bounds; + float4 run_color; }; float4 pixel(PixelInput input): SV_Target { - return float4(input.position.xy, 0.0, 1.0); + 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); } diff --git a/crates/gpui/src/platform/windows/direct_write.rs b/crates/gpui/src/platform/windows/direct_write.rs index 655a883938..a15732c7e6 100644 --- a/crates/gpui/src/platform/windows/direct_write.rs +++ b/crates/gpui/src/platform/windows/direct_write.rs @@ -10,16 +10,8 @@ use windows::{ Foundation::*, Globalization::GetUserDefaultLocaleName, Graphics::{ - Direct3D11::{ - D3D11_BIND_SHADER_RESOURCE, D3D11_BUFFER_DESC, D3D11_CPU_ACCESS_WRITE, - D3D11_MAP_WRITE_DISCARD, D3D11_RESOURCE_MISC_BUFFER_STRUCTURED, - D3D11_TEXTURE2D_DESC, D3D11_USAGE_DEFAULT, D3D11_USAGE_DYNAMIC, ID3D11Device, - ID3D11DeviceContext, ID3D11ShaderResourceView, ID3D11Texture2D, - }, - DirectWrite::*, - Dxgi::Common::*, - Gdi::LOGFONTW, - Imaging::*, + Direct3D::D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, Direct3D11::*, DirectWrite::*, + Dxgi::Common::*, Gdi::LOGFONTW, Imaging::*, }, System::SystemServices::LOCALE_NAME_MAX_LENGTH, UI::WindowsAndMessaging::*, @@ -847,8 +839,8 @@ impl DirectWriteState { measuring_mode, &transform, point(baseline_origin_x, baseline_origin_y), - size(DevicePixels(0), DevicePixels(0)), - size(0, 0), + bitmap_size, + size(texture_width, texture_height), ); // // todo: support more glyph image formats for more exotic fonts, for now it should fallback to monochrome rendering // let color_enumerator = unsafe { @@ -1175,24 +1167,14 @@ impl DirectWriteState { } } - let params = glyph_layers - .iter() - .enumerate() - .map(|(index, e)| GlyphLayerTextureParams { - run_color: e.run_color, - bounds: e.bounds, - alpha_texture_index: index as u32, - }) - .collect::>(); - let params_buffer = { let desc = D3D11_BUFFER_DESC { - ByteWidth: (std::mem::size_of::() * params.len()) as u32, + ByteWidth: std::mem::size_of::() as u32, Usage: D3D11_USAGE_DYNAMIC, - BindFlags: D3D11_BIND_SHADER_RESOURCE.0 as u32, + BindFlags: D3D11_BIND_CONSTANT_BUFFER.0 as u32, CPUAccessFlags: D3D11_CPU_ACCESS_WRITE.0 as u32, - MiscFlags: D3D11_RESOURCE_MISC_BUFFER_STRUCTURED.0 as u32, - StructureByteStride: std::mem::size_of::() as u32, + MiscFlags: 0, + StructureByteStride: 0, }; let mut buffer = None; @@ -1201,37 +1183,8 @@ impl DirectWriteState { .device .CreateBuffer(&desc, None, Some(&mut buffer)) }?; - buffer.unwrap() + [buffer] }; - let params_buffer_view = { - let mut view = None; - unsafe { - self.gpu_state.device.CreateShaderResourceView( - ¶ms_buffer, - None, - Some(&mut view), - ) - }?; - [view] - }; - - unsafe { - let mut dest = std::mem::zeroed(); - self.gpu_state.device_context.Map( - ¶ms_buffer, - 0, - D3D11_MAP_WRITE_DISCARD, - 0, - Some(&mut dest), - )?; - std::ptr::copy_nonoverlapping(params.as_ptr(), dest.pData as *mut _, params.len()); - self.gpu_state.device_context.Unmap(¶ms_buffer, 0); - }; - - let textures = glyph_layers - .iter() - .map(|layer| Some(layer.texture_view.clone())) - .collect::>(); let vertex_shader = { let source = @@ -1251,6 +1204,105 @@ impl DirectWriteState { shader.unwrap() }; + 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: D3D11_CPU_ACCESS_READ.0 as u32, + MiscFlags: 0, + }; + unsafe { + self.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 { + self.gpu_state.device.CreateRenderTargetView( + &render_target_texture, + Some(&desc), + Some(&mut rtv), + ) + }?; + [rtv] + }; + + 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_ONE, + 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 { + self.gpu_state + .device + .CreateBlendState(&desc, Some(&mut blend_state)) + }?; + blend_state.unwrap() + }; + + 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 { + self.gpu_state + .device + .CreateSamplerState(&desc, Some(&mut sampler)) + }?; + [sampler] + }; + let pixel_shader = { let source = shader_resources::build_shader_blob("color_text_raster", "pixel", "ps_5_0")?; @@ -1276,14 +1328,50 @@ impl DirectWriteState { .start_frame_capture(std::ptr::null(), std::ptr::null()); let device_context = &self.gpu_state.device_context; - unsafe { device_context.VSSetShaderResources(0, Some(textures.as_slice())) }; - unsafe { device_context.PSSetShaderResources(0, Some(textures.as_slice())) }; - unsafe { device_context.VSSetShaderResources(1, Some(¶ms_buffer_view)) }; - unsafe { device_context.PSSetShaderResources(1, Some(¶ms_buffer_view)) }; + unsafe { device_context.IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP) }; unsafe { device_context.VSSetShader(&vertex_shader, None) }; unsafe { device_context.PSSetShader(&pixel_shader, None) }; + unsafe { device_context.VSSetConstantBuffers(0, Some(¶ms_buffer)) }; + unsafe { device_context.PSSetConstantBuffers(0, Some(¶ms_buffer)) }; + unsafe { device_context.OMSetRenderTargets(Some(&render_target_view), None) }; + unsafe { device_context.PSSetSamplers(0, Some(&sampler)) }; + unsafe { device_context.OMSetBlendState(&blend_state, None, 0xffffffff) }; - unsafe { device_context.DrawInstanced(4, params.len() as u32, 0, 0) }; + for layer in glyph_layers { + let params = GlyphLayerTextureParams { + run_color: layer.run_color, + bounds: layer.bounds, + }; + unsafe { + let mut dest = std::mem::zeroed(); + self.gpu_state.device_context.Map( + params_buffer[0].as_ref().unwrap(), + 0, + D3D11_MAP_WRITE_DISCARD, + 0, + Some(&mut dest), + )?; + std::ptr::copy_nonoverlapping(¶ms as *const _, dest.pData as *mut _, 1); + self.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) }; + } #[cfg(feature = "enable-renderdoc")] self.renderdoc @@ -1440,9 +1528,8 @@ impl GlyphLayerTexture { #[repr(C)] struct GlyphLayerTextureParams { - run_color: Rgba, bounds: Bounds, - alpha_texture_index: u32, + run_color: Rgba, } struct TextRendererWrapper(pub IDWriteTextRenderer);