1#[cfg(feature = "bc15")]
4mod bc1_to_5;
5#[cfg(feature = "bc6h")]
6mod bc6h;
7#[cfg(feature = "bc7")]
8mod bc7;
9#[cfg(any(feature = "bc6h", feature = "bc7"))]
10mod common;
11
12#[cfg(feature = "bc15")]
13use self::bc1_to_5::BlockCompressorBC15;
14#[cfg(feature = "bc6h")]
15use self::bc6h::BlockCompressorBC6H;
16#[cfg(feature = "bc7")]
17use self::bc7::BlockCompressorBC7;
18#[cfg(feature = "bc6h")]
19use crate::BC6HSettings;
20#[cfg(feature = "bc7")]
21use crate::BC7Settings;
22#[cfg(any(feature = "bc15", feature = "bc6h", feature = "bc7"))]
23use crate::CompressionVariant;
24
25#[cfg(any(feature = "bc15", feature = "bc6h", feature = "bc7"))]
79#[cfg_attr(
80 docsrs,
81 doc(cfg(any(feature = "bc15", feature = "bc6h", feature = "bc7")))
82)]
83pub fn compress_rgba8(
84 variation: CompressionVariant,
85 rgba_data: &[u8],
86 blocks_buffer: &mut [u8],
87 width: u32,
88 height: u32,
89 stride: u32,
90) {
91 assert_eq!(height % 4, 0);
92 assert_eq!(width % 4, 0);
93
94 let required_size = variation.blocks_byte_size(width, height);
95
96 assert!(
97 blocks_buffer.len() >= required_size,
98 "blocks_buffer size ({}) is too small to hold compressed blocks. Required size: {}",
99 blocks_buffer.len(),
100 required_size
101 );
102
103 let stride = stride as usize;
104 let block_width = (width as usize).div_ceil(4);
105 let block_height = (height as usize).div_ceil(4);
106
107 match variation {
108 #[cfg(feature = "bc15")]
109 CompressionVariant::BC1 => {
110 compress_bc1(rgba_data, blocks_buffer, block_width, block_height, stride);
111 }
112 #[cfg(feature = "bc15")]
113 CompressionVariant::BC2 => {
114 compress_bc2(rgba_data, blocks_buffer, block_width, block_height, stride);
115 }
116 #[cfg(feature = "bc15")]
117 CompressionVariant::BC3 => {
118 compress_bc3(rgba_data, blocks_buffer, block_width, block_height, stride);
119 }
120 #[cfg(feature = "bc15")]
121 CompressionVariant::BC4 => {
122 compress_bc4(rgba_data, blocks_buffer, block_width, block_height, stride);
123 }
124 #[cfg(feature = "bc15")]
125 CompressionVariant::BC5 => {
126 compress_bc5(rgba_data, blocks_buffer, block_width, block_height, stride);
127 }
128 #[cfg(feature = "bc6h")]
129 CompressionVariant::BC6H(settings) => {
130 compress_bc6h_8bit(
131 rgba_data,
132 blocks_buffer,
133 block_width,
134 block_height,
135 stride,
136 &settings,
137 );
138 }
139 #[cfg(feature = "bc7")]
140 CompressionVariant::BC7(settings) => {
141 compress_bc7(
142 rgba_data,
143 blocks_buffer,
144 block_width,
145 block_height,
146 stride,
147 &settings,
148 );
149 }
150 }
151}
152
153#[cfg(feature = "bc6h")]
210#[cfg_attr(docsrs, doc(cfg(feature = "bc6h")))]
211pub fn compress_rgba16(
212 variation: CompressionVariant,
213 rgba_data: &[half::f16],
214 blocks_buffer: &mut [u8],
215 width: u32,
216 height: u32,
217 stride: u32,
218) {
219 assert_eq!(height % 4, 0);
220 assert_eq!(width % 4, 0);
221
222 let required_size = variation.blocks_byte_size(width, height);
223
224 assert!(
225 blocks_buffer.len() >= required_size,
226 "blocks_buffer size ({}) is too small to hold compressed blocks. Required size: {}",
227 blocks_buffer.len(),
228 required_size
229 );
230
231 let stride = stride as usize;
232 let block_width = (width as usize).div_ceil(4);
233 let block_height = (height as usize).div_ceil(4);
234
235 match variation {
236 CompressionVariant::BC6H(settings) => {
237 compress_bc6h_16bit(
238 rgba_data,
239 blocks_buffer,
240 block_width,
241 block_height,
242 stride,
243 &settings,
244 );
245 }
246 #[allow(unreachable_patterns)]
247 _ => {
248 panic!("only BC6H is supported for calling compress_rgba16");
249 }
250 }
251}
252
253#[cfg(feature = "bc15")]
254fn compress_bc1(
255 rgba_data: &[u8],
256 blocks_buffer: &mut [u8],
257 block_width: usize,
258 block_height: usize,
259 stride: usize,
260) {
261 for yy in 0..block_height {
262 for xx in 0..block_width {
263 let mut block_compressor = BlockCompressorBC15::default();
264
265 block_compressor.load_block_interleaved_rgba(rgba_data, xx, yy, stride);
266 let color_result = block_compressor.compress_block_bc1_core();
267 block_compressor.store_data(blocks_buffer, block_width, xx, yy, &color_result);
268 }
269 }
270}
271
272#[cfg(feature = "bc15")]
273fn compress_bc2(
274 rgba_data: &[u8],
275 blocks_buffer: &mut [u8],
276 block_width: usize,
277 block_height: usize,
278 stride: usize,
279) {
280 for yy in 0..block_height {
281 for xx in 0..block_width {
282 let mut block_compressor = BlockCompressorBC15::default();
283 let mut compressed_data = [0; 4];
284
285 let alpha_result = block_compressor.load_block_alpha_4bit(rgba_data, xx, yy, stride);
286
287 compressed_data[0] = alpha_result[0];
288 compressed_data[1] = alpha_result[1];
289
290 block_compressor.load_block_interleaved_rgba(rgba_data, xx, yy, stride);
291
292 let color_result = block_compressor.compress_block_bc1_core();
293 compressed_data[2] = color_result[0];
294 compressed_data[3] = color_result[1];
295
296 block_compressor.store_data(blocks_buffer, block_width, xx, yy, &compressed_data);
297 }
298 }
299}
300
301#[cfg(feature = "bc15")]
302fn compress_bc3(
303 rgba_data: &[u8],
304 blocks_buffer: &mut [u8],
305 block_width: usize,
306 block_height: usize,
307 stride: usize,
308) {
309 for yy in 0..block_height {
310 for xx in 0..block_width {
311 let mut block_compressor = BlockCompressorBC15::default();
312
313 let mut compressed_data = [0; 4];
314
315 block_compressor.load_block_interleaved_rgba(rgba_data, xx, yy, stride);
316
317 let alpha_result = block_compressor.compress_block_bc3_alpha();
318 compressed_data[0] = alpha_result[0];
319 compressed_data[1] = alpha_result[1];
320
321 let color_result = block_compressor.compress_block_bc1_core();
322 compressed_data[2] = color_result[0];
323 compressed_data[3] = color_result[1];
324
325 block_compressor.store_data(blocks_buffer, block_width, xx, yy, &compressed_data);
326 }
327 }
328}
329
330#[cfg(feature = "bc15")]
331fn compress_bc4(
332 rgba_data: &[u8],
333 blocks_buffer: &mut [u8],
334 block_width: usize,
335 block_height: usize,
336 stride: usize,
337) {
338 for yy in 0..block_height {
339 for xx in 0..block_width {
340 let mut block_compressor = BlockCompressorBC15::default();
341
342 let mut compressed_data = [0; 2];
343
344 block_compressor.load_block_r_8bit(rgba_data, xx, yy, stride);
345
346 let color_result = block_compressor.compress_block_bc3_alpha();
347 compressed_data[0] = color_result[0];
348 compressed_data[1] = color_result[1];
349
350 block_compressor.store_data(blocks_buffer, block_width, xx, yy, &compressed_data);
351 }
352 }
353}
354
355#[cfg(feature = "bc15")]
356fn compress_bc5(
357 rgba_data: &[u8],
358 blocks_buffer: &mut [u8],
359 block_width: usize,
360 block_height: usize,
361 stride: usize,
362) {
363 for yy in 0..block_height {
364 for xx in 0..block_width {
365 let mut block_compressor = BlockCompressorBC15::default();
366
367 let mut compressed_data = [0; 4];
368
369 block_compressor.load_block_r_8bit(rgba_data, xx, yy, stride);
370
371 let red_result = block_compressor.compress_block_bc3_alpha();
372 compressed_data[0] = red_result[0];
373 compressed_data[1] = red_result[1];
374
375 block_compressor.load_block_g_8bit(rgba_data, xx, yy, stride);
376
377 let green_result = block_compressor.compress_block_bc3_alpha();
378 compressed_data[2] = green_result[0];
379 compressed_data[3] = green_result[1];
380
381 block_compressor.store_data(blocks_buffer, block_width, xx, yy, &compressed_data);
382 }
383 }
384}
385
386#[cfg(feature = "bc6h")]
387fn compress_bc6h_8bit(
388 rgba_data: &[u8],
389 blocks_buffer: &mut [u8],
390 block_width: usize,
391 block_height: usize,
392 stride: usize,
393 settings: &BC6HSettings,
394) {
395 for yy in 0..block_height {
396 for xx in 0..block_width {
397 let mut block_compressor = BlockCompressorBC6H::new(settings);
398 block_compressor.load_block_interleaved_8bit(rgba_data, xx, yy, stride);
399 block_compressor.compress_bc6h_core();
400 block_compressor.store_data(blocks_buffer, block_width, xx, yy);
401 }
402 }
403}
404
405#[cfg(feature = "bc6h")]
406fn compress_bc6h_16bit(
407 rgba_data: &[half::f16],
408 blocks_buffer: &mut [u8],
409 block_width: usize,
410 block_height: usize,
411 stride: usize,
412 settings: &BC6HSettings,
413) {
414 for yy in 0..block_height {
415 for xx in 0..block_width {
416 let mut block_compressor = BlockCompressorBC6H::new(settings);
417 block_compressor.load_block_interleaved_16bit(rgba_data, xx, yy, stride);
418 block_compressor.compress_bc6h_core();
419 block_compressor.store_data(blocks_buffer, block_width, xx, yy);
420 }
421 }
422}
423
424#[cfg(feature = "bc7")]
425fn compress_bc7(
426 rgba_data: &[u8],
427 blocks_buffer: &mut [u8],
428 block_width: usize,
429 block_height: usize,
430 stride: usize,
431 settings: &BC7Settings,
432) {
433 for yy in 0..block_height {
434 for xx in 0..block_width {
435 let mut block_compressor = BlockCompressorBC7::new(settings);
436
437 block_compressor.load_block_interleaved_rgba(rgba_data, xx, yy, stride);
438 block_compressor.compute_opaque_err();
439 block_compressor.compress_block_bc7_core();
440 block_compressor.store_data(blocks_buffer, block_width, xx, yy);
441 }
442 }
443}