primase_core/
texformat.rs1#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
13pub enum TexFormat {
14 R8Unorm,
16 R8Snorm,
17 A8Unorm,
18 Rg8Unorm,
19 Rg8Snorm,
20 Rgba8Unorm,
21 Rgba8Snorm,
22 Bgra8Unorm,
23 Bgrx8Unorm,
25 B5g6r5Unorm,
28 B5g5r5a1Unorm,
30 B4g4r4a4Unorm,
32 Rgb10a2Unorm,
34 R16Unorm,
36 R16Float,
37 Rg16Unorm,
38 Rg16Snorm,
39 Rg16Float,
40 Rgba16Unorm,
41 Rgba16Float,
42 R32Float,
43 Rg32Float,
44 Rgba32Float,
45 Bc1,
48 Bc2,
50 Bc3,
52 Bc4Unorm,
53 Bc4Snorm,
54 Bc5Unorm,
55 Bc5Snorm,
56 Bc6hUfloat,
57 Bc6hSfloat,
58 Bc7,
59 Etc1,
61 Etc2Rgb,
62 Etc2Rgba,
63 Etc2RgbA1,
64 EacR11Unorm,
65 EacRg11Unorm,
66 Astc {
68 block_w: u8,
69 block_h: u8,
70 },
71}
72
73impl TexFormat {
74 pub fn block_dims(self) -> (u32, u32) {
76 use TexFormat::*;
77 match self {
78 Bc1 | Bc2 | Bc3 | Bc4Unorm | Bc4Snorm | Bc5Unorm | Bc5Snorm | Bc6hUfloat | Bc6hSfloat | Bc7
79 | Etc1 | Etc2Rgb | Etc2Rgba | Etc2RgbA1 | EacR11Unorm | EacRg11Unorm => (4, 4),
80 Astc { block_w, block_h } => (block_w as u32, block_h as u32),
81 _ => (1, 1),
82 }
83 }
84
85 pub fn block_bytes(self) -> u32 {
87 use TexFormat::*;
88 match self {
89 R8Unorm | R8Snorm | A8Unorm => 1,
90 Rg8Unorm | Rg8Snorm | B5g6r5Unorm | B5g5r5a1Unorm | B4g4r4a4Unorm | R16Unorm | R16Float => 2,
91 Rgba8Unorm | Rgba8Snorm | Bgra8Unorm | Bgrx8Unorm | Rgb10a2Unorm | Rg16Unorm | Rg16Snorm
92 | Rg16Float | R32Float => 4,
93 Rgba16Unorm | Rgba16Float | Rg32Float => 8,
94 Rgba32Float => 16,
95 Bc1 | Bc4Unorm | Bc4Snorm | Etc1 | Etc2Rgb | Etc2RgbA1 | EacR11Unorm => 8,
96 Bc2
97 | Bc3
98 | Bc5Unorm
99 | Bc5Snorm
100 | Bc6hUfloat
101 | Bc6hSfloat
102 | Bc7
103 | Etc2Rgba
104 | EacRg11Unorm
105 | Astc { .. } => 16,
106 }
107 }
108
109 pub fn is_block_compressed(self) -> bool {
110 self.block_dims() != (1, 1)
111 }
112
113 pub fn level_size(self, width: u32, height: u32) -> usize {
115 self.checked_level_size(width, height)
116 .expect("a level size that fits in memory")
117 }
118
119 pub fn checked_level_size(self, width: u32, height: u32) -> Option<usize> {
121 let (bw, bh) = self.block_dims();
122 let blocks_x = usize::try_from(width.div_ceil(bw).max(1)).ok()?;
123 let blocks_y = usize::try_from(height.div_ceil(bh).max(1)).ok()?;
124 blocks_x
125 .checked_mul(blocks_y)?
126 .checked_mul(usize::try_from(self.block_bytes()).ok()?)
127 }
128}
129
130#[cfg(test)]
131mod tests {
132 use super::TexFormat::*;
133
134 #[test]
135 fn level_sizes_round_up_to_whole_blocks() {
136 assert_eq!(Bc1.level_size(1, 1), 8);
137 assert_eq!(Bc1.level_size(5, 3), 2 * 8);
138 assert_eq!(Bc7.level_size(1024, 512), 256 * 128 * 16);
139 assert_eq!(Rgba8Unorm.level_size(3, 2), 24);
140 assert_eq!(
141 (Astc {
142 block_w: 6,
143 block_h: 5
144 })
145 .level_size(13, 10),
146 3 * 2 * 16
147 );
148 }
149}