use super::unpack::unpack_uastc;
pub fn write_bc4_solid_block(dst: &mut [u8; 8], a: u8) {
dst[0] = a;
dst[1] = a;
dst[2..8].fill(0);
}
pub fn encode_bc4(dst: &mut [u8; 8], pixels: &[u8; 16]) {
let (mut min0, mut max0) = (pixels[0] as u32, pixels[0] as u32);
let (mut min1, mut max1) = (pixels[1] as u32, pixels[1] as u32);
let (mut min2, mut max2) = (pixels[2] as u32, pixels[2] as u32);
let (mut min3, mut max3) = (pixels[3] as u32, pixels[3] as u32);
let acc = |i: usize, mn: &mut u32, mx: &mut u32| {
let v = pixels[i] as u32;
*mn = (*mn).min(v);
*mx = (*mx).max(v);
};
acc(4, &mut min0, &mut max0);
acc(5, &mut min1, &mut max1);
acc(6, &mut min2, &mut max2);
acc(7, &mut min3, &mut max3);
acc(8, &mut min0, &mut max0);
acc(9, &mut min1, &mut max1);
acc(10, &mut min2, &mut max2);
acc(11, &mut min3, &mut max3);
acc(12, &mut min0, &mut max0);
acc(13, &mut min1, &mut max1);
acc(14, &mut min2, &mut max2);
acc(15, &mut min3, &mut max3);
let min_v = min0.min(min1).min(min2).min(min3);
let max_v = max0.max(max1).max(max2).max(max3);
dst[0] = max_v as u8;
dst[1] = min_v as u8;
if max_v == min_v {
dst[2..8].fill(0);
return;
}
let delta = (max_v - min_v) as i32;
let t0 = delta * 13;
let t1 = delta * 11;
let t2 = delta * 9;
let t3 = delta * 7;
let t4 = delta * 5;
let t5 = delta * 3;
let t6 = delta;
let bias = 4 - min_v as i32 * 14;
const S_TRAN0: [u64; 8] = [1, 7, 6, 5, 4, 3, 2, 0];
const S_TRAN1: [u64; 8] = [1 << 3, 7 << 3, 6 << 3, 5 << 3, 4 << 3, 3 << 3, 2 << 3, 0];
const S_TRAN2: [u64; 8] = [1 << 6, 7 << 6, 6 << 6, 5 << 6, 4 << 6, 3 << 6, 2 << 6, 0];
const S_TRAN3: [u64; 8] = [1 << 9, 7 << 9, 6 << 9, 5 << 9, 4 << 9, 3 << 9, 2 << 9, 0];
#[inline]
fn sel(v: i32, t: &[i32; 7]) -> usize {
((v >= t[0]) as usize)
+ (v >= t[1]) as usize
+ (v >= t[2]) as usize
+ (v >= t[3]) as usize
+ (v >= t[4]) as usize
+ (v >= t[5]) as usize
+ (v >= t[6]) as usize
}
let t = [t0, t1, t2, t3, t4, t5, t6];
let mut a0: u64 = 0;
let mut a1: u64 = 0;
let mut a2: u64 = 0;
let mut a3: u64 = 0;
for group in 0..4 {
let base = group * 4;
let v0 = pixels[base] as i32 * 14 + bias;
let v1 = pixels[base + 1] as i32 * 14 + bias;
let v2 = pixels[base + 2] as i32 * 14 + bias;
let v3 = pixels[base + 3] as i32 * 14 + bias;
let shift = (group * 12) as u32;
a0 |= S_TRAN0[sel(v0, &t)] << shift;
a1 |= S_TRAN1[sel(v1, &t)] << shift;
a2 |= S_TRAN2[sel(v2, &t)] << shift;
a3 |= S_TRAN3[sel(v3, &t)] << shift;
}
let f = a0 | a1 | a2 | a3;
dst[2] = f as u8;
dst[3] = (f >> 8) as u8;
dst[4] = (f >> 16) as u8;
dst[5] = (f >> 24) as u8;
dst[6] = (f >> 32) as u8;
dst[7] = (f >> 40) as u8;
}
pub fn transcode_uastc_to_bc4(
src: &[u8; 16],
_high_quality: bool,
chan0: usize,
) -> Option<[u8; 8]> {
let px = unpack_uastc(src, false)?;
let mut chan = [0u8; 16];
for (i, p) in px.iter().enumerate() {
chan[i] = p.c[chan0];
}
let mut out = [0u8; 8];
encode_bc4(&mut out, &chan);
Some(out)
}