1use crate::bindings::kernel;
2use crate::RgbaSurface;
3
4#[derive(Debug, Copy, Clone)]
5pub struct EncodeSettings {
6 pub mode_selection: [bool; 4usize],
7 pub refine_iterations: [u32; 8usize],
8 pub skip_mode2: bool,
9 pub fast_skip_threshold_mode1: u32,
10 pub fast_skip_threshold_mode3: u32,
11 pub fast_skip_threshold_mode7: u32,
12 pub mode45_channel0: u32,
13 pub refine_iterations_channel: u32,
14 pub channels: i32,
15}
16
17#[inline(always)]
18pub fn calc_output_size(width: u32, height: u32) -> usize {
19 let block_count = crate::divide_up_by_multiple(width * height, 16) as usize;
21 block_count * 16
22}
23
24pub fn compress_blocks(settings: &EncodeSettings, surface: &RgbaSurface) -> Vec<u8> {
25 let output_size = calc_output_size(surface.width, surface.height);
26 let mut output = vec![0u8; output_size];
27 compress_blocks_into(settings, surface, &mut output);
28 output
29}
30
31pub fn compress_blocks_into(settings: &EncodeSettings, surface: &RgbaSurface, blocks: &mut [u8]) {
32 assert_eq!(
33 blocks.len(),
34 calc_output_size(surface.width, surface.height)
35 );
36 let mut surface = kernel::rgba_surface {
37 width: surface.width as i32,
38 height: surface.height as i32,
39 stride: surface.stride as i32,
40 ptr: surface.data.as_ptr() as *mut u8,
41 };
42 let mut settings = kernel::bc7_enc_settings {
43 mode_selection: settings.mode_selection,
44 refineIterations: [
45 settings.refine_iterations[0] as i32,
46 settings.refine_iterations[1] as i32,
47 settings.refine_iterations[2] as i32,
48 settings.refine_iterations[3] as i32,
49 settings.refine_iterations[4] as i32,
50 settings.refine_iterations[5] as i32,
51 settings.refine_iterations[6] as i32,
52 settings.refine_iterations[7] as i32,
53 ],
54 skip_mode2: settings.skip_mode2,
55 fastSkipTreshold_mode1: settings.fast_skip_threshold_mode1 as i32,
56 fastSkipTreshold_mode3: settings.fast_skip_threshold_mode3 as i32,
57 fastSkipTreshold_mode7: settings.fast_skip_threshold_mode7 as i32,
58 mode45_channel0: settings.mode45_channel0 as i32,
59 refineIterations_channel: settings.refine_iterations_channel as i32,
60 channels: settings.channels as i32,
61 };
62
63 unsafe {
64 kernel::CompressBlocksBC7_ispc(&mut surface, blocks.as_mut_ptr(), &mut settings);
65 }
66}
67
68#[inline(always)]
69pub fn opaque_ultra_fast_settings() -> EncodeSettings {
70 EncodeSettings {
71 channels: 3,
72 mode_selection: [false, false, false, true],
73 fast_skip_threshold_mode1: 3,
74 fast_skip_threshold_mode3: 1,
75 fast_skip_threshold_mode7: 0,
76 skip_mode2: true,
77 mode45_channel0: 0,
78 refine_iterations_channel: 0,
79 refine_iterations: [2, 2, 2, 1, 2, 2, 1, 0],
80 }
81}
82
83#[inline(always)]
84pub fn opaque_very_fast_settings() -> EncodeSettings {
85 EncodeSettings {
86 channels: 3,
87 mode_selection: [false, true, false, true],
88 fast_skip_threshold_mode1: 3,
89 fast_skip_threshold_mode3: 1,
90 fast_skip_threshold_mode7: 0,
91 skip_mode2: true,
92 mode45_channel0: 0,
93 refine_iterations_channel: 0,
94 refine_iterations: [2, 2, 2, 1, 2, 2, 1, 0],
95 }
96}
97
98#[inline(always)]
99pub fn opaque_fast_settings() -> EncodeSettings {
100 EncodeSettings {
101 channels: 3,
102 mode_selection: [false, true, false, true],
103 fast_skip_threshold_mode1: 12,
104 fast_skip_threshold_mode3: 4,
105 fast_skip_threshold_mode7: 0,
106 skip_mode2: true,
107 mode45_channel0: 0,
108 refine_iterations_channel: 0,
109 refine_iterations: [2, 2, 2, 1, 2, 2, 2, 0],
110 }
111}
112
113#[inline(always)]
114pub fn opaque_basic_settings() -> EncodeSettings {
115 EncodeSettings {
116 channels: 3,
117 mode_selection: [true, true, true, true],
118 fast_skip_threshold_mode1: 8 + 4,
119 fast_skip_threshold_mode3: 8,
120 fast_skip_threshold_mode7: 0,
121 skip_mode2: true,
122 mode45_channel0: 0,
123 refine_iterations_channel: 2,
124 refine_iterations: [2, 2, 2, 2, 2, 2, 2, 0],
125 }
126}
127
128#[inline(always)]
129pub fn opaque_slow_settings() -> EncodeSettings {
130 let more_refinement = 2;
131 EncodeSettings {
132 channels: 3,
133 mode_selection: [true, true, true, true],
134 fast_skip_threshold_mode1: 64,
135 fast_skip_threshold_mode3: 64,
136 fast_skip_threshold_mode7: 0,
137 skip_mode2: false,
138 mode45_channel0: 0,
139 refine_iterations_channel: 2 + more_refinement,
140 refine_iterations: [
141 2 + more_refinement,
142 2 + more_refinement,
143 2 + more_refinement,
144 2 + more_refinement,
145 2 + more_refinement,
146 2 + more_refinement,
147 2 + more_refinement,
148 0,
149 ],
150 }
151}
152
153#[inline(always)]
154pub fn alpha_ultra_fast_settings() -> EncodeSettings {
155 EncodeSettings {
156 channels: 4,
157 mode_selection: [false, false, true, true],
158 fast_skip_threshold_mode1: 0,
159 fast_skip_threshold_mode3: 0,
160 fast_skip_threshold_mode7: 4,
161 skip_mode2: true,
162 mode45_channel0: 3,
163 refine_iterations_channel: 1,
164 refine_iterations: [2, 1, 2, 1, 1, 1, 2, 2],
165 }
166}
167
168#[inline(always)]
169pub fn alpha_very_fast_settings() -> EncodeSettings {
170 EncodeSettings {
171 channels: 4,
172 mode_selection: [false, true, true, true],
173 fast_skip_threshold_mode1: 0,
174 fast_skip_threshold_mode3: 0,
175 fast_skip_threshold_mode7: 4,
176 skip_mode2: true,
177 mode45_channel0: 3,
178 refine_iterations_channel: 2,
179 refine_iterations: [2, 1, 2, 1, 2, 2, 2, 2],
180 }
181}
182
183#[inline(always)]
184pub fn alpha_fast_settings() -> EncodeSettings {
185 EncodeSettings {
186 channels: 4,
187 mode_selection: [false, true, true, true],
188 fast_skip_threshold_mode1: 4,
189 fast_skip_threshold_mode3: 4,
190 fast_skip_threshold_mode7: 8,
191 skip_mode2: true,
192 mode45_channel0: 3,
193 refine_iterations_channel: 2,
194 refine_iterations: [2, 1, 2, 1, 2, 2, 2, 2],
195 }
196}
197
198#[inline(always)]
199pub fn alpha_basic_settings() -> EncodeSettings {
200 EncodeSettings {
201 channels: 4,
202 mode_selection: [true, true, true, true],
203 fast_skip_threshold_mode1: 8 + 4,
204 fast_skip_threshold_mode3: 8,
205 fast_skip_threshold_mode7: 4,
206 skip_mode2: true,
207 mode45_channel0: 0,
208 refine_iterations_channel: 2,
209 refine_iterations: [2, 2, 2, 2, 2, 2, 2, 2],
210 }
211}
212
213#[inline(always)]
214pub fn alpha_slow_settings() -> EncodeSettings {
215 let more_refinement = 2;
216 EncodeSettings {
217 channels: 4,
218 mode_selection: [true, true, true, true],
219 fast_skip_threshold_mode1: 64,
220 fast_skip_threshold_mode3: 64,
221 fast_skip_threshold_mode7: 64,
222 skip_mode2: false,
223 mode45_channel0: 0,
224 refine_iterations_channel: 2 + more_refinement,
225 refine_iterations: [
226 2 + more_refinement,
227 2 + more_refinement,
228 2 + more_refinement,
229 2 + more_refinement,
230 2 + more_refinement,
231 2 + more_refinement,
232 2 + more_refinement,
233 2 + more_refinement,
234 ],
235 }
236}