1#![allow(dead_code)]
2#![allow(unused_variables)]
3
4use more_asserts::assert_ge;
5
6use crate::bindings::kernel_astc;
7use crate::{cal_block_count, RgbaSurface};
8
9#[derive(Debug, Copy, Clone)]
10pub struct EncodeSettings {
11 pub block_width: u32,
12 pub block_height: u32,
13 pub channels: u32,
14 pub fast_skip_threshold: u32,
15 pub refine_iterations: u32,
16}
17
18#[inline(always)]
48pub fn opaque_fast_settings(block_width: u32, block_height: u32) -> EncodeSettings {
49 EncodeSettings {
50 block_width,
51 block_height,
52 channels: 3,
53 fast_skip_threshold: 5,
54 refine_iterations: 2,
55 }
56}
57
58#[inline(always)]
59pub fn alpha_fast_settings(block_width: u32, block_height: u32) -> EncodeSettings {
60 EncodeSettings {
61 block_width,
62 block_height,
63 channels: 4,
64 fast_skip_threshold: 5,
65 refine_iterations: 2,
66 }
67}
68
69#[inline(always)]
70pub fn alpha_slow_settings(block_width: u32, block_height: u32) -> EncodeSettings {
71 EncodeSettings {
72 block_width,
73 block_height,
74 channels: 4,
75 fast_skip_threshold: 64,
76 refine_iterations: 2,
77 }
78}
79
80fn can_store(value: i32, bits: i32) -> bool {
81 if value < 0 {
82 return false;
83 }
84
85 if value >= 1 << bits {
86 return false;
87 }
88
89 true
90}
91
92fn astc_encode(
93 settings: &mut kernel_astc::astc_enc_settings,
94 surface: &mut kernel_astc::rgba_surface,
95 block_scores: &mut [f32],
96 blocks: &mut [u8],
97 list: &mut [u64],
98) {
99 unimplemented!();
100 }
109
110fn astc_rank(
111 settings: &mut kernel_astc::astc_enc_settings,
112 surface: &mut kernel_astc::rgba_surface,
113 xx: u32,
114 yy: u32,
115 mode_buffer: &mut [u32],
116) {
117 unsafe {
118 kernel_astc::astc_rank_ispc(
119 surface,
120 xx as i32,
121 yy as i32,
122 mode_buffer.as_mut_ptr(),
123 settings,
124 );
125 }
126}
127
128#[inline(always)]
129pub fn calc_output_size(width: u32, height: u32) -> usize {
130 let block_count = cal_block_count(width, height, 4, 4);
132 block_count as usize * 16
133}
134
135pub fn compress_blocks(settings: &EncodeSettings, surface: &RgbaSurface) -> Vec<u8> {
136 let output_size = calc_output_size(surface.width, surface.height);
137 let mut output = vec![0u8; output_size];
138 compress_blocks_into(settings, surface, &mut output);
139 output
140}
141
142pub fn compress_blocks_into(settings: &EncodeSettings, surface: &RgbaSurface, blocks: &mut [u8]) {
143 assert_eq!(surface.height % settings.block_height, 0);
144 assert_eq!(surface.width % settings.block_width, 0);
145 assert!(settings.block_height <= 8);
146 assert!(settings.block_width <= 8);
147 assert_ge!(
148 blocks.len(),
149 calc_output_size(surface.width, surface.height)
150 );
151
152 let tex_width = surface.width / settings.block_width;
153 let program_count = unsafe { kernel_astc::get_programCount() as u32 };
154
155 let mut block_scores =
156 vec![std::f32::INFINITY; (tex_width * surface.height / settings.block_height) as usize];
157
158 let mode_list_size = 3334usize;
159 let list_size = program_count as usize;
160
161 let mut mode_lists: Vec<u64> = vec![0; (list_size * mode_list_size) as usize];
162 let mut mode_buffer: Vec<u32> =
163 vec![0; (program_count * settings.fast_skip_threshold) as usize];
164
165 let mut surface = kernel_astc::rgba_surface {
166 width: surface.width as i32,
167 height: surface.height as i32,
168 stride: surface.stride as i32,
169 ptr: surface.data.as_ptr() as *mut u8,
170 };
171
172 let mut settings = kernel_astc::astc_enc_settings {
173 block_width: settings.block_width as i32,
174 block_height: settings.block_height as i32,
175 channels: settings.channels as i32,
176 fastSkipTreshold: settings.fast_skip_threshold as i32,
177 refineIterations: settings.refine_iterations as i32,
178 };
179
180 for yy in 0..(surface.height / settings.block_height) as u32 {
181 for xx in 0..((tex_width + program_count - 1) / program_count) as u32 {
182 let xx = xx * program_count;
183 astc_rank(&mut settings, &mut surface, xx, yy, &mut mode_buffer);
184 for i in 0..settings.fastSkipTreshold as u32 {
185 for k in 0..program_count {
186 if xx + k >= tex_width {
187 continue;
188 }
189 let offset = (yy << 16) + (xx + k);
190 let mode = u64::from(mode_buffer[(program_count * i + k) as usize]);
191 let mode_bin = mode >> 20;
192 let list_start = list_size * mode_bin as usize;
193 if mode_lists[list_start] < u64::from(program_count - 1) {
194 let index = (mode_lists[list_start] + 1) as usize;
195 mode_lists[list_start] = index as u64;
196 mode_lists[list_start + index] = (u64::from(offset) << 32) + mode;
197 } else {
198 mode_lists[list_start] = (u64::from(offset) << 32) + mode;
199 astc_encode(
200 &mut settings,
201 &mut surface,
202 &mut block_scores,
203 blocks,
204 &mut mode_lists[list_start..(list_start + list_size)],
205 );
206 for mode_list in mode_lists.iter_mut().skip(list_start).take(list_size) {
207 *mode_list = 0;
208 }
209 }
210 }
211 }
212 }
213 }
214
215 for mode_bin in 0usize..mode_list_size {
216 let list_start = list_size * mode_bin;
217 if mode_lists[list_start] == 0 {
218 continue;
219 }
220 mode_lists[list_start] = 0;
221 astc_encode(
222 &mut settings,
223 &mut surface,
224 &mut block_scores,
225 blocks,
226 &mut mode_lists[list_start..(list_start + list_size)],
227 );
228 for mode_list in mode_lists.iter_mut().skip(list_start).take(list_size) {
229 *mode_list = 0;
230 }
231 }
232}
233
234