Index: source/libvpx/third_party/libyuv/source/convert_from.cc |
diff --git a/source/libvpx/third_party/libyuv/source/convert_from.cc b/source/libvpx/third_party/libyuv/source/convert_from.cc |
index b743cde264bd7e0b42f7906d631651389a3265be..31f1ac992ae161799fd0bab41ca6a3c59e9fa627 100644 |
--- a/source/libvpx/third_party/libyuv/source/convert_from.cc |
+++ b/source/libvpx/third_party/libyuv/source/convert_from.cc |
@@ -739,6 +739,14 @@ int I420ToRGB24(const uint8* src_y, int src_stride_y, |
} |
} |
#endif |
+#if defined(HAS_I422TORGB24ROW_AVX2) |
+ if (TestCpuFlag(kCpuHasAVX2)) { |
+ I422ToRGB24Row = I422ToRGB24Row_Any_AVX2; |
+ if (IS_ALIGNED(width, 16)) { |
+ I422ToRGB24Row = I422ToRGB24Row_AVX2; |
+ } |
+ } |
+#endif |
#if defined(HAS_I422TORGB24ROW_NEON) |
if (TestCpuFlag(kCpuHasNEON)) { |
I422ToRGB24Row = I422ToRGB24Row_Any_NEON; |
@@ -791,6 +799,14 @@ int I420ToRAW(const uint8* src_y, int src_stride_y, |
} |
} |
#endif |
+#if defined(HAS_I422TORAWROW_AVX2) |
+ if (TestCpuFlag(kCpuHasAVX2)) { |
+ I422ToRAWRow = I422ToRAWRow_Any_AVX2; |
+ if (IS_ALIGNED(width, 16)) { |
+ I422ToRAWRow = I422ToRAWRow_AVX2; |
+ } |
+ } |
+#endif |
#if defined(HAS_I422TORAWROW_NEON) |
if (TestCpuFlag(kCpuHasNEON)) { |
I422ToRAWRow = I422ToRAWRow_Any_NEON; |
@@ -993,6 +1009,117 @@ int I420ToRGB565(const uint8* src_y, int src_stride_y, |
return 0; |
} |
+// Ordered 8x8 dither for 888 to 565. Values from 0 to 7. |
+static const uint8 kDither565_4x4[16] = { |
+ 0, 4, 1, 5, |
+ 6, 2, 7, 3, |
+ 1, 5, 0, 4, |
+ 7, 3, 6, 2, |
+}; |
+ |
+// Convert I420 to RGB565 with dithering. |
+LIBYUV_API |
+int I420ToRGB565Dither(const uint8* src_y, int src_stride_y, |
+ const uint8* src_u, int src_stride_u, |
+ const uint8* src_v, int src_stride_v, |
+ uint8* dst_rgb565, int dst_stride_rgb565, |
+ const uint8* dither4x4, int width, int height) { |
+ int y; |
+ void (*I422ToARGBRow)(const uint8* y_buf, |
+ const uint8* u_buf, |
+ const uint8* v_buf, |
+ uint8* rgb_buf, |
+ int width) = I422ToARGBRow_C; |
+ void (*ARGBToRGB565DitherRow)(const uint8* src_argb, uint8* dst_rgb, |
+ const uint32 dither4, int pix) = ARGBToRGB565DitherRow_C; |
+ if (!src_y || !src_u || !src_v || !dst_rgb565 || |
+ width <= 0 || height == 0) { |
+ return -1; |
+ } |
+ // Negative height means invert the image. |
+ if (height < 0) { |
+ height = -height; |
+ dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565; |
+ dst_stride_rgb565 = -dst_stride_rgb565; |
+ } |
+ if (!dither4x4) { |
+ dither4x4 = kDither565_4x4; |
+ } |
+#if defined(HAS_I422TOARGBROW_SSSE3) |
+ if (TestCpuFlag(kCpuHasSSSE3)) { |
+ I422ToARGBRow = I422ToARGBRow_Any_SSSE3; |
+ if (IS_ALIGNED(width, 8)) { |
+ I422ToARGBRow = I422ToARGBRow_SSSE3; |
+ } |
+ } |
+#endif |
+#if defined(HAS_I422TOARGBROW_AVX2) |
+ if (TestCpuFlag(kCpuHasAVX2)) { |
+ I422ToARGBRow = I422ToARGBRow_Any_AVX2; |
+ if (IS_ALIGNED(width, 16)) { |
+ I422ToARGBRow = I422ToARGBRow_AVX2; |
+ } |
+ } |
+#endif |
+#if defined(HAS_I422TOARGBROW_NEON) |
+ if (TestCpuFlag(kCpuHasNEON)) { |
+ I422ToARGBRow = I422ToARGBRow_Any_NEON; |
+ if (IS_ALIGNED(width, 8)) { |
+ I422ToARGBRow = I422ToARGBRow_NEON; |
+ } |
+ } |
+#endif |
+#if defined(HAS_I422TOARGBROW_MIPS_DSPR2) |
+ if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(width, 4) && |
+ IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) && |
+ IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) && |
+ IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2)) { |
+ I422ToARGBRow = I422ToARGBRow_MIPS_DSPR2; |
+ } |
+#endif |
+#if defined(HAS_ARGBTORGB565DITHERROW_SSE2) |
+ if (TestCpuFlag(kCpuHasSSE2)) { |
+ ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_SSE2; |
+ if (IS_ALIGNED(width, 4)) { |
+ ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_SSE2; |
+ } |
+ } |
+#endif |
+#if defined(HAS_ARGBTORGB565DITHERROW_AVX2) |
+ if (TestCpuFlag(kCpuHasAVX2)) { |
+ ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_AVX2; |
+ if (IS_ALIGNED(width, 8)) { |
+ ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_AVX2; |
+ } |
+ } |
+#endif |
+#if defined(HAS_ARGBTORGB565DITHERROW_NEON) |
+ if (TestCpuFlag(kCpuHasNEON)) { |
+ ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_NEON; |
+ if (IS_ALIGNED(width, 8)) { |
+ ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_NEON; |
+ } |
+ } |
+#endif |
+ { |
+ // Allocate a row of argb. |
+ align_buffer_64(row_argb, width * 4); |
+ for (y = 0; y < height; ++y) { |
+ I422ToARGBRow(src_y, src_u, src_v, row_argb, width); |
+ ARGBToRGB565DitherRow(row_argb, dst_rgb565, |
+ *(uint32*)(dither4x4 + ((y & 3) << 2)), width); |
+ dst_rgb565 += dst_stride_rgb565; |
+ src_y += src_stride_y; |
+ if (y & 1) { |
+ src_u += src_stride_u; |
+ src_v += src_stride_v; |
+ } |
+ } |
+ free_aligned_buffer_64(row_argb); |
+ } |
+ return 0; |
+} |
+ |
// Convert I420 to specified format |
LIBYUV_API |
int ConvertFromI420(const uint8* y, int y_stride, |