Skip to main content

inset_embedder/scene/
layer.rs

1//! The nodes of a frame's layer tree, after the engine's `flow/layers`: containers that do one
2//! thing to their children, the pictures the framework recorded, the composition layers it
3//! places, and the video frames it draws.
4//!
5//! A node never changes once built: a container the framework retains is the same `Arc` in every
6//! scene that holds it, so a host compares it by pointer and a later frame walks it again. The
7//! invariant a later editor must keep: nothing here draws or composites; the drawing is the
8//! pictures', and what the containers do is replayed by whoever walks the tree (`slices.rs`).
9
10use std::fmt;
11use std::sync::Arc;
12
13use crate::composition::CompositionLayer;
14use crate::geometry::{Clip, Matrix4, Offset, RRect, Rect};
15use crate::media::VideoFrameReader;
16use crate::painting::{BlendMode, ImageFilter, Path, Picture};
17
18/// One node of a frame's layer tree: the engine's `flow::Layer`.
19#[derive(Clone, Debug)]
20pub enum Layer {
21    /// Children under one effect: what a `push_*` opens and `pop` closes, or a subtree a
22    /// previous frame built, added again.
23    Container(EngineLayer),
24    /// A recorded picture at an offset: flow's `DisplayListLayer`, from `add_picture`.
25    DisplayList(DisplayListLayer),
26    /// A composition layer at its place in paint order: flow's `PlatformViewLayer`, from
27    /// `add_embedded_layer`. It draws nothing; the host places the layer and makes room for it.
28    Embedded(EmbeddedLayer),
29    /// A video, drawn as part of the picture at its place in paint order: Chromium's
30    /// `cc::VideoLayer`, from `add_video`. The host supplies the frame when it draws.
31    Video(VideoLayer),
32}
33
34/// Two layers are equal when they are the same node or show the same: a container by pointer
35/// first, so a retained subtree compares at once.
36impl PartialEq for Layer {
37    fn eq(&self, other: &Layer) -> bool {
38        match (self, other) {
39            (Layer::Container(a), Layer::Container(b)) => Arc::ptr_eq(a, b) || a == b,
40            (Layer::DisplayList(a), Layer::DisplayList(b)) => a == b,
41            (Layer::Embedded(a), Layer::Embedded(b)) => a == b,
42            (Layer::Video(a), Layer::Video(b)) => a == b,
43            _ => false,
44        }
45    }
46}
47
48/// dart:ui's `EngineLayer`: a container of the tree, which [`pop`](crate::SceneBuilder::pop)
49/// returns and [`add_retained`](crate::SceneBuilder::add_retained) adds again, as the same node,
50/// while the framework's subtree has not changed.
51pub type EngineLayer = Arc<ContainerLayer>;
52
53/// flow's `ContainerLayer` and the containers derived from it: children in paint order, the
54/// bottom-most first, under one effect.
55#[derive(Debug, PartialEq)]
56pub struct ContainerLayer {
57    pub effect: Effect,
58    pub children: Vec<Layer>,
59}
60
61/// What a container does to its children: which of flow's containers it is.
62#[derive(Clone, Debug, PartialEq)]
63pub enum Effect {
64    /// flow's `ContainerLayer` itself, which does nothing: the scene's root.
65    None,
66    /// `TransformLayer`: the children's coordinates taken through the matrix. `push_transform`,
67    /// and `push_offset` as a translation.
68    Transform(Matrix4),
69    /// `ClipRectLayer`: nothing of the children outside the rectangle.
70    ClipRect { rect: Rect, clip_behavior: Clip },
71    /// `ClipRRectLayer`: nothing of the children outside the rounded rectangle.
72    ClipRRect { rrect: RRect, clip_behavior: Clip },
73    /// `ClipPathLayer`: nothing of the children outside the path, filled non-zero.
74    ClipPath {
75        path: Arc<Path>,
76        clip_behavior: Clip,
77    },
78    /// `OpacityLayer`: the children moved by `offset` and composited as one at `alpha`, out of
79    /// 255.
80    Opacity { alpha: u8, offset: Offset },
81    /// `BackdropFilterLayer`: what lies beneath filtered, then blended back with `blend_mode`,
82    /// before the children paint. Filters sharing a `backdrop_id` sample one backdrop.
83    BackdropFilter {
84        filter: ImageFilter,
85        blend_mode: BlendMode,
86        backdrop_id: Option<u64>,
87    },
88}
89
90/// flow's `DisplayListLayer`: a picture the framework recorded, drawn at `offset`.
91#[derive(Clone, Debug, PartialEq)]
92pub struct DisplayListLayer {
93    pub offset: Offset,
94    pub picture: Arc<Picture>,
95}
96
97/// flow's `PlatformViewLayer`, named after Flutter's embedded views: a composition layer the
98/// host composites, embedded in the frame at `rect` in its container's coordinates.
99#[derive(Clone)]
100pub struct EmbeddedLayer {
101    /// The producer's own handle, so a host reaches the native object behind it directly.
102    pub layer: Arc<dyn CompositionLayer>,
103    pub rect: Rect,
104}
105
106/// Two are equal when they put the same composition layer, by pointer, at the same place.
107impl PartialEq for EmbeddedLayer {
108    fn eq(&self, other: &EmbeddedLayer) -> bool {
109        Arc::ptr_eq(&self.layer, &other.layer) && self.rect == other.rect
110    }
111}
112
113impl fmt::Debug for EmbeddedLayer {
114    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115        f.debug_struct("EmbeddedLayer")
116            .field("layer", &Arc::as_ptr(&self.layer).cast::<()>())
117            .field("rect", &self.rect)
118            .finish()
119    }
120}
121
122/// A video, drawn into `rect` in its container's coordinates: Chromium's `cc::VideoLayer` over its
123/// frame provider. The layer holds the reader, never a frame: whoever draws the scene asks the
124/// reader then for the frame of the moment the picture reaches the screen, so a frame is held only
125/// while it is on screen.
126#[derive(Clone)]
127pub struct VideoLayer {
128    pub reader: Arc<dyn VideoFrameReader>,
129    pub rect: Rect,
130}
131
132/// Two are equal when they draw the same reader, by pointer, into the same place: a new frame of
133/// the reader is not a change of the scene.
134impl PartialEq for VideoLayer {
135    fn eq(&self, other: &VideoLayer) -> bool {
136        Arc::ptr_eq(&self.reader, &other.reader) && self.rect == other.rect
137    }
138}
139
140impl fmt::Debug for VideoLayer {
141    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
142        f.debug_struct("VideoLayer")
143            .field("reader", &Arc::as_ptr(&self.reader).cast::<()>())
144            .field("rect", &self.rect)
145            .finish()
146    }
147}