diff --git a/README.chromium b/README.chromium index d9ab1089d..5cff5f2f4 100644 --- a/README.chromium +++ b/README.chromium @@ -1,6 +1,6 @@ Name: libyuv URL: http://code.google.com/p/libyuv/ -Version: 352 +Version: 353 License: BSD License File: LICENSE diff --git a/include/libyuv/planar_functions.h b/include/libyuv/planar_functions.h index 6949cdc13..e7cd51de7 100644 --- a/include/libyuv/planar_functions.h +++ b/include/libyuv/planar_functions.h @@ -68,6 +68,11 @@ int NV21ToRGB565(const uint8* src_y, int src_stride_y, #define ARGBToBGRA BGRAToARGB #define ARGBToABGR ABGRToARGB +// Convert ARGB To RGBA. +int ARGBToRGBA(const uint8* src_frame, int src_stride_frame, + uint8* dst_argb, int dst_stride_argb, + int width, int height); + // Convert ARGB To RGB24. int ARGBToRGB24(const uint8* src_argb, int src_stride_argb, uint8* dst_rgb24, int dst_stride_rgb24, diff --git a/include/libyuv/version.h b/include/libyuv/version.h index 81f32e813..04138749b 100644 --- a/include/libyuv/version.h +++ b/include/libyuv/version.h @@ -11,6 +11,6 @@ #ifndef INCLUDE_LIBYUV_VERSION_H_ // NOLINT #define INCLUDE_LIBYUV_VERSION_H_ -#define LIBYUV_VERSION 352 +#define LIBYUV_VERSION 353 #endif // INCLUDE_LIBYUV_VERSION_H_ NOLINT diff --git a/source/planar_functions.cc b/source/planar_functions.cc index 1f3b8ff3d..dc9ce47fb 100644 --- a/source/planar_functions.cc +++ b/source/planar_functions.cc @@ -296,6 +296,39 @@ int ARGBToI422(const uint8* src_argb, int src_stride_argb, return 0; } +// Convert ARGB to RGBA. +int ARGBToRGBA(const uint8* src_argb, int src_stride_argb, + uint8* dst_rgba, int dst_stride_rgba, + int width, int height) { + if (!src_argb || !dst_rgba || + width <= 0 || height == 0) { + return -1; + } + // Negative height means invert the image. + if (height < 0) { + height = -height; + src_argb = src_argb + (height - 1) * src_stride_argb; + src_stride_argb = -src_stride_argb; + } + void (*ARGBToRGBARow)(const uint8* src_argb, uint8* dst_rgba, int pix) = + ARGBToRGBARow_C; +#if defined(HAS_ARGBTORGBAROW_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3) && + IS_ALIGNED(width, 4) && + IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) && + IS_ALIGNED(dst_rgba, 16) && IS_ALIGNED(dst_stride_rgba, 16)) { + ARGBToRGBARow = ARGBToRGBARow_SSSE3; + } +#endif + + for (int y = 0; y < height; ++y) { + ARGBToRGBARow(src_argb, dst_rgba, width); + src_argb += src_stride_argb; + dst_rgba += dst_stride_rgba; + } + return 0; +} + // Convert ARGB To RGB24. int ARGBToRGB24(const uint8* src_argb, int src_stride_argb, uint8* dst_rgb24, int dst_stride_rgb24, diff --git a/source/row.h b/source/row.h index f1b3df2dd..1047e8660 100644 --- a/source/row.h +++ b/source/row.h @@ -38,6 +38,7 @@ extern "C" { #define HAS_ABGRTOUVROW_SSSE3 #define HAS_ABGRTOYROW_SSSE3 #define HAS_RGBATOARGBROW_SSSE3 +#define HAS_ARGBTORGBAROW_SSSE3 #define HAS_ARGB1555TOARGBROW_SSE2 #define HAS_ARGB4444TOARGBROW_SSE2 #define HAS_ARGBATTENUATEROW_SSSE3 @@ -232,12 +233,14 @@ void RGB565ToARGBRow_C(const uint8* src_rgb, uint8* dst_argb, int pix); void ARGB1555ToARGBRow_C(const uint8* src_argb, uint8* dst_argb, int pix); void ARGB4444ToARGBRow_C(const uint8* src_argb, uint8* dst_argb, int pix); +void ARGBToRGBARow_SSSE3(const uint8* src_argb, uint8* dst_rgb, int pix); void ARGBToRGB24Row_SSSE3(const uint8* src_argb, uint8* dst_rgb, int pix); void ARGBToRAWRow_SSSE3(const uint8* src_argb, uint8* dst_rgb, int pix); void ARGBToRGB565Row_SSE2(const uint8* src_argb, uint8* dst_rgb, int pix); void ARGBToARGB1555Row_SSE2(const uint8* src_argb, uint8* dst_rgb, int pix); void ARGBToARGB4444Row_SSE2(const uint8* src_argb, uint8* dst_rgb, int pix); +void ARGBToRGBARow_C(const uint8* src_argb, uint8* dst_rgb, int pix); void ARGBToRGB24Row_C(const uint8* src_argb, uint8* dst_rgb, int pix); void ARGBToRAWRow_C(const uint8* src_argb, uint8* dst_rgb, int pix); void ARGBToRGB565Row_C(const uint8* src_argb, uint8* dst_rgb, int pix); diff --git a/source/row_common.cc b/source/row_common.cc index de9add459..83d31a793 100644 --- a/source/row_common.cc +++ b/source/row_common.cc @@ -139,6 +139,21 @@ void ARGB4444ToARGBRow_C(const uint8* src_rgb, uint8* dst_argb, int width) { } } +void ARGBToRGBARow_C(const uint8* src_argb, uint8* dst_rgb, int width) { + for (int x = 0; x < width; ++x) { + uint8 b = src_argb[0]; + uint8 g = src_argb[1]; + uint8 r = src_argb[2]; + uint8 a = src_argb[3]; + dst_rgb[0] = a; + dst_rgb[1] = b; + dst_rgb[2] = g; + dst_rgb[3] = r; + dst_rgb += 4; + src_argb += 4; + } +} + void ARGBToRGB24Row_C(const uint8* src_argb, uint8* dst_rgb, int width) { for (int x = 0; x < width; ++x) { uint8 b = src_argb[0]; diff --git a/source/row_posix.cc b/source/row_posix.cc index 97feb2a38..0a9240d89 100644 --- a/source/row_posix.cc +++ b/source/row_posix.cc @@ -103,6 +103,11 @@ CONST uvec8 kShuffleMaskRGBAToARGB = { 1u, 2u, 3u, 0u, 5u, 6u, 7u, 4u, 9u, 10u, 11u, 8u, 13u, 14u, 15u, 12u }; +// Shuffle table for converting ARGB to RGBA. +CONST uvec8 kShuffleMaskARGBToRGBA = { + 3u, 0u, 1u, 2u, 7u, 4u, 5u, 6u, 11u, 8u, 9u, 10u, 15u, 12u, 13u, 14u +}; + // Shuffle table for converting ARGB to RGB24. CONST uvec8 kShuffleMaskARGBToRGB24 = { 0u, 1u, 2u, 4u, 5u, 6u, 8u, 9u, 10u, 12u, 13u, 14u, 128u, 128u, 128u, 128u @@ -214,6 +219,30 @@ void RGBAToARGBRow_SSSE3(const uint8* src_rgba, uint8* dst_argb, int pix) { ); } +void ARGBToRGBARow_SSSE3(const uint8* src_argb, uint8* dst_rgba, int pix) { + asm volatile ( + "movdqa %3,%%xmm5 \n" + "sub %0,%1 \n" + ".p2align 4 \n" + "1: \n" + "movdqa (%0),%%xmm0 \n" + "pshufb %%xmm5,%%xmm0 \n" + "sub $0x4,%2 \n" + "movdqa %%xmm0,(%0,%1,1) \n" + "lea 0x10(%0),%0 \n" + "jg 1b \n" + + : "+r"(src_argb), // %0 + "+r"(dst_rgba), // %1 + "+r"(pix) // %2 + : "m"(kShuffleMaskARGBToRGBA) // %3 + : "memory", "cc" +#if defined(__SSE2__) + , "xmm0", "xmm5" +#endif + ); +} + void RGB24ToARGBRow_SSSE3(const uint8* src_rgb24, uint8* dst_argb, int pix) { asm volatile ( "pcmpeqb %%xmm5,%%xmm5 \n" // generate mask 0xff000000 diff --git a/source/row_win.cc b/source/row_win.cc index 5ac8c9cc6..1afe052a7 100644 --- a/source/row_win.cc +++ b/source/row_win.cc @@ -93,6 +93,11 @@ static const uvec8 kShuffleMaskRGBAToARGB = { 1u, 2u, 3u, 0u, 5u, 6u, 7u, 4u, 9u, 10u, 11u, 8u, 13u, 14u, 15u, 12u }; +// Shuffle table for converting ARGB to RGBA. +static const uvec8 kShuffleMaskARGBToRGBA = { + 3u, 0u, 1u, 2u, 7u, 4u, 5u, 6u, 11u, 8u, 9u, 10u, 15u, 12u, 13u, 14u +}; + // Shuffle table for converting ARGB to RGB24. static const uvec8 kShuffleMaskARGBToRGB24 = { 0u, 1u, 2u, 4u, 5u, 6u, 8u, 9u, 10u, 12u, 13u, 14u, 128u, 128u, 128u, 128u @@ -194,6 +199,27 @@ __asm { } } +__declspec(naked) __declspec(align(16)) +void ARGBToRGBARow_SSSE3(const uint8* src_argb, uint8* dst_rgba, int pix) { +__asm { + mov eax, [esp + 4] // src_argb + mov edx, [esp + 8] // dst_rgba + mov ecx, [esp + 12] // pix + movdqa xmm5, kShuffleMaskARGBToRGBA + sub edx, eax + + align 16 + convertloop: + movdqa xmm0, [eax] + pshufb xmm0, xmm5 + sub ecx, 4 + movdqa [eax + edx], xmm0 + lea eax, [eax + 16] + jg convertloop + ret + } +} + __declspec(naked) __declspec(align(16)) void RGB24ToARGBRow_SSSE3(const uint8* src_rgb24, uint8* dst_argb, int pix) { __asm { diff --git a/unit_test/planar_test.cc b/unit_test/planar_test.cc index 62e0a4461..f12206022 100644 --- a/unit_test/planar_test.cc +++ b/unit_test/planar_test.cc @@ -299,6 +299,7 @@ TEST_F(libyuvTest, FMT_A##To##FMT_B##N##_OptVsC) { \ TESTATOB(ARGB, 4, 4, ARGB, 4) TESTATOB(ARGB, 4, 4, BGRA, 4) TESTATOB(ARGB, 4, 4, ABGR, 4) +TESTATOB(ARGB, 4, 4, RGBA, 4) TESTATOB(ARGB, 4, 4, RAW, 3) TESTATOB(ARGB, 4, 4, RGB24, 3) TESTATOB(ARGB, 4, 4, RGB565, 2) @@ -355,6 +356,7 @@ TEST_F(libyuvTest, FMT_A##To##FMT_B##_Random) { \ TESTATOBRANDOM(ARGB, 4, 4, ARGB, 4) TESTATOBRANDOM(ARGB, 4, 4, BGRA, 4) TESTATOBRANDOM(ARGB, 4, 4, ABGR, 4) +TESTATOBRANDOM(ARGB, 4, 4, RGBA, 4) TESTATOBRANDOM(ARGB, 4, 4, RAW, 3) TESTATOBRANDOM(ARGB, 4, 4, RGB24, 3) TESTATOBRANDOM(ARGB, 4, 4, RGB565, 2)