| Index: third_party/libwebp/dsp/filters_msa.c
|
| diff --git a/third_party/libwebp/dsp/filters_msa.c b/third_party/libwebp/dsp/filters_msa.c
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..4b8922d0bcccc7f181b2d7a55f062b752e183421
|
| --- /dev/null
|
| +++ b/third_party/libwebp/dsp/filters_msa.c
|
| @@ -0,0 +1,202 @@
|
| +// Copyright 2016 Google Inc. All Rights Reserved.
|
| +//
|
| +// Use of this source code is governed by a BSD-style license
|
| +// that can be found in the COPYING file in the root of the source
|
| +// tree. An additional intellectual property rights grant can be found
|
| +// in the file PATENTS. All contributing project authors may
|
| +// be found in the AUTHORS file in the root of the source tree.
|
| +// -----------------------------------------------------------------------------
|
| +//
|
| +// MSA variant of alpha filters
|
| +//
|
| +// Author: Prashant Patil (prashant.patil@imgtec.com)
|
| +
|
| +#include "./dsp.h"
|
| +
|
| +#if defined(WEBP_USE_MSA)
|
| +
|
| +#include "./msa_macro.h"
|
| +
|
| +#include <assert.h>
|
| +
|
| +static WEBP_INLINE void PredictLineInverse0(const uint8_t* src,
|
| + const uint8_t* pred,
|
| + uint8_t* dst, int length) {
|
| + v16u8 src0, pred0, dst0;
|
| + assert(length >= 0);
|
| + while (length >= 32) {
|
| + v16u8 src1, pred1, dst1;
|
| + LD_UB2(src, 16, src0, src1);
|
| + LD_UB2(pred, 16, pred0, pred1);
|
| + SUB2(src0, pred0, src1, pred1, dst0, dst1);
|
| + ST_UB2(dst0, dst1, dst, 16);
|
| + src += 32;
|
| + pred += 32;
|
| + dst += 32;
|
| + length -= 32;
|
| + }
|
| + if (length > 0) {
|
| + int i;
|
| + if (length >= 16) {
|
| + src0 = LD_UB(src);
|
| + pred0 = LD_UB(pred);
|
| + dst0 = src0 - pred0;
|
| + ST_UB(dst0, dst);
|
| + src += 16;
|
| + pred += 16;
|
| + dst += 16;
|
| + length -= 16;
|
| + }
|
| + for (i = 0; i < length; i++) {
|
| + dst[i] = src[i] - pred[i];
|
| + }
|
| + }
|
| +}
|
| +
|
| +//------------------------------------------------------------------------------
|
| +// Helpful macro.
|
| +
|
| +#define SANITY_CHECK(in, out) \
|
| + assert(in != NULL); \
|
| + assert(out != NULL); \
|
| + assert(width > 0); \
|
| + assert(height > 0); \
|
| + assert(stride >= width);
|
| +
|
| +//------------------------------------------------------------------------------
|
| +// Horrizontal filter
|
| +
|
| +static void HorizontalFilter(const uint8_t* data, int width, int height,
|
| + int stride, uint8_t* filtered_data) {
|
| + const uint8_t* preds = data;
|
| + const uint8_t* in = data;
|
| + uint8_t* out = filtered_data;
|
| + int row = 1;
|
| + SANITY_CHECK(in, out);
|
| +
|
| + // Leftmost pixel is the same as input for topmost scanline.
|
| + out[0] = in[0];
|
| + PredictLineInverse0(in + 1, preds, out + 1, width - 1);
|
| + preds += stride;
|
| + in += stride;
|
| + out += stride;
|
| + // Filter line-by-line.
|
| + while (row < height) {
|
| + // Leftmost pixel is predicted from above.
|
| + PredictLineInverse0(in, preds - stride, out, 1);
|
| + PredictLineInverse0(in + 1, preds, out + 1, width - 1);
|
| + ++row;
|
| + preds += stride;
|
| + in += stride;
|
| + out += stride;
|
| + }
|
| +}
|
| +
|
| +//------------------------------------------------------------------------------
|
| +// Gradient filter
|
| +
|
| +static WEBP_INLINE void PredictLineGradient(const uint8_t* pinput,
|
| + const uint8_t* ppred,
|
| + uint8_t* poutput, int stride,
|
| + int size) {
|
| + int w;
|
| + const v16i8 zero = { 0 };
|
| + while (size >= 16) {
|
| + v16u8 pred0, dst0;
|
| + v8i16 a0, a1, b0, b1, c0, c1;
|
| + const v16u8 tmp0 = LD_UB(ppred - 1);
|
| + const v16u8 tmp1 = LD_UB(ppred - stride);
|
| + const v16u8 tmp2 = LD_UB(ppred - stride - 1);
|
| + const v16u8 src0 = LD_UB(pinput);
|
| + ILVRL_B2_SH(zero, tmp0, a0, a1);
|
| + ILVRL_B2_SH(zero, tmp1, b0, b1);
|
| + ILVRL_B2_SH(zero, tmp2, c0, c1);
|
| + ADD2(a0, b0, a1, b1, a0, a1);
|
| + SUB2(a0, c0, a1, c1, a0, a1);
|
| + CLIP_SH2_0_255(a0, a1);
|
| + pred0 = (v16u8)__msa_pckev_b((v16i8)a1, (v16i8)a0);
|
| + dst0 = src0 - pred0;
|
| + ST_UB(dst0, poutput);
|
| + ppred += 16;
|
| + pinput += 16;
|
| + poutput += 16;
|
| + size -= 16;
|
| + }
|
| + for (w = 0; w < size; ++w) {
|
| + const int pred = ppred[w - 1] + ppred[w - stride] - ppred[w - stride - 1];
|
| + poutput[w] = pinput[w] - (pred < 0 ? 0 : pred > 255 ? 255 : pred);
|
| + }
|
| +}
|
| +
|
| +
|
| +static void GradientFilter(const uint8_t* data, int width, int height,
|
| + int stride, uint8_t* filtered_data) {
|
| + const uint8_t* in = data;
|
| + const uint8_t* preds = data;
|
| + uint8_t* out = filtered_data;
|
| + int row = 1;
|
| + SANITY_CHECK(in, out);
|
| +
|
| + // left prediction for top scan-line
|
| + out[0] = in[0];
|
| + PredictLineInverse0(in + 1, preds, out + 1, width - 1);
|
| + preds += stride;
|
| + in += stride;
|
| + out += stride;
|
| + // Filter line-by-line.
|
| + while (row < height) {
|
| + out[0] = in[0] - preds[- stride];
|
| + PredictLineGradient(preds + 1, in + 1, out + 1, stride, width - 1);
|
| + ++row;
|
| + preds += stride;
|
| + in += stride;
|
| + out += stride;
|
| + }
|
| +}
|
| +
|
| +//------------------------------------------------------------------------------
|
| +// Vertical filter
|
| +
|
| +static void VerticalFilter(const uint8_t* data, int width, int height,
|
| + int stride, uint8_t* filtered_data) {
|
| + const uint8_t* in = data;
|
| + const uint8_t* preds = data;
|
| + uint8_t* out = filtered_data;
|
| + int row = 1;
|
| + SANITY_CHECK(in, out);
|
| +
|
| + // Very first top-left pixel is copied.
|
| + out[0] = in[0];
|
| + // Rest of top scan-line is left-predicted.
|
| + PredictLineInverse0(in + 1, preds, out + 1, width - 1);
|
| + in += stride;
|
| + out += stride;
|
| +
|
| + // Filter line-by-line.
|
| + while (row < height) {
|
| + PredictLineInverse0(in, preds, out, width);
|
| + ++row;
|
| + preds += stride;
|
| + in += stride;
|
| + out += stride;
|
| + }
|
| +}
|
| +
|
| +#undef SANITY_CHECK
|
| +
|
| +//------------------------------------------------------------------------------
|
| +// Entry point
|
| +
|
| +extern void VP8FiltersInitMSA(void);
|
| +
|
| +WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInitMSA(void) {
|
| + WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter;
|
| + WebPFilters[WEBP_FILTER_VERTICAL] = VerticalFilter;
|
| + WebPFilters[WEBP_FILTER_GRADIENT] = GradientFilter;
|
| +}
|
| +
|
| +#else // !WEBP_USE_MSA
|
| +
|
| +WEBP_DSP_INIT_STUB(VP8FiltersInitMSA)
|
| +
|
| +#endif // WEBP_USE_MSA
|
|
|