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