diff --git a/render-wasm/src/main.rs b/render-wasm/src/main.rs index 2d1b35bdfc..085511bc3f 100644 --- a/render-wasm/src/main.rs +++ b/render-wasm/src/main.rs @@ -192,6 +192,7 @@ pub extern "C" fn set_view(zoom: f32, x: f32, y: f32) { with_state_mut!(state, { let render_state = state.render_state_mut(); render_state.viewbox.set_all(zoom, x, y); + state.render_state.cancel_animation_frame(); state.render_from_cache(); }); } diff --git a/render-wasm/src/render.rs b/render-wasm/src/render.rs index a4d6b214d6..afc74c2d25 100644 --- a/render-wasm/src/render.rs +++ b/render-wasm/src/render.rs @@ -1515,6 +1515,8 @@ impl RenderState { } self.render_in_progress = false; + self.surfaces.gc(); + // Cache target surface in a texture self.cached_viewbox = self.viewbox; self.cached_target_snapshot = Some(self.surfaces.snapshot(SurfaceId::Cache)); diff --git a/render-wasm/src/render/surfaces.rs b/render-wasm/src/render/surfaces.rs index acb23ececc..4cc0caf675 100644 --- a/render-wasm/src/render/surfaces.rs +++ b/render-wasm/src/render/surfaces.rs @@ -6,7 +6,7 @@ use skia_safe::{self as skia, IRect, Paint, RRect}; use super::{gpu_state::GpuState, tiles::Tile, tiles::TileViewbox, tiles::TILE_SIZE}; use base64::{engine::general_purpose, Engine as _}; -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; const TEXTURES_CACHE_CAPACITY: usize = 512; const TEXTURES_BATCH_DELETE: usize = 32; @@ -322,17 +322,12 @@ impl Surfaces { self.tiles.has(tile) } - pub fn remove_cached_tile_surface( - &mut self, - tile: Tile, - rect: skia::Rect, - color: skia::Color, - ) -> bool { + pub fn remove_cached_tile_surface(&mut self, tile: Tile, rect: skia::Rect, color: skia::Color) { // Clear the specific tile area in the cache surface with color let mut paint = skia::Paint::default(); paint.set_color(color); self.cache.canvas().draw_rect(rect, &paint); - self.tiles.remove(tile) + self.tiles.remove(tile); } pub fn draw_cached_tile_surface(&mut self, tile: Tile, rect: skia::Rect, color: skia::Color) { @@ -352,24 +347,50 @@ impl Surfaces { self.tiles.clear(); self.cache.canvas().clear(color); } + + pub fn gc(&mut self) { + self.tiles.gc(); + } } pub struct TileTextureCache { grid: HashMap, + removed: HashSet, } impl TileTextureCache { pub fn new() -> Self { Self { - grid: HashMap::new(), + grid: HashMap::default(), + removed: HashSet::default(), } } pub fn has(&self, tile: Tile) -> bool { - self.grid.contains_key(&tile) + self.grid.contains_key(&tile) && !self.removed.contains(&tile) } - fn remove_list(&mut self, marked: Vec) { + fn gc(&mut self) { + // Make a real remove + for tile in self.removed.iter() { + self.grid.remove(tile); + } + } + + fn free_tiles(&mut self, tile_viewbox: &TileViewbox) { + let marked: Vec<_> = self + .grid + .iter_mut() + .filter_map(|(tile, _)| { + if !tile_viewbox.is_visible(tile) { + Some(*tile) + } else { + None + } + }) + .take(TEXTURES_BATCH_DELETE) + .collect(); + for tile in marked.iter() { self.grid.remove(tile); } @@ -377,21 +398,19 @@ impl TileTextureCache { pub fn add(&mut self, tile_viewbox: &TileViewbox, tile: &Tile, image: skia::Image) { if self.grid.len() > TEXTURES_CACHE_CAPACITY { - let marked: Vec<_> = self - .grid - .iter_mut() - .filter_map(|(tile, _)| { - if !tile_viewbox.is_visible(tile) { - Some(*tile) - } else { - None - } - }) - .take(TEXTURES_BATCH_DELETE) - .collect(); - self.remove_list(marked); + // First we try to remove the obsolete tiles + self.gc(); } + + if self.grid.len() > TEXTURES_CACHE_CAPACITY { + self.free_tiles(tile_viewbox); + } + self.grid.insert(*tile, image); + + if self.removed.contains(tile) { + self.removed.remove(tile); + } } pub fn get(&mut self, tile: Tile) -> Result<&mut skia::Image, String> { @@ -399,15 +418,13 @@ impl TileTextureCache { Ok(image) } - pub fn remove(&mut self, tile: Tile) -> bool { - if !self.grid.contains_key(&tile) { - return false; - } - self.grid.remove(&tile); - true + pub fn remove(&mut self, tile: Tile) { + self.removed.insert(tile); } pub fn clear(&mut self) { - self.grid.clear(); + for k in self.grid.keys() { + self.removed.insert(*k); + } } }