Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions vendor/zed/PATCHES.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ Each local patch to this tree is a commit on the integrating branch, never on `z
| patch | commit | files |
|---|---|---|
| `assets/fonts` | this commit | `vendor/zed/assets/fonts/` |
| `backdrop-blur` | this commit | `vendor/zed/crates/gpui/src/color.rs`, `vendor/zed/crates/gpui/src/style.rs`, `vendor/zed/crates/gpui/src/styled.rs`, `vendor/zed/crates/gpui_wgpu/src/shaders.wgsl`, `vendor/zed/crates/gpui_wgpu/src/wgpu_renderer.rs`, `vendor/zed/crates/gpui_windows/src/directx_renderer.rs`, `vendor/zed/crates/gpui_windows/src/shaders.hlsl` |
34 changes: 34 additions & 0 deletions vendor/zed/crates/gpui/src/color.rs
Original file line number Diff line number Diff line change
Expand Up @@ -747,6 +747,11 @@ pub(crate) enum BackgroundTag {
LinearGradient = 1,
PatternSlash = 2,
Checkerboard = 3,
/// A blurred copy of the pixels drawn behind the element, tinted with
/// `solid`. `gradient_angle_or_pattern_height` carries the blur radius in
/// device pixels. Tag 4, because upstream added `Checkerboard` at 3 after
/// this patch was first written.
BackdropBlur = 4,
}

/// A color space for color interpolation.
Expand Down Expand Up @@ -805,6 +810,11 @@ impl std::fmt::Debug for Background {
"Checkerboard({:?}, {})",
self.solid, self.gradient_angle_or_pattern_height
),
BackgroundTag::BackdropBlur => write!(
f,
"BackdropBlur(radius: {}, tint: {:?})",
self.gradient_angle_or_pattern_height, self.solid
),
}
}
}
Expand Down Expand Up @@ -847,6 +857,22 @@ pub fn checkerboard(color: impl Into<Hsla>, size: f32) -> Background {
}
}

/// Creates a backdrop-blur background: the pixels already drawn behind the
/// element are blurred by `radius` device pixels and tinted with `tint`.
///
/// `tint`'s alpha is the tint strength — `hsla(0., 0., 0., 0.)` leaves the
/// blur untinted, an opaque tint hides it. A renderer that cannot capture its
/// own colour target (the Metal path today) draws `tint` as a flat colour
/// instead, which is why callers pick a tint that reads on its own.
pub fn backdrop_blur(radius: f32, tint: impl Into<Hsla>) -> Background {
Background {
tag: BackgroundTag::BackdropBlur,
solid: tint.into(),
gradient_angle_or_pattern_height: radius,
..Default::default()
}
}

/// Creates a solid background color.
pub fn solid_background(color: impl Into<Hsla>) -> Background {
Background {
Expand Down Expand Up @@ -943,8 +969,16 @@ impl Background {
BackgroundTag::LinearGradient => self.colors.iter().all(|c| c.color.is_transparent()),
BackgroundTag::PatternSlash => self.solid.is_transparent(),
BackgroundTag::Checkerboard => self.solid.is_transparent(),
// A blur always shows whatever is behind it, even with no tint.
BackgroundTag::BackdropBlur => false,
}
}

/// Whether this background needs the renderer to capture the pixels drawn
/// so far, so the quad shader can blur them.
pub fn needs_backdrop(&self) -> bool {
matches!(self.tag, BackgroundTag::BackdropBlur)
}
}

impl From<Hsla> for Background {
Expand Down
5 changes: 4 additions & 1 deletion vendor/zed/crates/gpui/src/style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -716,7 +716,10 @@ impl Style {
Some(color) => match color.tag {
BackgroundTag::Solid
| BackgroundTag::PatternSlash
| BackgroundTag::Checkerboard => color.solid,
| BackgroundTag::Checkerboard
// The blur's border fades against its tint, which is what
// the quad shader composites the blur under.
| BackgroundTag::BackdropBlur => color.solid,

BackgroundTag::LinearGradient => color
.colors
Expand Down
16 changes: 15 additions & 1 deletion vendor/zed/crates/gpui/src/styled.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::{
self as gpui, AbsoluteLength, AlignContent, AlignItems, AlignSelf, BorderStyle, CursorStyle,
DefiniteLength, Display, Fill, FlexDirection, FlexWrap, Font, FontFeatures, FontStyle,
FontWeight, GridPlacement, GridTemplate, GridTemplateMinSize, Hsla, JustifyContent, Length,
SharedString, StrikethroughStyle, StyleRefinement, TextAlign, TextOverflow,
Pixels, SharedString, StrikethroughStyle, StyleRefinement, TextAlign, TextOverflow,
TextStyleRefinement, UnderlineStyle, WhiteSpace, px, relative, rems,
};
pub use gpui_macros::{
Expand Down Expand Up @@ -496,6 +496,20 @@ pub trait Styled: Sized {
self
}

/// Blurs the pixels drawn behind the element by `radius` device pixels and
/// tints the result with `tint`. `tint`'s alpha is the tint strength.
///
/// Equivalent to `bg(backdrop_blur(radius, tint))`.
fn backdrop_blur(mut self, radius: impl Into<Pixels>, tint: impl Into<Hsla>) -> Self
where
Self: Sized,
{
self.style().background = Some(
crate::backdrop_blur(f32::from(radius.into()), tint).into(),
);
self
}

/// Sets the border style of the element.
fn border_dashed(mut self) -> Self {
self.style().border_style = Some(BorderStyle::Dashed);
Expand Down
67 changes: 64 additions & 3 deletions vendor/zed/crates/gpui_wgpu/src/shaders.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,13 @@ struct GammaParams {
@group(2) @binding(0) var t_sprite: texture_2d<f32>;
@group(2) @binding(1) var s_sprite: sampler;

// A copy of the colour target as it stood before the current quad batch,
// bound on the quads pipeline (group 3) and unused everywhere else. The quad
// fragment shader blurs it directly when a quad's background tag is
// BackdropBlur, so there is no separate blur pass.
@group(3) @binding(0) var t_backdrop: texture_2d<f32>;
@group(3) @binding(1) var s_backdrop: sampler;

const M_PI_F: f32 = 3.1415926;
const GRAYSCALE_FACTORS: vec3<f32> = vec3<f32>(0.2126, 0.7152, 0.0722);

Expand Down Expand Up @@ -135,6 +142,7 @@ struct Background {
// 1u is LinearGradient
// 2u is PatternSlash
// 3u is Checkerboard
// 4u is BackdropBlur
tag: u32,
// 0u is sRGB linear color
// 1u is Oklab color
Expand Down Expand Up @@ -405,7 +413,8 @@ fn prepare_gradient_color(tag: u32, color_space: u32,
solid: Hsla, colors: array<LinearColorStop, 2>) -> GradientColor {
var result = GradientColor();

if (tag == 0u || tag == 2u || tag == 3u) {
// 4u (BackdropBlur) carries its tint in `solid`.
if (tag == 0u || tag == 2u || tag == 3u || tag == 4u) {
result.solid = hsla_to_rgba(solid);
} else if (tag == 1u) {
// The hsla_to_rgba is returns a linear sRGB color
Expand Down Expand Up @@ -570,8 +579,60 @@ fn fs_quad(input: QuadVarying) -> @location(0) vec4<f32> {

let quad = load_quad(input.quad_id);

let background_color = gradient_color(quad.background, input.position.xy, quad.bounds,
input.background_solid, input.background_color0, input.background_color1);
var background_color: vec4<f32>;
if (quad.background.tag == 4u) {
// BackdropBlur. `t_backdrop` holds the colour target as it stood
// before this quad batch, and the blur radius rides in
// `gradient_angle_or_pattern_height` (device pixels). A 13-tap
// cross-pattern kernel approximates a gaussian of sigma = radius / 2,
// which is the look the old blade renderer produced with its own blur
// pass. `solid` is the tint: its alpha is the tint strength, and it
// composites over the blur with the standard "over" operator.
let radius = max(quad.background.gradient_angle_or_pattern_height, 0.5);
let uv = input.position.xy / globals.viewport_size;
let step = 1.0 / globals.viewport_size;
let off1 = step * (radius * 0.25);
let off2 = step * (radius * 0.5);
let off3 = step * (radius * 0.75);
let off4 = step * radius;

let w0 = 0.227027;
let w1 = 0.194594;
let w2 = 0.121622;
let w3 = 0.054054;
let w4 = 0.016216;

var blurred = textureSample(t_backdrop, s_backdrop, uv) * w0;
blurred += textureSample(t_backdrop, s_backdrop, uv + vec2<f32>(off1.x, 0.0)) * w1;
blurred += textureSample(t_backdrop, s_backdrop, uv - vec2<f32>(off1.x, 0.0)) * w1;
blurred += textureSample(t_backdrop, s_backdrop, uv + vec2<f32>(off2.x, 0.0)) * w2;
blurred += textureSample(t_backdrop, s_backdrop, uv - vec2<f32>(off2.x, 0.0)) * w2;
blurred += textureSample(t_backdrop, s_backdrop, uv + vec2<f32>(off3.x, 0.0)) * w3;
blurred += textureSample(t_backdrop, s_backdrop, uv - vec2<f32>(off3.x, 0.0)) * w3;
blurred += textureSample(t_backdrop, s_backdrop, uv + vec2<f32>(off4.x, 0.0)) * w4;
blurred += textureSample(t_backdrop, s_backdrop, uv - vec2<f32>(off4.x, 0.0)) * w4;
blurred += textureSample(t_backdrop, s_backdrop, uv + vec2<f32>(0.0, off1.y)) * w1;
blurred += textureSample(t_backdrop, s_backdrop, uv - vec2<f32>(0.0, off1.y)) * w1;
blurred += textureSample(t_backdrop, s_backdrop, uv + vec2<f32>(0.0, off2.y)) * w2;
blurred += textureSample(t_backdrop, s_backdrop, uv - vec2<f32>(0.0, off2.y)) * w2;
blurred += textureSample(t_backdrop, s_backdrop, uv + vec2<f32>(0.0, off3.y)) * w3;
blurred += textureSample(t_backdrop, s_backdrop, uv - vec2<f32>(0.0, off3.y)) * w3;
blurred += textureSample(t_backdrop, s_backdrop, uv + vec2<f32>(0.0, off4.y)) * w4;
blurred += textureSample(t_backdrop, s_backdrop, uv - vec2<f32>(0.0, off4.y)) * w4;

// w0 plus both axes of four offset pairs.
let total_weight = w0 + 4.0 * (w1 + w2 + w3 + w4);
blurred = blurred / total_weight;

let tint = input.background_solid;
background_color = vec4<f32>(
tint.rgb * tint.a + blurred.rgb * (1.0 - tint.a),
tint.a + blurred.a * (1.0 - tint.a),
);
} else {
background_color = gradient_color(quad.background, input.position.xy, quad.bounds,
input.background_solid, input.background_color0, input.background_color1);
}

let unrounded = quad.corner_radii.top_left == 0.0 &&
quad.corner_radii.bottom_left == 0.0 &&
Expand Down
Loading
Loading