ctt_intel_texture_compressor/
astc.rs1#![allow(dead_code)]
24#![allow(unused_variables)]
25
26use crate::RgbaSurface;
27use crate::bindings::kernel_astc;
28
29#[derive(Debug, Copy, Clone)]
30pub struct EncodeSettings {
31 pub block_width: u32,
32 pub block_height: u32,
33 pub channels: u32,
34 pub fast_skip_threshold: u32,
35 pub refine_iterations: u32,
36}
37
38pub fn opaque_fast_settings(block_width: u32, block_height: u32) -> EncodeSettings {
68 EncodeSettings {
69 block_width,
70 block_height,
71 channels: 3,
72 fast_skip_threshold: 5,
73 refine_iterations: 2,
74 }
75}
76
77pub fn alpha_fast_settings(block_width: u32, block_height: u32) -> EncodeSettings {
78 EncodeSettings {
79 block_width,
80 block_height,
81 channels: 4,
82 fast_skip_threshold: 5,
83 refine_iterations: 2,
84 }
85}
86
87pub fn alpha_slow_settings(block_width: u32, block_height: u32) -> EncodeSettings {
88 EncodeSettings {
89 block_width,
90 block_height,
91 channels: 4,
92 fast_skip_threshold: 64,
93 refine_iterations: 2,
94 }
95}
96
97fn can_store(value: i32, bits: i32) -> bool {
98 if value < 0 {
99 return false;
100 }
101
102 if value >= 1 << bits {
103 return false;
104 }
105
106 true
107}
108
109fn astc_encode(
110 settings: &mut kernel_astc::astc_enc_settings,
111 surface: &mut kernel_astc::rgba_surface,
112 block_scores: &mut [f32],
113 blocks: &mut [u8],
114 list: &mut [u64],
115) {
116 unimplemented!();
117 }
126
127fn astc_rank(
128 settings: &mut kernel_astc::astc_enc_settings,
129 surface: &mut kernel_astc::rgba_surface,
130 xx: u32,
131 yy: u32,
132 mode_buffer: &mut [u32],
133) {
134 unsafe {
135 kernel_astc::astc_rank_ispc(
136 surface,
137 xx as i32,
138 yy as i32,
139 mode_buffer.as_mut_ptr(),
140 settings,
141 );
142 }
143}
144
145#[must_use]
146pub fn calc_output_size(width: u32, height: u32, block_width: u32, block_height: u32) -> usize {
147 let block_count = (width.div_ceil(block_width) * height.div_ceil(block_height)) as usize;
149 block_count * 16
150}
151
152#[must_use]
153pub fn compress_blocks(settings: &EncodeSettings, surface: &RgbaSurface) -> Vec<u8> {
154 let output_size = calc_output_size(
155 surface.width,
156 surface.height,
157 settings.block_width,
158 settings.block_height,
159 );
160 let mut output = vec![0u8; output_size];
161 compress_blocks_into(settings, surface, &mut output);
162 output
163}
164
165pub fn compress_blocks_into(settings: &EncodeSettings, surface: &RgbaSurface, blocks: &mut [u8]) {
176 assert_eq!(surface.height % settings.block_height, 0);
177 assert_eq!(surface.width % settings.block_width, 0);
178 assert!(settings.block_height <= 8);
179 assert!(settings.block_width <= 8);
180 assert_eq!(
181 blocks.len(),
182 calc_output_size(
183 surface.width,
184 surface.height,
185 settings.block_width,
186 settings.block_height
187 )
188 );
189
190 let tex_width = surface.width / settings.block_width;
191 let program_count = unsafe { kernel_astc::get_programCount() as u32 };
192
193 let mut block_scores =
194 vec![f32::INFINITY; (tex_width * surface.height / settings.block_height) as usize];
195
196 let mode_list_size = 3334usize;
197 let list_size = program_count as usize;
198
199 let mut mode_lists: Vec<u64> = vec![0; list_size * mode_list_size];
200 let mut mode_buffer: Vec<u32> =
201 vec![0; (program_count * settings.fast_skip_threshold) as usize];
202
203 let mut surface = kernel_astc::rgba_surface {
206 width: surface.width as i32,
207 height: surface.height as i32,
208 stride: surface.stride as i32,
209 ptr: surface.data.as_ptr() as *mut u8,
210 };
211
212 let mut settings = kernel_astc::astc_enc_settings {
213 block_width: settings.block_width as i32,
214 block_height: settings.block_height as i32,
215 channels: settings.channels as i32,
216 fastSkipThreshold: settings.fast_skip_threshold as i32,
217 refineIterations: settings.refine_iterations as i32,
218 };
219
220 for yy in 0..(surface.height / settings.block_height) as u32 {
221 for xx in 0..tex_width.div_ceil(program_count) {
222 let xx = xx * program_count;
223 astc_rank(&mut settings, &mut surface, xx, yy, &mut mode_buffer);
224 for i in 0..settings.fastSkipThreshold as u32 {
225 for k in 0..program_count {
226 if xx + k >= tex_width {
227 continue;
228 }
229 let offset = (yy << 16) + (xx + k);
230 let mode = u64::from(mode_buffer[(program_count * i + k) as usize]);
231 let mode_bin = mode >> 20;
232 let list_start = list_size * mode_bin as usize;
233 if mode_lists[list_start] < u64::from(program_count - 1) {
234 let index = (mode_lists[list_start] + 1) as usize;
235 mode_lists[list_start] = index as u64;
236 mode_lists[list_start + index] = (u64::from(offset) << 32) + mode;
237 } else {
238 mode_lists[list_start] = (u64::from(offset) << 32) + mode;
239 astc_encode(
240 &mut settings,
241 &mut surface,
242 &mut block_scores,
243 blocks,
244 &mut mode_lists[list_start..(list_start + list_size)],
245 );
246 for mode_list in mode_lists.iter_mut().skip(list_start).take(list_size) {
247 *mode_list = 0;
248 }
249 }
250 }
251 }
252 }
253 }
254
255 for mode_bin in 0usize..mode_list_size {
256 let list_start = list_size * mode_bin;
257 if mode_lists[list_start] == 0 {
258 continue;
259 }
260 mode_lists[list_start] = 0;
261 astc_encode(
262 &mut settings,
263 &mut surface,
264 &mut block_scores,
265 blocks,
266 &mut mode_lists[list_start..(list_start + list_size)],
267 );
268 for mode_list in mode_lists.iter_mut().skip(list_start).take(list_size) {
269 *mode_list = 0;
270 }
271 }
272}
273
274