5#if defined(__x86_64__) || defined(__i386__)
12void packScalar(
const uint8_t* src, uint8_t* dst,
size_t pixels) {
29inline void store12(uint8_t* dst, __m128i packed) {
30 _mm_storel_epi64(
reinterpret_cast<__m128i*
>(dst), packed);
31 const auto tail =
static_cast<uint32_t
>(_mm_cvtsi128_si32(_mm_srli_si128(packed, 8)));
32 std::memcpy(dst + 8, &tail,
sizeof(tail));
35__attribute__((target(
"avx2")))
36void packAvx2(const uint8_t* src, uint8_t* dst,
size_t pixels) {
37 const __m256i shuffle = _mm256_setr_epi8(
38 0, 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, -1, -1, -1, -1,
39 0, 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, -1, -1, -1, -1);
41 const size_t wide = pixels & ~size_t{7};
42 for (
size_t at = 0; at < wide; at += 8) {
43 const __m256i loaded = _mm256_loadu_si256(
reinterpret_cast<const __m256i*
>(src));
44 const __m256i packed = _mm256_shuffle_epi8(loaded, shuffle);
47 store12(dst, _mm256_castsi256_si128(packed));
48 store12(dst + 12, _mm256_extracti128_si256(packed, 1));
53 packScalar(src, dst, pixels - wide);
56__attribute__((target(
"ssse3")))
57void packSsse3(const uint8_t* src, uint8_t* dst,
size_t pixels) {
58 const __m128i shuffle = _mm_setr_epi8(0, 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, -1, -1, -1, -1);
60 const size_t wide = pixels & ~size_t{3};
61 for (
size_t at = 0; at < wide; at += 4) {
62 store12(dst, _mm_shuffle_epi8(_mm_loadu_si128(
reinterpret_cast<const __m128i*
>(src)), shuffle));
66 packScalar(src, dst, pixels - wide);
76void pack(
const uint8_t* src, uint8_t* dst,
size_t pixels) {
78 if (__builtin_cpu_supports(
"avx2"))
return packAvx2(src, dst, pixels);
79 if (__builtin_cpu_supports(
"ssse3"))
return packSsse3(src, dst, pixels);
81 packScalar(src, dst, pixels);
95 const auto pixels =
static_cast<size_t>(size.width) *
static_cast<size_t>(size.height);
96 if (src.size() < pixels * 4 || dst.size() < pixels * 3) {
97 HAIO_FAIL(InvalidInput,
"rgba8888 to rgb888 got a buffer that is too small");
99 if (pixels == 0)
return {};
101 pack(src.data(), dst.data(), pixels);
Result< Image< Color::RGB888 > > Convert< Color::RGBA8888, Color::RGB888 >(Image< Color::RGBA8888 > src)
Result< void > Move< Color::RGBA8888, Color::RGB888 >(Bytes src, std::span< uint8_t > dst, Size size)
#define HAIO_FAIL(why, message)
Result< Image< To > > convertVia(Image< From > src)
std::expected< T, Error > Result
std::span< const uint8_t > Bytes