ispc_texcomp/
bc4.rs

1use more_asserts::assert_ge;
2
3use crate::bindings::kernel;
4use crate::RgbaSurface;
5
6#[inline(always)]
7pub fn calc_output_size(width: u32, height: u32) -> usize {
8    // BC4 uses 8 bytes to store each 4×4 block, giving it an average data rate of 0.5 bytes per pixel.
9    let block_count = crate::cal_block_count(width, height, 4, 4) as usize;
10    block_count * 8
11}
12
13pub fn compress_blocks(surface: &RgbaSurface) -> Vec<u8> {
14    let output_size = calc_output_size(surface.width, surface.height);
15    let mut output = vec![0u8; output_size];
16    compress_blocks_into(surface, &mut output);
17    output
18}
19
20pub fn compress_blocks_into(surface: &RgbaSurface, blocks: &mut [u8]) {
21    assert_ge!(
22        blocks.len(),
23        calc_output_size(surface.width, surface.height)
24    );
25
26    let mut r_data = vec![0_u8; (surface.width * surface.height) as usize];
27    let pitch = (surface.width * 32 + 7) / 8;
28    let mut offset = 0_u32;
29
30    for y in 0..surface.height {
31        for x in 0..surface.width {
32            // Copy R byte over
33            r_data[offset as usize] = surface.data[(x * 4 + y * pitch) as usize];
34            offset += 1;
35        }
36    }
37
38    let mut surface = kernel::rgba_surface {
39        width: surface.width as i32,
40        height: surface.height as i32,
41        stride: (surface.stride / 4) as i32,
42        ptr: (&r_data).as_ptr() as *mut u8,
43    };
44
45    unsafe {
46        kernel::CompressBlocksBC4_ispc(&mut surface, blocks.as_mut_ptr());
47    }
48}