Skip to content

Commit 7e6e427

Browse files
authored
Render thumbnails with Vello (#4805)
1 parent a566448 commit 7e6e427

22 files changed

Lines changed: 698 additions & 381 deletions

File tree

‎Cargo.lock‎

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎editor/Cargo.toml‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ workspace = true
1515

1616
[features]
1717
default = ["gpu"]
18-
wasm = ["graphene-std/wasm", "interpreted-executor/wasm", "dep:wasm-bindgen"]
18+
wasm = ["graphene-std/wasm", "interpreted-executor/wasm", "dep:wasm-bindgen", "dep:wasm-bindgen-futures"]
1919
gpu = ["interpreted-executor/gpu", "dep:wgpu-executor"]
2020

2121
[dependencies]
@@ -64,6 +64,7 @@ wgpu-executor = { workspace = true, optional = true }
6464

6565
# Optional workspace dependencies
6666
wasm-bindgen = { workspace = true, optional = true }
67+
wasm-bindgen-futures = { workspace = true, optional = true }
6768

6869
[target.'cfg(not(target_family = "wasm"))'.dependencies]
6970
tokio = { workspace = true }

‎editor/src/messages/frontend/frontend_message.rs‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,19 @@ pub enum FrontendMessage {
332332
ClearNodeThumbnails {
333333
ids: Vec<NodeId>,
334334
},
335+
UpdateNodeThumbnailPixels {
336+
id: NodeId,
337+
width: u32,
338+
height: u32,
339+
pixels: serde_bytes::ByteBuf,
340+
},
341+
UpdateNodeThumbnailCanvases {
342+
id: NodeId,
343+
#[serde(rename = "layersPanelCanvasId")]
344+
layers_panel_canvas_id: u64,
345+
#[serde(rename = "nodeGraphCanvasId")]
346+
node_graph_canvas_id: u64,
347+
},
335348
UpdateOpenDocumentsList {
336349
#[serde(rename = "openDocuments")]
337350
open_documents: Vec<DocumentInfo>,

‎editor/src/messages/portfolio/document/utility_types/layers_in_view.rs‎

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ pub struct LayersInView {
1010
layers_panel: HashSet<NodeId>,
1111
/// The nodes in view in the node graph while it's open.
1212
node_graph: HashSet<NodeId>,
13-
/// The latest thumbnail of each layer, as rendered by the graph runtime.
14-
thumbnails: HashMap<NodeId, String>,
13+
/// The message with the latest thumbnail of each layer, as rendered by the graph runtime.
14+
thumbnails: HashMap<NodeId, FrontendMessage>,
1515
/// The layers whose latest thumbnail the frontend has.
1616
thumbnails_sent: HashSet<NodeId>,
1717
}
@@ -40,10 +40,17 @@ impl LayersInView {
4040
responses.add(PortfolioMessage::SubmitThumbnailsInView);
4141
}
4242

43-
/// Keeps a layer's newly rendered thumbnail, sending it to the frontend only if the layer is in view.
44-
pub fn receive_thumbnail(&mut self, layer: NodeId, thumbnail: String, responses: &mut VecDeque<Message>) {
43+
pub fn thumbnail_layer(message: &FrontendMessage) -> Option<NodeId> {
44+
match message {
45+
FrontendMessage::UpdateNodeThumbnail { id, .. } | FrontendMessage::UpdateNodeThumbnailCanvases { id, .. } | FrontendMessage::UpdateNodeThumbnailPixels { id, .. } => Some(*id),
46+
_ => None,
47+
}
48+
}
49+
50+
/// Keeps the message with a layer's newly rendered thumbnail, sending it to the frontend only if the layer is in view.
51+
pub fn receive_thumbnail(&mut self, layer: NodeId, thumbnail: FrontendMessage, responses: &mut VecDeque<Message>) {
4552
if self.in_view(&layer) {
46-
responses.add(FrontendMessage::UpdateNodeThumbnail { id: layer, value: thumbnail.clone() });
53+
responses.add(thumbnail.clone());
4754
self.thumbnails_sent.insert(layer);
4855
} else {
4956
// Out of view, the frontend's copy is now stale until the layer comes back into view
@@ -84,7 +91,7 @@ impl LayersInView {
8491
}
8592
let Some(thumbnail) = self.thumbnails.get(&layer) else { continue };
8693

87-
responses.add(FrontendMessage::UpdateNodeThumbnail { id: layer, value: thumbnail.clone() });
94+
responses.add(thumbnail.clone());
8895
self.thumbnails_sent.insert(layer);
8996
}
9097
}
@@ -94,6 +101,10 @@ impl LayersInView {
94101
mod tests {
95102
use super::*;
96103

104+
fn svg_thumbnail(layer: NodeId, svg: &str) -> FrontendMessage {
105+
FrontendMessage::UpdateNodeThumbnail { id: layer, value: svg.to_string() }
106+
}
107+
97108
fn thumbnails_sent(responses: VecDeque<Message>) -> Vec<(NodeId, String)> {
98109
responses
99110
.into_iter()
@@ -110,8 +121,8 @@ mod tests {
110121
let mut layers_in_view = LayersInView::default();
111122

112123
let mut responses = VecDeque::new();
113-
layers_in_view.receive_thumbnail(layer, "first".to_string(), &mut responses);
114-
layers_in_view.receive_thumbnail(layer, "latest".to_string(), &mut responses);
124+
layers_in_view.receive_thumbnail(layer, svg_thumbnail(layer, "first"), &mut responses);
125+
layers_in_view.receive_thumbnail(layer, svg_thumbnail(layer, "latest"), &mut responses);
115126
assert!(thumbnails_sent(responses).is_empty(), "out of view, a thumbnail isn't sent");
116127

117128
let mut responses = VecDeque::new();
@@ -130,12 +141,12 @@ mod tests {
130141

131142
let mut responses = VecDeque::new();
132143
layers_in_view.set_layers_panel(HashSet::from([layer]), &mut responses);
133-
layers_in_view.receive_thumbnail(layer, "in view".to_string(), &mut responses);
144+
layers_in_view.receive_thumbnail(layer, svg_thumbnail(layer, "in view"), &mut responses);
134145
assert_eq!(thumbnails_sent(responses), vec![(layer, "in view".to_string())], "in view, a thumbnail is sent as it's received");
135146

136147
let mut responses = VecDeque::new();
137148
layers_in_view.set_layers_panel(HashSet::new(), &mut responses);
138-
layers_in_view.receive_thumbnail(layer, "changed".to_string(), &mut responses);
149+
layers_in_view.receive_thumbnail(layer, svg_thumbnail(layer, "changed"), &mut responses);
139150
layers_in_view.set_layers_panel(HashSet::from([layer]), &mut responses);
140151
assert_eq!(thumbnails_sent(responses), vec![(layer, "changed".to_string())]);
141152
}
@@ -147,7 +158,7 @@ mod tests {
147158

148159
let mut responses = VecDeque::new();
149160
layers_in_view.set_layers_panel(HashSet::from([layer]), &mut responses);
150-
layers_in_view.receive_thumbnail(layer, "before".to_string(), &mut responses);
161+
layers_in_view.receive_thumbnail(layer, svg_thumbnail(layer, "before"), &mut responses);
151162

152163
let mut responses = VecDeque::new();
153164
layers_in_view.forget_thumbnails(&[layer, other_documents_layer], &mut responses);
@@ -163,7 +174,7 @@ mod tests {
163174
assert!(thumbnails_sent(responses).is_empty(), "a forgotten thumbnail isn't sent again");
164175

165176
let mut responses = VecDeque::new();
166-
layers_in_view.receive_thumbnail(layer, "after".to_string(), &mut responses);
177+
layers_in_view.receive_thumbnail(layer, svg_thumbnail(layer, "after"), &mut responses);
167178
assert_eq!(thumbnails_sent(responses), vec![(layer, "after".to_string())], "rendered anew, it's sent as before");
168179
}
169180
}

‎editor/src/node_graph_executor.rs‎

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::messages::frontend::utility_types::{ExportBounds, FileType, RasterizedImage, RenderStatus};
22
use crate::messages::portfolio::document::node_graph::utility_types::NodeEvaluationError;
3+
use crate::messages::portfolio::document::utility_types::layers_in_view::LayersInView;
34
use crate::messages::portfolio::document::utility_types::network_interface::InputConnector;
45
use crate::messages::prelude::*;
56
use glam::{DAffine2, DVec2, UVec2};
@@ -497,14 +498,14 @@ impl NodeGraphExecutor {
497498

498499
// Thumbnails reach the frontend only for the layers it shows in view
499500
for response in existing_responses {
500-
match response {
501-
FrontendMessage::UpdateNodeThumbnail { id, value } => {
501+
match LayersInView::thumbnail_layer(&response) {
502+
Some(layer) => {
502503
// A render finishing after a switch to another document has thumbnails of the previous one's layers
503504
if execution_context.document_id == document_id {
504-
document.layers_in_view.receive_thumbnail(id, value, responses);
505+
document.layers_in_view.receive_thumbnail(layer, response, responses);
505506
}
506507
}
507-
response => responses.add(response),
508+
None => responses.add(response),
508509
}
509510
}
510511
document.network_interface.update_vector_modify(vector_modify);
@@ -616,8 +617,9 @@ impl NodeGraphExecutor {
616617

617618
fn receive_thumbnails(document: &mut DocumentMessageHandler, thumbnails: VecDeque<FrontendMessage>, responses: &mut VecDeque<Message>) {
618619
for thumbnail in thumbnails {
619-
if let FrontendMessage::UpdateNodeThumbnail { id, value } = thumbnail {
620-
document.layers_in_view.receive_thumbnail(id, value, responses);
620+
match LayersInView::thumbnail_layer(&thumbnail) {
621+
Some(layer) => document.layers_in_view.receive_thumbnail(layer, thumbnail, responses),
622+
None => responses.add(thumbnail),
621623
}
622624
}
623625
}

0 commit comments

Comments
 (0)