1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
use crate::uses::{prefetch::*, *}; use crate::GL::{atlas, tex::*, uImage}; #[derive(Debug)] pub struct VTex2d<S: TexSize, F: TexFmt> { pub region: Vec4, pub tex: Rc<Tex2d<S, F>>, } impl<S: TexSize, F: TexFmt> PartialEq for VTex2d<S, F> { fn eq(&self, r: &Self) -> bool { let Self { region, tex } = self; Rc::ptr_eq(tex, &r.tex) && *region == r.region } } impl<S: TexSize, F: TexFmt> Eq for VTex2d<S, F> {} impl<S: TexSize, F: TexFmt> Clone for VTex2d<S, F> { fn clone(&self) -> Self { let VTex2d { region, tex } = self; let (region, tex) = (*region, tex.clone()); VTex2d { region, tex } } } pub type AtlasTex2d<'a, S> = Prefetched<'a, u32, VTex2d<S, u8>, TexAtlas<S>>; #[derive(Default)] pub struct TexAtlas<S: TexSize> { t: UnsafeCell<(Vec<FS::File::Resource>, HashMap<u32, VTex2d<S, u8>>)>, } impl<S: TexSize> TexAtlas<S> { pub fn new() -> Self { Self::default() } pub fn load(&self, name: &str) -> AtlasTex2d<S> { let (reqs, textures) = unsafe { &mut *self.t.get() }; ASSERT!(textures.is_empty(), "Loading into atlas after batching"); let k = u32::to(reqs.len()); reqs.push(FS::Preload::File(CONCAT!("res/", name))); Prefetched::new(k, self) } fn initialize(&self) { let (reqs, textures) = unsafe { &mut *self.t.get() }; let reqs: Vec<(u32, _)> = reqs.into_iter().enumerate().map(|(n, r)| (u32::to(n), uImage::<S>::new(r.get()))).collect(); let max_side = GL::MAX_TEXTURE_SIZE(); let (mut atlas, mut tail) = atlas::pack_into_atlas::<_, _, S, _>(reqs, max_side, max_side); if tail.is_empty() { textures.extend(atlas.into_iter()); } else { let mut last_s = tail.len(); while !tail.is_empty() { textures.extend(atlas.into_iter()); let (a, l) = atlas::pack_into_atlas::<_, _, S, _>(tail, max_side, max_side); atlas = a; tail = l; if tail.len() == last_s { ERROR!("Graphics card can't fit textures: {:?}", tail); } last_s = tail.len(); } } } } impl<S: TexSize> Fetcher<u32, VTex2d<S, u8>> for TexAtlas<S> { fn get(&self, k: u32) -> &VTex2d<S, u8> { let (_, textures) = unsafe { &mut *self.t.get() }; if textures.is_empty() { self.initialize(); } textures.get(&k).unwrap() } fn take(&self, k: u32) -> VTex2d<S, u8> { let (_, textures) = unsafe { &mut *self.t.get() }; if textures.is_empty() { self.initialize(); } textures.remove(&k).take().unwrap() } }