diff --git a/Cargo.toml b/Cargo.toml index 6935a7d..be5b304 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,8 +30,20 @@ categories = [ paste = "^1.0.12" [features] -default = ["alloc"] +default = ["alloc", "astc", "atc", "bc1", "bc2", "bc3", "bc4", "bc5", "bc6", "bc7", "crunch", "etc", "pvrtc"] alloc = [] +astc = [] +atc = ["bc3"] +bc1 = [] +bc2 = ["bc1"] +bc3 = ["bc1"] +bc4 = ["bc3"] +bc5 = ["bc3"] +bc6 = [] +bc7 = [] +crunch = ["bc1", "bc3", "bc4", "bc5", "etc"] +etc = [] +pvrtc = [] [dev-dependencies] ddsfile = "^0.5.1" diff --git a/src/bcn.rs b/src/bcn.rs index 03c0642..8ca4632 100644 --- a/src/bcn.rs +++ b/src/bcn.rs @@ -1,33 +1,58 @@ use crate::macros::block_decoder; +#[cfg(feature = "bc1")] pub(crate) mod bc1; +#[cfg(feature = "bc2")] pub(crate) mod bc2; +#[cfg(feature = "bc3")] pub(crate) mod bc3; +#[cfg(feature = "bc4")] pub(crate) mod bc4; +#[cfg(feature = "bc5")] pub(crate) mod bc5; +#[cfg(feature = "bc6")] pub(crate) mod bc6; +#[cfg(feature = "bc7")] pub(crate) mod bc7; pub(crate) mod consts; +#[cfg(feature = "bc1")] pub use bc1::decode_bc1_block; +#[cfg(feature = "bc1")] pub use bc1::decode_bc1a_block; +#[cfg(feature = "bc2")] pub use bc2::decode_bc2_block; +#[cfg(feature = "bc3")] pub use bc3::decode_bc3_block; +#[cfg(feature = "bc4")] pub use bc4::decode_bc4_block; +#[cfg(feature = "bc5")] pub use bc5::decode_bc5_block; +#[cfg(feature = "bc6")] pub use bc6::{decode_bc6_block, decode_bc6_block_signed, decode_bc6_block_unsigned}; +#[cfg(feature = "bc7")] pub use bc7::decode_bc7_block; +#[cfg(feature = "bc1")] block_decoder!("bc1", 4, 4, 8, decode_bc1_block); +#[cfg(feature = "bc1")] block_decoder!("bc1a", 4, 4, 8, decode_bc1a_block); +#[cfg(feature = "bc2")] block_decoder!("bc2", 4, 4, 16, decode_bc2_block); +#[cfg(feature = "bc3")] block_decoder!("bc3", 4, 4, 16, decode_bc3_block); +#[cfg(feature = "bc4")] block_decoder!("bc4", 4, 4, 8, decode_bc4_block); +#[cfg(feature = "bc5")] block_decoder!("bc5", 4, 4, 16, decode_bc5_block); +#[cfg(feature = "bc6")] block_decoder!("bc6_signed", 4, 4, 16, decode_bc6_block_signed); +#[cfg(feature = "bc6")] block_decoder!("bc6_unsigned", 4, 4, 16, decode_bc6_block_unsigned); +#[cfg(feature = "bc7")] block_decoder!("bc7", 4, 4, 16, decode_bc7_block); +#[cfg(feature = "bc6")] pub fn decode_bc6( data: &[u8], width: usize, diff --git a/src/bcn/consts.rs b/src/bcn/consts.rs index 999445a..c5b6022 100644 --- a/src/bcn/consts.rs +++ b/src/bcn/consts.rs @@ -1,4 +1,5 @@ // BC 6 & 7 +#[cfg(any(feature = "bc6", feature = "bc7"))] pub(crate) static S_BPTC_A2: [usize; 64] = [ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 8, 2, 2, 8, 8, 15, 2, 8, 2, 2, 8, 8, 2, 2, 15, 15, 6, 8, 2, 8, 15, 15, 2, 8, 2, 2, 2, 15, 15, 6, 6, 2, 6, 8, 15, 15, 2, @@ -6,6 +7,7 @@ pub(crate) static S_BPTC_A2: [usize; 64] = [ ]; // BC7 +#[cfg(feature = "bc7")] pub(crate) static S_BPTC_A3: [[usize; 64]; 2] = [ [ 3, 3, 15, 15, 8, 3, 15, 15, 8, 8, 6, 6, 6, 5, 3, 3, 3, 3, 8, 15, 3, 3, 6, 10, 5, 8, 8, 6, @@ -20,6 +22,7 @@ pub(crate) static S_BPTC_A3: [[usize; 64]; 2] = [ ]; // BC 6 & 7 +#[cfg(any(feature = "bc6", feature = "bc7"))] pub(crate) static S_BPTC_FACTORS: [[u8; 16]; 3] = [ [0, 21, 43, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 9, 18, 27, 37, 46, 55, 64, 0, 0, 0, 0, 0, 0, 0, 0], @@ -27,6 +30,7 @@ pub(crate) static S_BPTC_FACTORS: [[u8; 16]; 3] = [ ]; // BC 6 & 7 +#[cfg(any(feature = "bc6", feature = "bc7"))] pub(crate) static S_BPTC_P2: [usize; 64] = [ // 3210 0000000000 1111111111 2222222222 3333333333 0xcccc, // 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 @@ -96,6 +100,7 @@ pub(crate) static S_BPTC_P2: [usize; 64] = [ ]; // BC7 +#[cfg(feature = "bc7")] pub(crate) static S_BPTC_P3: [usize; 64] = [ // 76543210 0000 1111 2222 3333 4444 5555 6666 7777 0xaa685050, // 0, 0, 1, 1, 0, 0, 1, 1, 0, 2, 2, 1, 2, 2, 2, 2 diff --git a/src/bitreader.rs b/src/bitreader.rs index 2789d0d..501875c 100644 --- a/src/bitreader.rs +++ b/src/bitreader.rs @@ -1,3 +1,4 @@ +#[cfg(any(feature = "astc", feature = "bc6", feature = "bc7"))] #[inline] fn getbits_raw(buf: &[u8], bit_offset: usize, num_bits: usize, dst: &mut [u8]) { let bytes_offset = bit_offset / 8; @@ -5,6 +6,7 @@ fn getbits_raw(buf: &[u8], bit_offset: usize, num_bits: usize, dst: &mut [u8]) { dst[0..(bytes_end - bytes_offset)].copy_from_slice(&buf[bytes_offset..bytes_end]); } +#[cfg(feature = "astc")] #[inline] pub fn getbits(buf: &[u8], bit_offset: usize, num_bits: usize) -> i32 { let shift = bit_offset % 8; @@ -16,6 +18,7 @@ pub fn getbits(buf: &[u8], bit_offset: usize, num_bits: usize) -> i32 { i32::from_le_bytes(raw) >> shift & ((1 << num_bits) - 1) } +#[cfg(feature = "astc")] #[inline] pub fn getbits64(buf: &[u8], bit: isize, len: usize) -> u64 { let mask: u64 = if len == 64 { @@ -38,11 +41,13 @@ pub fn getbits64(buf: &[u8], bit: isize, len: usize) -> u64 { } } +#[cfg(any(feature = "bc6", feature = "bc7"))] pub struct BitReader<'a> { data: &'a [u8], bit_pos: usize, } +#[cfg(any(feature = "bc6", feature = "bc7"))] impl BitReader<'_> { #[inline] pub const fn new(data: &[u8], bit_pos: usize) -> BitReader { diff --git a/src/color.rs b/src/color.rs index e107ac0..aa33280 100644 --- a/src/color.rs +++ b/src/color.rs @@ -1,5 +1,6 @@ #![allow(clippy::too_many_arguments)] +#[cfg(feature = "etc")] pub static TRANSPARENT_MASK: u32 = { #[cfg(target_endian = "little")] { @@ -11,6 +12,7 @@ pub static TRANSPARENT_MASK: u32 = { } }; +#[cfg(feature = "etc")] pub static TRANSPARENT_SHIFT: u32 = { #[cfg(target_endian = "little")] { @@ -40,6 +42,7 @@ pub const fn color(r: u8, g: u8, b: u8, a: u8) -> u32 { // } // #[cfg(target_endian = "little")] +#[cfg(feature = "bc1")] #[inline] pub const fn rgb565_le(d: u16) -> (u8, u8, u8) { ( diff --git a/src/lib.rs b/src/lib.rs index 2b59550..8e2535f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -80,28 +80,46 @@ //! #![no_std] +#[cfg(not(any(feature = "astc", feature = "atc", feature = "bc1", feature = "bc2", feature = "bc3", feature = "bc4", feature = "bc5", feature = "bc6", feature = "bc7", feature = "crunch", feature = "etc", feature = "pvrtc")))] +compile_error!("at least one of the texture formats must be enabled"); + mod bitreader; mod color; +#[cfg(any(feature = "astc", feature = "bc6"))] mod f16; mod macros; +#[cfg(feature = "astc")] mod astc; +#[cfg(feature = "atc")] mod atc; +#[cfg(any(feature = "bc1", feature = "bc2", feature = "bc3", feature = "bc4", feature = "bc5", feature = "bc6", feature = "bc7"))] mod bcn; +#[cfg(feature = "crunch")] mod crnlib; -#[cfg(feature = "alloc")] +#[cfg(all(feature = "crunch", feature = "alloc"))] mod crunch; +#[cfg(feature = "etc")] mod etc; +#[cfg(feature = "pvrtc")] mod pvrtc; -#[cfg(feature = "alloc")] +#[cfg(all(feature = "crunch", feature = "alloc"))] mod unitycrunch; // import decode functions +#[cfg(feature = "astc")] pub use astc::*; +#[cfg(feature = "atc")] pub use atc::*; +#[cfg(any(feature = "bc1", feature = "bc2", feature = "bc3", feature = "bc4", feature = "bc5", feature = "bc6", feature = "bc7"))] pub use bcn::*; +#[cfg(feature = "crunch")] pub use crnlib::CrnTextureInfo; +#[cfg(feature = "crunch")] pub use crunch::decode_crunch; +#[cfg(feature = "etc")] pub use etc::*; +#[cfg(feature = "pvrtc")] pub use pvrtc::*; +#[cfg(feature = "crunch")] pub use unitycrunch::decode_unity_crunch; diff --git a/src/macros.rs b/src/macros.rs index ab6ab4b..126a5d4 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1,4 +1,5 @@ // macro to generate generic block decoder functions +#[cfg(any(feature = "atc", feature = "bc1", feature = "bc2", feature = "bc3", feature = "bc4", feature = "bc5", feature = "bc6", feature = "bc7", feature = "etc"))] macro_rules! block_decoder{ ($name: expr, $block_width: expr, $block_height: expr, $raw_block_size: expr, $block_decode_func: expr) => { paste::item! { @@ -43,6 +44,10 @@ macro_rules! block_decoder{ }; } +#[cfg(any(feature = "atc", feature = "bc1", feature = "bc2", feature = "bc3", feature = "bc4", feature = "bc5", feature = "bc6", feature = "bc7", feature = "etc"))] +pub(crate) use block_decoder; + +#[cfg(feature = "crunch")] macro_rules! CRND_HUFF_DECODE { ($codec: expr, $model: expr, $symbol: expr) => { $symbol = match $codec.decode($model) { @@ -52,6 +57,10 @@ macro_rules! CRND_HUFF_DECODE { }; } +#[cfg(feature = "crunch")] +pub(crate) use CRND_HUFF_DECODE; + +#[cfg(feature = "crunch")] macro_rules! WRITE_TO_INT_BUFFER { ($buf: expr, $index: expr, $val: expr) => { let t_index = ($index * 4) as usize; @@ -66,6 +75,10 @@ macro_rules! WRITE_TO_INT_BUFFER { }; } +#[cfg(feature = "crunch")] +pub(crate) use WRITE_TO_INT_BUFFER; + +#[cfg(feature = "crunch")] macro_rules! WRITE_OR_U8_INTO_U16_BUFFER { ($buf: expr, $index: expr, $val: expr) => { let t_index = ($index >> 1) as usize; @@ -78,6 +91,5 @@ macro_rules! WRITE_OR_U8_INTO_U16_BUFFER { }; } -pub(crate) use { - block_decoder, CRND_HUFF_DECODE, WRITE_OR_U8_INTO_U16_BUFFER, WRITE_TO_INT_BUFFER, -}; +#[cfg(feature = "crunch")] +pub(crate) use WRITE_OR_U8_INTO_U16_BUFFER; diff --git a/tests/test.rs b/tests/test.rs index 71ed92d..bad1928 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -21,211 +21,253 @@ mod tests { extern crate ddsfile; extern crate ktx2; + #[cfg(feature = "atc")] #[test] fn test_ATC_RGB() { test_format("ATC_RGB", "dds", decode_atc_rgb4) } + #[cfg(feature = "atc")] #[test] fn test_ATC_RGBA_Explicit() { test_format("ATC_RGBA_Explicit", "dds", decode_atc_rgba8) } + #[cfg(feature = "atc")] #[test] fn test_ATC_RGBA_Interpolated() { test_format("ATC_RGBA_Interpolated", "dds", decode_atc_rgba8) } + #[cfg(feature = "astc")] #[test] fn test_ASTC_4x4() { test_format("ASTC_4x4", "ktx2", decode_astc_4_4) } + #[cfg(feature = "astc")] #[test] fn test_ASTC_5x4() { test_format("ASTC_5x4", "ktx2", decode_astc_5_4) } + #[cfg(feature = "astc")] #[test] fn test_ASTC_5x5() { test_format("ASTC_5x5", "ktx2", decode_astc_5_5) } + #[cfg(feature = "astc")] #[test] fn test_ASTC_6x5() { test_format("ASTC_6x5", "ktx2", decode_astc_6_5) } + #[cfg(feature = "astc")] #[test] fn test_ASTC_6x6() { test_format("ASTC_6x6", "ktx2", decode_astc_6_6) } + #[cfg(feature = "astc")] #[test] fn test_ASTC_8x5() { test_format("ASTC_8x5", "ktx2", decode_astc_8_5) } + #[cfg(feature = "astc")] #[test] fn test_ASTC_8x6() { test_format("ASTC_8x6", "ktx2", decode_astc_8_6) } + #[cfg(feature = "astc")] #[test] fn test_ASTC_8x8() { test_format("ASTC_8x8", "ktx2", decode_astc_8_8) } + #[cfg(feature = "bc1")] #[test] fn test_BC1() { test_format("BC1", "ktx2", decode_bc1) } + #[cfg(feature = "bc1")] #[test] fn test_BC1A() { test_format("BC1A", "ktx2", decode_bc1a) } + #[cfg(feature = "bc2")] #[test] fn test_BC2() { test_format("BC2", "ktx2", decode_bc2) } + #[cfg(feature = "bc3")] #[test] fn test_BC3() { test_format("BC3", "ktx2", decode_bc3) } + #[cfg(feature = "bc4")] #[test] fn test_BC4() { test_format("BC4", "ktx2", decode_bc4) } + #[cfg(feature = "bc5")] #[test] fn test_BC5() { test_format("BC5", "ktx2", decode_bc5) } + #[cfg(feature = "bc6")] #[test] fn test_BC6H() { test_format("BC6H", "ktx2", decode_bc6_unsigned) } + #[cfg(feature = "bc7")] #[test] fn test_BC7() { test_format("BC7", "ktx2", decode_bc7) } + #[cfg(feature = "etc")] #[test] fn test_ETC1_RGB() { test_format("ETC1_RGB", "ktx2", decode_etc1) } + #[cfg(feature = "etc")] #[test] fn test_ETC2_RGB() { test_format("ETC2_RGB", "ktx2", decode_etc2_rgb) } + #[cfg(feature = "etc")] #[test] fn test_ETC2_RGBA() { test_format("ETC2_RGBA", "ktx2", decode_etc2_rgba8) } + #[cfg(feature = "etc")] #[test] fn test_ETC2_RGB_A1() { test_format("ETC2_RGB_A1", "ktx2", decode_etc2_rgba1) } + #[cfg(feature = "pvrtc")] #[test] fn test_PVRTCI_2bpp_RGB() { test_format("PVRTCI_2bpp_RGB", "ktx2", decode_pvrtc_2bpp) } + #[cfg(feature = "pvrtc")] #[test] fn test_PVRTCI_2bpp_RGBA() { test_format("PVRTCI_2bpp_RGBA", "ktx2", decode_pvrtc_2bpp) } + #[cfg(feature = "pvrtc")] #[test] fn test_PVRTCI_4bpp_RGB() { test_format("PVRTCI_4bpp_RGB", "ktx2", decode_pvrtc_4bpp) } + #[cfg(feature = "pvrtc")] #[test] fn test_PVRTCI_4bpp_RGBA() { test_format("PVRTCI_4bpp_RGBA", "ktx2", decode_pvrtc_4bpp) } + #[cfg(feature = "etc")] #[test] fn test_EAC_R11() { test_format("EAC_R11", "ktx2", decode_eacr) } + #[cfg(feature = "etc")] #[test] fn test_EAC_RG11() { test_format("EAC_RG11", "ktx2", decode_eacrg) } + #[cfg(feature = "crunch")] #[test] fn test_CRUNCH_DXT1() { test_format("CRUNCH_DXT1", "crn", decode_crunch) } + #[cfg(feature = "crunch")] #[test] fn test_CRUNCH_DXT5() { test_format("CRUNCH_DXT5", "crn", decode_crunch) } + #[cfg(feature = "crunch")] #[test] fn test_CRUNCH_DXT5A() { test_format("CRUNCH_DXT5A", "crn", decode_crunch) } + #[cfg(feature = "crunch")] #[test] fn test_CRUNCH_DXN() { test_format("CRUNCH_DXN", "crn", decode_crunch) } + #[cfg(feature = "crunch")] #[test] fn test_UNITYCRUNCH_DXT1() { test_format("UNITYCRUNCH_DXT1", "crn", decode_unity_crunch) } + #[cfg(feature = "crunch")] #[test] fn test_UNITYCRUNCH_DXT5() { test_format("UNITYCRUNCH_DXT5", "crn", decode_unity_crunch) } + #[cfg(feature = "crunch")] #[test] fn test_UNITYCRUNCH_DXT5A() { test_format("UNITYCRUNCH_DXT5A", "crn", decode_unity_crunch) } + #[cfg(feature = "crunch")] #[test] fn test_UNITYCRUNCH_DXN() { test_format("UNITYCRUNCH_DXN", "crn", decode_unity_crunch) } + #[cfg(feature = "crunch")] #[test] fn test_UNITYCRUNCH_ETC1() { test_format("UNITYCRUNCH_ETC1", "crn", decode_unity_crunch) } + #[cfg(feature = "crunch")] #[test] fn test_UNITYCRUNCH_ETC1S() { test_format("UNITYCRUNCH_ETC1S", "crn", decode_unity_crunch) } + #[cfg(feature = "crunch")] #[test] fn test_UNITYCRUNCH_ETC2() { test_format("UNITYCRUNCH_ETC2", "crn", decode_unity_crunch) } + #[cfg(feature = "crunch")] #[test] fn test_UNITYCRUNCH_ETC2A() { test_format("UNITYCRUNCH_ETC2A", "crn", decode_unity_crunch) } + #[cfg(feature = "crunch")] #[test] fn test_UNITYCRUNCH_ETC2AS() { test_format("UNITYCRUNCH_ETC2AS", "crn", decode_unity_crunch) @@ -252,6 +294,7 @@ mod tests { match extension { "ktx2" | "KTX2" => Texture::from_ktx2_file(fp), "dds" | "DDS" => Texture::from_dds_file(fp), + #[cfg(feature = "crunch")] "crn" | "CRN" => Texture::from_crn_file(fp), _ => panic!("Unsupported file format"), } @@ -277,6 +320,7 @@ mod tests { Texture::new(dds.header.width, dds.header.height, dds.data) } + #[cfg(feature = "crunch")] fn from_crn_file(fp: &str) -> Texture { let crn_data = fs::read(fp).unwrap(); let mut tex_info = CrnTextureInfo::default();