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 GL::{atlas, tex::*, uImage};
#[derive(Debug)]
pub struct VTex2d<S, F> {
pub region: Vec4,
pub tex: Rc<Tex2d<S, F>>,
}
impl<S, F> 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, F> Eq for VTex2d<S, F> {}
impl<S, F> 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> {
t: UnsafeCell<(Vec<FS::File::Resource>, HashMap<u32, VTex2d<S, u8>>)>,
}
impl<S: TexSize> TexAtlas<S> {
pub fn new() -> Self {
Def()
}
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(reqs.len());
reqs.push(FS::Preload::File(conc!("res/", name)));
Prefetched::new(k, self)
}
fn initialize(&self) {
let (reqs, textures) = unsafe { &mut *self.t.get() };
let reqs: Vec<(u32, _)> = reqs.iter_mut().enumerate().map(|(n, r)| (u32(n), EXPECT!(uImage::<S>::load(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()
}
}