Detailed changes
@@ -206,7 +206,7 @@ impl Size<Length> {
}
}
-#[derive(Refineable, Clone, Default, Debug, PartialEq)]
+#[derive(Refineable, Clone, Default, Debug, Eq, PartialEq)]
#[refineable(debug)]
#[repr(C)]
pub struct Bounds<T: Clone + Debug> {
@@ -289,7 +289,7 @@ impl<T: Clone + Debug + PartialOrd + Add<T, Output = T>> Bounds<T> {
impl<T: Clone + Debug + Copy> Copy for Bounds<T> {}
-#[derive(Refineable, Clone, Default, Debug)]
+#[derive(Refineable, Clone, Default, Debug, Eq, PartialEq)]
#[refineable(debug)]
#[repr(C)]
pub struct Edges<T: Clone + Debug> {
@@ -396,7 +396,7 @@ impl Edges<AbsoluteLength> {
}
}
-#[derive(Refineable, Clone, Default, Debug)]
+#[derive(Refineable, Clone, Default, Debug, Eq, PartialEq)]
#[refineable(debug)]
#[repr(C)]
pub struct Corners<T: Clone + Debug> {
@@ -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<Key>: 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<DevicePixels>,
}
-#[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<etagere::AllocId> 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<Ordering> {
+ Some(self.cmp(other))
+ }
+}
pub trait PlatformInputHandler {
fn selected_text_range(&self) -> Option<Range<usize>>;
@@ -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(
@@ -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<DevicePixels>,
@@ -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<f32>;
@@ -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<Item = PrimitiveBatch> {
- 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<Item = &'a Quad>,
S: Iterator<Item = &'a MonochromeSprite>,
{
- next_batch_kind: Option<PrimitiveKind>,
quads: &'a [Quad],
sprites: &'a [MonochromeSprite],
quads_start: usize,
@@ -92,41 +92,52 @@ where
type Item = PrimitiveBatch<'a>;
fn next(&mut self) -> Option<Self::Item> {
- 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<S>,
) -> 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<PrimitiveKind>) -> Option<u32> {
- 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<std::cmp::Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
impl From<Quad> 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<std::cmp::Ordering> {
+ Some(self.cmp(other))
}
}
@@ -261,7 +271,3 @@ impl From<MonochromeSprite> for Primitive {
#[derive(Copy, Clone, Debug)]
pub struct AtlasId(pub(crate) usize);
-
-use collections::BTreeMap;
-use etagere::AllocId as TileId;
-use smallvec::SmallVec;
@@ -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,