History

Checkpoint

Antonio Scandurra committed 3 years ago

Commit d889cde1 parent 6a4c2a08 files · +463 −258Browse files

Unified · Split

8 files
  1. crates/gpui3/build.rs +1 −1
  2. crates/gpui3/src/platform.rs +25 −7
  3. crates/gpui3/src/platform/mac/metal_atlas.rs +75 −43
  4. crates/gpui3/src/platform/mac/metal_renderer.rs +20 −6
  5. crates/gpui3/src/platform/mac/window.rs +3 −3
  6. crates/gpui3/src/scene.rs +214 −105
  7. crates/gpui3/src/style.rs +16 −43
  8. crates/gpui3/src/window.rs +109 −50
crates/gpui3/build.rs+1−1
@@ -47,7 +47,7 @@ fn generate_shader_bindings() -> PathBuf { · 46 unmodified lines
4747 "Pixels".into(),
4848 "PointF".into(),
4949 "Hsla".into(),
50− "ScaledContentMask".into(),
50+ "ContentMask".into(),
5151 "Uniforms".into(),
5252 "AtlasTile".into(),
5353 "ShadowInputIndex".into(),
crates/gpui3/src/platform.rs+25−7
@@ -40,7 +40,7 @@ pub(crate) fn current_platform() -> Arc<dyn Platform> { · 39 unmodified lines
4040 Arc::new(MacPlatform::new())
4141 }
4242
43−pub trait Platform: 'static {
43+pub(crate) trait Platform: 'static {
4444 fn executor(&self) -> Executor;
4545 fn display_linker(&self) -> Arc<dyn PlatformDisplayLinker>;
4646 fn text_system(&self) -> Arc<dyn PlatformTextSystem>;
@@ -113,7 +113,7 @@ impl Debug for DisplayId { · 66 unmodified lines
113113
114114 unsafe impl Send for DisplayId {}
115115
116−pub trait PlatformWindow {
116+pub(crate) trait PlatformWindow {
117117 fn bounds(&self) -> WindowBounds;
118118 fn content_size(&self) -> Size<Pixels>;
119119 fn scale_factor(&self) -> f32;
@@ -194,11 +194,17 @@ pub enum AtlasKey { · 74 unmodified lines
194194 }
195195
196196 impl AtlasKey {
197− pub fn is_monochrome(&self) -> bool {
197+ pub(crate) fn texture_kind(&self) -> AtlasTextureKind {
198198 match self {
199− AtlasKey::Glyph(params) => !params.is_emoji,
200− AtlasKey::Svg(_) => true,
201− AtlasKey::Image(_) => false,
199+ AtlasKey::Glyph(params) => {
200+ if params.is_emoji {
201+ AtlasTextureKind::Polychrome
202+ } else {
203+ AtlasTextureKind::Monochrome
204+ }
205+ }
206+ AtlasKey::Svg(_) => AtlasTextureKind::Monochrome,
207+ AtlasKey::Image(_) => AtlasTextureKind::Polychrome,
202208 }
203209 }
204210 }
@@ -241,7 +247,19 @@ pub struct AtlasTile { · 36 unmodified lines
241247
242248 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
243249 #[repr(C)]
244−pub(crate) struct AtlasTextureId(pub(crate) u32); // We use u32 instead of usize for Metal Shader Language compatibility
250+pub(crate) struct AtlasTextureId {
251+ // We use u32 instead of usize for Metal Shader Language compatibility
252+ pub(crate) index: u32,
253+ pub(crate) kind: AtlasTextureKind,
254+}
255+
256+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
257+#[repr(C)]
258+pub(crate) enum AtlasTextureKind {
259+ Monochrome = 0,
260+ Polychrome = 1,
261+ Path = 2,
262+}
245263
246264 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
247265 #[repr(C)]
crates/gpui3/src/platform/mac/metal_atlas.rs+75−43
@@ -1,14 +1,14 @@
1−use std::borrow::Cow;
2−
31 use crate::{
4− AtlasKey, AtlasTextureId, AtlasTile, Bounds, DevicePixels, PlatformAtlas, Point, Size,
2+ AtlasKey, AtlasTextureId, AtlasTextureKind, AtlasTile, Bounds, DevicePixels, PlatformAtlas,
3+ Point, Size,
54 };
6−use anyhow::{anyhow, Result};
5+use anyhow::Result;
76 use collections::HashMap;
87 use derive_more::{Deref, DerefMut};
98 use etagere::BucketedAtlasAllocator;
109 use metal::Device;
1110 use parking_lot::Mutex;
11+use std::borrow::Cow;
1212
1313 pub struct MetalAtlas(Mutex<MetalAtlasState>);
1414
@@ -16,19 +16,31 @@ impl MetalAtlas { · 1 unmodified line
1616 pub fn new(device: Device) -> Self {
1717 MetalAtlas(Mutex::new(MetalAtlasState {
1818 device: AssertSend(device),
19− textures: Default::default(),
19+ monochrome_textures: Default::default(),
20+ polychrome_textures: Default::default(),
21+ path_textures: Default::default(),
2022 tiles_by_key: Default::default(),
2123 }))
2224 }
2325
24− pub(crate) fn texture(&self, id: AtlasTextureId) -> metal::Texture {
25− self.0.lock().textures[id.0 as usize].metal_texture.clone()
26+ pub(crate) fn metal_texture(&self, id: AtlasTextureId) -> metal::Texture {
27+ self.0.lock().texture(id).metal_texture.clone()
28+ }
29+
30+ pub(crate) fn allocate(
31+ &self,
32+ size: Size<DevicePixels>,
33+ texture_kind: AtlasTextureKind,
34+ ) -> AtlasTile {
35+ self.0.lock().allocate(size, texture_kind)
2636 }
2737 }
2838
2939 struct MetalAtlasState {
3040 device: AssertSend<Device>,
31− textures: Vec<MetalAtlasTexture>,
41+ monochrome_textures: Vec<MetalAtlasTexture>,
42+ polychrome_textures: Vec<MetalAtlasTexture>,
43+ path_textures: Vec<MetalAtlasTexture>,
3244 tiles_by_key: HashMap<AtlasKey, AtlasTile>,
3345 }
3446
@@ -43,23 +55,9 @@ impl PlatformAtlas for MetalAtlas { · 8 unmodified lines
4355 return Ok(tile.clone());
4456 } else {
4557 let (size, bytes) = build()?;
46− let tile = lock
47− .textures
48− .iter_mut()
49− .rev()
50− .find_map(|texture| {
51− if texture.monochrome == key.is_monochrome() {
52− texture.upload(size, &bytes)
53− } else {
54− None
55− }
56− })
57− .or_else(|| {
58− let texture = lock.push_texture(size, key.is_monochrome());
59− texture.upload(size, &bytes)
60− })
61− .ok_or_else(|| anyhow!("could not allocate in new texture"))?;
62− lock.tiles_by_key.insert(key.clone(), tile.clone());
58+ let tile = lock.allocate(size, key.texture_kind());
59+ let texture = lock.texture(tile.texture_id);
60+ texture.upload(tile.bounds, &bytes);
6361 Ok(tile)
6462 }
6563 }
@@ -70,10 +68,26 @@ impl PlatformAtlas for MetalAtlas { · 4 unmodified lines
7068 }
7169
7270 impl MetalAtlasState {
71+ fn allocate(&mut self, size: Size<DevicePixels>, texture_kind: AtlasTextureKind) -> AtlasTile {
72+ let textures = match texture_kind {
73+ AtlasTextureKind::Monochrome => &mut self.monochrome_textures,
74+ AtlasTextureKind::Polychrome => &mut self.polychrome_textures,
75+ AtlasTextureKind::Path => &mut self.path_textures,
76+ };
77+ textures
78+ .iter_mut()
79+ .rev()
80+ .find_map(|texture| texture.allocate(size))
81+ .unwrap_or_else(|| {
82+ let texture = self.push_texture(size, texture_kind);
83+ texture.allocate(size).unwrap()
84+ })
85+ }
86+
7387 fn push_texture(
7488 &mut self,
7589 min_size: Size<DevicePixels>,
76− monochrome: bool,
90+ kind: AtlasTextureKind,
7791 ) -> &mut MetalAtlasTexture {
7892 const DEFAULT_ATLAS_SIZE: Size<DevicePixels> = Size {
7993 width: DevicePixels(1024),
@@ -84,21 +98,38 @@ impl MetalAtlasState { · 4 unmodified lines
8498 let texture_descriptor = metal::TextureDescriptor::new();
8599 texture_descriptor.set_width(size.width.into());
86100 texture_descriptor.set_height(size.height.into());
87− if monochrome {
88− texture_descriptor.set_pixel_format(metal::MTLPixelFormat::A8Unorm);
89− } else {
90− texture_descriptor.set_pixel_format(metal::MTLPixelFormat::BGRA8Unorm);
91− }
101+ let pixel_format = match kind {
102+ AtlasTextureKind::Monochrome => metal::MTLPixelFormat::A8Unorm,
103+ AtlasTextureKind::Polychrome => metal::MTLPixelFormat::BGRA8Unorm,
104+ AtlasTextureKind::Path => metal::MTLPixelFormat::R16Float,
105+ };
106+ texture_descriptor.set_pixel_format(pixel_format);
92107 let metal_texture = self.device.new_texture(&texture_descriptor);
93108
109+ let textures = match kind {
110+ AtlasTextureKind::Monochrome => &mut self.monochrome_textures,
111+ AtlasTextureKind::Polychrome => &mut self.polychrome_textures,
112+ AtlasTextureKind::Path => &mut self.path_textures,
113+ };
94114 let atlas_texture = MetalAtlasTexture {
95− id: AtlasTextureId(self.textures.len() as u32),
115+ id: AtlasTextureId {
116+ index: textures.len() as u32,
117+ kind,
118+ },
96119 allocator: etagere::BucketedAtlasAllocator::new(size.into()),
97120 metal_texture: AssertSend(metal_texture),
98− monochrome,
99121 };
100− self.textures.push(atlas_texture);
101− self.textures.last_mut().unwrap()
122+ textures.push(atlas_texture);
123+ textures.last_mut().unwrap()
124+ }
125+
126+ fn texture(&self, id: AtlasTextureId) -> &MetalAtlasTexture {
127+ let textures = match id.kind {
128+ crate::AtlasTextureKind::Monochrome => &self.monochrome_textures,
129+ crate::AtlasTextureKind::Polychrome => &self.polychrome_textures,
130+ crate::AtlasTextureKind::Path => &self.path_textures,
131+ };
132+ &textures[id.index as usize]
102133 }
103134 }
104135
@@ -106,11 +137,10 @@ struct MetalAtlasTexture { · 1 unmodified line
106137 id: AtlasTextureId,
107138 allocator: BucketedAtlasAllocator,
108139 metal_texture: AssertSend<metal::Texture>,
109− monochrome: bool,
110140 }
111141
112142 impl MetalAtlasTexture {
113− fn upload(&mut self, size: Size<DevicePixels>, bytes: &[u8]) -> Option<AtlasTile> {
143+ fn allocate(&mut self, size: Size<DevicePixels>) -> Option<AtlasTile> {
114144 let allocation = self.allocator.allocate(size.into())?;
115145 let tile = AtlasTile {
116146 texture_id: self.id,
@@ -120,20 +150,22 @@ impl MetalAtlasTexture { · 3 unmodified lines
120150 size,
121151 },
122152 };
153+ Some(tile)
154+ }
123155
156+ fn upload(&self, bounds: Bounds<DevicePixels>, bytes: &[u8]) {
124157 let region = metal::MTLRegion::new_2d(
125− tile.bounds.origin.x.into(),
126− tile.bounds.origin.y.into(),
127− tile.bounds.size.width.into(),
128− tile.bounds.size.height.into(),
158+ bounds.origin.x.into(),
159+ bounds.origin.y.into(),
160+ bounds.size.width.into(),
161+ bounds.size.height.into(),
129162 );
130163 self.metal_texture.replace_region(
131164 region,
132165 0,
133166 bytes.as_ptr() as *const _,
134− u32::from(tile.bounds.size.width.to_bytes(self.bytes_per_pixel())) as u64,
167+ u32::from(bounds.size.width.to_bytes(self.bytes_per_pixel())) as u64,
135168 );
136− Some(tile)
137169 }
138170
139171 fn bytes_per_pixel(&self) -> u8 {
crates/gpui3/src/platform/mac/metal_renderer.rs+20−6
@@ -1,12 +1,14 @@
11 use crate::{
2− point, size, AtlasTextureId, DevicePixels, MetalAtlas, MonochromeSprite, PolychromeSprite,
3− PrimitiveBatch, Quad, Scene, Shadow, Size, Underline,
2+ point, size, AtlasTextureId, AtlasTextureKind, AtlasTile, DevicePixels, MetalAtlas,
3+ MonochromeSprite, PathId, PolychromeSprite, PrimitiveBatch, Quad, Scene, Shadow, Size,
4+ Underline,
45 };
56 use cocoa::{
67 base::{NO, YES},
78 foundation::NSUInteger,
89 quartzcore::AutoresizingMask,
910 };
11+use collections::HashMap;
1012 use metal::{CommandQueue, MTLPixelFormat, MTLResourceOptions, NSRange};
1113 use objc::{self, msg_send, sel, sel_impl};
1214 use std::{ffi::c_void, mem, ptr, sync::Arc};
@@ -14,7 +16,7 @@ use std::{ffi::c_void, mem, ptr, sync::Arc}; · 1 unmodified line
1416 const SHADERS_METALLIB: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/shaders.metallib"));
1517 const INSTANCE_BUFFER_SIZE: usize = 8192 * 1024; // This is an arbitrary decision. There's probably a more optimal value.
1618
17−pub struct MetalRenderer {
19+pub(crate) struct MetalRenderer {
1820 layer: metal::MetalLayer,
1921 command_queue: CommandQueue,
2022 shadows_pipeline_state: metal::RenderPipelineState,
@@ -150,7 +152,7 @@ impl MetalRenderer { · 129 unmodified lines
150152 &self.sprite_atlas
151153 }
152154
153− pub fn draw(&mut self, scene: &mut Scene) {
155+ pub fn draw(&mut self, scene: &Scene) {
154156 let layer = self.layer.clone();
155157 let viewport_size = layer.drawable_size();
156158 let viewport_size: Size<DevicePixels> = size(
@@ -192,6 +194,15 @@ impl MetalRenderer { · 35 unmodified lines
192194 });
193195
194196 let mut instance_offset = 0;
197+
198+ let mut path_tiles: HashMap<PathId, AtlasTile> = HashMap::default();
199+ for path in scene.paths() {
200+ let tile = self
201+ .sprite_atlas
202+ .allocate(path.bounds.size.map(Into::into), AtlasTextureKind::Path);
203+ path_tiles.insert(path.id, tile);
204+ }
205+
195206 for batch in scene.batches() {
196207 match batch {
197208 PrimitiveBatch::Shadows(shadows) => {
@@ -205,6 +216,9 @@ impl MetalRenderer { · 7 unmodified lines
205216 PrimitiveBatch::Quads(quads) => {
206217 self.draw_quads(quads, &mut instance_offset, viewport_size, command_encoder);
207218 }
219+ PrimitiveBatch::Paths(paths) => {
220+ // self.draw_paths(paths, &mut instance_offset, viewport_size, command_encoder);
221+ }
208222 PrimitiveBatch::Underlines(underlines) => {
209223 self.draw_underlines(
210224 underlines,
@@ -441,7 +455,7 @@ impl MetalRenderer { · 230 unmodified lines
441455 }
442456 align_offset(offset);
443457
444− let texture = self.sprite_atlas.texture(texture_id);
458+ let texture = self.sprite_atlas.metal_texture(texture_id);
445459 let texture_size = size(
446460 DevicePixels(texture.width() as i32),
447461 DevicePixels(texture.height() as i32),
@@ -512,7 +526,7 @@ impl MetalRenderer { · 64 unmodified lines
512526 }
513527 align_offset(offset);
514528
515− let texture = self.sprite_atlas.texture(texture_id);
529+ let texture = self.sprite_atlas.metal_texture(texture_id);
516530 let texture_size = size(
517531 DevicePixels(texture.width() as i32),
518532 DevicePixels(texture.height() as i32),
crates/gpui3/src/platform/mac/window.rs+3−3
@@ -911,7 +911,7 @@ impl PlatformWindow for MacWindow { · 910 unmodified lines
911911 }
912912 }
913913
914− fn draw(&self, scene: crate::Scene) {
914+ fn draw(&self, scene: Scene) {
915915 let mut this = self.0.lock();
916916 this.scene_to_render = Some(scene);
917917 unsafe {
@@ -1395,8 +1395,8 @@ extern "C" fn display_layer(this: &Object, _: Sel, _: id) { · 477 unmodified lines
13951395 unsafe {
13961396 let window_state = get_window_state(this);
13971397 let mut window_state = window_state.as_ref().lock();
1398− if let Some(mut scene) = window_state.scene_to_render.take() {
1399− window_state.renderer.draw(&mut scene);
1398+ if let Some(scene) = window_state.scene_to_render.take() {
1399+ window_state.renderer.draw(&scene);
14001400 }
14011401 }
14021402 }
crates/gpui3/src/scene.rs+214−105
@@ -1,16 +1,12 @@
11 use crate::{
2− point, px, AtlasTextureId, AtlasTile, Bounds, Corners, Edges, Hsla, Pixels, Point,
3− ScaledContentMask, ScaledPixels,
2+ point, AtlasTextureId, AtlasTile, Bounds, ContentMask, Corners, Edges, Hsla, Pixels, Point,
3+ ScaledPixels,
44 };
55 use collections::BTreeMap;
66 use etagere::euclid::{Point3D, Vector3D};
77 use plane_split::{BspSplitter, Polygon as BspPolygon};
88 use smallvec::SmallVec;
9−use std::{
10− iter::Peekable,
11− mem, slice,
12− sync::atomic::{AtomicU32, Ordering::SeqCst},
13−};
9+use std::{fmt::Debug, iter::Peekable, mem, slice};
1410
1511 // Exported to metal
1612 pub type PointF = Point<f32>;
@@ -18,94 +14,57 @@ pub type StackingOrder = SmallVec<[u32; 16]>; · 1 unmodified line
1814 pub type LayerId = u32;
1915 pub type DrawOrder = u32;
2016
21−#[derive(Debug)]
22−pub struct Scene {
23− pub(crate) scale_factor: f32,
24− pub(crate) layers: BTreeMap<StackingOrder, LayerId>,
25− pub shadows: Vec<Shadow>,
26− pub quads: Vec<Quad>,
27− pub underlines: Vec<Underline>,
28− pub monochrome_sprites: Vec<MonochromeSprite>,
29− pub polychrome_sprites: Vec<PolychromeSprite>,
30−}
31−
32−impl Scene {
33− pub fn new(scale_factor: f32) -> Scene {
34− Scene {
35− scale_factor,
36− layers: BTreeMap::new(),
17+pub(crate) struct SceneBuilder {
18+ layers_by_order: BTreeMap<StackingOrder, LayerId>,
19+ splitter: BspSplitter<(PrimitiveKind, usize)>,
20+ shadows: Vec<Shadow>,
21+ quads: Vec<Quad>,
22+ paths: Vec<Path<ScaledPixels>>,
23+ underlines: Vec<Underline>,
24+ monochrome_sprites: Vec<MonochromeSprite>,
25+ polychrome_sprites: Vec<PolychromeSprite>,
26+}
27+
28+impl SceneBuilder {
29+ pub fn new() -> SceneBuilder {
30+ SceneBuilder {
31+ layers_by_order: BTreeMap::new(),
32+ splitter: BspSplitter::new(),
3733 shadows: Vec::new(),
3834 quads: Vec::new(),
35+ paths: Vec::new(),
3936 underlines: Vec::new(),
4037 monochrome_sprites: Vec::new(),
4138 polychrome_sprites: Vec::new(),
4239 }
4340 }
4441
45− pub fn take(&mut self) -> Scene {
46− Scene {
47− scale_factor: self.scale_factor,
48− layers: mem::take(&mut self.layers),
49− shadows: mem::take(&mut self.shadows),
50− quads: mem::take(&mut self.quads),
51− underlines: mem::take(&mut self.underlines),
52− monochrome_sprites: mem::take(&mut self.monochrome_sprites),
53− polychrome_sprites: mem::take(&mut self.polychrome_sprites),
54− }
55− }
56−
57− pub fn insert(&mut self, layer_id: StackingOrder, primitive: impl Into<Primitive>) {
58− let next_id = self.layers.len() as LayerId;
59− let layer_id = *self.layers.entry(layer_id).or_insert(next_id);
60− let primitive = primitive.into();
61− match primitive {
62− Primitive::Shadow(mut shadow) => {
63− shadow.order = layer_id;
64− self.shadows.push(shadow);
65− }
66− Primitive::Quad(mut quad) => {
67− quad.order = layer_id;
68− self.quads.push(quad);
69− }
70− Primitive::Underline(mut underline) => {
71− underline.order = layer_id;
72− self.underlines.push(underline);
73− }
74− Primitive::MonochromeSprite(mut sprite) => {
75− sprite.order = layer_id;
76− self.monochrome_sprites.push(sprite);
77− }
78− Primitive::PolychromeSprite(mut sprite) => {
79− sprite.order = layer_id;
80− self.polychrome_sprites.push(sprite);
81− }
82− }
83− }
84−
85− pub(crate) fn batches(&mut self) -> impl Iterator<Item = PrimitiveBatch> {
42+ pub fn build(&mut self) -> Scene {
8643 // Map each layer id to a float between 0. and 1., with 1. closer to the viewer.
87− let mut layer_z_values = vec![0.; self.layers.len()];
88− for (ix, layer_id) in self.layers.values().enumerate() {
89− layer_z_values[*layer_id as usize] = ix as f32 / self.layers.len() as f32;
44+ let mut layer_z_values = vec![0.; self.layers_by_order.len()];
45+ for (ix, layer_id) in self.layers_by_order.values().enumerate() {
46+ layer_z_values[*layer_id as usize] = ix as f32 / self.layers_by_order.len() as f32;
9047 }
48+ self.layers_by_order.clear();
9149
9250 // Add all primitives to the BSP splitter to determine draw order
93− // todo!("reuse the same splitter")
94− let mut splitter = BspSplitter::new();
51+ self.splitter.reset();
9552
9653 for (ix, shadow) in self.shadows.iter().enumerate() {
9754 let z = layer_z_values[shadow.order as LayerId as usize];
98− splitter.add(shadow.bounds.to_bsp_polygon(z, (PrimitiveKind::Shadow, ix)));
55+ self.splitter
56+ .add(shadow.bounds.to_bsp_polygon(z, (PrimitiveKind::Shadow, ix)));
9957 }
10058
10159 for (ix, quad) in self.quads.iter().enumerate() {
10260 let z = layer_z_values[quad.order as LayerId as usize];
103− splitter.add(quad.bounds.to_bsp_polygon(z, (PrimitiveKind::Quad, ix)));
61+ self.splitter
62+ .add(quad.bounds.to_bsp_polygon(z, (PrimitiveKind::Quad, ix)));
10463 }
10564
10665 for (ix, underline) in self.underlines.iter().enumerate() {
10766 let z = layer_z_values[underline.order as LayerId as usize];
108− splitter.add(
67+ self.splitter.add(
10968 underline
11069 .bounds
11170 .to_bsp_polygon(z, (PrimitiveKind::Underline, ix)),
@@ -114,7 +73,7 @@ impl Scene { · 2 unmodified lines
11473
11574 for (ix, monochrome_sprite) in self.monochrome_sprites.iter().enumerate() {
11675 let z = layer_z_values[monochrome_sprite.order as LayerId as usize];
117− splitter.add(
76+ self.splitter.add(
11877 monochrome_sprite
11978 .bounds
12079 .to_bsp_polygon(z, (PrimitiveKind::MonochromeSprite, ix)),
@@ -123,7 +82,7 @@ impl Scene { · 2 unmodified lines
12382
12483 for (ix, polychrome_sprite) in self.polychrome_sprites.iter().enumerate() {
12584 let z = layer_z_values[polychrome_sprite.order as LayerId as usize];
126− splitter.add(
85+ self.splitter.add(
12786 polychrome_sprite
12887 .bounds
12988 .to_bsp_polygon(z, (PrimitiveKind::PolychromeSprite, ix)),
@@ -132,10 +91,16 @@ impl Scene { · 2 unmodified lines
13291
13392 // Sort all polygons, then reassign the order field of each primitive to `draw_order`
13493 // We need primitives to be repr(C), hence the weird reuse of the order field for two different types.
135− for (draw_order, polygon) in splitter.sort(Vector3D::new(0., 0., 1.)).iter().enumerate() {
94+ for (draw_order, polygon) in self
95+ .splitter
96+ .sort(Vector3D::new(0., 0., 1.))
97+ .iter()
98+ .enumerate()
99+ {
136100 match polygon.anchor {
137101 (PrimitiveKind::Shadow, ix) => self.shadows[ix].order = draw_order as DrawOrder,
138102 (PrimitiveKind::Quad, ix) => self.quads[ix].order = draw_order as DrawOrder,
103+ (PrimitiveKind::Path, ix) => self.paths[ix].order = draw_order as DrawOrder,
139104 (PrimitiveKind::Underline, ix) => {
140105 self.underlines[ix].order = draw_order as DrawOrder
141106 }
@@ -148,13 +113,78 @@ impl Scene { · 6 unmodified lines
148113 }
149114 }
150115
151− // Sort the primitives
152116 self.shadows.sort_unstable();
153117 self.quads.sort_unstable();
118+ self.paths.sort_unstable();
154119 self.underlines.sort_unstable();
155120 self.monochrome_sprites.sort_unstable();
156121 self.polychrome_sprites.sort_unstable();
157122
123+ Scene {
124+ shadows: mem::take(&mut self.shadows),
125+ quads: mem::take(&mut self.quads),
126+ paths: mem::take(&mut self.paths),
127+ underlines: mem::take(&mut self.underlines),
128+ monochrome_sprites: mem::take(&mut self.monochrome_sprites),
129+ polychrome_sprites: mem::take(&mut self.polychrome_sprites),
130+ }
131+ }
132+
133+ pub fn insert(&mut self, order: &StackingOrder, primitive: impl Into<Primitive>) {
134+ let layer_id = if let Some(layer_id) = self.layers_by_order.get(order) {
135+ *layer_id
136+ } else {
137+ let next_id = self.layers_by_order.len() as LayerId;
138+ self.layers_by_order.insert(order.clone(), next_id);
139+ next_id
140+ };
141+
142+ let primitive = primitive.into();
143+ match primitive {
144+ Primitive::Shadow(mut shadow) => {
145+ shadow.order = layer_id;
146+ self.shadows.push(shadow);
147+ }
148+ Primitive::Quad(mut quad) => {
149+ quad.order = layer_id;
150+ self.quads.push(quad);
151+ }
152+ Primitive::Path(mut path) => {
153+ path.order = layer_id;
154+ path.id = PathId(self.paths.len());
155+ self.paths.push(path);
156+ }
157+ Primitive::Underline(mut underline) => {
158+ underline.order = layer_id;
159+ self.underlines.push(underline);
160+ }
161+ Primitive::MonochromeSprite(mut sprite) => {
162+ sprite.order = layer_id;
163+ self.monochrome_sprites.push(sprite);
164+ }
165+ Primitive::PolychromeSprite(mut sprite) => {
166+ sprite.order = layer_id;
167+ self.polychrome_sprites.push(sprite);
168+ }
169+ }
170+ }
171+}
172+
173+pub(crate) struct Scene {
174+ pub shadows: Vec<Shadow>,
175+ pub quads: Vec<Quad>,
176+ pub paths: Vec<Path<ScaledPixels>>,
177+ pub underlines: Vec<Underline>,
178+ pub monochrome_sprites: Vec<MonochromeSprite>,
179+ pub polychrome_sprites: Vec<PolychromeSprite>,
180+}
181+
182+impl Scene {
183+ pub fn paths(&self) -> impl Iterator<Item = &Path<ScaledPixels>> {
184+ self.paths.iter()
185+ }
186+
187+ pub fn batches(&self) -> impl Iterator<Item = PrimitiveBatch> {
158188 BatchIterator {
159189 shadows: &self.shadows,
160190 shadows_start: 0,
@@ -162,6 +192,9 @@ impl Scene { · 1 unmodified line
162192 quads: &self.quads,
163193 quads_start: 0,
164194 quads_iter: self.quads.iter().peekable(),
195+ paths: &self.paths,
196+ paths_start: 0,
197+ paths_iter: self.paths.iter().peekable(),
165198 underlines: &self.underlines,
166199 underlines_start: 0,
167200 underlines_iter: self.underlines.iter().peekable(),
@@ -176,12 +209,15 @@ impl Scene { · 8 unmodified lines
176209 }
177210
178211 struct BatchIterator<'a> {
179− quads: &'a [Quad],
180− quads_start: usize,
181− quads_iter: Peekable<slice::Iter<'a, Quad>>,
182212 shadows: &'a [Shadow],
183213 shadows_start: usize,
184214 shadows_iter: Peekable<slice::Iter<'a, Shadow>>,
215+ quads: &'a [Quad],
216+ quads_start: usize,
217+ quads_iter: Peekable<slice::Iter<'a, Quad>>,
218+ paths: &'a [Path<ScaledPixels>],
219+ paths_start: usize,
220+ paths_iter: Peekable<slice::Iter<'a, Path<ScaledPixels>>>,
185221 underlines: &'a [Underline],
186222 underlines_start: usize,
187223 underlines_iter: Peekable<slice::Iter<'a, Underline>>,
@@ -255,6 +291,19 @@ impl<'a> Iterator for BatchIterator<'a> { · 67 unmodified lines
255291 self.quads_start = quads_end;
256292 Some(PrimitiveBatch::Quads(&self.quads[quads_start..quads_end]))
257293 }
294+ PrimitiveKind::Path => {
295+ let paths_start = self.paths_start;
296+ let mut paths_end = paths_start;
297+ while self
298+ .paths_iter
299+ .next_if(|path| path.order <= max_order)
300+ .is_some()
301+ {
302+ paths_end += 1;
303+ }
304+ self.paths_start = paths_end;
305+ Some(PrimitiveBatch::Paths(&self.paths[paths_start..paths_end]))
306+ }
258307 PrimitiveKind::Underline => {
259308 let underlines_start = self.underlines_start;
260309 let mut underlines_end = underlines_start;
@@ -317,15 +366,16 @@ pub enum PrimitiveKind { · 56 unmodified lines
317366 Shadow,
318367 #[default]
319368 Quad,
369+ Path,
320370 Underline,
321371 MonochromeSprite,
322372 PolychromeSprite,
323373 }
324374
325−#[derive(Clone, Debug)]
326375 pub enum Primitive {
327376 Shadow(Shadow),
328377 Quad(Quad),
378+ Path(Path<ScaledPixels>),
329379 Underline(Underline),
330380 MonochromeSprite(MonochromeSprite),
331381 PolychromeSprite(PolychromeSprite),
@@ -335,6 +385,7 @@ pub enum Primitive { · 3 unmodified lines
335385 pub(crate) enum PrimitiveBatch<'a> {
336386 Shadows(&'a [Shadow]),
337387 Quads(&'a [Quad]),
388+ Paths(&'a [Path<ScaledPixels>]),
338389 Underlines(&'a [Underline]),
339390 MonochromeSprites {
340391 texture_id: AtlasTextureId,
@@ -351,7 +402,7 @@ pub(crate) enum PrimitiveBatch<'a> { · 10 unmodified lines
351402 pub struct Quad {
352403 pub order: u32, // Initially a LayerId, then a DrawOrder.
353404 pub bounds: Bounds<ScaledPixels>,
354− pub content_mask: ScaledContentMask,
405+ pub content_mask: ContentMask<ScaledPixels>,
355406 pub background: Hsla,
356407 pub border_color: Hsla,
357408 pub corner_radii: Corners<ScaledPixels>,
@@ -381,7 +432,7 @@ impl From<Quad> for Primitive { · 23 unmodified lines
381432 pub struct Underline {
382433 pub order: u32,
383434 pub bounds: Bounds<ScaledPixels>,
384− pub content_mask: ScaledContentMask,
435+ pub content_mask: ContentMask<ScaledPixels>,
385436 pub thickness: ScaledPixels,
386437 pub color: Hsla,
387438 pub wavy: bool,
@@ -411,7 +462,7 @@ pub struct Shadow { · 23 unmodified lines
411462 pub order: u32,
412463 pub bounds: Bounds<ScaledPixels>,
413464 pub corner_radii: Corners<ScaledPixels>,
414− pub content_mask: ScaledContentMask,
465+ pub content_mask: ContentMask<ScaledPixels>,
415466 pub color: Hsla,
416467 pub blur_radius: ScaledPixels,
417468 }
@@ -439,7 +490,7 @@ impl From<Shadow> for Primitive { · 21 unmodified lines
439490 pub struct MonochromeSprite {
440491 pub order: u32,
441492 pub bounds: Bounds<ScaledPixels>,
442− pub content_mask: ScaledContentMask,
493+ pub content_mask: ContentMask<ScaledPixels>,
443494 pub color: Hsla,
444495 pub tile: AtlasTile,
445496 }
@@ -470,7 +521,7 @@ impl From<MonochromeSprite> for Primitive { · 24 unmodified lines
470521 pub struct PolychromeSprite {
471522 pub order: u32,
472523 pub bounds: Bounds<ScaledPixels>,
473− pub content_mask: ScaledContentMask,
524+ pub content_mask: ContentMask<ScaledPixels>,
474525 pub corner_radii: Corners<ScaledPixels>,
475526 pub tile: AtlasTile,
476527 pub grayscale: bool,
@@ -497,21 +548,24 @@ impl From<PolychromeSprite> for Primitive { · 20 unmodified lines
497548 }
498549 }
499550
500−#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
501−pub struct PathId(u32);
551+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
552+pub(crate) struct PathId(pub(crate) usize);
502553
503−pub struct PathBuilder {
504− bounds: Bounds<Pixels>,
505− vertices: Vec<PathVertex>,
506− start: Option<Point<Pixels>>,
507− current: Point<Pixels>,
554+#[derive(Debug)]
555+pub struct Path<P: Clone + Debug> {
556+ pub(crate) id: PathId,
557+ order: u32,
558+ pub(crate) bounds: Bounds<P>,
559+ pub(crate) vertices: Vec<PathVertex<P>>,
560+ start: Option<Point<P>>,
561+ current: Point<P>,
508562 }
509563
510−impl PathBuilder {
564+impl Path<Pixels> {
511565 pub fn new() -> Self {
512− const NEXT_PATH_ID: AtomicU32 = AtomicU32::new(0);
513−
514566 Self {
567+ id: PathId(0),
568+ order: 0,
515569 vertices: Vec::new(),
516570 start: Default::default(),
517571 current: Default::default(),
@@ -519,6 +573,21 @@ impl PathBuilder { · 1 unmodified line
519573 }
520574 }
521575
576+ pub fn scale(&self, factor: f32) -> Path<ScaledPixels> {
577+ Path {
578+ id: self.id,
579+ order: self.order,
580+ bounds: self.bounds.scale(factor),
581+ vertices: self
582+ .vertices
583+ .iter()
584+ .map(|vertex| vertex.scale(factor))
585+ .collect(),
586+ start: self.start.map(|start| start.scale(factor)),
587+ current: self.current.scale(factor),
588+ }
589+ }
590+
522591 pub fn line_to(&mut self, to: Point<Pixels>) {
523592 if let Some(start) = self.start {
524593 self.push_triangle(
@@ -568,23 +637,63 @@ impl PathBuilder { · 43 unmodified lines
568637 self.vertices.push(PathVertex {
569638 xy_position: xy.0,
570639 st_position: st.0,
640+ content_mask: Default::default(),
571641 });
572642 self.vertices.push(PathVertex {
573643 xy_position: xy.1,
574644 st_position: st.1,
645+ content_mask: Default::default(),
575646 });
576647 self.vertices.push(PathVertex {
577648 xy_position: xy.2,
578649 st_position: st.2,
650+ content_mask: Default::default(),
579651 });
580652 }
581653 }
582654
583−#[derive(Clone, Debug)]
655+impl Eq for Path<ScaledPixels> {}
656+
657+impl PartialEq for Path<ScaledPixels> {
658+ fn eq(&self, other: &Self) -> bool {
659+ self.order == other.order
660+ }
661+}
662+
663+impl Ord for Path<ScaledPixels> {
664+ fn cmp(&self, other: &Self) -> std::cmp::Ordering {
665+ self.order.cmp(&other.order)
666+ }
667+}
668+
669+impl PartialOrd for Path<ScaledPixels> {
670+ fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
671+ Some(self.cmp(other))
672+ }
673+}
674+
675+impl From<Path<ScaledPixels>> for Primitive {
676+ fn from(path: Path<ScaledPixels>) -> Self {
677+ Primitive::Path(path)
678+ }
679+}
680+
681+#[derive(Debug)]
584682 #[repr(C)]
585−pub struct PathVertex {
586− pub xy_position: Point<Pixels>,
587− pub st_position: Point<f32>,
683+pub struct PathVertex<P: Clone + Debug> {
684+ pub(crate) xy_position: Point<P>,
685+ pub(crate) st_position: Point<f32>,
686+ pub(crate) content_mask: ContentMask<P>,
687+}
688+
689+impl PathVertex<Pixels> {
690+ pub fn scale(&self, factor: f32) -> PathVertex<ScaledPixels> {
691+ PathVertex {
692+ xy_position: self.xy_position.scale(factor),
693+ st_position: self.st_position,
694+ content_mask: self.content_mask.scale(factor),
695+ }
696+ }
588697 }
589698
590699 #[derive(Copy, Clone, Debug)]
@@ -619,15 +728,15 @@ mod tests { · 28 unmodified lines
619728
620729 #[test]
621730 fn test_scene() {
622− let mut scene = Scene::new(1.0);
623− assert_eq!(scene.layers.len(), 0);
731+ let mut scene = SceneBuilder::new();
732+ assert_eq!(scene.layers_by_order.len(), 0);
624733
625− scene.insert(smallvec![1], quad());
626− scene.insert(smallvec![2], shadow());
627− scene.insert(smallvec![3], quad());
734+ scene.insert(&smallvec![1], quad());
735+ scene.insert(&smallvec![2], shadow());
736+ scene.insert(&smallvec![3], quad());
628737
629738 let mut batches_count = 0;
630− for _ in scene.batches() {
739+ for _ in scene.build().batches() {
631740 batches_count += 1;
632741 }
633742 assert_eq!(batches_count, 3);
crates/gpui3/src/style.rs+16−43
@@ -1,8 +1,8 @@
11 use crate::{
22 phi, point, rems, AbsoluteLength, BorrowAppContext, BorrowWindow, Bounds, ContentMask, Corners,
33 CornersRefinement, DefiniteLength, Edges, EdgesRefinement, Font, FontFeatures, FontStyle,
4− FontWeight, Hsla, Length, Pixels, Point, PointRefinement, Quad, Rems, Result, RunStyle, Shadow,
5− SharedString, Size, SizeRefinement, ViewContext, WindowContext,
4+ FontWeight, Hsla, Length, Pixels, Point, PointRefinement, Rems, Result, RunStyle, SharedString,
5+ Size, SizeRefinement, ViewContext, WindowContext,
66 };
77 use refineable::Refineable;
88 use smallvec::SmallVec;
@@ -243,51 +243,24 @@ impl Style { · 234 unmodified lines
243243 /// Paints the background of an element styled with this style.
244244 pub fn paint<V: 'static>(&self, bounds: Bounds<Pixels>, cx: &mut ViewContext<V>) {
245245 let rem_size = cx.rem_size();
246− let scale = cx.scale_factor();
247−
248− for shadow in &self.box_shadow {
249− let content_mask = cx.content_mask();
250− let mut shadow_bounds = bounds;
251− shadow_bounds.origin += shadow.offset;
252− shadow_bounds.dilate(shadow.spread_radius);
253− cx.stack(0, |cx| {
254− let layer_id = cx.current_stacking_order();
255− cx.scene().insert(
256− layer_id,
257− Shadow {
258− order: 0,
259− bounds: shadow_bounds.scale(scale),
260− content_mask: content_mask.scale(scale),
261− corner_radii: self
262− .corner_radii
263− .to_pixels(shadow_bounds.size, rem_size)
264− .scale(scale),
265− color: shadow.color,
266− blur_radius: shadow.blur_radius.scale(scale),
267− },
268− );
269− })
270− }
246+
247+ cx.stack(0, |cx| {
248+ cx.paint_shadows(
249+ bounds,
250+ self.corner_radii.to_pixels(bounds.size, rem_size),
251+ &self.box_shadow,
252+ );
253+ });
271254
272255 let background_color = self.fill.as_ref().and_then(Fill::color);
273256 if background_color.is_some() || self.is_border_visible() {
274− let content_mask = cx.content_mask();
275257 cx.stack(1, |cx| {
276− let order = cx.current_stacking_order();
277− cx.scene().insert(
278− order,
279− Quad {
280− order: 0,
281− bounds: bounds.scale(scale),
282− content_mask: content_mask.scale(scale),
283− background: background_color.unwrap_or_default(),
284− border_color: self.border_color.unwrap_or_default(),
285− corner_radii: self
286− .corner_radii
287− .to_pixels(bounds.size, rem_size)
288− .scale(scale),
289− border_widths: self.border_widths.to_pixels(rem_size).scale(scale),
290− },
258+ cx.paint_quad(
259+ bounds,
260+ self.corner_radii.to_pixels(bounds.size, rem_size),
261+ background_color.unwrap_or_default(),
262+ self.border_widths.to_pixels(rem_size),
263+ self.border_color.unwrap_or_default(),
291264 );
292265 });
293266 }
crates/gpui3/src/window.rs+109−50
@@ -1,15 +1,17 @@
11 use crate::{
22 image_cache::RenderImageParams, px, size, AnyView, AppContext, AsyncWindowContext,
3− AvailableSpace, BorrowAppContext, Bounds, Context, Corners, DevicePixels, DisplayId, Effect,
4− Element, EntityId, FontId, GlyphId, Handle, Hsla, ImageData, IsZero, LayoutId, MainThread,
5− MainThreadOnly, MonochromeSprite, Pixels, PlatformAtlas, PlatformWindow, Point,
6− PolychromeSprite, Reference, RenderGlyphParams, RenderSvgParams, ScaledPixels, Scene,
7− SharedString, Size, StackingOrder, Style, TaffyLayoutEngine, Task, Underline, UnderlineStyle,
8− WeakHandle, WindowOptions, SUBPIXEL_VARIANTS,
3+ AvailableSpace, BorrowAppContext, Bounds, BoxShadow, Context, Corners, DevicePixels, DisplayId,
4+ Edges, Effect, Element, EntityId, FontId, GlyphId, Handle, Hsla, ImageData, IsZero, LayoutId,
5+ MainThread, MainThreadOnly, MonochromeSprite, Path, Pixels, PlatformAtlas, PlatformWindow,
6+ Point, PolychromeSprite, Quad, Reference, RenderGlyphParams, RenderSvgParams, ScaledPixels,
7+ SceneBuilder, Shadow, SharedString, Size, StackingOrder, Style, TaffyLayoutEngine, Task,
8+ Underline, UnderlineStyle, WeakHandle, WindowOptions, SUBPIXEL_VARIANTS,
99 };
1010 use anyhow::Result;
1111 use smallvec::SmallVec;
12−use std::{any::TypeId, borrow::Cow, future::Future, marker::PhantomData, mem, sync::Arc};
12+use std::{
13+ any::TypeId, borrow::Cow, fmt::Debug, future::Future, marker::PhantomData, mem, sync::Arc,
14+};
1315 use util::ResultExt;
1416
1517 pub struct AnyWindow {}
@@ -25,8 +27,9 @@ pub struct Window { · 9 unmodified lines
2527 pub(crate) root_view: Option<AnyView<()>>,
2628 mouse_position: Point<Pixels>,
2729 current_stacking_order: StackingOrder,
28− content_mask_stack: Vec<ContentMask>,
29− pub(crate) scene: Scene,
30+ content_mask_stack: Vec<ContentMask<Pixels>>,
31+ scale_factor: f32,
32+ pub(crate) scene_builder: SceneBuilder,
3033 pub(crate) dirty: bool,
3134 }
3235
@@ -47,7 +50,8 @@ impl Window { · 14 unmodified lines
4750 let cx = cx.to_async();
4851 move |content_size, scale_factor| {
4952 cx.update_window(handle, |cx| {
50− cx.window.scene = Scene::new(scale_factor);
53+ cx.window.scale_factor = scale_factor;
54+ cx.window.scene_builder = SceneBuilder::new();
5155 cx.window.content_size = content_size;
5256 cx.window.display_id = cx
5357 .window
@@ -75,20 +79,22 @@ impl Window { · 21 unmodified lines
7579 mouse_position,
7680 current_stacking_order: SmallVec::new(),
7781 content_mask_stack: Vec::new(),
78− scene: Scene::new(scale_factor),
82+ scale_factor,
83+ scene_builder: SceneBuilder::new(),
7984 dirty: true,
8085 }
8186 }
8287 }
8388
84−#[derive(Clone, Debug)]
85−pub struct ContentMask {
86− pub bounds: Bounds<Pixels>,
89+#[derive(Clone, Debug, Default, PartialEq, Eq)]
90+#[repr(C)]
91+pub struct ContentMask<P: Clone + Debug> {
92+ pub bounds: Bounds<P>,
8793 }
8894
89−impl ContentMask {
90− pub fn scale(&self, factor: f32) -> ScaledContentMask {
91− ScaledContentMask {
95+impl ContentMask<Pixels> {
96+ pub fn scale(&self, factor: f32) -> ContentMask<ScaledPixels> {
97+ ContentMask {
9298 bounds: self.bounds.scale(factor),
9399 }
94100 }
@@ -99,12 +105,6 @@ impl ContentMask { · 4 unmodified lines
99105 }
100106 }
101107
102−#[derive(Default, Clone, Debug, PartialEq, Eq)]
103−#[repr(C)]
104−pub struct ScaledContentMask {
105− bounds: Bounds<ScaledPixels>,
106−}
107−
108108 pub struct WindowContext<'a, 'w> {
109109 app: Reference<'a, AppContext>,
110110 window: Reference<'w, Window>,
@@ -234,7 +234,7 @@ impl<'a, 'w> WindowContext<'a, 'w> { · 123 unmodified lines
234234 }
235235
236236 pub fn scale_factor(&self) -> f32 {
237− self.window.scene.scale_factor
237+ self.window.scale_factor
238238 }
239239
240240 pub fn rem_size(&self) -> Pixels {
@@ -245,10 +245,6 @@ impl<'a, 'w> WindowContext<'a, 'w> { · 4 unmodified lines
245245 self.window.mouse_position
246246 }
247247
248− pub fn scene(&mut self) -> &mut Scene {
249− &mut self.window.scene
250− }
251−
252248 pub fn stack<R>(&mut self, order: u32, f: impl FnOnce(&mut Self) -> R) -> R {
253249 self.window.current_stacking_order.push(order);
254250 let result = f(self);
@@ -256,8 +252,69 @@ impl<'a, 'w> WindowContext<'a, 'w> { · 1 unmodified line
256252 result
257253 }
258254
259− pub fn current_stacking_order(&self) -> StackingOrder {
260− self.window.current_stacking_order.clone()
255+ pub fn paint_shadows(
256+ &mut self,
257+ bounds: Bounds<Pixels>,
258+ corner_radii: Corners<Pixels>,
259+ shadows: &[BoxShadow],
260+ ) {
261+ let scale_factor = self.scale_factor();
262+ let content_mask = self.content_mask();
263+ let window = &mut *self.window;
264+ for shadow in shadows {
265+ let mut shadow_bounds = bounds;
266+ shadow_bounds.origin += shadow.offset;
267+ shadow_bounds.dilate(shadow.spread_radius);
268+ window.scene_builder.insert(
269+ &window.current_stacking_order,
270+ Shadow {
271+ order: 0,
272+ bounds: shadow_bounds.scale(scale_factor),
273+ content_mask: content_mask.scale(scale_factor),
274+ corner_radii: corner_radii.scale(scale_factor),
275+ color: shadow.color,
276+ blur_radius: shadow.blur_radius.scale(scale_factor),
277+ },
278+ );
279+ }
280+ }
281+
282+ pub fn paint_quad(
283+ &mut self,
284+ bounds: Bounds<Pixels>,
285+ corner_radii: Corners<Pixels>,
286+ background: impl Into<Hsla>,
287+ border_widths: Edges<Pixels>,
288+ border_color: impl Into<Hsla>,
289+ ) {
290+ let scale_factor = self.scale_factor();
291+ let content_mask = self.content_mask();
292+
293+ let window = &mut *self.window;
294+ window.scene_builder.insert(
295+ &window.current_stacking_order,
296+ Quad {
297+ order: 0,
298+ bounds: bounds.scale(scale_factor),
299+ content_mask: content_mask.scale(scale_factor),
300+ background: background.into(),
301+ border_color: border_color.into(),
302+ corner_radii: corner_radii.scale(scale_factor),
303+ border_widths: border_widths.scale(scale_factor),
304+ },
305+ );
306+ }
307+
308+ pub fn paint_path(&mut self, mut path: Path<Pixels>) {
309+ let scale_factor = self.scale_factor();
310+ let content_mask = self.content_mask();
311+ for vertex in &mut path.vertices {
312+ vertex.content_mask = content_mask.clone();
313+ }
314+ let window = &mut *self.window;
315+ window
316+ .scene_builder
317+ .insert(&window.current_stacking_order, path.scale(scale_factor));
261318 }
262319
263320 pub fn paint_underline(
@@ -277,9 +334,9 @@ impl<'a, 'w> WindowContext<'a, 'w> { · 13 unmodified lines
277334 size: size(width, height),
278335 };
279336 let content_mask = self.content_mask();
280− let layer_id = self.current_stacking_order();
281− self.window.scene.insert(
282− layer_id,
337+ let window = &mut *self.window;
338+ window.scene_builder.insert(
339+ &window.current_stacking_order,
283340 Underline {
284341 order: 0,
285342 bounds: bounds.scale(scale_factor),
@@ -317,7 +374,6 @@ impl<'a, 'w> WindowContext<'a, 'w> { · 31 unmodified lines
317374
318375 let raster_bounds = self.text_system().raster_bounds(&params)?;
319376 if !raster_bounds.is_zero() {
320− let layer_id = self.current_stacking_order();
321377 let tile =
322378 self.window
323379 .sprite_atlas
@@ -330,9 +386,9 @@ impl<'a, 'w> WindowContext<'a, 'w> { · 6 unmodified lines
330386 size: tile.bounds.size.map(Into::into),
331387 };
332388 let content_mask = self.content_mask().scale(scale_factor);
333−
334− self.window.scene.insert(
335− layer_id,
389+ let window = &mut *self.window;
390+ window.scene_builder.insert(
391+ &window.current_stacking_order,
336392 MonochromeSprite {
337393 order: 0,
338394 bounds,
@@ -366,7 +422,6 @@ impl<'a, 'w> WindowContext<'a, 'w> { · 27 unmodified lines
366422
367423 let raster_bounds = self.text_system().raster_bounds(&params)?;
368424 if !raster_bounds.is_zero() {
369− let layer_id = self.current_stacking_order();
370425 let tile =
371426 self.window
372427 .sprite_atlas
@@ -379,9 +434,10 @@ impl<'a, 'w> WindowContext<'a, 'w> { · 6 unmodified lines
379434 size: tile.bounds.size.map(Into::into),
380435 };
381436 let content_mask = self.content_mask().scale(scale_factor);
437+ let window = &mut *self.window;
382438
383− self.window.scene.insert(
384− layer_id,
439+ window.scene_builder.insert(
440+ &window.current_stacking_order,
385441 PolychromeSprite {
386442 order: 0,
387443 bounds,
@@ -411,7 +467,6 @@ impl<'a, 'w> WindowContext<'a, 'w> { · 23 unmodified lines
411467 .map(|pixels| DevicePixels::from((pixels.0 * 2.).ceil() as i32)),
412468 };
413469
414− let layer_id = self.current_stacking_order();
415470 let tile =
416471 self.window
417472 .sprite_atlas
@@ -421,8 +476,9 @@ impl<'a, 'w> WindowContext<'a, 'w> { · 3 unmodified lines
421476 })?;
422477 let content_mask = self.content_mask().scale(scale_factor);
423478
424− self.window.scene.insert(
425− layer_id,
479+ let window = &mut *self.window;
480+ window.scene_builder.insert(
481+ &window.current_stacking_order,
426482 MonochromeSprite {
427483 order: 0,
428484 bounds,
@@ -446,7 +502,6 @@ impl<'a, 'w> WindowContext<'a, 'w> { · 17 unmodified lines
446502 let bounds = bounds.scale(scale_factor);
447503 let params = RenderImageParams { image_id: data.id };
448504
449− let order = self.current_stacking_order();
450505 let tile = self
451506 .window
452507 .sprite_atlas
@@ -456,8 +511,9 @@ impl<'a, 'w> WindowContext<'a, 'w> { · 3 unmodified lines
456511 let content_mask = self.content_mask().scale(scale_factor);
457512 let corner_radii = corner_radii.scale(scale_factor);
458513
459− self.window.scene.insert(
460− order,
514+ let window = &mut *self.window;
515+ window.scene_builder.insert(
516+ &window.current_stacking_order,
461517 PolychromeSprite {
462518 order: 0,
463519 bounds,
@@ -467,7 +523,6 @@ impl<'a, 'w> WindowContext<'a, 'w> { · 3 unmodified lines
467523 grayscale,
468524 },
469525 );
470−
471526 Ok(())
472527 }
473528
@@ -485,7 +540,7 @@ impl<'a, 'w> WindowContext<'a, 'w> { · 11 unmodified lines
485540
486541 root_view.paint(layout, &mut (), &mut frame_state, cx)?;
487542 cx.window.root_view = Some(root_view);
488− let scene = cx.window.scene.take();
543+ let scene = cx.window.scene_builder.build();
489544
490545 cx.run_on_main(view, |_, cx| {
491546 cx.window
@@ -557,7 +612,11 @@ pub trait BorrowWindow: BorrowAppContext { · 65 unmodified lines
557612 fn window(&self) -> &Window;
558613 fn window_mut(&mut self) -> &mut Window;
559614
560− fn with_content_mask<R>(&mut self, mask: ContentMask, f: impl FnOnce(&mut Self) -> R) -> R {
615+ fn with_content_mask<R>(
616+ &mut self,
617+ mask: ContentMask<Pixels>,
618+ f: impl FnOnce(&mut Self) -> R,
619+ ) -> R {
561620 let mask = mask.intersect(&self.content_mask());
562621 self.window_mut().content_mask_stack.push(mask);
563622 let result = f(self);
@@ -565,7 +624,7 @@ pub trait BorrowWindow: BorrowAppContext { · 1 unmodified line
565624 result
566625 }
567626
568− fn content_mask(&self) -> ContentMask {
627+ fn content_mask(&self) -> ContentMask<Pixels> {
569628 self.window()
570629 .content_mask_stack
571630 .last()

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t