iced_wgpu/image/
raster.rs
1use crate::core::Size;
2use crate::core::image;
3use crate::graphics;
4use crate::graphics::image::image_rs;
5use crate::image::atlas::{self, Atlas};
6
7use rustc_hash::{FxHashMap, FxHashSet};
8
9#[derive(Debug)]
11pub enum Memory {
12 Host(image_rs::ImageBuffer<image_rs::Rgba<u8>, image::Bytes>),
14 Device(atlas::Entry),
16 NotFound,
18 Invalid,
20}
21
22impl Memory {
23 pub fn dimensions(&self) -> Size<u32> {
25 match self {
26 Memory::Host(image) => {
27 let (width, height) = image.dimensions();
28
29 Size::new(width, height)
30 }
31 Memory::Device(entry) => entry.size(),
32 Memory::NotFound => Size::new(1, 1),
33 Memory::Invalid => Size::new(1, 1),
34 }
35 }
36}
37
38#[derive(Debug, Default)]
40pub struct Cache {
41 map: FxHashMap<image::Id, Memory>,
42 hits: FxHashSet<image::Id>,
43 should_trim: bool,
44}
45
46impl Cache {
47 pub fn load(&mut self, handle: &image::Handle) -> &mut Memory {
49 if self.contains(handle) {
50 return self.get(handle).unwrap();
51 }
52
53 let memory = match graphics::image::load(handle) {
54 Ok(image) => Memory::Host(image),
55 Err(image_rs::error::ImageError::IoError(_)) => Memory::NotFound,
56 Err(_) => Memory::Invalid,
57 };
58
59 self.should_trim = true;
60
61 self.insert(handle, memory);
62 self.get(handle).unwrap()
63 }
64
65 pub fn upload(
67 &mut self,
68 device: &wgpu::Device,
69 encoder: &mut wgpu::CommandEncoder,
70 handle: &image::Handle,
71 atlas: &mut Atlas,
72 ) -> Option<&atlas::Entry> {
73 let memory = self.load(handle);
74
75 if let Memory::Host(image) = memory {
76 let (width, height) = image.dimensions();
77
78 let entry = atlas.upload(device, encoder, width, height, image)?;
79
80 *memory = Memory::Device(entry);
81 }
82
83 if let Memory::Device(allocation) = memory {
84 Some(allocation)
85 } else {
86 None
87 }
88 }
89
90 pub fn trim(&mut self, atlas: &mut Atlas) {
92 if !self.should_trim {
94 return;
95 }
96
97 let hits = &self.hits;
98
99 self.map.retain(|k, memory| {
100 let retain = hits.contains(k);
101
102 if !retain {
103 if let Memory::Device(entry) = memory {
104 atlas.remove(entry);
105 }
106 }
107
108 retain
109 });
110
111 self.hits.clear();
112 self.should_trim = false;
113 }
114
115 fn get(&mut self, handle: &image::Handle) -> Option<&mut Memory> {
116 let _ = self.hits.insert(handle.id());
117
118 self.map.get_mut(&handle.id())
119 }
120
121 fn insert(&mut self, handle: &image::Handle, memory: Memory) {
122 let _ = self.map.insert(handle.id(), memory);
123 }
124
125 fn contains(&self, handle: &image::Handle) -> bool {
126 self.map.contains_key(&handle.id())
127 }
128}