go-libwebp

Experimental translation from libwebp to Go source.
Log | Files | Refs | README | LICENSE

filters_msa.c (6112B)


      1 // Copyright 2016 Google Inc. All Rights Reserved.
      2 //
      3 // Use of this source code is governed by a BSD-style license
      4 // that can be found in the COPYING file in the root of the source
      5 // tree. An additional intellectual property rights grant can be found
      6 // in the file PATENTS. All contributing project authors may
      7 // be found in the AUTHORS file in the root of the source tree.
      8 // -----------------------------------------------------------------------------
      9 //
     10 // MSA variant of alpha filters
     11 //
     12 // Author: Prashant Patil (prashant.patil@imgtec.com)
     13 
     14 #include "src/dsp/dsp.h"
     15 
     16 #if defined(WEBP_USE_MSA)
     17 
     18 #include "src/dsp/msa_macro.h"
     19 
     20 #include <assert.h>
     21 
     22 static WEBP_INLINE void PredictLineInverse0(const uint8_t* src,
     23                                             const uint8_t* pred,
     24                                             uint8_t* WEBP_RESTRICT dst,
     25                                             int length) {
     26   v16u8 src0, pred0, dst0;
     27   assert(length >= 0);
     28   while (length >= 32) {
     29     v16u8 src1, pred1, dst1;
     30     LD_UB2(src, 16, src0, src1);
     31     LD_UB2(pred, 16, pred0, pred1);
     32     SUB2(src0, pred0, src1, pred1, dst0, dst1);
     33     ST_UB2(dst0, dst1, dst, 16);
     34     src += 32;
     35     pred += 32;
     36     dst += 32;
     37     length -= 32;
     38   }
     39   if (length > 0) {
     40     int i;
     41     if (length >= 16) {
     42       src0 = LD_UB(src);
     43       pred0 = LD_UB(pred);
     44       dst0 = src0 - pred0;
     45       ST_UB(dst0, dst);
     46       src += 16;
     47       pred += 16;
     48       dst += 16;
     49       length -= 16;
     50     }
     51     for (i = 0; i < length; i++) {
     52       dst[i] = src[i] - pred[i];
     53     }
     54   }
     55 }
     56 
     57 //------------------------------------------------------------------------------
     58 // Helpful macro.
     59 
     60 #define DCHECK(in, out)        \
     61   do {                         \
     62     assert((in) != NULL);      \
     63     assert((out) != NULL);     \
     64     assert((in) != (out));     \
     65     assert(width > 0);         \
     66     assert(height > 0);        \
     67     assert(stride >= width);   \
     68   } while (0)
     69 
     70 //------------------------------------------------------------------------------
     71 // Horrizontal filter
     72 
     73 static void HorizontalFilter_MSA(const uint8_t* WEBP_RESTRICT data,
     74                                  int width, int height, int stride,
     75                                  uint8_t* WEBP_RESTRICT filtered_data) {
     76   const uint8_t* preds = data;
     77   const uint8_t* in = data;
     78   uint8_t* out = filtered_data;
     79   int row = 1;
     80   DCHECK(in, out);
     81 
     82   // Leftmost pixel is the same as input for topmost scanline.
     83   out[0] = in[0];
     84   PredictLineInverse0(in + 1, preds, out + 1, width - 1);
     85   preds += stride;
     86   in += stride;
     87   out += stride;
     88   // Filter line-by-line.
     89   while (row < height) {
     90     // Leftmost pixel is predicted from above.
     91     PredictLineInverse0(in, preds - stride, out, 1);
     92     PredictLineInverse0(in + 1, preds, out + 1, width - 1);
     93     ++row;
     94     preds += stride;
     95     in += stride;
     96     out += stride;
     97   }
     98 }
     99 
    100 //------------------------------------------------------------------------------
    101 // Gradient filter
    102 
    103 static WEBP_INLINE void PredictLineGradient(const uint8_t* pinput,
    104                                             const uint8_t* ppred,
    105                                             uint8_t* WEBP_RESTRICT poutput,
    106                                             int stride, int size) {
    107   int w;
    108   const v16i8 zero = { 0 };
    109   while (size >= 16) {
    110     v16u8 pred0, dst0;
    111     v8i16 a0, a1, b0, b1, c0, c1;
    112     const v16u8 tmp0 = LD_UB(ppred - 1);
    113     const v16u8 tmp1 = LD_UB(ppred - stride);
    114     const v16u8 tmp2 = LD_UB(ppred - stride - 1);
    115     const v16u8 src0 = LD_UB(pinput);
    116     ILVRL_B2_SH(zero, tmp0, a0, a1);
    117     ILVRL_B2_SH(zero, tmp1, b0, b1);
    118     ILVRL_B2_SH(zero, tmp2, c0, c1);
    119     ADD2(a0, b0, a1, b1, a0, a1);
    120     SUB2(a0, c0, a1, c1, a0, a1);
    121     CLIP_SH2_0_255(a0, a1);
    122     pred0 = (v16u8)__msa_pckev_b((v16i8)a1, (v16i8)a0);
    123     dst0 = src0 - pred0;
    124     ST_UB(dst0, poutput);
    125     ppred += 16;
    126     pinput += 16;
    127     poutput += 16;
    128     size -= 16;
    129   }
    130   for (w = 0; w < size; ++w) {
    131     const int pred = ppred[w - 1] + ppred[w - stride] - ppred[w - stride - 1];
    132     poutput[w] = pinput[w] - (pred < 0 ? 0 : pred > 255 ? 255 : pred);
    133   }
    134 }
    135 
    136 
    137 static void GradientFilter_MSA(const uint8_t* WEBP_RESTRICT data,
    138                                int width, int height, int stride,
    139                                uint8_t* WEBP_RESTRICT filtered_data) {
    140   const uint8_t* in = data;
    141   const uint8_t* preds = data;
    142   uint8_t* out = filtered_data;
    143   int row = 1;
    144   DCHECK(in, out);
    145 
    146   // left prediction for top scan-line
    147   out[0] = in[0];
    148   PredictLineInverse0(in + 1, preds, out + 1, width - 1);
    149   preds += stride;
    150   in += stride;
    151   out += stride;
    152   // Filter line-by-line.
    153   while (row < height) {
    154     out[0] = in[0] - preds[- stride];
    155     PredictLineGradient(preds + 1, in + 1, out + 1, stride, width - 1);
    156     ++row;
    157     preds += stride;
    158     in += stride;
    159     out += stride;
    160   }
    161 }
    162 
    163 //------------------------------------------------------------------------------
    164 // Vertical filter
    165 
    166 static void VerticalFilter_MSA(const uint8_t* WEBP_RESTRICT data,
    167                                int width, int height, int stride,
    168                                uint8_t* WEBP_RESTRICT filtered_data) {
    169   const uint8_t* in = data;
    170   const uint8_t* preds = data;
    171   uint8_t* out = filtered_data;
    172   int row = 1;
    173   DCHECK(in, out);
    174 
    175   // Very first top-left pixel is copied.
    176   out[0] = in[0];
    177   // Rest of top scan-line is left-predicted.
    178   PredictLineInverse0(in + 1, preds, out + 1, width - 1);
    179   in += stride;
    180   out += stride;
    181 
    182   // Filter line-by-line.
    183   while (row < height) {
    184     PredictLineInverse0(in, preds, out, width);
    185     ++row;
    186     preds += stride;
    187     in += stride;
    188     out += stride;
    189   }
    190 }
    191 
    192 #undef DCHECK
    193 
    194 //------------------------------------------------------------------------------
    195 // Entry point
    196 
    197 extern void VP8FiltersInitMSA(void);
    198 
    199 WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInitMSA(void) {
    200   WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter_MSA;
    201   WebPFilters[WEBP_FILTER_VERTICAL] = VerticalFilter_MSA;
    202   WebPFilters[WEBP_FILTER_GRADIENT] = GradientFilter_MSA;
    203 }
    204 
    205 #else  // !WEBP_USE_MSA
    206 
    207 WEBP_DSP_INIT_STUB(VP8FiltersInitMSA)
    208 
    209 #endif  // WEBP_USE_MSA