From aaf432fcd24a0472c8d7da2a5d11894a8ebf4ad9 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Wed, 5 Feb 2025 19:17:26 +0200 Subject: [PATCH] Revert recent anti-aliasing improvements (#24289) This reverts commit 31fa4144226fcbd140bb4f26d80001f0abd6facd. This reverts commit b9e0aae49fad996ddb0ce55225873e5c1d5abecd. `lyon` commit revert: ![image](https://github.com/user-attachments/assets/0243f61c-0713-416d-b8db-47372e04abaa) `MSAA` commit revert: ![image](https://github.com/user-attachments/assets/b1a4a9fe-0192-47ef-be6f-52e03c025724) cc @huacnlee , @\as-cii had decided to revert this PR due to a selection right corner rendering bug. Not sure what to propose for a fix from my side Release Notes: - N/A --- Cargo.lock | 76 +----- Cargo.toml | 6 +- crates/editor/src/element.rs | 48 ++-- crates/gpui/Cargo.toml | 2 - crates/gpui/examples/gradient.rs | 14 +- crates/gpui/examples/painting.rs | 141 ++++------ crates/gpui/src/gpui.rs | 2 - crates/gpui/src/path_builder.rs | 241 ------------------ crates/gpui/src/platform/blade/blade_atlas.rs | 49 +--- .../gpui/src/platform/blade/blade_renderer.rs | 60 ++--- crates/gpui/src/platform/mac/metal_atlas.rs | 22 +- .../gpui/src/platform/mac/metal_renderer.rs | 27 +- crates/gpui/src/scene.rs | 10 +- 13 files changed, 113 insertions(+), 585 deletions(-) delete mode 100644 crates/gpui/src/path_builder.rs diff --git a/Cargo.lock b/Cargo.lock index 42afceedd4..dadaeeaba1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1821,7 +1821,7 @@ dependencies = [ [[package]] name = "blade-graphics" version = "0.6.0" -source = "git+https://github.com/kvark/blade?rev=b16f5c7bd873c7126f48c82c39e7ae64602ae74f#b16f5c7bd873c7126f48c82c39e7ae64602ae74f" +source = "git+https://github.com/kvark/blade?rev=091a8401033847bb9b6ace3fcf70448d069621c5#091a8401033847bb9b6ace3fcf70448d069621c5" dependencies = [ "ash", "ash-window", @@ -1853,7 +1853,7 @@ dependencies = [ [[package]] name = "blade-macros" version = "0.3.0" -source = "git+https://github.com/kvark/blade?rev=b16f5c7bd873c7126f48c82c39e7ae64602ae74f#b16f5c7bd873c7126f48c82c39e7ae64602ae74f" +source = "git+https://github.com/kvark/blade?rev=091a8401033847bb9b6ace3fcf70448d069621c5#091a8401033847bb9b6ace3fcf70448d069621c5" dependencies = [ "proc-macro2", "quote", @@ -1863,7 +1863,7 @@ dependencies = [ [[package]] name = "blade-util" version = "0.2.0" -source = "git+https://github.com/kvark/blade?rev=b16f5c7bd873c7126f48c82c39e7ae64602ae74f#b16f5c7bd873c7126f48c82c39e7ae64602ae74f" +source = "git+https://github.com/kvark/blade?rev=091a8401033847bb9b6ace3fcf70448d069621c5#091a8401033847bb9b6ace3fcf70448d069621c5" dependencies = [ "blade-graphics", "bytemuck", @@ -4668,12 +4668,6 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ce81f49ae8a0482e4c55ea62ebbd7e5a686af544c00b9d090bba3ff9be97b3d" -[[package]] -name = "float_next_after" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bf7cc16383c4b8d58b9905a8509f02926ce3058053c056376248d958c9df1e8" - [[package]] name = "flume" version = "0.11.1" @@ -5418,7 +5412,6 @@ dependencies = [ "inventory", "itertools 0.14.0", "log", - "lyon", "media", "metal", "naga", @@ -7435,69 +7428,6 @@ dependencies = [ "url", ] -[[package]] -name = "lyon" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e7f9cda98b5430809e63ca5197b06c7d191bf7e26dfc467d5a3f0290e2a74f" -dependencies = [ - "lyon_algorithms", - "lyon_extra", - "lyon_tessellation", -] - -[[package]] -name = "lyon_algorithms" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f13c9be19d257c7d37e70608ed858e8eab4b2afcea2e3c9a622e892acbf43c08" -dependencies = [ - "lyon_path", - "num-traits", -] - -[[package]] -name = "lyon_extra" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ca94c7bf1e2557c2798989c43416822c12fc5dcc5e17cc3307ef0e71894a955" -dependencies = [ - "lyon_path", - "thiserror 1.0.69", -] - -[[package]] -name = "lyon_geom" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8af69edc087272df438b3ee436c4bb6d7c04aa8af665cfd398feae627dbd8570" -dependencies = [ - "arrayvec", - "euclid", - "num-traits", -] - -[[package]] -name = "lyon_path" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e0b8aec2f58586f6eef237985b9a9b7cb3a3aff4417c575075cf95bf925252e" -dependencies = [ - "lyon_geom", - "num-traits", -] - -[[package]] -name = "lyon_tessellation" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "579d42360a4b09846eff2feef28f538696c7d6c7439bfa65874ff3cbe0951b2c" -dependencies = [ - "float_next_after", - "lyon_path", - "num-traits", -] - [[package]] name = "mac" version = "0.1.1" diff --git a/Cargo.toml b/Cargo.toml index 1b47335b4c..a0e80d7392 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -375,9 +375,9 @@ async-watch = "0.3.1" async_zip = { version = "0.0.17", features = ["deflate", "deflate64"] } base64 = "0.22" bitflags = "2.6.0" -blade-graphics = { git = "https://github.com/kvark/blade", rev = "b16f5c7bd873c7126f48c82c39e7ae64602ae74f" } -blade-macros = { git = "https://github.com/kvark/blade", rev = "b16f5c7bd873c7126f48c82c39e7ae64602ae74f" } -blade-util = { git = "https://github.com/kvark/blade", rev = "b16f5c7bd873c7126f48c82c39e7ae64602ae74f" } +blade-graphics = { git = "https://github.com/kvark/blade", rev = "091a8401033847bb9b6ace3fcf70448d069621c5" } +blade-macros = { git = "https://github.com/kvark/blade", rev = "091a8401033847bb9b6ace3fcf70448d069621c5" } +blade-util = { git = "https://github.com/kvark/blade", rev = "091a8401033847bb9b6ace3fcf70448d069621c5" } naga = { version = "23.1.0", features = ["wgsl-in"] } blake3 = "1.5.3" bytes = "1.0" diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 97cfec90c1..f0b0730ad5 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -8197,8 +8197,8 @@ impl HighlightedRange { }; let top_curve_width = curve_width(first_line.start_x, first_line.end_x); - let mut builder = gpui::PathBuilder::fill(); - builder.curve_to(first_top_right + curve_height, first_top_right); + let mut path = gpui::Path::new(first_top_right - top_curve_width); + path.curve_to(first_top_right + curve_height, first_top_right); let mut iter = lines.iter().enumerate().peekable(); while let Some((ix, line)) = iter.next() { @@ -8209,42 +8209,42 @@ impl HighlightedRange { match next_top_right.x.partial_cmp(&bottom_right.x).unwrap() { Ordering::Equal => { - builder.line_to(bottom_right); + path.line_to(bottom_right); } Ordering::Less => { let curve_width = curve_width(next_top_right.x, bottom_right.x); - builder.line_to(bottom_right - curve_height); + path.line_to(bottom_right - curve_height); if self.corner_radius > Pixels::ZERO { - builder.curve_to(bottom_right - curve_width, bottom_right); + path.curve_to(bottom_right - curve_width, bottom_right); } - builder.line_to(next_top_right + curve_width); + path.line_to(next_top_right + curve_width); if self.corner_radius > Pixels::ZERO { - builder.curve_to(next_top_right + curve_height, next_top_right); + path.curve_to(next_top_right + curve_height, next_top_right); } } Ordering::Greater => { let curve_width = curve_width(bottom_right.x, next_top_right.x); - builder.line_to(bottom_right - curve_height); + path.line_to(bottom_right - curve_height); if self.corner_radius > Pixels::ZERO { - builder.curve_to(bottom_right + curve_width, bottom_right); + path.curve_to(bottom_right + curve_width, bottom_right); } - builder.line_to(next_top_right - curve_width); + path.line_to(next_top_right - curve_width); if self.corner_radius > Pixels::ZERO { - builder.curve_to(next_top_right + curve_height, next_top_right); + path.curve_to(next_top_right + curve_height, next_top_right); } } } } else { let curve_width = curve_width(line.start_x, line.end_x); - builder.line_to(bottom_right - curve_height); + path.line_to(bottom_right - curve_height); if self.corner_radius > Pixels::ZERO { - builder.curve_to(bottom_right - curve_width, bottom_right); + path.curve_to(bottom_right - curve_width, bottom_right); } let bottom_left = point(line.start_x, bottom_right.y); - builder.line_to(bottom_left + curve_width); + path.line_to(bottom_left + curve_width); if self.corner_radius > Pixels::ZERO { - builder.curve_to(bottom_left - curve_height, bottom_left); + path.curve_to(bottom_left - curve_height, bottom_left); } } } @@ -8252,26 +8252,24 @@ impl HighlightedRange { if first_line.start_x > last_line.start_x { let curve_width = curve_width(last_line.start_x, first_line.start_x); let second_top_left = point(last_line.start_x, start_y + self.line_height); - builder.line_to(second_top_left + curve_height); + path.line_to(second_top_left + curve_height); if self.corner_radius > Pixels::ZERO { - builder.curve_to(second_top_left + curve_width, second_top_left); + path.curve_to(second_top_left + curve_width, second_top_left); } let first_bottom_left = point(first_line.start_x, second_top_left.y); - builder.line_to(first_bottom_left - curve_width); + path.line_to(first_bottom_left - curve_width); if self.corner_radius > Pixels::ZERO { - builder.curve_to(first_bottom_left - curve_height, first_bottom_left); + path.curve_to(first_bottom_left - curve_height, first_bottom_left); } } - builder.line_to(first_top_left + curve_height); + path.line_to(first_top_left + curve_height); if self.corner_radius > Pixels::ZERO { - builder.curve_to(first_top_left + top_curve_width, first_top_left); + path.curve_to(first_top_left + top_curve_width, first_top_left); } - builder.line_to(first_top_right - top_curve_width); + path.line_to(first_top_right - top_curve_width); - if let Ok(path) = builder.build() { - window.paint_path(path, self.color); - } + window.paint_path(path, self.color); } } diff --git a/crates/gpui/Cargo.toml b/crates/gpui/Cargo.toml index 05a5b28e76..a0220cd572 100644 --- a/crates/gpui/Cargo.toml +++ b/crates/gpui/Cargo.toml @@ -108,7 +108,6 @@ thiserror.workspace = true util.workspace = true uuid.workspace = true waker-fn = "1.2.0" -lyon = "1.0" [target.'cfg(target_os = "macos")'.dependencies] block = "0.1" @@ -206,7 +205,6 @@ rand.workspace = true util = { workspace = true, features = ["test-support"] } http_client = { workspace = true, features = ["test-support"] } unicode-segmentation.workspace = true -lyon = { version = "1.0", features = ["extra"] } [target.'cfg(target_os = "windows")'.build-dependencies] embed-resource = "3.0" diff --git a/crates/gpui/examples/gradient.rs b/crates/gpui/examples/gradient.rs index ec4cdf9bfc..45de8cdd0a 100644 --- a/crates/gpui/examples/gradient.rs +++ b/crates/gpui/examples/gradient.rs @@ -218,17 +218,13 @@ impl Render for GradientViewer { let height = square_bounds.size.height; let horizontal_offset = height; let vertical_offset = px(30.); - let mut builder = gpui::PathBuilder::fill(); - builder.move_to(square_bounds.bottom_left()); - builder - .line_to(square_bounds.origin + point(horizontal_offset, vertical_offset)); - builder.line_to( + let mut path = gpui::Path::new(square_bounds.bottom_left()); + path.line_to(square_bounds.origin + point(horizontal_offset, vertical_offset)); + path.line_to( square_bounds.top_right() + point(-horizontal_offset, vertical_offset), ); - - builder.line_to(square_bounds.bottom_right()); - builder.line_to(square_bounds.bottom_left()); - let path = builder.build().unwrap(); + path.line_to(square_bounds.bottom_right()); + path.line_to(square_bounds.bottom_left()); window.paint_path( path, linear_gradient( diff --git a/crates/gpui/examples/painting.rs b/crates/gpui/examples/painting.rs index 7c1a6a367d..9a8ab79065 100644 --- a/crates/gpui/examples/painting.rs +++ b/crates/gpui/examples/painting.rs @@ -1,62 +1,46 @@ use gpui::{ - canvas, div, linear_color_stop, linear_gradient, point, prelude::*, px, rgb, size, Application, - Background, Bounds, ColorSpace, Context, MouseDownEvent, Path, PathBuilder, PathStyle, Pixels, - Point, Render, StrokeOptions, Window, WindowOptions, + canvas, div, point, prelude::*, px, size, App, Application, Bounds, Context, MouseDownEvent, + Path, Pixels, Point, Render, Window, WindowOptions, }; - struct PaintingViewer { - default_lines: Vec<(Path, Background)>, + default_lines: Vec>, lines: Vec>>, start: Point, _painting: bool, } impl PaintingViewer { - fn new(_window: &mut Window, _cx: &mut Context) -> Self { + fn new() -> Self { let mut lines = vec![]; - // draw a Rust logo - let mut builder = lyon::path::Path::svg_builder(); - lyon::extra::rust_logo::build_logo_path(&mut builder); - // move down the Path - let mut builder: PathBuilder = builder.into(); - builder.translate(point(px(10.), px(100.))); - builder.scale(0.9); - let path = builder.build().unwrap(); - lines.push((path, gpui::black().into())); + // draw a line + let mut path = Path::new(point(px(50.), px(180.))); + path.line_to(point(px(100.), px(120.))); + // go back to close the path + path.line_to(point(px(100.), px(121.))); + path.line_to(point(px(50.), px(181.))); + lines.push(path); // draw a lightening bolt ⚡ - let mut builder = PathBuilder::fill(); - builder.move_to(point(px(150.), px(200.))); - builder.line_to(point(px(200.), px(125.))); - builder.line_to(point(px(200.), px(175.))); - builder.line_to(point(px(250.), px(100.))); - let path = builder.build().unwrap(); - lines.push((path, rgb(0x1d4ed8).into())); + let mut path = Path::new(point(px(150.), px(200.))); + path.line_to(point(px(200.), px(125.))); + path.line_to(point(px(200.), px(175.))); + path.line_to(point(px(250.), px(100.))); + lines.push(path); // draw a ⭐ - let mut builder = PathBuilder::fill(); - builder.move_to(point(px(350.), px(100.))); - builder.line_to(point(px(370.), px(160.))); - builder.line_to(point(px(430.), px(160.))); - builder.line_to(point(px(380.), px(200.))); - builder.line_to(point(px(400.), px(260.))); - builder.line_to(point(px(350.), px(220.))); - builder.line_to(point(px(300.), px(260.))); - builder.line_to(point(px(320.), px(200.))); - builder.line_to(point(px(270.), px(160.))); - builder.line_to(point(px(330.), px(160.))); - builder.line_to(point(px(350.), px(100.))); - let path = builder.build().unwrap(); - lines.push(( - path, - linear_gradient( - 180., - linear_color_stop(rgb(0xFACC15), 0.7), - linear_color_stop(rgb(0xD56D0C), 1.), - ) - .color_space(ColorSpace::Oklab), - )); + let mut path = Path::new(point(px(350.), px(100.))); + path.line_to(point(px(370.), px(160.))); + path.line_to(point(px(430.), px(160.))); + path.line_to(point(px(380.), px(200.))); + path.line_to(point(px(400.), px(260.))); + path.line_to(point(px(350.), px(220.))); + path.line_to(point(px(300.), px(260.))); + path.line_to(point(px(320.), px(200.))); + path.line_to(point(px(270.), px(160.))); + path.line_to(point(px(330.), px(160.))); + path.line_to(point(px(350.), px(100.))); + lines.push(path); let square_bounds = Bounds { origin: point(px(450.), px(100.)), @@ -65,42 +49,18 @@ impl PaintingViewer { let height = square_bounds.size.height; let horizontal_offset = height; let vertical_offset = px(30.); - let mut builder = PathBuilder::fill(); - builder.move_to(square_bounds.bottom_left()); - builder.curve_to( + let mut path = Path::new(square_bounds.bottom_left()); + path.curve_to( square_bounds.origin + point(horizontal_offset, vertical_offset), square_bounds.origin + point(px(0.0), vertical_offset), ); - builder.line_to(square_bounds.top_right() + point(-horizontal_offset, vertical_offset)); - builder.curve_to( + path.line_to(square_bounds.top_right() + point(-horizontal_offset, vertical_offset)); + path.curve_to( square_bounds.bottom_right(), square_bounds.top_right() + point(px(0.0), vertical_offset), ); - builder.line_to(square_bounds.bottom_left()); - let path = builder.build().unwrap(); - lines.push(( - path, - linear_gradient( - 180., - linear_color_stop(gpui::blue(), 0.4), - linear_color_stop(gpui::red(), 1.), - ), - )); - - // draw a wave - let options = StrokeOptions::default() - .with_line_width(1.) - .with_line_join(lyon::path::LineJoin::Bevel); - let mut builder = PathBuilder::stroke(px(1.)).with_style(PathStyle::Stroke(options)); - builder.move_to(point(px(40.), px(320.))); - for i in 0..50 { - builder.line_to(point( - px(40.0 + i as f32 * 10.0), - px(320.0 + (i as f32 * 10.0).sin() * 40.0), - )); - } - let path = builder.build().unwrap(); - lines.push((path, gpui::green().into())); + path.line_to(square_bounds.bottom_left()); + lines.push(path); Self { default_lines: lines.clone(), @@ -155,28 +115,27 @@ impl Render for PaintingViewer { canvas( move |_, _, _| {}, move |_, _, window, _| { - - for (path, color) in default_lines { - window.paint_path(path, color); + const STROKE_WIDTH: Pixels = px(2.0); + for path in default_lines { + window.paint_path(path, gpui::black()); } - for points in lines { - if points.len() < 2 { - continue; + let mut path = Path::new(points[0]); + for p in points.iter().skip(1) { + path.line_to(*p); } - let mut builder = PathBuilder::stroke(px(1.)); - for (i, p) in points.into_iter().enumerate() { - if i == 0 { - builder.move_to(p); - } else { - builder.line_to(p); + let mut last = points.last().unwrap(); + for p in points.iter().rev() { + let mut offset_x = px(0.); + if last.x == p.x { + offset_x = STROKE_WIDTH; } + path.line_to(point(p.x + offset_x, p.y + STROKE_WIDTH)); + last = p; } - if let Ok(path) = builder.build() { - window.paint_path(path, gpui::black()); - } + window.paint_path(path, gpui::black()); } }, ) @@ -226,13 +185,13 @@ impl Render for PaintingViewer { } fn main() { - Application::new().run(|cx| { + Application::new().run(|cx: &mut App| { cx.open_window( WindowOptions { focus: true, ..Default::default() }, - |window, cx| cx.new(|cx| PaintingViewer::new(window, cx)), + |_, cx| cx.new(|_| PaintingViewer::new()), ) .unwrap(); cx.activate(true); diff --git a/crates/gpui/src/gpui.rs b/crates/gpui/src/gpui.rs index 1ebfc643ee..db33bfca2e 100644 --- a/crates/gpui/src/gpui.rs +++ b/crates/gpui/src/gpui.rs @@ -82,7 +82,6 @@ mod input; mod interactive; mod key_dispatch; mod keymap; -mod path_builder; mod platform; pub mod prelude; mod scene; @@ -136,7 +135,6 @@ pub use input::*; pub use interactive::*; use key_dispatch::*; pub use keymap::*; -pub use path_builder::*; pub use platform::*; pub use refineable::*; pub use scene::*; diff --git a/crates/gpui/src/path_builder.rs b/crates/gpui/src/path_builder.rs deleted file mode 100644 index 0fd8eb6fa5..0000000000 --- a/crates/gpui/src/path_builder.rs +++ /dev/null @@ -1,241 +0,0 @@ -use anyhow::Error; -use etagere::euclid::Vector2D; -use lyon::geom::Angle; -use lyon::tessellation::{ - BuffersBuilder, FillTessellator, FillVertex, StrokeTessellator, StrokeVertex, VertexBuffers, -}; - -pub use lyon::math::Transform; -pub use lyon::tessellation::{FillOptions, FillRule, StrokeOptions}; - -use crate::{point, px, Path, Pixels, Point}; - -/// Style of the PathBuilder -pub enum PathStyle { - /// Stroke style - Stroke(StrokeOptions), - /// Fill style - Fill(FillOptions), -} - -/// A [`Path`] builder. -pub struct PathBuilder { - raw: lyon::path::builder::WithSvg, - transform: Option, - /// PathStyle of the PathBuilder - pub style: PathStyle, -} - -impl From for PathBuilder { - fn from(builder: lyon::path::Builder) -> Self { - Self { - raw: builder.with_svg(), - ..Default::default() - } - } -} - -impl From> for PathBuilder { - fn from(raw: lyon::path::builder::WithSvg) -> Self { - Self { - raw, - ..Default::default() - } - } -} - -impl From for Point { - fn from(p: lyon::math::Point) -> Self { - point(px(p.x), px(p.y)) - } -} - -impl From> for lyon::math::Point { - fn from(p: Point) -> Self { - lyon::math::point(p.x.0, p.y.0) - } -} - -impl Default for PathBuilder { - fn default() -> Self { - Self { - raw: lyon::path::Path::builder().with_svg(), - style: PathStyle::Fill(FillOptions::default()), - transform: None, - } - } -} - -impl PathBuilder { - /// Creates a new [`PathBuilder`] to build a Stroke path. - pub fn stroke(width: Pixels) -> Self { - Self { - style: PathStyle::Stroke(StrokeOptions::default().with_line_width(width.0)), - ..Self::default() - } - } - - /// Creates a new [`PathBuilder`] to build a Fill path. - pub fn fill() -> Self { - Self::default() - } - - /// Sets the style of the [`PathBuilder`]. - pub fn with_style(self, style: PathStyle) -> Self { - Self { style, ..self } - } - - /// Move the current point to the given point. - #[inline] - pub fn move_to(&mut self, to: Point) { - self.raw.move_to(to.into()); - } - - /// Draw a straight line from the current point to the given point. - #[inline] - pub fn line_to(&mut self, to: Point) { - self.raw.line_to(to.into()); - } - - /// Draw a curve from the current point to the given point, using the given control point. - #[inline] - pub fn curve_to(&mut self, to: Point, ctrl: Point) { - self.raw.quadratic_bezier_to(ctrl.into(), to.into()); - } - - /// Adds a cubic Bézier to the [`Path`] given its two control points - /// and its end point. - #[inline] - pub fn cubic_bezier_to( - &mut self, - to: Point, - control_a: Point, - control_b: Point, - ) { - self.raw - .cubic_bezier_to(control_a.into(), control_b.into(), to.into()); - } - - /// Close the current sub-path. - #[inline] - pub fn close(&mut self) { - self.raw.close(); - } - - /// Applies a transform to the path. - #[inline] - pub fn transform(&mut self, transform: Transform) { - self.transform = Some(transform); - } - - /// Applies a translation to the path. - #[inline] - pub fn translate(&mut self, to: Point) { - if let Some(transform) = self.transform { - self.transform = Some(transform.then_translate(Vector2D::new(to.x.0, to.y.0))); - } else { - self.transform = Some(Transform::translation(to.x.0, to.y.0)) - } - } - - /// Applies a scale to the path. - #[inline] - pub fn scale(&mut self, scale: f32) { - if let Some(transform) = self.transform { - self.transform = Some(transform.then_scale(scale, scale)); - } else { - self.transform = Some(Transform::scale(scale, scale)); - } - } - - /// Applies a rotation to the path. - /// - /// The `angle` is in degrees value in the range 0.0 to 360.0. - #[inline] - pub fn rotate(&mut self, angle: f32) { - let radians = angle.to_radians(); - if let Some(transform) = self.transform { - self.transform = Some(transform.then_rotate(Angle::radians(radians))); - } else { - self.transform = Some(Transform::rotation(Angle::radians(radians))); - } - } - - /// Builds into a [`Path`]. - #[inline] - pub fn build(self) -> Result, Error> { - let path = if let Some(transform) = self.transform { - self.raw.build().transformed(&transform) - } else { - self.raw.build() - }; - - match self.style { - PathStyle::Stroke(options) => Self::tessellate_stroke(&path, &options), - PathStyle::Fill(options) => Self::tessellate_fill(&path, &options), - } - } - - fn tessellate_fill( - path: &lyon::path::Path, - options: &FillOptions, - ) -> Result, Error> { - // Will contain the result of the tessellation. - let mut buf: VertexBuffers = VertexBuffers::new(); - let mut tessellator = FillTessellator::new(); - - // Compute the tessellation. - tessellator.tessellate_path( - path, - options, - &mut BuffersBuilder::new(&mut buf, |vertex: FillVertex| vertex.position()), - )?; - - Ok(Self::build_path(buf)) - } - - fn tessellate_stroke( - path: &lyon::path::Path, - options: &StrokeOptions, - ) -> Result, Error> { - // Will contain the result of the tessellation. - let mut buf: VertexBuffers = VertexBuffers::new(); - let mut tessellator = StrokeTessellator::new(); - - // Compute the tessellation. - tessellator.tessellate_path( - path, - options, - &mut BuffersBuilder::new(&mut buf, |vertex: StrokeVertex| vertex.position()), - )?; - - Ok(Self::build_path(buf)) - } - - /// Builds a [`Path`] from a [`lyon::VertexBuffers`]. - pub fn build_path(buf: VertexBuffers) -> Path { - if buf.vertices.is_empty() { - return Path::new(Point::default()); - } - - let first_point = buf.vertices[0]; - - let mut path = Path::new(first_point.into()); - for i in 0..buf.indices.len() / 3 { - let i0 = buf.indices[i * 3] as usize; - let i1 = buf.indices[i * 3 + 1] as usize; - let i2 = buf.indices[i * 3 + 2] as usize; - - let v0 = buf.vertices[i0]; - let v1 = buf.vertices[i1]; - let v2 = buf.vertices[i2]; - - path.push_triangle( - (v0.into(), v1.into(), v2.into()), - (point(0., 1.), point(0., 1.), point(0., 1.)), - ); - } - - path - } -} diff --git a/crates/gpui/src/platform/blade/blade_atlas.rs b/crates/gpui/src/platform/blade/blade_atlas.rs index 2783d57127..fb703f2a41 100644 --- a/crates/gpui/src/platform/blade/blade_atlas.rs +++ b/crates/gpui/src/platform/blade/blade_atlas.rs @@ -27,7 +27,6 @@ struct BladeAtlasState { tiles_by_key: FxHashMap, initializations: Vec, uploads: Vec, - path_sample_count: u32, } #[cfg(gles)] @@ -43,11 +42,10 @@ impl BladeAtlasState { pub struct BladeTextureInfo { pub size: gpu::Extent, pub raw_view: gpu::TextureView, - pub msaa_view: Option, } impl BladeAtlas { - pub(crate) fn new(gpu: &Arc, path_sample_count: u32) -> Self { + pub(crate) fn new(gpu: &Arc) -> Self { BladeAtlas(Mutex::new(BladeAtlasState { gpu: Arc::clone(gpu), upload_belt: BufferBelt::new(BufferBeltDescriptor { @@ -59,7 +57,6 @@ impl BladeAtlas { tiles_by_key: Default::default(), initializations: Vec::new(), uploads: Vec::new(), - path_sample_count, })) } @@ -109,7 +106,6 @@ impl BladeAtlas { depth: 1, }, raw_view: texture.raw_view, - msaa_view: texture.msaa_view, } } } @@ -208,39 +204,6 @@ impl BladeAtlasState { } } - // We currently only enable MSAA for path textures. - let (msaa, msaa_view) = if self.path_sample_count > 1 && kind == AtlasTextureKind::Path { - let msaa = self.gpu.create_texture(gpu::TextureDesc { - name: "msaa path texture", - format, - size: gpu::Extent { - width: size.width.into(), - height: size.height.into(), - depth: 1, - }, - array_layer_count: 1, - mip_level_count: 1, - sample_count: self.path_sample_count, - dimension: gpu::TextureDimension::D2, - usage: gpu::TextureUsage::TARGET, - }); - - ( - Some(msaa), - Some(self.gpu.create_texture_view( - msaa, - gpu::TextureViewDesc { - name: "msaa texture view", - format, - dimension: gpu::ViewDimension::D2, - subresources: &Default::default(), - }, - )), - ) - } else { - (None, None) - }; - let raw = self.gpu.create_texture(gpu::TextureDesc { name: "atlas", format, @@ -277,8 +240,6 @@ impl BladeAtlasState { format, raw, raw_view, - msaa, - msaa_view, live_atlas_keys: 0, }; @@ -393,8 +354,6 @@ struct BladeAtlasTexture { allocator: BucketedAtlasAllocator, raw: gpu::Texture, raw_view: gpu::TextureView, - msaa: Option, - msaa_view: Option, format: gpu::TextureFormat, live_atlas_keys: u32, } @@ -422,12 +381,6 @@ impl BladeAtlasTexture { fn destroy(&mut self, gpu: &gpu::Context) { gpu.destroy_texture(self.raw); gpu.destroy_texture_view(self.raw_view); - if let Some(msaa) = self.msaa { - gpu.destroy_texture(msaa); - } - if let Some(msaa_view) = self.msaa_view { - gpu.destroy_texture_view(msaa_view); - } } fn bytes_per_pixel(&self) -> u8 { diff --git a/crates/gpui/src/platform/blade/blade_renderer.rs b/crates/gpui/src/platform/blade/blade_renderer.rs index 200ebaaf07..ee8ffdfda7 100644 --- a/crates/gpui/src/platform/blade/blade_renderer.rs +++ b/crates/gpui/src/platform/blade/blade_renderer.rs @@ -7,18 +7,16 @@ use crate::{ MonochromeSprite, Path, PathId, PathVertex, PolychromeSprite, PrimitiveBatch, Quad, ScaledPixels, Scene, Shadow, Size, Underline, }; -use blade_graphics as gpu; -use blade_util::{BufferBelt, BufferBeltDescriptor}; use bytemuck::{Pod, Zeroable}; use collections::HashMap; #[cfg(target_os = "macos")] use media::core_video::CVMetalTextureCache; + +use blade_graphics as gpu; +use blade_util::{BufferBelt, BufferBeltDescriptor}; use std::{mem, sync::Arc}; const MAX_FRAME_TIME_MS: u32 = 10000; -// Use 4x MSAA, all devices support it. -// https://developer.apple.com/documentation/metal/mtldevice/1433355-supportstexturesamplecount -const PATH_SAMPLE_COUNT: u32 = 4; #[repr(C)] #[derive(Clone, Copy, Pod, Zeroable)] @@ -210,10 +208,7 @@ impl BladePipelines { blend: Some(gpu::BlendState::ADDITIVE), write_mask: gpu::ColorWrites::default(), }], - multisample_state: gpu::MultisampleState { - sample_count: PATH_SAMPLE_COUNT, - ..Default::default() - }, + multisample_state: gpu::MultisampleState::default(), }), paths: gpu.create_render_pipeline(gpu::RenderPipelineDesc { name: "paths", @@ -353,7 +348,7 @@ impl BladeRenderer { min_chunk_size: 0x1000, alignment: 0x40, // Vulkan `minStorageBufferOffsetAlignment` on Intel Xe }); - let atlas = Arc::new(BladeAtlas::new(&context.gpu, PATH_SAMPLE_COUNT)); + let atlas = Arc::new(BladeAtlas::new(&context.gpu)); let atlas_sampler = context.gpu.create_sampler(gpu::SamplerDesc { name: "atlas", mag_filter: gpu::FilterMode::Linear, @@ -502,38 +497,27 @@ impl BladeRenderer { }; let vertex_buf = unsafe { self.instance_belt.alloc_typed(&vertices, &self.gpu) }; - let frame_view = tex_info.raw_view; - let color_target = if let Some(msaa_view) = tex_info.msaa_view { - gpu::RenderTarget { - view: msaa_view, - init_op: gpu::InitOp::Clear(gpu::TextureColor::OpaqueBlack), - finish_op: gpu::FinishOp::ResolveTo(frame_view), - } - } else { - gpu::RenderTarget { - view: frame_view, - init_op: gpu::InitOp::Clear(gpu::TextureColor::OpaqueBlack), - finish_op: gpu::FinishOp::Store, - } - }; - - if let mut pass = self.command_encoder.render( + let mut pass = self.command_encoder.render( "paths", gpu::RenderTargetSet { - colors: &[color_target], + colors: &[gpu::RenderTarget { + view: tex_info.raw_view, + init_op: gpu::InitOp::Clear(gpu::TextureColor::OpaqueBlack), + finish_op: gpu::FinishOp::Store, + }], depth_stencil: None, }, - ) { - let mut encoder = pass.with(&self.pipelines.path_rasterization); - encoder.bind( - 0, - &ShaderPathRasterizationData { - globals, - b_path_vertices: vertex_buf, - }, - ); - encoder.draw(0, vertices.len() as u32, 0, 1); - } + ); + + let mut encoder = pass.with(&self.pipelines.path_rasterization); + encoder.bind( + 0, + &ShaderPathRasterizationData { + globals, + b_path_vertices: vertex_buf, + }, + ); + encoder.draw(0, vertices.len() as u32, 0, 1); } } diff --git a/crates/gpui/src/platform/mac/metal_atlas.rs b/crates/gpui/src/platform/mac/metal_atlas.rs index 4662761a7d..ca595c5ce3 100644 --- a/crates/gpui/src/platform/mac/metal_atlas.rs +++ b/crates/gpui/src/platform/mac/metal_atlas.rs @@ -13,14 +13,13 @@ use std::borrow::Cow; pub(crate) struct MetalAtlas(Mutex); impl MetalAtlas { - pub(crate) fn new(device: Device, path_sample_count: u32) -> Self { + pub(crate) fn new(device: Device) -> Self { MetalAtlas(Mutex::new(MetalAtlasState { device: AssertSend(device), monochrome_textures: Default::default(), polychrome_textures: Default::default(), path_textures: Default::default(), tiles_by_key: Default::default(), - path_sample_count, })) } @@ -28,10 +27,6 @@ impl MetalAtlas { self.0.lock().texture(id).metal_texture.clone() } - pub(crate) fn msaa_texture(&self, id: AtlasTextureId) -> Option { - self.0.lock().texture(id).msaa_texture.clone() - } - pub(crate) fn allocate( &self, size: Size, @@ -59,7 +54,6 @@ struct MetalAtlasState { polychrome_textures: AtlasTextureList, path_textures: AtlasTextureList, tiles_by_key: FxHashMap, - path_sample_count: u32, } impl PlatformAtlas for MetalAtlas { @@ -182,18 +176,6 @@ impl MetalAtlasState { texture_descriptor.set_usage(usage); let metal_texture = self.device.new_texture(&texture_descriptor); - // We currently only enable MSAA for path textures. - let msaa_texture = if self.path_sample_count > 1 && kind == AtlasTextureKind::Path { - let mut descriptor = texture_descriptor.clone(); - descriptor.set_texture_type(metal::MTLTextureType::D2Multisample); - descriptor.set_storage_mode(metal::MTLStorageMode::Private); - descriptor.set_sample_count(self.path_sample_count as _); - let msaa_texture = self.device.new_texture(&descriptor); - Some(msaa_texture) - } else { - None - }; - let texture_list = match kind { AtlasTextureKind::Monochrome => &mut self.monochrome_textures, AtlasTextureKind::Polychrome => &mut self.polychrome_textures, @@ -209,7 +191,6 @@ impl MetalAtlasState { }, allocator: etagere::BucketedAtlasAllocator::new(size.into()), metal_texture: AssertSend(metal_texture), - msaa_texture: AssertSend(msaa_texture), live_atlas_keys: 0, }; @@ -236,7 +217,6 @@ struct MetalAtlasTexture { id: AtlasTextureId, allocator: BucketedAtlasAllocator, metal_texture: AssertSend, - msaa_texture: AssertSend>, live_atlas_keys: u32, } diff --git a/crates/gpui/src/platform/mac/metal_renderer.rs b/crates/gpui/src/platform/mac/metal_renderer.rs index 56109d2ff6..c290d12f7e 100644 --- a/crates/gpui/src/platform/mac/metal_renderer.rs +++ b/crates/gpui/src/platform/mac/metal_renderer.rs @@ -28,9 +28,6 @@ pub(crate) type PointF = crate::Point; const SHADERS_METALLIB: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/shaders.metallib")); #[cfg(feature = "runtime_shaders")] const SHADERS_SOURCE_FILE: &str = include_str!(concat!(env!("OUT_DIR"), "/stitched_shaders.metal")); -// Use 4x MSAA, all devices support it. -// https://developer.apple.com/documentation/metal/mtldevice/1433355-supportstexturesamplecount -const PATH_SAMPLE_COUNT: u32 = 4; pub type Context = Arc>; pub type Renderer = MetalRenderer; @@ -173,7 +170,6 @@ impl MetalRenderer { "path_rasterization_vertex", "path_rasterization_fragment", MTLPixelFormat::R16Float, - PATH_SAMPLE_COUNT, ); let path_sprites_pipeline_state = build_pipeline_state( &device, @@ -233,7 +229,7 @@ impl MetalRenderer { ); let command_queue = device.new_command_queue(); - let sprite_atlas = Arc::new(MetalAtlas::new(device.clone(), PATH_SAMPLE_COUNT)); + let sprite_atlas = Arc::new(MetalAtlas::new(device.clone())); let core_video_texture_cache = unsafe { CVMetalTextureCache::new(device.as_ptr()).unwrap() }; @@ -535,20 +531,10 @@ impl MetalRenderer { .unwrap(); let texture = self.sprite_atlas.metal_texture(texture_id); - let msaa_texture = self.sprite_atlas.msaa_texture(texture_id); - - if let Some(msaa_texture) = msaa_texture { - color_attachment.set_texture(Some(&msaa_texture)); - color_attachment.set_resolve_texture(Some(&texture)); - color_attachment.set_load_action(metal::MTLLoadAction::Clear); - color_attachment.set_store_action(metal::MTLStoreAction::MultisampleResolve); - } else { - color_attachment.set_texture(Some(&texture)); - color_attachment.set_load_action(metal::MTLLoadAction::Clear); - color_attachment.set_store_action(metal::MTLStoreAction::Store); - } + color_attachment.set_texture(Some(&texture)); + color_attachment.set_load_action(metal::MTLLoadAction::Clear); + color_attachment.set_store_action(metal::MTLStoreAction::Store); color_attachment.set_clear_color(metal::MTLClearColor::new(0., 0., 0., 1.)); - let command_encoder = command_buffer.new_render_command_encoder(render_pass_descriptor); command_encoder.set_render_pipeline_state(&self.paths_rasterization_pipeline_state); command_encoder.set_vertex_buffer( @@ -1174,7 +1160,6 @@ fn build_path_rasterization_pipeline_state( vertex_fn_name: &str, fragment_fn_name: &str, pixel_format: metal::MTLPixelFormat, - path_sample_count: u32, ) -> metal::RenderPipelineState { let vertex_fn = library .get_function(vertex_fn_name, None) @@ -1187,10 +1172,6 @@ fn build_path_rasterization_pipeline_state( descriptor.set_label(label); descriptor.set_vertex_function(Some(vertex_fn.as_ref())); descriptor.set_fragment_function(Some(fragment_fn.as_ref())); - if path_sample_count > 1 { - descriptor.set_raster_sample_count(path_sample_count as _); - descriptor.set_alpha_to_coverage_enabled(true); - } let color_attachment = descriptor.color_attachments().object_at(0).unwrap(); color_attachment.set_pixel_format(pixel_format); color_attachment.set_blending_enabled(true); diff --git a/crates/gpui/src/scene.rs b/crates/gpui/src/scene.rs index b837f2ad91..778a5d1f27 100644 --- a/crates/gpui/src/scene.rs +++ b/crates/gpui/src/scene.rs @@ -715,13 +715,6 @@ impl Path { } } - /// Move the start, current point to the given point. - pub fn move_to(&mut self, to: Point) { - self.contour_count += 1; - self.start = to; - self.current = to; - } - /// Draw a straight line from the current point to the given point. pub fn line_to(&mut self, to: Point) { self.contour_count += 1; @@ -751,8 +744,7 @@ impl Path { self.current = to; } - /// Push a triangle to the Path. - pub fn push_triangle( + fn push_triangle( &mut self, xy: (Point, Point, Point), st: (Point, Point, Point),