egui/load/
texture_loader.rs

1use super::{
2    BytesLoader, Context, HashMap, ImagePoll, Mutex, SizeHint, SizedTexture, TextureHandle,
3    TextureLoadResult, TextureLoader, TextureOptions, TexturePoll,
4};
5
6#[derive(Default)]
7pub struct DefaultTextureLoader {
8    cache: Mutex<HashMap<(String, TextureOptions), TextureHandle>>,
9}
10
11impl TextureLoader for DefaultTextureLoader {
12    fn id(&self) -> &str {
13        crate::generate_loader_id!(DefaultTextureLoader)
14    }
15
16    fn load(
17        &self,
18        ctx: &Context,
19        uri: &str,
20        texture_options: TextureOptions,
21        size_hint: SizeHint,
22    ) -> TextureLoadResult {
23        let mut cache = self.cache.lock();
24        if let Some(handle) = cache.get(&(uri.into(), texture_options)) {
25            let texture = SizedTexture::from_handle(handle);
26            Ok(TexturePoll::Ready { texture })
27        } else {
28            match ctx.try_load_image(uri, size_hint)? {
29                ImagePoll::Pending { size } => Ok(TexturePoll::Pending { size }),
30                ImagePoll::Ready { image } => {
31                    let handle = ctx.load_texture(uri, image, texture_options);
32                    let texture = SizedTexture::from_handle(&handle);
33                    cache.insert((uri.into(), texture_options), handle);
34                    let reduce_texture_memory = ctx.options(|o| o.reduce_texture_memory);
35                    if reduce_texture_memory {
36                        let loaders = ctx.loaders();
37                        loaders.include.forget(uri);
38                        for loader in loaders.bytes.lock().iter().rev() {
39                            loader.forget(uri);
40                        }
41                        for loader in loaders.image.lock().iter().rev() {
42                            loader.forget(uri);
43                        }
44                    }
45                    Ok(TexturePoll::Ready { texture })
46                }
47            }
48        }
49    }
50
51    fn forget(&self, uri: &str) {
52        #[cfg(feature = "log")]
53        log::trace!("forget {uri:?}");
54
55        self.cache.lock().retain(|(u, _), _| u != uri);
56    }
57
58    fn forget_all(&self) {
59        #[cfg(feature = "log")]
60        log::trace!("forget all");
61
62        self.cache.lock().clear();
63    }
64
65    fn end_pass(&self, _: usize) {}
66
67    fn byte_size(&self) -> usize {
68        self.cache
69            .lock()
70            .values()
71            .map(|texture| texture.byte_size())
72            .sum()
73    }
74}