Blame src/dsp/rescaler_msa.c

Packit 9c6abc
// Copyright 2016 Google Inc. All Rights Reserved.
Packit 9c6abc
//
Packit 9c6abc
// Use of this source code is governed by a BSD-style license
Packit 9c6abc
// that can be found in the COPYING file in the root of the source
Packit 9c6abc
// tree. An additional intellectual property rights grant can be found
Packit 9c6abc
// in the file PATENTS. All contributing project authors may
Packit 9c6abc
// be found in the AUTHORS file in the root of the source tree.
Packit 9c6abc
// -----------------------------------------------------------------------------
Packit 9c6abc
//
Packit 9c6abc
// MSA version of rescaling functions
Packit 9c6abc
//
Packit 9c6abc
// Author: Prashant Patil (prashant.patil@imgtec.com)
Packit 9c6abc
Packit 9c6abc
#include "src/dsp/dsp.h"
Packit 9c6abc
Packit 9c6abc
#if defined(WEBP_USE_MSA) && !defined(WEBP_REDUCE_SIZE)
Packit 9c6abc
Packit 9c6abc
#include <assert.h>
Packit 9c6abc
Packit 9c6abc
#include "src/utils/rescaler_utils.h"
Packit 9c6abc
#include "src/dsp/msa_macro.h"
Packit 9c6abc
Packit 9c6abc
#define ROUNDER (WEBP_RESCALER_ONE >> 1)
Packit 9c6abc
#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
Packit 9c6abc
Packit 9c6abc
#define CALC_MULT_FIX_16(in0, in1, in2, in3, scale, shift, dst) do {  \
Packit 9c6abc
  v4u32 tmp0, tmp1, tmp2, tmp3;                                       \
Packit 9c6abc
  v16u8 t0, t1, t2, t3, t4, t5;                                       \
Packit 9c6abc
  v2u64 out0, out1, out2, out3;                                       \
Packit 9c6abc
  ILVRL_W2_UW(zero, in0, tmp0, tmp1);                                 \
Packit 9c6abc
  ILVRL_W2_UW(zero, in1, tmp2, tmp3);                                 \
Packit 9c6abc
  DOTP_UW2_UD(tmp0, tmp1, scale, scale, out0, out1);                  \
Packit 9c6abc
  DOTP_UW2_UD(tmp2, tmp3, scale, scale, out2, out3);                  \
Packit 9c6abc
  SRAR_D4_UD(out0, out1, out2, out3, shift);                          \
Packit 9c6abc
  PCKEV_B2_UB(out1, out0, out3, out2, t0, t1);                        \
Packit 9c6abc
  ILVRL_W2_UW(zero, in2, tmp0, tmp1);                                 \
Packit 9c6abc
  ILVRL_W2_UW(zero, in3, tmp2, tmp3);                                 \
Packit 9c6abc
  DOTP_UW2_UD(tmp0, tmp1, scale, scale, out0, out1);                  \
Packit 9c6abc
  DOTP_UW2_UD(tmp2, tmp3, scale, scale, out2, out3);                  \
Packit 9c6abc
  SRAR_D4_UD(out0, out1, out2, out3, shift);                          \
Packit 9c6abc
  PCKEV_B2_UB(out1, out0, out3, out2, t2, t3);                        \
Packit 9c6abc
  PCKEV_B2_UB(t1, t0, t3, t2, t4, t5);                                \
Packit 9c6abc
  dst = (v16u8)__msa_pckev_b((v16i8)t5, (v16i8)t4);                   \
Packit 9c6abc
} while (0)
Packit 9c6abc
Packit 9c6abc
#define CALC_MULT_FIX_4(in0, scale, shift, dst) do {  \
Packit 9c6abc
  v4u32 tmp0, tmp1;                                   \
Packit 9c6abc
  v16i8 t0, t1;                                       \
Packit 9c6abc
  v2u64 out0, out1;                                   \
Packit 9c6abc
  ILVRL_W2_UW(zero, in0, tmp0, tmp1);                 \
Packit 9c6abc
  DOTP_UW2_UD(tmp0, tmp1, scale, scale, out0, out1);  \
Packit 9c6abc
  SRAR_D2_UD(out0, out1, shift);                      \
Packit 9c6abc
  t0 = __msa_pckev_b((v16i8)out1, (v16i8)out0);       \
Packit 9c6abc
  t1 = __msa_pckev_b(t0, t0);                         \
Packit 9c6abc
  t0 = __msa_pckev_b(t1, t1);                         \
Packit 9c6abc
  dst = __msa_copy_s_w((v4i32)t0, 0);                 \
Packit 9c6abc
} while (0)
Packit 9c6abc
Packit 9c6abc
#define CALC_MULT_FIX1_16(in0, in1, in2, in3, fyscale, shift,  \
Packit 9c6abc
                          dst0, dst1, dst2, dst3) do {         \
Packit 9c6abc
  v4u32 tmp0, tmp1, tmp2, tmp3;                                \
Packit 9c6abc
  v2u64 out0, out1, out2, out3;                                \
Packit 9c6abc
  ILVRL_W2_UW(zero, in0, tmp0, tmp1);                          \
Packit 9c6abc
  ILVRL_W2_UW(zero, in1, tmp2, tmp3);                          \
Packit 9c6abc
  DOTP_UW2_UD(tmp0, tmp1, fyscale, fyscale, out0, out1);       \
Packit 9c6abc
  DOTP_UW2_UD(tmp2, tmp3, fyscale, fyscale, out2, out3);       \
Packit 9c6abc
  SRAR_D4_UD(out0, out1, out2, out3, shift);                   \
Packit 9c6abc
  PCKEV_W2_UW(out1, out0, out3, out2, dst0, dst1);             \
Packit 9c6abc
  ILVRL_W2_UW(zero, in2, tmp0, tmp1);                          \
Packit 9c6abc
  ILVRL_W2_UW(zero, in3, tmp2, tmp3);                          \
Packit 9c6abc
  DOTP_UW2_UD(tmp0, tmp1, fyscale, fyscale, out0, out1);       \
Packit 9c6abc
  DOTP_UW2_UD(tmp2, tmp3, fyscale, fyscale, out2, out3);       \
Packit 9c6abc
  SRAR_D4_UD(out0, out1, out2, out3, shift);                   \
Packit 9c6abc
  PCKEV_W2_UW(out1, out0, out3, out2, dst2, dst3);             \
Packit 9c6abc
} while (0)
Packit 9c6abc
Packit 9c6abc
#define CALC_MULT_FIX1_4(in0, scale, shift, dst) do {    \
Packit 9c6abc
  v4u32 tmp0, tmp1;                                      \
Packit 9c6abc
  v2u64 out0, out1;                                      \
Packit 9c6abc
  ILVRL_W2_UW(zero, in0, tmp0, tmp1);                    \
Packit 9c6abc
  DOTP_UW2_UD(tmp0, tmp1, scale, scale, out0, out1);     \
Packit 9c6abc
  SRAR_D2_UD(out0, out1, shift);                         \
Packit 9c6abc
  dst = (v4u32)__msa_pckev_w((v4i32)out1, (v4i32)out0);  \
Packit 9c6abc
} while (0)
Packit 9c6abc
Packit 9c6abc
#define CALC_MULT_FIX2_16(in0, in1, in2, in3, mult, scale, shift,  \
Packit 9c6abc
                          dst0, dst1) do {                         \
Packit 9c6abc
  v4u32 tmp0, tmp1, tmp2, tmp3;                                    \
Packit 9c6abc
  v2u64 out0, out1, out2, out3;                                    \
Packit 9c6abc
  ILVRL_W2_UW(in0, in2, tmp0, tmp1);                               \
Packit 9c6abc
  ILVRL_W2_UW(in1, in3, tmp2, tmp3);                               \
Packit 9c6abc
  DOTP_UW2_UD(tmp0, tmp1, mult, mult, out0, out1);                 \
Packit 9c6abc
  DOTP_UW2_UD(tmp2, tmp3, mult, mult, out2, out3);                 \
Packit 9c6abc
  SRAR_D4_UD(out0, out1, out2, out3, shift);                       \
Packit 9c6abc
  DOTP_UW2_UD(out0, out1, scale, scale, out0, out1);               \
Packit 9c6abc
  DOTP_UW2_UD(out2, out3, scale, scale, out2, out3);               \
Packit 9c6abc
  SRAR_D4_UD(out0, out1, out2, out3, shift);                       \
Packit 9c6abc
  PCKEV_B2_UB(out1, out0, out3, out2, dst0, dst1);                 \
Packit 9c6abc
} while (0)
Packit 9c6abc
Packit 9c6abc
#define CALC_MULT_FIX2_4(in0, in1, mult, scale, shift, dst) do {  \
Packit 9c6abc
  v4u32 tmp0, tmp1;                                               \
Packit 9c6abc
  v2u64 out0, out1;                                               \
Packit 9c6abc
  v16i8 t0, t1;                                                   \
Packit 9c6abc
  ILVRL_W2_UW(in0, in1, tmp0, tmp1);                              \
Packit 9c6abc
  DOTP_UW2_UD(tmp0, tmp1, mult, mult, out0, out1);                \
Packit 9c6abc
  SRAR_D2_UD(out0, out1, shift);                                  \
Packit 9c6abc
  DOTP_UW2_UD(out0, out1, scale, scale, out0, out1);              \
Packit 9c6abc
  SRAR_D2_UD(out0, out1, shift);                                  \
Packit 9c6abc
  t0 = __msa_pckev_b((v16i8)out1, (v16i8)out0);                   \
Packit 9c6abc
  t1 = __msa_pckev_b(t0, t0);                                     \
Packit 9c6abc
  t0 = __msa_pckev_b(t1, t1);                                     \
Packit 9c6abc
  dst = __msa_copy_s_w((v4i32)t0, 0);                             \
Packit 9c6abc
} while (0)
Packit 9c6abc
Packit 9c6abc
static WEBP_INLINE void ExportRowExpand_0(const uint32_t* frow, uint8_t* dst,
Packit 9c6abc
                                          int length,
Packit 9c6abc
                                          WebPRescaler* const wrk) {
Packit 9c6abc
  const v4u32 scale = (v4u32)__msa_fill_w(wrk->fy_scale);
Packit 9c6abc
  const v4u32 shift = (v4u32)__msa_fill_w(WEBP_RESCALER_RFIX);
Packit 9c6abc
  const v4i32 zero = { 0 };
Packit 9c6abc
Packit 9c6abc
  while (length >= 16) {
Packit 9c6abc
    v4u32 src0, src1, src2, src3;
Packit 9c6abc
    v16u8 out;
Packit 9c6abc
    LD_UW4(frow, 4, src0, src1, src2, src3);
Packit 9c6abc
    CALC_MULT_FIX_16(src0, src1, src2, src3, scale, shift, out);
Packit 9c6abc
    ST_UB(out, dst);
Packit 9c6abc
    length -= 16;
Packit 9c6abc
    frow   += 16;
Packit 9c6abc
    dst    += 16;
Packit 9c6abc
  }
Packit 9c6abc
  if (length > 0) {
Packit 9c6abc
    int x_out;
Packit 9c6abc
    if (length >= 12) {
Packit 9c6abc
      uint32_t val0_m, val1_m, val2_m;
Packit 9c6abc
      v4u32 src0, src1, src2;
Packit 9c6abc
      LD_UW3(frow, 4, src0, src1, src2);
Packit 9c6abc
      CALC_MULT_FIX_4(src0, scale, shift, val0_m);
Packit 9c6abc
      CALC_MULT_FIX_4(src1, scale, shift, val1_m);
Packit 9c6abc
      CALC_MULT_FIX_4(src2, scale, shift, val2_m);
Packit 9c6abc
      SW3(val0_m, val1_m, val2_m, dst, 4);
Packit 9c6abc
      length -= 12;
Packit 9c6abc
      frow   += 12;
Packit 9c6abc
      dst    += 12;
Packit 9c6abc
    } else if (length >= 8) {
Packit 9c6abc
      uint32_t val0_m, val1_m;
Packit 9c6abc
      v4u32 src0, src1;
Packit 9c6abc
      LD_UW2(frow, 4, src0, src1);
Packit 9c6abc
      CALC_MULT_FIX_4(src0, scale, shift, val0_m);
Packit 9c6abc
      CALC_MULT_FIX_4(src1, scale, shift, val1_m);
Packit 9c6abc
      SW2(val0_m, val1_m, dst, 4);
Packit 9c6abc
      length -= 8;
Packit 9c6abc
      frow   += 8;
Packit 9c6abc
      dst    += 8;
Packit 9c6abc
    } else if (length >= 4) {
Packit 9c6abc
      uint32_t val0_m;
Packit 9c6abc
      const v4u32 src0 = LD_UW(frow);
Packit 9c6abc
      CALC_MULT_FIX_4(src0, scale, shift, val0_m);
Packit 9c6abc
      SW(val0_m, dst);
Packit 9c6abc
      length -= 4;
Packit 9c6abc
      frow   += 4;
Packit 9c6abc
      dst    += 4;
Packit 9c6abc
    }
Packit 9c6abc
    for (x_out = 0; x_out < length; ++x_out) {
Packit 9c6abc
      const uint32_t J = frow[x_out];
Packit 9c6abc
      const int v = (int)MULT_FIX(J, wrk->fy_scale);
Packit 9c6abc
      assert(v >= 0 && v <= 255);
Packit 9c6abc
      dst[x_out] = v;
Packit 9c6abc
    }
Packit 9c6abc
  }
Packit 9c6abc
}
Packit 9c6abc
Packit 9c6abc
static WEBP_INLINE void ExportRowExpand_1(const uint32_t* frow, uint32_t* irow,
Packit 9c6abc
                                          uint8_t* dst, int length,
Packit 9c6abc
                                          WebPRescaler* const wrk) {
Packit 9c6abc
  const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub);
Packit 9c6abc
  const uint32_t A = (uint32_t)(WEBP_RESCALER_ONE - B);
Packit 9c6abc
  const v4i32 B1 = __msa_fill_w(B);
Packit 9c6abc
  const v4i32 A1 = __msa_fill_w(A);
Packit 9c6abc
  const v4i32 AB = __msa_ilvr_w(A1, B1);
Packit 9c6abc
  const v4u32 scale = (v4u32)__msa_fill_w(wrk->fy_scale);
Packit 9c6abc
  const v4u32 shift = (v4u32)__msa_fill_w(WEBP_RESCALER_RFIX);
Packit 9c6abc
Packit 9c6abc
  while (length >= 16) {
Packit 9c6abc
    v4u32 frow0, frow1, frow2, frow3, irow0, irow1, irow2, irow3;
Packit 9c6abc
    v16u8 t0, t1, t2, t3, t4, t5;
Packit 9c6abc
    LD_UW4(frow, 4, frow0, frow1, frow2, frow3);
Packit 9c6abc
    LD_UW4(irow, 4, irow0, irow1, irow2, irow3);
Packit 9c6abc
    CALC_MULT_FIX2_16(frow0, frow1, irow0, irow1, AB, scale, shift, t0, t1);
Packit 9c6abc
    CALC_MULT_FIX2_16(frow2, frow3, irow2, irow3, AB, scale, shift, t2, t3);
Packit 9c6abc
    PCKEV_B2_UB(t1, t0, t3, t2, t4, t5);
Packit 9c6abc
    t0 = (v16u8)__msa_pckev_b((v16i8)t5, (v16i8)t4);
Packit 9c6abc
    ST_UB(t0, dst);
Packit 9c6abc
    frow   += 16;
Packit 9c6abc
    irow   += 16;
Packit 9c6abc
    dst    += 16;
Packit 9c6abc
    length -= 16;
Packit 9c6abc
  }
Packit 9c6abc
  if (length > 0) {
Packit 9c6abc
    int x_out;
Packit 9c6abc
    if (length >= 12) {
Packit 9c6abc
      uint32_t val0_m, val1_m, val2_m;
Packit 9c6abc
      v4u32 frow0, frow1, frow2, irow0, irow1, irow2;
Packit 9c6abc
      LD_UW3(frow, 4, frow0, frow1, frow2);
Packit 9c6abc
      LD_UW3(irow, 4, irow0, irow1, irow2);
Packit 9c6abc
      CALC_MULT_FIX2_4(frow0, irow0, AB, scale, shift, val0_m);
Packit 9c6abc
      CALC_MULT_FIX2_4(frow1, irow1, AB, scale, shift, val1_m);
Packit 9c6abc
      CALC_MULT_FIX2_4(frow2, irow2, AB, scale, shift, val2_m);
Packit 9c6abc
      SW3(val0_m, val1_m, val2_m, dst, 4);
Packit 9c6abc
      frow   += 12;
Packit 9c6abc
      irow   += 12;
Packit 9c6abc
      dst    += 12;
Packit 9c6abc
      length -= 12;
Packit 9c6abc
    } else if (length >= 8) {
Packit 9c6abc
      uint32_t val0_m, val1_m;
Packit 9c6abc
      v4u32 frow0, frow1, irow0, irow1;
Packit 9c6abc
      LD_UW2(frow, 4, frow0, frow1);
Packit 9c6abc
      LD_UW2(irow, 4, irow0, irow1);
Packit 9c6abc
      CALC_MULT_FIX2_4(frow0, irow0, AB, scale, shift, val0_m);
Packit 9c6abc
      CALC_MULT_FIX2_4(frow1, irow1, AB, scale, shift, val1_m);
Packit 9c6abc
      SW2(val0_m, val1_m, dst, 4);
Packit 9c6abc
      frow   += 4;
Packit 9c6abc
      irow   += 4;
Packit 9c6abc
      dst    += 4;
Packit 9c6abc
      length -= 4;
Packit 9c6abc
    } else if (length >= 4) {
Packit 9c6abc
      uint32_t val0_m;
Packit 9c6abc
      const v4u32 frow0 = LD_UW(frow + 0);
Packit 9c6abc
      const v4u32 irow0 = LD_UW(irow + 0);
Packit 9c6abc
      CALC_MULT_FIX2_4(frow0, irow0, AB, scale, shift, val0_m);
Packit 9c6abc
      SW(val0_m, dst);
Packit 9c6abc
      frow   += 4;
Packit 9c6abc
      irow   += 4;
Packit 9c6abc
      dst    += 4;
Packit 9c6abc
      length -= 4;
Packit 9c6abc
    }
Packit 9c6abc
    for (x_out = 0; x_out < length; ++x_out) {
Packit 9c6abc
      const uint64_t I = (uint64_t)A * frow[x_out]
Packit 9c6abc
                       + (uint64_t)B * irow[x_out];
Packit 9c6abc
      const uint32_t J = (uint32_t)((I + ROUNDER) >> WEBP_RESCALER_RFIX);
Packit 9c6abc
      const int v = (int)MULT_FIX(J, wrk->fy_scale);
Packit 9c6abc
      assert(v >= 0 && v <= 255);
Packit 9c6abc
      dst[x_out] = v;
Packit 9c6abc
    }
Packit 9c6abc
  }
Packit 9c6abc
}
Packit 9c6abc
Packit 9c6abc
static void RescalerExportRowExpand_MIPSdspR2(WebPRescaler* const wrk) {
Packit 9c6abc
  uint8_t* dst = wrk->dst;
Packit 9c6abc
  rescaler_t* irow = wrk->irow;
Packit 9c6abc
  const int x_out_max = wrk->dst_width * wrk->num_channels;
Packit 9c6abc
  const rescaler_t* frow = wrk->frow;
Packit 9c6abc
  assert(!WebPRescalerOutputDone(wrk));
Packit 9c6abc
  assert(wrk->y_accum <= 0);
Packit 9c6abc
  assert(wrk->y_expand);
Packit 9c6abc
  assert(wrk->y_sub != 0);
Packit 9c6abc
  if (wrk->y_accum == 0) {
Packit 9c6abc
    ExportRowExpand_0(frow, dst, x_out_max, wrk);
Packit 9c6abc
  } else {
Packit 9c6abc
    ExportRowExpand_1(frow, irow, dst, x_out_max, wrk);
Packit 9c6abc
  }
Packit 9c6abc
}
Packit 9c6abc
Packit 9c6abc
static WEBP_INLINE void ExportRowShrink_0(const uint32_t* frow, uint32_t* irow,
Packit 9c6abc
                                          uint8_t* dst, int length,
Packit 9c6abc
                                          const uint32_t yscale,
Packit 9c6abc
                                          WebPRescaler* const wrk) {
Packit 9c6abc
  const v4u32 y_scale = (v4u32)__msa_fill_w(yscale);
Packit 9c6abc
  const v4u32 fxyscale = (v4u32)__msa_fill_w(wrk->fxy_scale);
Packit 9c6abc
  const v4u32 shiftval = (v4u32)__msa_fill_w(WEBP_RESCALER_RFIX);
Packit 9c6abc
  const v4i32 zero = { 0 };
Packit 9c6abc
Packit 9c6abc
  while (length >= 16) {
Packit 9c6abc
    v4u32 src0, src1, src2, src3, frac0, frac1, frac2, frac3;
Packit 9c6abc
    v16u8 out;
Packit 9c6abc
    LD_UW4(frow, 4, src0, src1, src2, src3);
Packit 9c6abc
    CALC_MULT_FIX1_16(src0, src1, src2, src3, y_scale, shiftval,
Packit 9c6abc
                      frac0, frac1, frac2, frac3);
Packit 9c6abc
    LD_UW4(irow, 4, src0, src1, src2, src3);
Packit 9c6abc
    SUB4(src0, frac0, src1, frac1, src2, frac2, src3, frac3,
Packit 9c6abc
         src0, src1, src2, src3);
Packit 9c6abc
    CALC_MULT_FIX_16(src0, src1, src2, src3, fxyscale, shiftval, out);
Packit 9c6abc
    ST_UB(out, dst);
Packit 9c6abc
    ST_UW4(frac0, frac1, frac2, frac3, irow, 4);
Packit 9c6abc
    frow   += 16;
Packit 9c6abc
    irow   += 16;
Packit 9c6abc
    dst    += 16;
Packit 9c6abc
    length -= 16;
Packit 9c6abc
  }
Packit 9c6abc
  if (length > 0) {
Packit 9c6abc
    int x_out;
Packit 9c6abc
    if (length >= 12) {
Packit 9c6abc
      uint32_t val0_m, val1_m, val2_m;
Packit 9c6abc
      v4u32 src0, src1, src2, frac0, frac1, frac2;
Packit 9c6abc
      LD_UW3(frow, 4, src0, src1, src2);
Packit 9c6abc
      CALC_MULT_FIX1_4(src0, y_scale, shiftval, frac0);
Packit 9c6abc
      CALC_MULT_FIX1_4(src1, y_scale, shiftval, frac1);
Packit 9c6abc
      CALC_MULT_FIX1_4(src2, y_scale, shiftval, frac2);
Packit 9c6abc
      LD_UW3(irow, 4, src0, src1, src2);
Packit 9c6abc
      SUB3(src0, frac0, src1, frac1, src2, frac2, src0, src1, src2);
Packit 9c6abc
      CALC_MULT_FIX_4(src0, fxyscale, shiftval, val0_m);
Packit 9c6abc
      CALC_MULT_FIX_4(src1, fxyscale, shiftval, val1_m);
Packit 9c6abc
      CALC_MULT_FIX_4(src2, fxyscale, shiftval, val2_m);
Packit 9c6abc
      SW3(val0_m, val1_m, val2_m, dst, 4);
Packit 9c6abc
      ST_UW3(frac0, frac1, frac2, irow, 4);
Packit 9c6abc
      frow   += 12;
Packit 9c6abc
      irow   += 12;
Packit 9c6abc
      dst    += 12;
Packit 9c6abc
      length -= 12;
Packit 9c6abc
    } else if (length >= 8) {
Packit 9c6abc
      uint32_t val0_m, val1_m;
Packit 9c6abc
      v4u32 src0, src1, frac0, frac1;
Packit 9c6abc
      LD_UW2(frow, 4, src0, src1);
Packit 9c6abc
      CALC_MULT_FIX1_4(src0, y_scale, shiftval, frac0);
Packit 9c6abc
      CALC_MULT_FIX1_4(src1, y_scale, shiftval, frac1);
Packit 9c6abc
      LD_UW2(irow, 4, src0, src1);
Packit 9c6abc
      SUB2(src0, frac0, src1, frac1, src0, src1);
Packit 9c6abc
      CALC_MULT_FIX_4(src0, fxyscale, shiftval, val0_m);
Packit 9c6abc
      CALC_MULT_FIX_4(src1, fxyscale, shiftval, val1_m);
Packit 9c6abc
      SW2(val0_m, val1_m, dst, 4);
Packit 9c6abc
      ST_UW2(frac0, frac1, irow, 4);
Packit 9c6abc
      frow   += 8;
Packit 9c6abc
      irow   += 8;
Packit 9c6abc
      dst    += 8;
Packit 9c6abc
      length -= 8;
Packit 9c6abc
    } else if (length >= 4) {
Packit 9c6abc
      uint32_t val0_m;
Packit 9c6abc
      v4u32 frac0;
Packit 9c6abc
      v4u32 src0 = LD_UW(frow);
Packit 9c6abc
      CALC_MULT_FIX1_4(src0, y_scale, shiftval, frac0);
Packit 9c6abc
      src0 = LD_UW(irow);
Packit 9c6abc
      src0 = src0 - frac0;
Packit 9c6abc
      CALC_MULT_FIX_4(src0, fxyscale, shiftval, val0_m);
Packit 9c6abc
      SW(val0_m, dst);
Packit 9c6abc
      ST_UW(frac0, irow);
Packit 9c6abc
      frow   += 4;
Packit 9c6abc
      irow   += 4;
Packit 9c6abc
      dst    += 4;
Packit 9c6abc
      length -= 4;
Packit 9c6abc
    }
Packit 9c6abc
    for (x_out = 0; x_out < length; ++x_out) {
Packit 9c6abc
      const uint32_t frac = (uint32_t)MULT_FIX(frow[x_out], yscale);
Packit 9c6abc
      const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale);
Packit 9c6abc
      assert(v >= 0 && v <= 255);
Packit 9c6abc
      dst[x_out] = v;
Packit 9c6abc
      irow[x_out] = frac;
Packit 9c6abc
    }
Packit 9c6abc
  }
Packit 9c6abc
}
Packit 9c6abc
Packit 9c6abc
static WEBP_INLINE void ExportRowShrink_1(uint32_t* irow, uint8_t* dst,
Packit 9c6abc
                                          int length,
Packit 9c6abc
                                          WebPRescaler* const wrk) {
Packit 9c6abc
  const v4u32 scale = (v4u32)__msa_fill_w(wrk->fxy_scale);
Packit 9c6abc
  const v4u32 shift = (v4u32)__msa_fill_w(WEBP_RESCALER_RFIX);
Packit 9c6abc
  const v4i32 zero = { 0 };
Packit 9c6abc
Packit 9c6abc
  while (length >= 16) {
Packit 9c6abc
    v4u32 src0, src1, src2, src3;
Packit 9c6abc
    v16u8 dst0;
Packit 9c6abc
    LD_UW4(irow, 4, src0, src1, src2, src3);
Packit 9c6abc
    CALC_MULT_FIX_16(src0, src1, src2, src3, scale, shift, dst0);
Packit 9c6abc
    ST_UB(dst0, dst);
Packit 9c6abc
    ST_SW4(zero, zero, zero, zero, irow, 4);
Packit 9c6abc
    length -= 16;
Packit 9c6abc
    irow   += 16;
Packit 9c6abc
    dst    += 16;
Packit 9c6abc
  }
Packit 9c6abc
  if (length > 0) {
Packit 9c6abc
    int x_out;
Packit 9c6abc
    if (length >= 12) {
Packit 9c6abc
      uint32_t val0_m, val1_m, val2_m;
Packit 9c6abc
      v4u32 src0, src1, src2;
Packit 9c6abc
      LD_UW3(irow, 4, src0, src1, src2);
Packit 9c6abc
      CALC_MULT_FIX_4(src0, scale, shift, val0_m);
Packit 9c6abc
      CALC_MULT_FIX_4(src1, scale, shift, val1_m);
Packit 9c6abc
      CALC_MULT_FIX_4(src2, scale, shift, val2_m);
Packit 9c6abc
      SW3(val0_m, val1_m, val2_m, dst, 4);
Packit 9c6abc
      ST_SW3(zero, zero, zero, irow, 4);
Packit 9c6abc
      length -= 12;
Packit 9c6abc
      irow   += 12;
Packit 9c6abc
      dst    += 12;
Packit 9c6abc
    } else if (length >= 8) {
Packit 9c6abc
      uint32_t val0_m, val1_m;
Packit 9c6abc
      v4u32 src0, src1;
Packit 9c6abc
      LD_UW2(irow, 4, src0, src1);
Packit 9c6abc
      CALC_MULT_FIX_4(src0, scale, shift, val0_m);
Packit 9c6abc
      CALC_MULT_FIX_4(src1, scale, shift, val1_m);
Packit 9c6abc
      SW2(val0_m, val1_m, dst, 4);
Packit 9c6abc
      ST_SW2(zero, zero, irow, 4);
Packit 9c6abc
      length -= 8;
Packit 9c6abc
      irow   += 8;
Packit 9c6abc
      dst    += 8;
Packit 9c6abc
    } else if (length >= 4) {
Packit 9c6abc
      uint32_t val0_m;
Packit 9c6abc
      const v4u32 src0 = LD_UW(irow + 0);
Packit 9c6abc
      CALC_MULT_FIX_4(src0, scale, shift, val0_m);
Packit 9c6abc
      SW(val0_m, dst);
Packit 9c6abc
      ST_SW(zero, irow);
Packit 9c6abc
      length -= 4;
Packit 9c6abc
      irow   += 4;
Packit 9c6abc
      dst    += 4;
Packit 9c6abc
    }
Packit 9c6abc
    for (x_out = 0; x_out < length; ++x_out) {
Packit 9c6abc
      const int v = (int)MULT_FIX(irow[x_out], wrk->fxy_scale);
Packit 9c6abc
      assert(v >= 0 && v <= 255);
Packit 9c6abc
      dst[x_out] = v;
Packit 9c6abc
      irow[x_out] = 0;
Packit 9c6abc
    }
Packit 9c6abc
  }
Packit 9c6abc
}
Packit 9c6abc
Packit 9c6abc
static void RescalerExportRowShrink_MIPSdspR2(WebPRescaler* const wrk) {
Packit 9c6abc
  uint8_t* dst = wrk->dst;
Packit 9c6abc
  rescaler_t* irow = wrk->irow;
Packit 9c6abc
  const int x_out_max = wrk->dst_width * wrk->num_channels;
Packit 9c6abc
  const rescaler_t* frow = wrk->frow;
Packit 9c6abc
  const uint32_t yscale = wrk->fy_scale * (-wrk->y_accum);
Packit 9c6abc
  assert(!WebPRescalerOutputDone(wrk));
Packit 9c6abc
  assert(wrk->y_accum <= 0);
Packit 9c6abc
  assert(!wrk->y_expand);
Packit 9c6abc
  if (yscale) {
Packit 9c6abc
    ExportRowShrink_0(frow, irow, dst, x_out_max, yscale, wrk);
Packit 9c6abc
  } else {
Packit 9c6abc
    ExportRowShrink_1(irow, dst, x_out_max, wrk);
Packit 9c6abc
  }
Packit 9c6abc
}
Packit 9c6abc
Packit 9c6abc
//------------------------------------------------------------------------------
Packit 9c6abc
// Entry point
Packit 9c6abc
Packit 9c6abc
extern void WebPRescalerDspInitMSA(void);
Packit 9c6abc
Packit 9c6abc
WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitMSA(void) {
Packit 9c6abc
  WebPRescalerExportRowExpand = RescalerExportRowExpand_MIPSdspR2;
Packit 9c6abc
  WebPRescalerExportRowShrink = RescalerExportRowShrink_MIPSdspR2;
Packit 9c6abc
}
Packit 9c6abc
Packit 9c6abc
#else     // !WEBP_USE_MSA
Packit 9c6abc
Packit 9c6abc
WEBP_DSP_INIT_STUB(WebPRescalerDspInitMSA)
Packit 9c6abc
Packit 9c6abc
#endif    // WEBP_USE_MSA