mirror of
https://github.com/penpot/penpot.git
synced 2025-02-23 23:35:58 -05:00
Merge pull request #5827 from penpot/superalex-fix-wasm-glitches
🐛 Fix wasm glitches
This commit is contained in:
commit
39bbb4c2bd
5 changed files with 68 additions and 14 deletions
|
@ -18,7 +18,6 @@
|
|||
[app.main.render :as render]
|
||||
[app.render-wasm.helpers :as h]
|
||||
[app.util.debug :as dbg]
|
||||
[app.util.functions :as fns]
|
||||
[app.util.http :as http]
|
||||
[app.util.webapi :as wapi]
|
||||
[beicon.v2.core :as rx]
|
||||
|
@ -522,13 +521,13 @@
|
|||
(h/call internal-module "_add_shape_shadow" rgba blur spread x y (translate-shadow-style style) hidden)
|
||||
(recur (inc index)))))))
|
||||
|
||||
(def debounce-render (fns/debounce render 100))
|
||||
|
||||
(defn set-view-box
|
||||
[zoom vbox]
|
||||
(h/call internal-module "_set_view" zoom (- (:x vbox)) (- (:y vbox)))
|
||||
(h/call internal-module "_render_from_cache")
|
||||
(debounce-render))
|
||||
(render nil))
|
||||
|
||||
(defn clear-cache []
|
||||
(h/call internal-module "_clear_cache"))
|
||||
|
||||
(defn set-objects
|
||||
[objects]
|
||||
|
@ -589,6 +588,7 @@
|
|||
(let [pending' (concat (set-shape-fills fills) (set-shape-strokes strokes))]
|
||||
(recur (inc index) (into pending pending'))))
|
||||
pending))]
|
||||
(clear-cache)
|
||||
(request-render "set-objects")
|
||||
(when-let [pending (seq pending)]
|
||||
(->> (rx/from pending)
|
||||
|
|
|
@ -142,6 +142,7 @@
|
|||
;; when something synced with wasm
|
||||
;; is modified, we need to request
|
||||
;; a new render.
|
||||
(api/clear-cache)
|
||||
(api/request-render "set-wasm-attrs")))
|
||||
|
||||
(defn- impl-assoc
|
||||
|
|
|
@ -47,6 +47,13 @@ pub extern "C" fn clean_up() {
|
|||
mem::free_bytes();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn clear_cache() {
|
||||
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
|
||||
let render_state = state.render_state();
|
||||
render_state.clear_cache();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn set_render_options(debug: u32, dpr: f32) {
|
||||
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
|
||||
|
@ -98,7 +105,9 @@ pub extern "C" fn resize_viewbox(width: i32, height: i32) {
|
|||
#[no_mangle]
|
||||
pub extern "C" fn set_view(zoom: f32, x: f32, y: f32) {
|
||||
let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer");
|
||||
state.render_state().viewbox.set_all(zoom, x, y);
|
||||
let render_state = state.render_state();
|
||||
render_state.invalidate_cache_if_needed();
|
||||
render_state.viewbox.set_all(zoom, x, y);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use skia::Contains;
|
||||
use skia_safe as skia;
|
||||
use std::collections::HashMap;
|
||||
use uuid::Uuid;
|
||||
|
@ -71,6 +72,7 @@ pub(crate) struct RenderState {
|
|||
pub render_in_progress: bool,
|
||||
// Stack of nodes pending to be rendered.
|
||||
pub pending_nodes: Vec<NodeRenderState>,
|
||||
pub render_complete: bool,
|
||||
}
|
||||
|
||||
impl RenderState {
|
||||
|
@ -112,6 +114,7 @@ impl RenderState {
|
|||
render_request_id: None,
|
||||
render_in_progress: false,
|
||||
pending_nodes: vec![],
|
||||
render_complete: true,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -236,6 +239,12 @@ impl RenderState {
|
|||
.clear(skia::Color::TRANSPARENT);
|
||||
}
|
||||
|
||||
pub fn invalidate_cache_if_needed(&mut self) {
|
||||
if let Some(ref mut cached_surface_image) = self.cached_surface_image {
|
||||
cached_surface_image.invalidate_if_dirty(&self.viewbox);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_shape(
|
||||
&mut self,
|
||||
shape: &mut Shape,
|
||||
|
@ -325,6 +334,7 @@ impl RenderState {
|
|||
}];
|
||||
self.render_in_progress = true;
|
||||
self.process_animation_frame(tree, modifiers, timestamp)?;
|
||||
self.render_complete = true;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -359,22 +369,41 @@ impl RenderState {
|
|||
}
|
||||
|
||||
// self.render_in_progress can have changed
|
||||
if !self.render_in_progress {
|
||||
if self.render_in_progress {
|
||||
if self.cached_surface_image.is_some() {
|
||||
self.render_from_cache()?;
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Chech if cached_surface_image is not set or is invalid
|
||||
if self
|
||||
.cached_surface_image
|
||||
.as_ref()
|
||||
.map_or(true, |img| img.invalid)
|
||||
{
|
||||
self.cached_surface_image = Some(CachedSurfaceImage {
|
||||
image: self.render_surface.image_snapshot(),
|
||||
viewbox: self.viewbox,
|
||||
invalid: false,
|
||||
has_all_shapes: self.render_complete,
|
||||
});
|
||||
if self.options.is_debug_visible() {
|
||||
self.render_debug();
|
||||
}
|
||||
|
||||
debug::render_wasm_label(self);
|
||||
self.apply_render_to_final_canvas();
|
||||
self.flush();
|
||||
}
|
||||
|
||||
if self.options.is_debug_visible() {
|
||||
self.render_debug();
|
||||
}
|
||||
|
||||
debug::render_wasm_label(self);
|
||||
self.apply_render_to_final_canvas();
|
||||
self.flush();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn clear_cache(&mut self) {
|
||||
self.cached_surface_image = None;
|
||||
}
|
||||
|
||||
pub fn render_from_cache(&mut self) -> Result<(), String> {
|
||||
let cached = self
|
||||
.cached_surface_image
|
||||
|
@ -397,6 +426,7 @@ impl RenderState {
|
|||
navigate_x * self.options.dpr(),
|
||||
navigate_y * self.options.dpr(),
|
||||
));
|
||||
self.final_surface.canvas().clear(self.background_color);
|
||||
self.final_surface
|
||||
.canvas()
|
||||
.draw_image(image, (0, 0), Some(&paint));
|
||||
|
@ -437,6 +467,7 @@ impl RenderState {
|
|||
.to_string(),
|
||||
)?;
|
||||
|
||||
let render_complete = self.viewbox.area.contains(element.bounds());
|
||||
if visited_children {
|
||||
if !visited_mask {
|
||||
match element.kind {
|
||||
|
@ -488,6 +519,7 @@ impl RenderState {
|
|||
if !node_render_state.id.is_nil() {
|
||||
if !element.bounds().intersects(self.viewbox.area) || element.hidden() {
|
||||
debug::render_debug_shape(self, element, false);
|
||||
self.render_complete = render_complete;
|
||||
continue;
|
||||
} else {
|
||||
debug::render_debug_shape(self, element, true);
|
||||
|
|
|
@ -1,6 +1,18 @@
|
|||
use super::{Image, Viewbox};
|
||||
use skia::Contains;
|
||||
use skia_safe as skia;
|
||||
|
||||
pub(crate) struct CachedSurfaceImage {
|
||||
pub image: Image,
|
||||
pub viewbox: Viewbox,
|
||||
pub invalid: bool,
|
||||
pub has_all_shapes: bool,
|
||||
}
|
||||
|
||||
impl CachedSurfaceImage {
|
||||
pub fn invalidate_if_dirty(&mut self, viewbox: &Viewbox) {
|
||||
if !self.has_all_shapes && !self.viewbox.area.contains(viewbox.area) {
|
||||
self.invalid = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue