egui/load/
texture_loader.rs

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