From 87c797b3c29cc6fb233fc329a93aace2942ba2d9 Mon Sep 17 00:00:00 2001 From: Wan-Teh Chang Date: Mon, 17 Aug 2026 12:47:07 -0700 Subject: [PATCH] Add the ARGBToRGB565Row_SSE2() function back Add the ARGBToRGB565Row_SSE2() and ARGBToRGB565Row_Any_SSE2() functions back because they hide the unaligned access in ARGBToRGB565Row_C(). To reproduce the unalgined access error, run the following command in Google's internal repository: blaze test --config=asan third_party/libyuv:libyuv_test \ --test_filter=LibYUVConvertTest.I420ToARGBToRGB565_Unaligned Bug: b:547803993 Change-Id: I9cc6b643bc007c100dfc092ef3ec814428789219 Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/8265046 Commit-Queue: Wan-Teh Chang Reviewed-by: Frank Barchard --- include/libyuv/row.h | 7 +++++-- source/convert_from_argb.cc | 9 ++++++++- source/row_any.cc | 2 +- source/row_gcc.cc | 37 +++++++++++++++++++++++++++++++++++++ 4 files changed, 51 insertions(+), 4 deletions(-) diff --git a/include/libyuv/row.h b/include/libyuv/row.h index f5b0e7db1..e05132c40 100644 --- a/include/libyuv/row.h +++ b/include/libyuv/row.h @@ -42,6 +42,7 @@ extern "C" { #define HAS_ARGBSHUFFLEROW_SSSE3 #define HAS_ARGBTORAWROW_SSSE3 #define HAS_ARGBTORGB24ROW_SSSE3 +#define HAS_ARGBTORGB565ROW_SSE2 #define HAS_COPYROW_ERMS #define HAS_COPYROW_SSE2 #define HAS_I422TOARGBROW_SSSE3 @@ -4086,7 +4087,7 @@ void ARGB4444ToARGBRow_Any_LASX(const uint8_t* src_ptr, void ARGBToRGB24Row_SSSE3(const uint8_t* src, uint8_t* dst, int width); void ARGBToRAWRow_SSSE3(const uint8_t* src, uint8_t* dst, int width); - +void ARGBToRGB565Row_SSE2(const uint8_t* src, uint8_t* dst, int width); void ABGRToAR30Row_SSSE3(const uint8_t* src, uint8_t* dst, int width); void ARGBToAR30Row_SSSE3(const uint8_t* src, uint8_t* dst, int width); @@ -5378,7 +5379,9 @@ void ARGBToRGB24Row_Any_SSSE3(const uint8_t* src_ptr, void ARGBToRAWRow_Any_SSSE3(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); - +void ARGBToRGB565Row_Any_SSE2(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); void ABGRToAR30Row_Any_SSSE3(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); diff --git a/source/convert_from_argb.cc b/source/convert_from_argb.cc index 11e54fcf1..70ad39d27 100644 --- a/source/convert_from_argb.cc +++ b/source/convert_from_argb.cc @@ -1675,7 +1675,14 @@ int ARGBToRGB565(const uint8_t* src_argb, height = 1; src_stride_argb = dst_stride_rgb565 = 0; } - +#if defined(HAS_ARGBTORGB565ROW_SSE2) + if (TestCpuFlag(kCpuHasSSE2)) { + ARGBToRGB565Row = ARGBToRGB565Row_Any_SSE2; + if (IS_ALIGNED(width, 4)) { + ARGBToRGB565Row = ARGBToRGB565Row_SSE2; + } + } +#endif #if defined(HAS_ARGBTORGB565ROW_AVX2) if (TestCpuFlag(kCpuHasAVX2)) { ARGBToRGB565Row = ARGBToRGB565Row_Any_AVX2; diff --git a/source/row_any.cc b/source/row_any.cc index 38784e144..0fe9afb03 100644 --- a/source/row_any.cc +++ b/source/row_any.cc @@ -1000,7 +1000,7 @@ ANY11(CopyRow_Any_NEON, CopyRow_NEON, 0, 1, 1, 31) #if defined(HAS_ARGBTORGB24ROW_SSSE3) ANY11(ARGBToRGB24Row_Any_SSSE3, ARGBToRGB24Row_SSSE3, 0, 4, 3, 15) ANY11(ARGBToRAWRow_Any_SSSE3, ARGBToRAWRow_SSSE3, 0, 4, 3, 15) - +ANY11(ARGBToRGB565Row_Any_SSE2, ARGBToRGB565Row_SSE2, 0, 4, 2, 3) #endif #if defined(HAS_ARGBTORGB24ROW_AVX2) ANY11(ARGBToRGB24Row_Any_AVX2, ARGBToRGB24Row_AVX2, 0, 4, 3, 31) diff --git a/source/row_gcc.cc b/source/row_gcc.cc index e2bcc85b3..dd3962a0f 100644 --- a/source/row_gcc.cc +++ b/source/row_gcc.cc @@ -875,6 +875,43 @@ void ARGBToRAWRow_AVX2(const uint8_t* src, uint8_t* dst, int width) { } #endif +void ARGBToRGB565Row_SSE2(const uint8_t* src, uint8_t* dst, int width) { + asm volatile( + "pcmpeqb %%xmm3,%%xmm3 \n" + "psrld $0x1b,%%xmm3 \n" + "pcmpeqb %%xmm4,%%xmm4 \n" + "psrld $0x1a,%%xmm4 \n" + "pslld $0x5,%%xmm4 \n" + "pcmpeqb %%xmm5,%%xmm5 \n" + "pslld $0xb,%%xmm5 \n" + + LABELALIGN + "1: \n" + "movdqu (%0),%%xmm0 \n" + "movdqa %%xmm0,%%xmm1 \n" + "movdqa %%xmm0,%%xmm2 \n" + "pslld $0x8,%%xmm0 \n" + "psrld $0x3,%%xmm1 \n" + "psrld $0x5,%%xmm2 \n" + "psrad $0x10,%%xmm0 \n" + "pand %%xmm3,%%xmm1 \n" + "pand %%xmm4,%%xmm2 \n" + "pand %%xmm5,%%xmm0 \n" + "por %%xmm2,%%xmm1 \n" + "por %%xmm1,%%xmm0 \n" + "packssdw %%xmm0,%%xmm0 \n" + "lea 0x10(%0),%0 \n" + "movq %%xmm0,(%1) \n" + "lea 0x8(%1),%1 \n" + "sub $0x4,%2 \n" + "jg 1b \n" + : "+r"(src), // %0 + "+r"(dst), // %1 + "+r"(width) // %2 + ::"memory", + "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5"); +} + #ifdef HAS_ARGBTORGB565DITHERROW_AVX2 void ARGBToRGB565DitherRow_AVX2(const uint8_t* src, uint8_t* dst,