diff --git a/frontend/src/app/render_wasm/api.cljs b/frontend/src/app/render_wasm/api.cljs index 0eb0367e1e..d291566ae8 100644 --- a/frontend/src/app/render_wasm/api.cljs +++ b/frontend/src/app/render_wasm/api.cljs @@ -883,6 +883,9 @@ (defn set-view-box [prev-zoom zoom vbox] + ;; Enable fast mode at the start of pan/zoom interaction + ;; This will be disabled when render-finish fires (after debounce delay) + (h/call wasm/internal-module "_set_view_start") (h/call wasm/internal-module "_set_view" zoom (- (:x vbox)) (- (:y vbox))) (if (mth/close? prev-zoom zoom) diff --git a/render-wasm/src/main.rs b/render-wasm/src/main.rs index 68a318675e..4be07c56ec 100644 --- a/render-wasm/src/main.rs +++ b/render-wasm/src/main.rs @@ -235,9 +235,20 @@ pub extern "C" fn set_view(zoom: f32, x: f32, y: f32) { }); } +/// Called at the start of pan/zoom interaction to enable fast rendering mode. +/// In fast mode, expensive operations like shadows are skipped for better performance. +#[no_mangle] +pub extern "C" fn set_view_start() { + with_state_mut!(state, { + state.render_state.options.set_fast_mode(true); + }); +} + #[no_mangle] pub extern "C" fn set_view_end() { with_state_mut!(state, { + // Disable fast mode when interaction ends + state.render_state.options.set_fast_mode(false); // We can have renders in progress state.render_state.cancel_animation_frame(); if state.render_state.options.is_profile_rebuild_tiles() { diff --git a/render-wasm/src/options.rs b/render-wasm/src/options.rs index 37afacfc21..1267c900ea 100644 --- a/render-wasm/src/options.rs +++ b/render-wasm/src/options.rs @@ -1,2 +1,3 @@ pub const DEBUG_VISIBLE: u32 = 0x01; pub const PROFILE_REBUILD_TILES: u32 = 0x02; +pub const FAST_MODE: u32 = 0x04; diff --git a/render-wasm/src/render.rs b/render-wasm/src/render.rs index 2b3038999d..8f789fd663 100644 --- a/render-wasm/src/render.rs +++ b/render-wasm/src/render.rs @@ -1479,8 +1479,11 @@ impl RenderState { .surfaces .get_render_context_translation(self.render_area, scale); + // Skip expensive drop shadow rendering in fast mode (during pan/zoom) + let skip_shadows = self.options.is_fast_mode(); + // For text shapes, render drop shadow using text rendering logic - if !matches!(element.shape_type, Type::Text(_)) { + if !skip_shadows && !matches!(element.shape_type, Type::Text(_)) { // Shadow rendering technique: Two-pass approach for proper opacity handling // // The shadow rendering uses a two-pass technique to ensure that overlapping diff --git a/render-wasm/src/render/options.rs b/render-wasm/src/render/options.rs index 74fb1cf70c..7e87f9e80f 100644 --- a/render-wasm/src/render/options.rs +++ b/render-wasm/src/render/options.rs @@ -15,6 +15,20 @@ impl RenderOptions { self.flags & options::PROFILE_REBUILD_TILES == options::PROFILE_REBUILD_TILES } + /// Fast mode is enabled during interactive pan/zoom operations. + /// When active, expensive operations like shadows are skipped for better performance. + pub fn is_fast_mode(&self) -> bool { + self.flags & options::FAST_MODE == options::FAST_MODE + } + + pub fn set_fast_mode(&mut self, enabled: bool) { + if enabled { + self.flags |= options::FAST_MODE; + } else { + self.flags &= !options::FAST_MODE; + } + } + pub fn dpr(&self) -> f32 { self.dpr.unwrap_or(1.0) }