Index: third_party/libwebp/dsp/yuv.c |
diff --git a/third_party/libwebp/dsp/yuv.c b/third_party/libwebp/dsp/yuv.c |
index 6f422da532f76f55a51ce7d2cfeec269cde4f1df..f50a253168fee677de8effcd772d846cdeb3f3dd 100644 |
--- a/third_party/libwebp/dsp/yuv.c |
+++ b/third_party/libwebp/dsp/yuv.c |
@@ -26,7 +26,7 @@ int32_t VP8kVToG[256], VP8kUToG[256]; |
uint8_t VP8kClip[YUV_RANGE_MAX - YUV_RANGE_MIN]; |
uint8_t VP8kClip4Bits[YUV_RANGE_MAX - YUV_RANGE_MIN]; |
-void VP8YUVInit(void) { |
+WEBP_TSAN_IGNORE_FUNCTION void VP8YUVInit(void) { |
int i; |
if (done) { |
return; |
@@ -62,7 +62,7 @@ void VP8YUVInit(void) { |
#else |
-void VP8YUVInit(void) {} |
+WEBP_TSAN_IGNORE_FUNCTION void VP8YUVInit(void) {} |
#endif // WEBP_YUV_USE_TABLE |
@@ -122,11 +122,12 @@ WebPSamplerRowFunc WebPSamplers[MODE_LAST]; |
extern void WebPInitSamplersSSE2(void); |
extern void WebPInitSamplersMIPS32(void); |
+extern void WebPInitSamplersMIPSdspR2(void); |
static volatile VP8CPUInfo yuv_last_cpuinfo_used = |
(VP8CPUInfo)&yuv_last_cpuinfo_used; |
-void WebPInitSamplers(void) { |
+WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplers(void) { |
if (yuv_last_cpuinfo_used == VP8GetCPUInfo) return; |
WebPSamplers[MODE_RGB] = YuvToRgbRow; |
@@ -153,8 +154,127 @@ void WebPInitSamplers(void) { |
WebPInitSamplersMIPS32(); |
} |
#endif // WEBP_USE_MIPS32 |
+#if defined(WEBP_USE_MIPS_DSP_R2) |
+ if (VP8GetCPUInfo(kMIPSdspR2)) { |
+ WebPInitSamplersMIPSdspR2(); |
+ } |
+#endif // WEBP_USE_MIPS_DSP_R2 |
} |
yuv_last_cpuinfo_used = VP8GetCPUInfo; |
} |
//----------------------------------------------------------------------------- |
+// ARGB -> YUV converters |
+ |
+static void ConvertARGBToY(const uint32_t* argb, uint8_t* y, int width) { |
+ int i; |
+ for (i = 0; i < width; ++i) { |
+ const uint32_t p = argb[i]; |
+ y[i] = VP8RGBToY((p >> 16) & 0xff, (p >> 8) & 0xff, (p >> 0) & 0xff, |
+ YUV_HALF); |
+ } |
+} |
+ |
+void WebPConvertARGBToUV_C(const uint32_t* argb, uint8_t* u, uint8_t* v, |
+ int src_width, int do_store) { |
+ // No rounding. Last pixel is dealt with separately. |
+ const int uv_width = src_width >> 1; |
+ int i; |
+ for (i = 0; i < uv_width; ++i) { |
+ const uint32_t v0 = argb[2 * i + 0]; |
+ const uint32_t v1 = argb[2 * i + 1]; |
+ // VP8RGBToU/V expects four accumulated pixels. Hence we need to |
+ // scale r/g/b value by a factor 2. We just shift v0/v1 one bit less. |
+ const int r = ((v0 >> 15) & 0x1fe) + ((v1 >> 15) & 0x1fe); |
+ const int g = ((v0 >> 7) & 0x1fe) + ((v1 >> 7) & 0x1fe); |
+ const int b = ((v0 << 1) & 0x1fe) + ((v1 << 1) & 0x1fe); |
+ const int tmp_u = VP8RGBToU(r, g, b, YUV_HALF << 2); |
+ const int tmp_v = VP8RGBToV(r, g, b, YUV_HALF << 2); |
+ if (do_store) { |
+ u[i] = tmp_u; |
+ v[i] = tmp_v; |
+ } else { |
+ // Approximated average-of-four. But it's an acceptable diff. |
+ u[i] = (u[i] + tmp_u + 1) >> 1; |
+ v[i] = (v[i] + tmp_v + 1) >> 1; |
+ } |
+ } |
+ if (src_width & 1) { // last pixel |
+ const uint32_t v0 = argb[2 * i + 0]; |
+ const int r = (v0 >> 14) & 0x3fc; |
+ const int g = (v0 >> 6) & 0x3fc; |
+ const int b = (v0 << 2) & 0x3fc; |
+ const int tmp_u = VP8RGBToU(r, g, b, YUV_HALF << 2); |
+ const int tmp_v = VP8RGBToV(r, g, b, YUV_HALF << 2); |
+ if (do_store) { |
+ u[i] = tmp_u; |
+ v[i] = tmp_v; |
+ } else { |
+ u[i] = (u[i] + tmp_u + 1) >> 1; |
+ v[i] = (v[i] + tmp_v + 1) >> 1; |
+ } |
+ } |
+} |
+ |
+//----------------------------------------------------------------------------- |
+ |
+static void ConvertRGB24ToY(const uint8_t* rgb, uint8_t* y, int width) { |
+ int i; |
+ for (i = 0; i < width; ++i, rgb += 3) { |
+ y[i] = VP8RGBToY(rgb[0], rgb[1], rgb[2], YUV_HALF); |
+ } |
+} |
+ |
+static void ConvertBGR24ToY(const uint8_t* bgr, uint8_t* y, int width) { |
+ int i; |
+ for (i = 0; i < width; ++i, bgr += 3) { |
+ y[i] = VP8RGBToY(bgr[2], bgr[1], bgr[0], YUV_HALF); |
+ } |
+} |
+ |
+void WebPConvertRGBA32ToUV_C(const uint16_t* rgb, |
+ uint8_t* u, uint8_t* v, int width) { |
+ int i; |
+ for (i = 0; i < width; i += 1, rgb += 4) { |
+ const int r = rgb[0], g = rgb[1], b = rgb[2]; |
+ u[i] = VP8RGBToU(r, g, b, YUV_HALF << 2); |
+ v[i] = VP8RGBToV(r, g, b, YUV_HALF << 2); |
+ } |
+} |
+ |
+//----------------------------------------------------------------------------- |
+ |
+void (*WebPConvertRGB24ToY)(const uint8_t* rgb, uint8_t* y, int width); |
+void (*WebPConvertBGR24ToY)(const uint8_t* bgr, uint8_t* y, int width); |
+void (*WebPConvertRGBA32ToUV)(const uint16_t* rgb, |
+ uint8_t* u, uint8_t* v, int width); |
+ |
+void (*WebPConvertARGBToY)(const uint32_t* argb, uint8_t* y, int width); |
+void (*WebPConvertARGBToUV)(const uint32_t* argb, uint8_t* u, uint8_t* v, |
+ int src_width, int do_store); |
+ |
+static volatile VP8CPUInfo rgba_to_yuv_last_cpuinfo_used = |
+ (VP8CPUInfo)&rgba_to_yuv_last_cpuinfo_used; |
+ |
+extern void WebPInitConvertARGBToYUVSSE2(void); |
+ |
+WEBP_TSAN_IGNORE_FUNCTION void WebPInitConvertARGBToYUV(void) { |
+ if (rgba_to_yuv_last_cpuinfo_used == VP8GetCPUInfo) return; |
+ |
+ WebPConvertARGBToY = ConvertARGBToY; |
+ WebPConvertARGBToUV = WebPConvertARGBToUV_C; |
+ |
+ WebPConvertRGB24ToY = ConvertRGB24ToY; |
+ WebPConvertBGR24ToY = ConvertBGR24ToY; |
+ |
+ WebPConvertRGBA32ToUV = WebPConvertRGBA32ToUV_C; |
+ |
+ if (VP8GetCPUInfo != NULL) { |
+#if defined(WEBP_USE_SSE2) |
+ if (VP8GetCPUInfo(kSSE2)) { |
+ WebPInitConvertARGBToYUVSSE2(); |
+ } |
+#endif // WEBP_USE_SSE2 |
+ } |
+ rgba_to_yuv_last_cpuinfo_used = VP8GetCPUInfo; |
+} |