From 2b6d041cb62ebdb5a0f3ff0d5e7b223be731e917 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 3 Oct 2023 17:36:12 +0200 Subject: [PATCH] Checkpoint --- crates/gpui3/src/geometry.rs | 6 +- crates/gpui3/src/platform.rs | 27 ++- crates/gpui3/src/platform/mac/metal_atlas.rs | 2 +- .../gpui3/src/platform/mac/metal_renderer.rs | 10 +- crates/gpui3/src/scene.rs | 160 +++++++++--------- crates/gpui3/src/style.rs | 3 +- 6 files changed, 121 insertions(+), 87 deletions(-) diff --git a/crates/gpui3/src/geometry.rs b/crates/gpui3/src/geometry.rs index 5f92c927bdeca0e57824a84c8c06532f140033bb..87b11a6cb3984fa80bfaa13ea62b11ece61798cc 100644 --- a/crates/gpui3/src/geometry.rs +++ b/crates/gpui3/src/geometry.rs @@ -206,7 +206,7 @@ impl Size { } } -#[derive(Refineable, Clone, Default, Debug, PartialEq)] +#[derive(Refineable, Clone, Default, Debug, Eq, PartialEq)] #[refineable(debug)] #[repr(C)] pub struct Bounds { @@ -289,7 +289,7 @@ impl> Bounds { impl Copy for Bounds {} -#[derive(Refineable, Clone, Default, Debug)] +#[derive(Refineable, Clone, Default, Debug, Eq, PartialEq)] #[refineable(debug)] #[repr(C)] pub struct Edges { @@ -396,7 +396,7 @@ impl Edges { } } -#[derive(Refineable, Clone, Default, Debug)] +#[derive(Refineable, Clone, Default, Debug, Eq, PartialEq)] #[refineable(debug)] #[repr(C)] pub struct Corners { diff --git a/crates/gpui3/src/platform.rs b/crates/gpui3/src/platform.rs index e7e7e4a4fb69c1893b68eb21615d8121343aafc2..2c81cb4fbba8cf94b9a4af203cc06aae5d130b46 100644 --- a/crates/gpui3/src/platform.rs +++ b/crates/gpui3/src/platform.rs @@ -14,6 +14,7 @@ use async_task::Runnable; use futures::channel::oneshot; use seahash::SeaHasher; use serde::{Deserialize, Serialize}; +use std::cmp::Ordering; use std::ffi::c_void; use std::hash::{Hash, Hasher}; use std::{ @@ -187,7 +188,7 @@ pub trait PlatformAtlas: Send + Sync { fn clear(&self); } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq, Eq)] #[repr(C)] pub struct AtlasTile { pub(crate) texture_id: AtlasTextureId, @@ -195,11 +196,31 @@ pub struct AtlasTile { pub(crate) bounds_in_atlas: Bounds, } -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[repr(C)] pub(crate) struct AtlasTextureId(pub(crate) usize); -pub(crate) type TileId = etagere::AllocId; +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[repr(C)] +pub(crate) struct TileId(pub(crate) etagere::AllocId); + +impl From for TileId { + fn from(id: etagere::AllocId) -> Self { + Self(id) + } +} + +impl Ord for TileId { + fn cmp(&self, other: &Self) -> Ordering { + self.0.serialize().cmp(&other.0.serialize()) + } +} + +impl PartialOrd for TileId { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} pub trait PlatformInputHandler { fn selected_text_range(&self) -> Option>; diff --git a/crates/gpui3/src/platform/mac/metal_atlas.rs b/crates/gpui3/src/platform/mac/metal_atlas.rs index 4e3d661670bea7aeceefe1f844ef76c97e03a192..db1347e5572e3aa65cb944b15249ba80a29520dc 100644 --- a/crates/gpui3/src/platform/mac/metal_atlas.rs +++ b/crates/gpui3/src/platform/mac/metal_atlas.rs @@ -119,7 +119,7 @@ impl MetalAtlasTexture { let allocation = self.allocator.allocate(size)?; let tile = AtlasTile { texture_id: self.id, - tile_id: allocation.id, + tile_id: allocation.id.into(), bounds_in_atlas: allocation.rectangle.into(), }; let region = metal::MTLRegion::new_2d( diff --git a/crates/gpui3/src/platform/mac/metal_renderer.rs b/crates/gpui3/src/platform/mac/metal_renderer.rs index 56c0f130810f32f4eed3cb0605f3a9fb4737e718..a7d81e24afad850193bbf4f3dd4bb2471aebde97 100644 --- a/crates/gpui3/src/platform/mac/metal_renderer.rs +++ b/crates/gpui3/src/platform/mac/metal_renderer.rs @@ -1,5 +1,6 @@ use crate::{ - point, size, DevicePixels, MetalAtlas, MonochromeSprite, Quad, RasterizedGlyphId, Scene, Size, + point, size, AtlasTextureId, DevicePixels, MetalAtlas, MonochromeSprite, Quad, + RasterizedGlyphId, Scene, Size, }; use bytemuck::{Pod, Zeroable}; use cocoa::{ @@ -186,8 +187,12 @@ impl MetalRenderer { command_encoder, ); } - crate::PrimitiveBatch::Sprites(sprites) => { + crate::PrimitiveBatch::Sprites { + texture_id, + sprites, + } => { self.draw_monochrome_sprites( + texture_id, sprites, &mut instance_offset, viewport_size, @@ -270,6 +275,7 @@ impl MetalRenderer { fn draw_monochrome_sprites( &mut self, + texture_id: AtlasTextureId, monochrome: &[MonochromeSprite], offset: &mut usize, viewport_size: Size, diff --git a/crates/gpui3/src/scene.rs b/crates/gpui3/src/scene.rs index 00882097916b096b3b9210f715cd01d8da9873d7..8ccbd45ff350094dfe11b636abd67acef3837f3a 100644 --- a/crates/gpui3/src/scene.rs +++ b/crates/gpui3/src/scene.rs @@ -1,8 +1,10 @@ use std::{iter::Peekable, mem}; use super::{Bounds, Hsla, Pixels, Point}; -use crate::{AtlasTile, Corners, DevicePixels, Edges}; +use crate::{AtlasTextureId, AtlasTile, Corners, Edges}; use bytemuck::{Pod, Zeroable}; +use collections::BTreeMap; +use smallvec::SmallVec; // Exported to metal pub type PointF = Point; @@ -38,8 +40,7 @@ impl Scene { quad.scale(self.scale_factor); layer.quads.push(quad); } - Primitive::Sprite(mut sprite) => { - sprite.scale(self.scale_factor); + Primitive::Sprite(sprite) => { layer.sprites.push(sprite); } } @@ -58,8 +59,8 @@ pub(crate) struct SceneLayer { impl SceneLayer { pub fn batches(&mut self) -> impl Iterator { - self.quads.sort_unstable_by(|a, b| a.order.cmp(&b.order)); - self.sprites.sort_unstable_by(|a, b| a.order.cmp(&b.order)); + self.quads.sort_unstable(); + self.sprites.sort_unstable(); BatchIterator::new( &self.quads, @@ -75,7 +76,6 @@ where Q: Iterator, S: Iterator, { - next_batch_kind: Option, quads: &'a [Quad], sprites: &'a [MonochromeSprite], quads_start: usize, @@ -92,41 +92,52 @@ where type Item = PrimitiveBatch<'a>; fn next(&mut self) -> Option { - if let Some(batch_kind) = self.next_batch_kind.take() { - match batch_kind { - PrimitiveKind::Quad => { - let max_order = self - .next_order(Some(PrimitiveKind::Quad)) - .unwrap_or(u32::MAX); - let quads_start = self.quads_start; - let quads_end = quads_start - + self - .quads_iter - .by_ref() - .take_while(|quad| quad.order <= max_order) - .count(); - self.quads_start = quads_end; - Some(PrimitiveBatch::Quads(&self.quads[quads_start..quads_end])) - } - PrimitiveKind::Sprite => { - let max_order = self - .next_order(Some(PrimitiveKind::Sprite)) - .unwrap_or(u32::MAX); - let sprites_start = self.sprites_start; - let sprites_end = sprites_start - + self - .sprites_iter - .by_ref() - .take_while(|sprite| sprite.order <= max_order) - .count(); - self.sprites_start = sprites_end; - Some(PrimitiveBatch::Sprites( - &self.sprites[sprites_start..sprites_end], - )) - } - } + let mut kinds_and_orders = [ + (PrimitiveKind::Quad, self.quads_iter.peek().map(|q| q.order)), + ( + PrimitiveKind::Sprite, + self.sprites_iter.peek().map(|s| s.order), + ), + ]; + kinds_and_orders.sort_by_key(|(_, order)| order.unwrap_or(u32::MAX)); + + let first = kinds_and_orders[0]; + let second = kinds_and_orders[1]; + let (batch_kind, max_order) = if first.1.is_some() { + (first.0, second.1.unwrap_or(u32::MAX)) } else { - None + return None; + }; + + match batch_kind { + PrimitiveKind::Quad => { + let quads_start = self.quads_start; + let quads_end = quads_start + + self + .quads_iter + .by_ref() + .take_while(|quad| quad.order <= max_order) + .count(); + self.quads_start = quads_end; + Some(PrimitiveBatch::Quads(&self.quads[quads_start..quads_end])) + } + PrimitiveKind::Sprite => { + let texture_id = self.sprites_iter.peek().unwrap().tile.texture_id; + let sprites_start = self.sprites_start; + let sprites_end = sprites_start + + self + .sprites_iter + .by_ref() + .take_while(|sprite| { + sprite.order <= max_order && sprite.tile.texture_id == texture_id + }) + .count(); + self.sprites_start = sprites_end; + Some(PrimitiveBatch::Sprites { + texture_id, + sprites: &self.sprites[sprites_start..sprites_end], + }) + } } } } @@ -142,39 +153,14 @@ where sprites: &'a [MonochromeSprite], sprites_iter: Peekable, ) -> Self { - let mut this = Self { + Self { quads, quads_start: 0, quads_iter, sprites, sprites_start: 0, sprites_iter, - next_batch_kind: None, - }; - this.next_order(None); // Called for its side effect of setting this.next_batch_kind - this - } - - fn next_order(&mut self, exclude_kind: Option) -> Option { - let mut next_order = u32::MAX; - - if exclude_kind != Some(PrimitiveKind::Quad) { - if let Some(next_quad) = self.quads_iter.peek() { - self.next_batch_kind = Some(PrimitiveKind::Quad); - next_order = next_quad.order; - } } - - if exclude_kind != Some(PrimitiveKind::Sprite) { - if let Some(next_sprite) = self.sprites_iter.peek() { - if next_sprite.order < next_order { - self.next_batch_kind = Some(PrimitiveKind::Sprite); - next_order = next_sprite.order; - } - } - } - - (next_order < u32::MAX).then_some(next_order) } } @@ -190,12 +176,15 @@ pub enum Primitive { Sprite(MonochromeSprite), } -pub enum PrimitiveBatch<'a> { +pub(crate) enum PrimitiveBatch<'a> { Quads(&'a [Quad]), - Sprites(&'a [MonochromeSprite]), + Sprites { + texture_id: AtlasTextureId, + sprites: &'a [MonochromeSprite], + }, } -#[derive(Debug, Copy, Clone, Zeroable, Pod)] +#[derive(Debug, Copy, Clone, Zeroable, Pod, Eq, PartialEq)] #[repr(C)] pub struct Quad { pub order: u32, @@ -232,13 +221,25 @@ impl Quad { } } +impl Ord for Quad { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.order.cmp(&other.order) + } +} + +impl PartialOrd for Quad { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + impl From for Primitive { fn from(quad: Quad) -> Self { Primitive::Quad(quad) } } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Eq, PartialEq)] #[repr(C)] pub struct MonochromeSprite { pub order: u32, @@ -247,9 +248,18 @@ pub struct MonochromeSprite { pub tile: AtlasTile, } -impl MonochromeSprite { - pub fn scale(&mut self, factor: f32) { - self.bounds *= factor; +impl Ord for MonochromeSprite { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + match self.order.cmp(&other.order) { + std::cmp::Ordering::Equal => self.tile.tile_id.cmp(&other.tile.tile_id), + order => order, + } + } +} + +impl PartialOrd for MonochromeSprite { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) } } @@ -261,7 +271,3 @@ impl From for Primitive { #[derive(Copy, Clone, Debug)] pub struct AtlasId(pub(crate) usize); - -use collections::BTreeMap; -use etagere::AllocId as TileId; -use smallvec::SmallVec; diff --git a/crates/gpui3/src/style.rs b/crates/gpui3/src/style.rs index f972b2ead3a436504962930b666ae0375466ea10..aae76349c6e92811b59ff0caaae9ad28f7be43b9 100644 --- a/crates/gpui3/src/style.rs +++ b/crates/gpui3/src/style.rs @@ -185,8 +185,9 @@ impl Style { let background_color = self.fill.as_ref().and_then(Fill::color); if background_color.is_some() || self.is_border_visible() { + let layer_id = cx.current_layer_id(); cx.scene().insert( - todo!(), + layer_id, Quad { order, bounds,