ispc_texcomp/
astc.rs

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/*
19#[derive(Debug, Copy, Clone)]
20pub struct EncodeContext {
21    pub width: u32,
22    pub height: u32,
23    pub channels: u32,
24    pub dual_plane: bool,
25    pub partitions: u32,
26    pub color_endpoint_pairs: u32,
27}
28
29#[derive(Copy, Clone)]
30pub struct Block {
31    pub width: u32,
32    pub height: u32,
33    pub dual_plane: bool,
34    pub weight_range: u32,
35    pub weights: [u8; 64usize],
36    pub color_component_selector: u32,
37    pub partitions: u32,
38    pub partition_id: u32,
39    pub color_endpoint_pairs: u32,
40    pub channels: u32,
41    pub color_endpoint_modes: [u32; 4usize],
42    pub endpoint_range: u32,
43    pub endpoints: [u8; 18usize],
44}
45*/
46
47#[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    /*
101    ispc::astc_enc_context list_context;
102    setup_list_context(&list_context, uint32_t(list[1] & 0xFFFFFFFF));
103
104    assert(sizeof(ispc::rgba_surface) == sizeof(rgba_surface));
105    assert(sizeof(ispc::astc_enc_settings) == sizeof(astc_enc_settings));
106    ispc::astc_encode_ispc((ispc::rgba_surface*)src, block_scores, dst, list, &list_context, (ispc::astc_enc_settings*)settings);
107    */
108}
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    // ASTC uses a fixed block size of 16 bytes (128 bits).
131    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/*
235#[repr(C)]
236#[derive(Debug, Copy, Clone)]
237pub struct astc_enc_context {
238    pub width: i32,
239    pub height: i32,
240    pub channels: i32,
241    pub dual_plane: bool,
242    pub partitions: i32,
243    pub color_endpoint_pairs: i32,
244}
245
246#[repr(C)]
247#[derive(Copy, Clone)]
248pub struct astc_block {
249    pub width: i32,
250    pub height: i32,
251    pub dual_plane: bool,
252    pub weight_range: i32,
253    pub weights: [u8; 64usize],
254    pub color_component_selector: i32,
255    pub partitions: i32,
256    pub partition_id: i32,
257    pub color_endpoint_pairs: i32,
258    pub channels: i32,
259    pub color_endpoint_modes: [i32; 4usize],
260    pub endpoint_range: i32,
261    pub endpoints: [u8; 18usize],
262}
263
264extern "C" {
265    #[link_name = "\u{1}_astc_encode_ispc"]
266    pub fn astc_encode_ispc(
267        src: *mut rgba_surface,
268        block_scores: *mut f32,
269        dst: *mut u8,
270        list: *mut u64,
271        list_context: *mut astc_enc_context,
272        settings: *mut astc_enc_settings,
273    );
274}
275extern "C" {
276    #[link_name = "\u{1}_astc_rank_ispc"]
277    pub fn astc_rank_ispc(
278        src: *mut rgba_surface,
279        xx: i32,
280        yy: i32,
281        mode_buffer: *mut u32,
282        settings: *mut astc_enc_settings,
283    );
284}
285*/