mirror of
https://github.com/penpot/penpot.git
synced 2025-12-11 22:14:05 +01:00
✨ Render WASM dashboard thumbnails
This commit is contained in:
@@ -1,8 +1,16 @@
|
||||
addToLibrary({
|
||||
wapi_requestAnimationFrame: function wapi_requestAnimationFrame() {
|
||||
return window.requestAnimationFrame(Module._process_animation_frame);
|
||||
if (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope) {
|
||||
setTimeout(Module._process_animation_frame);
|
||||
} else {
|
||||
return window.requestAnimationFrame(Module._process_animation_frame);
|
||||
}
|
||||
},
|
||||
wapi_cancelAnimationFrame: function wapi_cancelAnimationFrame(frameId) {
|
||||
return window.cancelAnimationFrame(frameId);
|
||||
if (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope) {
|
||||
clearTimeout(frameId);
|
||||
} else {
|
||||
return window.cancelAnimationFrame(frameId);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -149,6 +149,27 @@ pub extern "C" fn render(_: i32) {
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn render_sync() {
|
||||
with_state_mut!(state, {
|
||||
state.rebuild_tiles();
|
||||
state
|
||||
.render_sync(performance::get_time())
|
||||
.expect("Error rendering");
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn render_sync_shape(a: u32, b: u32, c: u32, d: u32) {
|
||||
with_state_mut!(state, {
|
||||
let id = uuid_from_u32_quartet(a, b, c, d);
|
||||
state.rebuild_tiles_from(Some(&id));
|
||||
state
|
||||
.render_sync_shape(&id, performance::get_time())
|
||||
.expect("Error rendering");
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn render_from_cache(_: i32) {
|
||||
with_state_mut!(state, {
|
||||
|
||||
@@ -867,7 +867,13 @@ impl RenderState {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start_render_loop(&mut self, tree: ShapesPoolRef, timestamp: i32) -> Result<(), String> {
|
||||
pub fn start_render_loop(
|
||||
&mut self,
|
||||
base_object: Option<&Uuid>,
|
||||
tree: ShapesPoolRef,
|
||||
timestamp: i32,
|
||||
sync_render: bool,
|
||||
) -> Result<(), String> {
|
||||
let scale = self.get_scale();
|
||||
self.tile_viewbox.update(self.viewbox, scale);
|
||||
|
||||
@@ -917,20 +923,27 @@ impl RenderState {
|
||||
self.current_tile = None;
|
||||
self.render_in_progress = true;
|
||||
self.apply_drawing_to_render_canvas(None);
|
||||
self.process_animation_frame(tree, timestamp)?;
|
||||
|
||||
if sync_render {
|
||||
self.render_shape_tree_sync(base_object, tree, timestamp)?;
|
||||
} else {
|
||||
self.process_animation_frame(base_object, tree, timestamp)?;
|
||||
}
|
||||
|
||||
performance::end_measure!("start_render_loop");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn process_animation_frame(
|
||||
&mut self,
|
||||
base_object: Option<&Uuid>,
|
||||
tree: ShapesPoolRef,
|
||||
timestamp: i32,
|
||||
) -> Result<(), String> {
|
||||
performance::begin_measure!("process_animation_frame");
|
||||
if self.render_in_progress {
|
||||
if tree.len() != 0 {
|
||||
self.render_shape_tree_partial(tree, timestamp)?;
|
||||
self.render_shape_tree_partial(base_object, tree, timestamp, true)?;
|
||||
} else {
|
||||
println!("Empty tree");
|
||||
}
|
||||
@@ -947,6 +960,22 @@ impl RenderState {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn render_shape_tree_sync(
|
||||
&mut self,
|
||||
base_object: Option<&Uuid>,
|
||||
tree: ShapesPoolRef,
|
||||
timestamp: i32,
|
||||
) -> Result<(), String> {
|
||||
if tree.len() != 0 {
|
||||
self.render_shape_tree_partial(base_object, tree, timestamp, false)?;
|
||||
} else {
|
||||
println!("Empty tree");
|
||||
}
|
||||
self.flush_and_submit();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn should_stop_rendering(&self, iteration: i32, timestamp: i32) -> bool {
|
||||
iteration % NODE_BATCH_THRESHOLD == 0
|
||||
@@ -1215,6 +1244,7 @@ impl RenderState {
|
||||
&mut self,
|
||||
tree: ShapesPoolRef,
|
||||
timestamp: i32,
|
||||
allow_stop: bool,
|
||||
) -> Result<(bool, bool), String> {
|
||||
let mut iteration = 0;
|
||||
let mut is_empty = true;
|
||||
@@ -1495,7 +1525,7 @@ impl RenderState {
|
||||
}
|
||||
|
||||
// We try to avoid doing too many calls to get_time
|
||||
if self.should_stop_rendering(iteration, timestamp) {
|
||||
if allow_stop && self.should_stop_rendering(iteration, timestamp) {
|
||||
return Ok((is_empty, true));
|
||||
}
|
||||
iteration += 1;
|
||||
@@ -1505,8 +1535,10 @@ impl RenderState {
|
||||
|
||||
pub fn render_shape_tree_partial(
|
||||
&mut self,
|
||||
base_object: Option<&Uuid>,
|
||||
tree: ShapesPoolRef,
|
||||
timestamp: i32,
|
||||
allow_stop: bool,
|
||||
) -> Result<(), String> {
|
||||
let mut should_stop = false;
|
||||
while !should_stop {
|
||||
@@ -1532,7 +1564,7 @@ impl RenderState {
|
||||
} else {
|
||||
performance::begin_measure!("render_shape_tree::uncached");
|
||||
let (is_empty, early_return) =
|
||||
self.render_shape_tree_partial_uncached(tree, timestamp)?;
|
||||
self.render_shape_tree_partial_uncached(tree, timestamp, allow_stop)?;
|
||||
|
||||
if early_return {
|
||||
return Ok(());
|
||||
@@ -1564,10 +1596,16 @@ impl RenderState {
|
||||
.canvas(SurfaceId::Current)
|
||||
.clear(self.background_color);
|
||||
|
||||
let Some(root) = tree.get(&Uuid::nil()) else {
|
||||
return Err(String::from("Root shape not found"));
|
||||
let root_ids = {
|
||||
if let Some(shape_id) = base_object {
|
||||
vec![*shape_id]
|
||||
} else {
|
||||
let Some(root) = tree.get(&Uuid::nil()) else {
|
||||
return Err(String::from("Root shape not found"));
|
||||
};
|
||||
root.children_ids(false)
|
||||
}
|
||||
};
|
||||
let root_ids = root.children_ids(false);
|
||||
|
||||
// If we finish processing every node rendering is complete
|
||||
// let's check if there are more pending nodes
|
||||
@@ -1711,13 +1749,19 @@ impl RenderState {
|
||||
performance::end_measure!("rebuild_tiles_shallow");
|
||||
}
|
||||
|
||||
pub fn rebuild_tiles(&mut self, tree: ShapesPoolRef) {
|
||||
pub fn rebuild_tiles_from(&mut self, tree: ShapesPoolRef, base_id: Option<&Uuid>) {
|
||||
performance::begin_measure!("rebuild_tiles");
|
||||
|
||||
self.tiles.invalidate();
|
||||
|
||||
let mut all_tiles = HashSet::<tiles::Tile>::new();
|
||||
let mut nodes = vec![Uuid::nil()];
|
||||
let mut nodes = {
|
||||
if let Some(base_id) = base_id {
|
||||
vec![*base_id]
|
||||
} else {
|
||||
vec![Uuid::nil()]
|
||||
}
|
||||
};
|
||||
|
||||
while let Some(shape_id) = nodes.pop() {
|
||||
if let Some(shape) = tree.get(&shape_id) {
|
||||
@@ -1737,7 +1781,6 @@ impl RenderState {
|
||||
for tile in all_tiles {
|
||||
self.remove_cached_tile(tile);
|
||||
}
|
||||
|
||||
performance::end_measure!("rebuild_tiles");
|
||||
}
|
||||
|
||||
|
||||
@@ -63,15 +63,27 @@ impl<'a> State<'a> {
|
||||
self.render_state.render_from_cache(&self.shapes);
|
||||
}
|
||||
|
||||
pub fn render_sync(&mut self, timestamp: i32) -> Result<(), String> {
|
||||
self.render_state
|
||||
.start_render_loop(None, &self.shapes, timestamp, true)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn render_sync_shape(&mut self, id: &Uuid, timestamp: i32) -> Result<(), String> {
|
||||
self.render_state
|
||||
.start_render_loop(Some(id), &self.shapes, timestamp, true)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn start_render_loop(&mut self, timestamp: i32) -> Result<(), String> {
|
||||
self.render_state
|
||||
.start_render_loop(&self.shapes, timestamp)?;
|
||||
.start_render_loop(None, &self.shapes, timestamp, false)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn process_animation_frame(&mut self, timestamp: i32) -> Result<(), String> {
|
||||
self.render_state
|
||||
.process_animation_frame(&self.shapes, timestamp)?;
|
||||
.process_animation_frame(None, &self.shapes, timestamp)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -162,7 +174,11 @@ impl<'a> State<'a> {
|
||||
}
|
||||
|
||||
pub fn rebuild_tiles(&mut self) {
|
||||
self.render_state.rebuild_tiles(&self.shapes);
|
||||
self.render_state.rebuild_tiles_from(&self.shapes, None);
|
||||
}
|
||||
|
||||
pub fn rebuild_tiles_from(&mut self, base_id: Option<&Uuid>) {
|
||||
self.render_state.rebuild_tiles_from(&self.shapes, base_id);
|
||||
}
|
||||
|
||||
pub fn rebuild_touched_tiles(&mut self) {
|
||||
|
||||
Reference in New Issue
Block a user