#![allow(
clippy::many_single_char_names,
clippy::cast_lossless,
clippy::cast_possible_truncation,
clippy::similar_names,
clippy::cast_sign_loss
)]
#[cfg(all(feature = "simd", any(target_arch = "x86_64", target_arch = "x86")))]
#[inline]
#[allow(unsafe_op_in_unsafe_fn, clippy::cast_ptr_alignment)]
pub(crate) unsafe fn rgb555_pack_to_bgra_sse2(pixels: &[[u8; 2]; 4], swap: bool) -> [u8; 16] {
use core::arch::x86_64::{
__m128i, _mm_and_si128, _mm_loadl_epi64, _mm_or_si128, _mm_packus_epi16, _mm_set1_epi8, _mm_set1_epi16,
_mm_setzero_si128, _mm_slli_epi16, _mm_srli_epi16, _mm_storeu_si128, _mm_unpacklo_epi8, _mm_xor_si128,
};
let v = _mm_loadl_epi64(pixels.as_ptr().cast::<__m128i>());
let mask5 = _mm_set1_epi16(0x1F);
let zero = _mm_setzero_si128();
let r5_default = _mm_and_si128(_mm_srli_epi16(v, 10), mask5);
let g5 = _mm_and_si128(_mm_srli_epi16(v, 5), mask5);
let b5_default = _mm_and_si128(v, mask5);
let swap_mask = if swap { _mm_set1_epi16(-1i16) } else { zero };
let diff = _mm_xor_si128(r5_default, b5_default);
let masked = _mm_and_si128(diff, swap_mask);
let r5 = _mm_xor_si128(r5_default, masked);
let b5 = _mm_xor_si128(b5_default, masked);
let r8 = _mm_or_si128(_mm_slli_epi16(r5, 3), _mm_srli_epi16(r5, 2));
let g8 = _mm_or_si128(_mm_slli_epi16(g5, 3), _mm_srli_epi16(g5, 2));
let b8 = _mm_or_si128(_mm_slli_epi16(b5, 3), _mm_srli_epi16(b5, 2));
let vb = _mm_packus_epi16(b8, zero);
let vg = _mm_packus_epi16(g8, zero);
let vr = _mm_packus_epi16(r8, zero);
let va = _mm_set1_epi8(-1i8);
let br = _mm_unpacklo_epi8(vb, vr);
let ga = _mm_unpacklo_epi8(vg, va);
let result = _mm_unpacklo_epi8(br, ga);
let mut out = [0u8; 16];
_mm_storeu_si128(out.as_mut_ptr().cast::<__m128i>(), result);
out
}
#[cfg(all(feature = "simd", any(target_arch = "x86_64", target_arch = "x86")))]
#[target_feature(enable = "ssse3")]
#[cfg(test)]
#[allow(unsafe_op_in_unsafe_fn, clippy::cast_ptr_alignment)]
pub(crate) unsafe fn rgb555_pack_to_bgra_ssse3(pixels: &[[u8; 2]; 4], swap: bool) -> [u8; 16] {
use core::arch::x86_64::{
__m128i, _mm_add_epi8, _mm_and_si128, _mm_cmpeq_epi8, _mm_loadl_epi64, _mm_packus_epi16, _mm_set1_epi8,
_mm_set1_epi16, _mm_setr_epi8, _mm_setzero_si128, _mm_shuffle_epi8, _mm_srli_epi16, _mm_storeu_si128,
_mm_unpacklo_epi8, _mm_xor_si128,
};
let v = _mm_loadl_epi64(pixels.as_ptr().cast::<__m128i>());
let mask5 = _mm_set1_epi16(0x1F);
let zero = _mm_setzero_si128();
let r5_default = _mm_and_si128(_mm_srli_epi16(v, 10), mask5);
let g5 = _mm_and_si128(_mm_srli_epi16(v, 5), mask5);
let b5_default = _mm_and_si128(v, mask5);
let swap_mask = if swap { _mm_set1_epi16(-1i16) } else { zero };
let diff = _mm_xor_si128(r5_default, b5_default);
let masked = _mm_and_si128(diff, swap_mask);
let r5 = _mm_xor_si128(r5_default, masked);
let b5 = _mm_xor_si128(b5_default, masked);
let r5_u8 = _mm_packus_epi16(r5, zero);
let g5_u8 = _mm_packus_epi16(g5, zero);
let b5_u8 = _mm_packus_epi16(b5, zero);
let expand_lut = _mm_setr_epi8(0, 8, 16, 24, 33, 41, 49, 57, 66, 74, 82, 90, 99, 107, 115, 123);
let hi_bit_mask = _mm_set1_epi8(0x10i8);
let hi_offset = _mm_set1_epi8(-124i8); let nibble_mask = _mm_set1_epi8(0x0Fi8);
let r_lo = _mm_and_si128(r5_u8, nibble_mask);
let r_hi = _mm_and_si128(r5_u8, hi_bit_mask);
let r_hi_sel = _mm_and_si128(hi_offset, _mm_cmpeq_epi8(r_hi, hi_bit_mask));
let r8 = _mm_add_epi8(_mm_shuffle_epi8(expand_lut, r_lo), r_hi_sel);
let g_lo = _mm_and_si128(g5_u8, nibble_mask);
let g_hi = _mm_and_si128(g5_u8, hi_bit_mask);
let g_hi_sel = _mm_and_si128(hi_offset, _mm_cmpeq_epi8(g_hi, hi_bit_mask));
let g8 = _mm_add_epi8(_mm_shuffle_epi8(expand_lut, g_lo), g_hi_sel);
let b_lo = _mm_and_si128(b5_u8, nibble_mask);
let b_hi = _mm_and_si128(b5_u8, hi_bit_mask);
let b_hi_sel = _mm_and_si128(hi_offset, _mm_cmpeq_epi8(b_hi, hi_bit_mask));
let b8 = _mm_add_epi8(_mm_shuffle_epi8(expand_lut, b_lo), b_hi_sel);
let a = _mm_set1_epi8(-1i8);
let br = _mm_unpacklo_epi8(b8, r8);
let ga = _mm_unpacklo_epi8(g8, a);
let bgra = _mm_unpacklo_epi8(br, ga);
let mut out = [0u8; 16];
_mm_storeu_si128(out.as_mut_ptr().cast::<__m128i>(), bgra);
out
}
#[cfg(all(feature = "simd", target_arch = "x86_64"))]
#[target_feature(enable = "avx2")]
#[inline]
#[cfg(test)]
#[allow(unsafe_op_in_unsafe_fn, clippy::cast_ptr_alignment)]
pub(crate) unsafe fn rgb555_pack_to_bgra_avx2(pixels: &[[u8; 2]; 4], swap: bool) -> [u8; 16] {
use core::arch::x86_64::{
__m128i, _mm_add_epi8, _mm_and_si128, _mm_cmpeq_epi8, _mm_loadl_epi64, _mm_packus_epi16, _mm_set1_epi8,
_mm_setr_epi8, _mm_setzero_si128, _mm_shuffle_epi8, _mm_storeu_si128, _mm_unpacklo_epi8, _mm256_and_si256,
_mm256_cvtepu16_epi32, _mm256_extracti128_si256, _mm256_packus_epi32, _mm256_set1_epi32, _mm256_setzero_si256,
_mm256_srli_epi32, _mm256_xor_si256,
};
let v128 = _mm_loadl_epi64(pixels.as_ptr().cast::<__m128i>());
let w = _mm256_cvtepu16_epi32(v128);
let mask5 = _mm256_set1_epi32(0x1F);
let zero = _mm256_setzero_si256();
let r5_default = _mm256_and_si256(_mm256_srli_epi32(w, 10), mask5);
let g5 = _mm256_and_si256(_mm256_srli_epi32(w, 5), mask5);
let b5_default = _mm256_and_si256(w, mask5);
let swap_vec = if swap { _mm256_set1_epi32(-1) } else { zero };
let diff = _mm256_xor_si256(r5_default, b5_default);
let masked = _mm256_and_si256(diff, swap_vec);
let r5 = _mm256_xor_si256(r5_default, masked);
let b5 = _mm256_xor_si256(b5_default, masked);
let r16x8 = _mm256_packus_epi32(r5, zero);
let g16x8 = _mm256_packus_epi32(g5, zero);
let b16x8 = _mm256_packus_epi32(b5, zero);
let r_lo = _mm256_extracti128_si256(r16x8, 0);
let g_lo = _mm256_extracti128_si256(g16x8, 0);
let b_lo = _mm256_extracti128_si256(b16x8, 0);
let r5_u8 = _mm_packus_epi16(r_lo, _mm_setzero_si128());
let g5_u8 = _mm_packus_epi16(g_lo, _mm_setzero_si128());
let b5_u8 = _mm_packus_epi16(b_lo, _mm_setzero_si128());
let expand_lut = _mm_setr_epi8(0, 8, 16, 24, 33, 41, 49, 57, 66, 74, 82, 90, 99, 107, 115, 123);
let hi_bit_mask = _mm_set1_epi8(0x10i8);
let hi_offset = _mm_set1_epi8(-124i8); let nibble_mask = _mm_set1_epi8(0x0Fi8);
let r_lo_nib = _mm_and_si128(r5_u8, nibble_mask);
let r_hi = _mm_and_si128(r5_u8, hi_bit_mask);
let r_hi_sel = _mm_and_si128(hi_offset, _mm_cmpeq_epi8(r_hi, hi_bit_mask));
let r8 = _mm_add_epi8(_mm_shuffle_epi8(expand_lut, r_lo_nib), r_hi_sel);
let g_lo_nib = _mm_and_si128(g5_u8, nibble_mask);
let g_hi = _mm_and_si128(g5_u8, hi_bit_mask);
let g_hi_sel = _mm_and_si128(hi_offset, _mm_cmpeq_epi8(g_hi, hi_bit_mask));
let g8 = _mm_add_epi8(_mm_shuffle_epi8(expand_lut, g_lo_nib), g_hi_sel);
let b_lo_nib = _mm_and_si128(b5_u8, nibble_mask);
let b_hi = _mm_and_si128(b5_u8, hi_bit_mask);
let b_hi_sel = _mm_and_si128(hi_offset, _mm_cmpeq_epi8(b_hi, hi_bit_mask));
let b8 = _mm_add_epi8(_mm_shuffle_epi8(expand_lut, b_lo_nib), b_hi_sel);
let a = _mm_set1_epi8(-1i8);
let br = _mm_unpacklo_epi8(b8, r8);
let ga = _mm_unpacklo_epi8(g8, a);
let bgra = _mm_unpacklo_epi8(br, ga);
let mut out = [0u8; 16];
_mm_storeu_si128(out.as_mut_ptr().cast::<__m128i>(), bgra);
out
}
#[must_use]
pub fn rgb555_pack_to_bgra(pixels: [[u8; 2]; 4], swap: bool) -> [u8; 16] {
#[cfg(all(feature = "simd", any(target_arch = "x86_64", target_arch = "x86")))]
unsafe {
rgb555_pack_to_bgra_sse2(&pixels, swap)
}
#[cfg(not(all(feature = "simd", any(target_arch = "x86_64", target_arch = "x86"))))]
super::scalar::rgb555_pack_to_bgra(pixels, swap)
}