feat: Lancsoz downsampler when target size is relatively too small
This commit is contained in:
parent
cc5ca1ce29
commit
511180679b
4 changed files with 233 additions and 2 deletions
|
|
@ -5,6 +5,8 @@ use crate::image::atlas::{self, Atlas};
|
|||
#[cfg(all(feature = "image", not(target_arch = "wasm32")))]
|
||||
use worker::Worker;
|
||||
|
||||
#[cfg(feature = "image")]
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
#[cfg(feature = "image")]
|
||||
use std::collections::HashMap;
|
||||
|
||||
|
|
@ -38,6 +40,9 @@ impl Cache {
|
|||
raster: Raster {
|
||||
cache: crate::image::raster::Cache::default(),
|
||||
pending: HashMap::new(),
|
||||
resampled: FxHashMap::default(),
|
||||
resampled_hits: FxHashSet::default(),
|
||||
should_trim: false,
|
||||
belt: wgpu::util::StagingBelt::new(
|
||||
device.clone(),
|
||||
2 * 1024 * 1024,
|
||||
|
|
@ -209,7 +214,9 @@ impl Cache {
|
|||
encoder: &mut wgpu::CommandEncoder,
|
||||
belt: &mut wgpu::util::StagingBelt,
|
||||
handle: &core::image::Handle,
|
||||
bounds: Size<f32>,
|
||||
) -> Option<(&atlas::Entry, &Arc<wgpu::BindGroup>)> {
|
||||
use crate::graphics::image::{downsample, downsample_target, load};
|
||||
use crate::image::raster::Memory;
|
||||
|
||||
self.receive();
|
||||
|
|
@ -223,6 +230,34 @@ impl Cache {
|
|||
None,
|
||||
)?;
|
||||
|
||||
if let Some(target) = downsample_target(memory.dimensions(), bounds) {
|
||||
let key = (handle.id(), target.width, target.height);
|
||||
|
||||
if !self.raster.resampled.contains_key(&key) {
|
||||
let image = memory.host().or_else(|| load(handle).ok())?;
|
||||
let image = downsample(&image, target);
|
||||
|
||||
let entry = self.atlas.upload(
|
||||
device,
|
||||
encoder,
|
||||
belt,
|
||||
target.width,
|
||||
target.height,
|
||||
&image,
|
||||
)?;
|
||||
|
||||
let _ = self.raster.resampled.insert(key, entry);
|
||||
self.raster.should_trim = true;
|
||||
}
|
||||
|
||||
let _ = self.raster.resampled_hits.insert(key);
|
||||
|
||||
return Some((
|
||||
self.raster.resampled.get(&key)?,
|
||||
self.atlas.bind_group(),
|
||||
));
|
||||
}
|
||||
|
||||
if let Memory::Device {
|
||||
entry, bind_group, ..
|
||||
} = memory
|
||||
|
|
@ -303,6 +338,23 @@ impl Cache {
|
|||
#[cfg(not(target_arch = "wasm32"))]
|
||||
self.worker.drop(_bind_group);
|
||||
});
|
||||
|
||||
if self.raster.should_trim {
|
||||
let hits = &self.raster.resampled_hits;
|
||||
let atlas = &mut self.atlas;
|
||||
|
||||
self.raster.resampled.retain(|key, entry| {
|
||||
let retain = hits.contains(key);
|
||||
|
||||
if !retain {
|
||||
atlas.remove(entry);
|
||||
}
|
||||
|
||||
retain
|
||||
});
|
||||
self.raster.resampled_hits.clear();
|
||||
self.raster.should_trim = false;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "svg")]
|
||||
|
|
@ -376,6 +428,9 @@ impl Drop for Cache {
|
|||
struct Raster {
|
||||
cache: crate::image::raster::Cache,
|
||||
pending: HashMap<core::image::Id, Vec<Callback>>,
|
||||
resampled: FxHashMap<(core::image::Id, u32, u32), atlas::Entry>,
|
||||
resampled_hits: FxHashSet<(core::image::Id, u32, u32)>,
|
||||
should_trim: bool,
|
||||
belt: wgpu::util::StagingBelt,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -267,7 +267,13 @@ impl State {
|
|||
clip_bounds,
|
||||
} => {
|
||||
if let Some((atlas_entry, bind_group)) = cache
|
||||
.upload_raster(device, encoder, belt, &image.handle)
|
||||
.upload_raster(
|
||||
device,
|
||||
encoder,
|
||||
belt,
|
||||
&image.handle,
|
||||
bounds.size() * scale,
|
||||
)
|
||||
{
|
||||
match atlas.as_mut() {
|
||||
None => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue