17c8da7ce66017295a65ec028084b90800be377f8James Zern// Copyright 2011 Google Inc. All Rights Reserved.
27c8da7ce66017295a65ec028084b90800be377f8James Zern//
37c8da7ce66017295a65ec028084b90800be377f8James Zern// Use of this source code is governed by a BSD-style license
47c8da7ce66017295a65ec028084b90800be377f8James Zern// that can be found in the COPYING file in the root of the source
57c8da7ce66017295a65ec028084b90800be377f8James Zern// tree. An additional intellectual property rights grant can be found
67c8da7ce66017295a65ec028084b90800be377f8James Zern// in the file PATENTS. All contributing project authors may
77c8da7ce66017295a65ec028084b90800be377f8James Zern// be found in the AUTHORS file in the root of the source tree.
87c8da7ce66017295a65ec028084b90800be377f8James Zern// -----------------------------------------------------------------------------
97c8da7ce66017295a65ec028084b90800be377f8James Zern//
107c8da7ce66017295a65ec028084b90800be377f8James Zern// Spatial prediction using various filters
117c8da7ce66017295a65ec028084b90800be377f8James Zern//
127c8da7ce66017295a65ec028084b90800be377f8James Zern// Author: Urvang (urvang@google.com)
137c8da7ce66017295a65ec028084b90800be377f8James Zern
147c8da7ce66017295a65ec028084b90800be377f8James Zern#include "./dsp.h"
157c8da7ce66017295a65ec028084b90800be377f8James Zern#include <assert.h>
167c8da7ce66017295a65ec028084b90800be377f8James Zern#include <stdlib.h>
177c8da7ce66017295a65ec028084b90800be377f8James Zern#include <string.h>
187c8da7ce66017295a65ec028084b90800be377f8James Zern
197c8da7ce66017295a65ec028084b90800be377f8James Zern//------------------------------------------------------------------------------
207c8da7ce66017295a65ec028084b90800be377f8James Zern// Helpful macro.
217c8da7ce66017295a65ec028084b90800be377f8James Zern
227c8da7ce66017295a65ec028084b90800be377f8James Zern# define SANITY_CHECK(in, out)                                                 \
237c8da7ce66017295a65ec028084b90800be377f8James Zern  assert(in != NULL);                                                          \
247c8da7ce66017295a65ec028084b90800be377f8James Zern  assert(out != NULL);                                                         \
257c8da7ce66017295a65ec028084b90800be377f8James Zern  assert(width > 0);                                                           \
267c8da7ce66017295a65ec028084b90800be377f8James Zern  assert(height > 0);                                                          \
277c8da7ce66017295a65ec028084b90800be377f8James Zern  assert(stride >= width);                                                     \
287c8da7ce66017295a65ec028084b90800be377f8James Zern  assert(row >= 0 && num_rows > 0 && row + num_rows <= height);                \
297c8da7ce66017295a65ec028084b90800be377f8James Zern  (void)height;  // Silence unused warning.
307c8da7ce66017295a65ec028084b90800be377f8James Zern
317c8da7ce66017295a65ec028084b90800be377f8James Zernstatic WEBP_INLINE void PredictLine(const uint8_t* src, const uint8_t* pred,
327c8da7ce66017295a65ec028084b90800be377f8James Zern                                    uint8_t* dst, int length, int inverse) {
337c8da7ce66017295a65ec028084b90800be377f8James Zern  int i;
347c8da7ce66017295a65ec028084b90800be377f8James Zern  if (inverse) {
357c8da7ce66017295a65ec028084b90800be377f8James Zern    for (i = 0; i < length; ++i) dst[i] = src[i] + pred[i];
367c8da7ce66017295a65ec028084b90800be377f8James Zern  } else {
377c8da7ce66017295a65ec028084b90800be377f8James Zern    for (i = 0; i < length; ++i) dst[i] = src[i] - pred[i];
387c8da7ce66017295a65ec028084b90800be377f8James Zern  }
397c8da7ce66017295a65ec028084b90800be377f8James Zern}
407c8da7ce66017295a65ec028084b90800be377f8James Zern
417c8da7ce66017295a65ec028084b90800be377f8James Zern//------------------------------------------------------------------------------
427c8da7ce66017295a65ec028084b90800be377f8James Zern// Horizontal filter.
437c8da7ce66017295a65ec028084b90800be377f8James Zern
447c8da7ce66017295a65ec028084b90800be377f8James Zernstatic WEBP_INLINE void DoHorizontalFilter(const uint8_t* in,
457c8da7ce66017295a65ec028084b90800be377f8James Zern                                           int width, int height, int stride,
467c8da7ce66017295a65ec028084b90800be377f8James Zern                                           int row, int num_rows,
477c8da7ce66017295a65ec028084b90800be377f8James Zern                                           int inverse, uint8_t* out) {
487c8da7ce66017295a65ec028084b90800be377f8James Zern  const uint8_t* preds;
497c8da7ce66017295a65ec028084b90800be377f8James Zern  const size_t start_offset = row * stride;
507c8da7ce66017295a65ec028084b90800be377f8James Zern  const int last_row = row + num_rows;
517c8da7ce66017295a65ec028084b90800be377f8James Zern  SANITY_CHECK(in, out);
527c8da7ce66017295a65ec028084b90800be377f8James Zern  in += start_offset;
537c8da7ce66017295a65ec028084b90800be377f8James Zern  out += start_offset;
547c8da7ce66017295a65ec028084b90800be377f8James Zern  preds = inverse ? out : in;
557c8da7ce66017295a65ec028084b90800be377f8James Zern
567c8da7ce66017295a65ec028084b90800be377f8James Zern  if (row == 0) {
577c8da7ce66017295a65ec028084b90800be377f8James Zern    // Leftmost pixel is the same as input for topmost scanline.
587c8da7ce66017295a65ec028084b90800be377f8James Zern    out[0] = in[0];
597c8da7ce66017295a65ec028084b90800be377f8James Zern    PredictLine(in + 1, preds, out + 1, width - 1, inverse);
607c8da7ce66017295a65ec028084b90800be377f8James Zern    row = 1;
617c8da7ce66017295a65ec028084b90800be377f8James Zern    preds += stride;
627c8da7ce66017295a65ec028084b90800be377f8James Zern    in += stride;
637c8da7ce66017295a65ec028084b90800be377f8James Zern    out += stride;
647c8da7ce66017295a65ec028084b90800be377f8James Zern  }
657c8da7ce66017295a65ec028084b90800be377f8James Zern
667c8da7ce66017295a65ec028084b90800be377f8James Zern  // Filter line-by-line.
677c8da7ce66017295a65ec028084b90800be377f8James Zern  while (row < last_row) {
687c8da7ce66017295a65ec028084b90800be377f8James Zern    // Leftmost pixel is predicted from above.
697c8da7ce66017295a65ec028084b90800be377f8James Zern    PredictLine(in, preds - stride, out, 1, inverse);
707c8da7ce66017295a65ec028084b90800be377f8James Zern    PredictLine(in + 1, preds, out + 1, width - 1, inverse);
717c8da7ce66017295a65ec028084b90800be377f8James Zern    ++row;
727c8da7ce66017295a65ec028084b90800be377f8James Zern    preds += stride;
737c8da7ce66017295a65ec028084b90800be377f8James Zern    in += stride;
747c8da7ce66017295a65ec028084b90800be377f8James Zern    out += stride;
757c8da7ce66017295a65ec028084b90800be377f8James Zern  }
767c8da7ce66017295a65ec028084b90800be377f8James Zern}
777c8da7ce66017295a65ec028084b90800be377f8James Zern
787c8da7ce66017295a65ec028084b90800be377f8James Zern//------------------------------------------------------------------------------
797c8da7ce66017295a65ec028084b90800be377f8James Zern// Vertical filter.
807c8da7ce66017295a65ec028084b90800be377f8James Zern
817c8da7ce66017295a65ec028084b90800be377f8James Zernstatic WEBP_INLINE void DoVerticalFilter(const uint8_t* in,
827c8da7ce66017295a65ec028084b90800be377f8James Zern                                         int width, int height, int stride,
837c8da7ce66017295a65ec028084b90800be377f8James Zern                                         int row, int num_rows,
847c8da7ce66017295a65ec028084b90800be377f8James Zern                                         int inverse, uint8_t* out) {
857c8da7ce66017295a65ec028084b90800be377f8James Zern  const uint8_t* preds;
867c8da7ce66017295a65ec028084b90800be377f8James Zern  const size_t start_offset = row * stride;
877c8da7ce66017295a65ec028084b90800be377f8James Zern  const int last_row = row + num_rows;
887c8da7ce66017295a65ec028084b90800be377f8James Zern  SANITY_CHECK(in, out);
897c8da7ce66017295a65ec028084b90800be377f8James Zern  in += start_offset;
907c8da7ce66017295a65ec028084b90800be377f8James Zern  out += start_offset;
917c8da7ce66017295a65ec028084b90800be377f8James Zern  preds = inverse ? out : in;
927c8da7ce66017295a65ec028084b90800be377f8James Zern
937c8da7ce66017295a65ec028084b90800be377f8James Zern  if (row == 0) {
947c8da7ce66017295a65ec028084b90800be377f8James Zern    // Very first top-left pixel is copied.
957c8da7ce66017295a65ec028084b90800be377f8James Zern    out[0] = in[0];
967c8da7ce66017295a65ec028084b90800be377f8James Zern    // Rest of top scan-line is left-predicted.
977c8da7ce66017295a65ec028084b90800be377f8James Zern    PredictLine(in + 1, preds, out + 1, width - 1, inverse);
987c8da7ce66017295a65ec028084b90800be377f8James Zern    row = 1;
997c8da7ce66017295a65ec028084b90800be377f8James Zern    in += stride;
1007c8da7ce66017295a65ec028084b90800be377f8James Zern    out += stride;
1017c8da7ce66017295a65ec028084b90800be377f8James Zern  } else {
1027c8da7ce66017295a65ec028084b90800be377f8James Zern    // We are starting from in-between. Make sure 'preds' points to prev row.
1037c8da7ce66017295a65ec028084b90800be377f8James Zern    preds -= stride;
1047c8da7ce66017295a65ec028084b90800be377f8James Zern  }
1057c8da7ce66017295a65ec028084b90800be377f8James Zern
1067c8da7ce66017295a65ec028084b90800be377f8James Zern  // Filter line-by-line.
1077c8da7ce66017295a65ec028084b90800be377f8James Zern  while (row < last_row) {
1087c8da7ce66017295a65ec028084b90800be377f8James Zern    PredictLine(in, preds, out, width, inverse);
1097c8da7ce66017295a65ec028084b90800be377f8James Zern    ++row;
1107c8da7ce66017295a65ec028084b90800be377f8James Zern    preds += stride;
1117c8da7ce66017295a65ec028084b90800be377f8James Zern    in += stride;
1127c8da7ce66017295a65ec028084b90800be377f8James Zern    out += stride;
1137c8da7ce66017295a65ec028084b90800be377f8James Zern  }
1147c8da7ce66017295a65ec028084b90800be377f8James Zern}
1157c8da7ce66017295a65ec028084b90800be377f8James Zern
1167c8da7ce66017295a65ec028084b90800be377f8James Zern//------------------------------------------------------------------------------
1177c8da7ce66017295a65ec028084b90800be377f8James Zern// Gradient filter.
1187c8da7ce66017295a65ec028084b90800be377f8James Zern
1197c8da7ce66017295a65ec028084b90800be377f8James Zernstatic WEBP_INLINE int GradientPredictor(uint8_t a, uint8_t b, uint8_t c) {
1207c8da7ce66017295a65ec028084b90800be377f8James Zern  const int g = a + b - c;
1217c8da7ce66017295a65ec028084b90800be377f8James Zern  return ((g & ~0xff) == 0) ? g : (g < 0) ? 0 : 255;  // clip to 8bit
1227c8da7ce66017295a65ec028084b90800be377f8James Zern}
1237c8da7ce66017295a65ec028084b90800be377f8James Zern
1247c8da7ce66017295a65ec028084b90800be377f8James Zernstatic WEBP_INLINE void DoGradientFilter(const uint8_t* in,
1257c8da7ce66017295a65ec028084b90800be377f8James Zern                                         int width, int height, int stride,
1267c8da7ce66017295a65ec028084b90800be377f8James Zern                                         int row, int num_rows,
1277c8da7ce66017295a65ec028084b90800be377f8James Zern                                         int inverse, uint8_t* out) {
1287c8da7ce66017295a65ec028084b90800be377f8James Zern  const uint8_t* preds;
1297c8da7ce66017295a65ec028084b90800be377f8James Zern  const size_t start_offset = row * stride;
1307c8da7ce66017295a65ec028084b90800be377f8James Zern  const int last_row = row + num_rows;
1317c8da7ce66017295a65ec028084b90800be377f8James Zern  SANITY_CHECK(in, out);
1327c8da7ce66017295a65ec028084b90800be377f8James Zern  in += start_offset;
1337c8da7ce66017295a65ec028084b90800be377f8James Zern  out += start_offset;
1347c8da7ce66017295a65ec028084b90800be377f8James Zern  preds = inverse ? out : in;
1357c8da7ce66017295a65ec028084b90800be377f8James Zern
1367c8da7ce66017295a65ec028084b90800be377f8James Zern  // left prediction for top scan-line
1377c8da7ce66017295a65ec028084b90800be377f8James Zern  if (row == 0) {
1387c8da7ce66017295a65ec028084b90800be377f8James Zern    out[0] = in[0];
1397c8da7ce66017295a65ec028084b90800be377f8James Zern    PredictLine(in + 1, preds, out + 1, width - 1, inverse);
1407c8da7ce66017295a65ec028084b90800be377f8James Zern    row = 1;
1417c8da7ce66017295a65ec028084b90800be377f8James Zern    preds += stride;
1427c8da7ce66017295a65ec028084b90800be377f8James Zern    in += stride;
1437c8da7ce66017295a65ec028084b90800be377f8James Zern    out += stride;
1447c8da7ce66017295a65ec028084b90800be377f8James Zern  }
1457c8da7ce66017295a65ec028084b90800be377f8James Zern
1467c8da7ce66017295a65ec028084b90800be377f8James Zern  // Filter line-by-line.
1477c8da7ce66017295a65ec028084b90800be377f8James Zern  while (row < last_row) {
1487c8da7ce66017295a65ec028084b90800be377f8James Zern    int w;
1497c8da7ce66017295a65ec028084b90800be377f8James Zern    // leftmost pixel: predict from above.
1507c8da7ce66017295a65ec028084b90800be377f8James Zern    PredictLine(in, preds - stride, out, 1, inverse);
1517c8da7ce66017295a65ec028084b90800be377f8James Zern    for (w = 1; w < width; ++w) {
1527c8da7ce66017295a65ec028084b90800be377f8James Zern      const int pred = GradientPredictor(preds[w - 1],
1537c8da7ce66017295a65ec028084b90800be377f8James Zern                                         preds[w - stride],
1547c8da7ce66017295a65ec028084b90800be377f8James Zern                                         preds[w - stride - 1]);
1557c8da7ce66017295a65ec028084b90800be377f8James Zern      out[w] = in[w] + (inverse ? pred : -pred);
1567c8da7ce66017295a65ec028084b90800be377f8James Zern    }
1577c8da7ce66017295a65ec028084b90800be377f8James Zern    ++row;
1587c8da7ce66017295a65ec028084b90800be377f8James Zern    preds += stride;
1597c8da7ce66017295a65ec028084b90800be377f8James Zern    in += stride;
1607c8da7ce66017295a65ec028084b90800be377f8James Zern    out += stride;
1617c8da7ce66017295a65ec028084b90800be377f8James Zern  }
1627c8da7ce66017295a65ec028084b90800be377f8James Zern}
1637c8da7ce66017295a65ec028084b90800be377f8James Zern
1647c8da7ce66017295a65ec028084b90800be377f8James Zern#undef SANITY_CHECK
1657c8da7ce66017295a65ec028084b90800be377f8James Zern
1667c8da7ce66017295a65ec028084b90800be377f8James Zern//------------------------------------------------------------------------------
1677c8da7ce66017295a65ec028084b90800be377f8James Zern
1687c8da7ce66017295a65ec028084b90800be377f8James Zernstatic void HorizontalFilter(const uint8_t* data, int width, int height,
1697c8da7ce66017295a65ec028084b90800be377f8James Zern                             int stride, uint8_t* filtered_data) {
1707c8da7ce66017295a65ec028084b90800be377f8James Zern  DoHorizontalFilter(data, width, height, stride, 0, height, 0, filtered_data);
1717c8da7ce66017295a65ec028084b90800be377f8James Zern}
1727c8da7ce66017295a65ec028084b90800be377f8James Zern
1737c8da7ce66017295a65ec028084b90800be377f8James Zernstatic void VerticalFilter(const uint8_t* data, int width, int height,
1747c8da7ce66017295a65ec028084b90800be377f8James Zern                           int stride, uint8_t* filtered_data) {
1757c8da7ce66017295a65ec028084b90800be377f8James Zern  DoVerticalFilter(data, width, height, stride, 0, height, 0, filtered_data);
1767c8da7ce66017295a65ec028084b90800be377f8James Zern}
1777c8da7ce66017295a65ec028084b90800be377f8James Zern
1787c8da7ce66017295a65ec028084b90800be377f8James Zern
1797c8da7ce66017295a65ec028084b90800be377f8James Zernstatic void GradientFilter(const uint8_t* data, int width, int height,
1807c8da7ce66017295a65ec028084b90800be377f8James Zern                           int stride, uint8_t* filtered_data) {
1817c8da7ce66017295a65ec028084b90800be377f8James Zern  DoGradientFilter(data, width, height, stride, 0, height, 0, filtered_data);
1827c8da7ce66017295a65ec028084b90800be377f8James Zern}
1837c8da7ce66017295a65ec028084b90800be377f8James Zern
1847c8da7ce66017295a65ec028084b90800be377f8James Zern
1857c8da7ce66017295a65ec028084b90800be377f8James Zern//------------------------------------------------------------------------------
1867c8da7ce66017295a65ec028084b90800be377f8James Zern
1870912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zernstatic void HorizontalUnfilter(const uint8_t* prev, const uint8_t* in,
1880912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zern                               uint8_t* out, int width) {
1890912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zern  uint8_t pred = (prev == NULL) ? 0 : prev[0];
1900912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zern  int i;
1910912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zern  for (i = 0; i < width; ++i) {
1920912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zern    out[i] = pred + in[i];
1930912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zern    pred = out[i];
1940912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zern  }
1957c8da7ce66017295a65ec028084b90800be377f8James Zern}
1967c8da7ce66017295a65ec028084b90800be377f8James Zern
1970912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zernstatic void VerticalUnfilter(const uint8_t* prev, const uint8_t* in,
1980912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zern                             uint8_t* out, int width) {
1990912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zern  if (prev == NULL) {
2000912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zern    HorizontalUnfilter(NULL, in, out, width);
2010912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zern  } else {
2020912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zern    int i;
2030912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zern    for (i = 0; i < width; ++i) out[i] = prev[i] + in[i];
2040912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zern  }
2057c8da7ce66017295a65ec028084b90800be377f8James Zern}
2067c8da7ce66017295a65ec028084b90800be377f8James Zern
2070912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zernstatic void GradientUnfilter(const uint8_t* prev, const uint8_t* in,
2080912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zern                             uint8_t* out, int width) {
2090912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zern  if (prev == NULL) {
2100912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zern    HorizontalUnfilter(NULL, in, out, width);
2110912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zern  } else {
2120912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zern    uint8_t top = prev[0], top_left = top, left = top;
2130912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zern    int i;
2140912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zern    for (i = 0; i < width; ++i) {
2150912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zern      top = prev[i];  // need to read this first, in case prev==out
2160912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zern      left = in[i] + GradientPredictor(left, top, top_left);
2170912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zern      top_left = top;
2180912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zern      out[i] = left;
2190912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zern    }
2200912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zern  }
2217c8da7ce66017295a65ec028084b90800be377f8James Zern}
2227c8da7ce66017295a65ec028084b90800be377f8James Zern
2237c8da7ce66017295a65ec028084b90800be377f8James Zern//------------------------------------------------------------------------------
2247c8da7ce66017295a65ec028084b90800be377f8James Zern// Init function
2257c8da7ce66017295a65ec028084b90800be377f8James Zern
2267c8da7ce66017295a65ec028084b90800be377f8James ZernWebPFilterFunc WebPFilters[WEBP_FILTER_LAST];
2277c8da7ce66017295a65ec028084b90800be377f8James ZernWebPUnfilterFunc WebPUnfilters[WEBP_FILTER_LAST];
2287c8da7ce66017295a65ec028084b90800be377f8James Zern
2297c8da7ce66017295a65ec028084b90800be377f8James Zernextern void VP8FiltersInitMIPSdspR2(void);
230fa39824bb690c5806358871f46940d0450973d8aJames Zernextern void VP8FiltersInitMSA(void);
231fa39824bb690c5806358871f46940d0450973d8aJames Zernextern void VP8FiltersInitNEON(void);
2327c8da7ce66017295a65ec028084b90800be377f8James Zernextern void VP8FiltersInitSSE2(void);
2337c8da7ce66017295a65ec028084b90800be377f8James Zern
2347c8da7ce66017295a65ec028084b90800be377f8James Zernstatic volatile VP8CPUInfo filters_last_cpuinfo_used =
2357c8da7ce66017295a65ec028084b90800be377f8James Zern    (VP8CPUInfo)&filters_last_cpuinfo_used;
2367c8da7ce66017295a65ec028084b90800be377f8James Zern
2377c8da7ce66017295a65ec028084b90800be377f8James ZernWEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInit(void) {
2387c8da7ce66017295a65ec028084b90800be377f8James Zern  if (filters_last_cpuinfo_used == VP8GetCPUInfo) return;
2397c8da7ce66017295a65ec028084b90800be377f8James Zern
2407c8da7ce66017295a65ec028084b90800be377f8James Zern  WebPUnfilters[WEBP_FILTER_NONE] = NULL;
2417c8da7ce66017295a65ec028084b90800be377f8James Zern  WebPUnfilters[WEBP_FILTER_HORIZONTAL] = HorizontalUnfilter;
2427c8da7ce66017295a65ec028084b90800be377f8James Zern  WebPUnfilters[WEBP_FILTER_VERTICAL] = VerticalUnfilter;
2437c8da7ce66017295a65ec028084b90800be377f8James Zern  WebPUnfilters[WEBP_FILTER_GRADIENT] = GradientUnfilter;
2447c8da7ce66017295a65ec028084b90800be377f8James Zern
2457c8da7ce66017295a65ec028084b90800be377f8James Zern  WebPFilters[WEBP_FILTER_NONE] = NULL;
2467c8da7ce66017295a65ec028084b90800be377f8James Zern  WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter;
2477c8da7ce66017295a65ec028084b90800be377f8James Zern  WebPFilters[WEBP_FILTER_VERTICAL] = VerticalFilter;
2487c8da7ce66017295a65ec028084b90800be377f8James Zern  WebPFilters[WEBP_FILTER_GRADIENT] = GradientFilter;
2497c8da7ce66017295a65ec028084b90800be377f8James Zern
2507c8da7ce66017295a65ec028084b90800be377f8James Zern  if (VP8GetCPUInfo != NULL) {
2517c8da7ce66017295a65ec028084b90800be377f8James Zern#if defined(WEBP_USE_SSE2)
2527c8da7ce66017295a65ec028084b90800be377f8James Zern    if (VP8GetCPUInfo(kSSE2)) {
2537c8da7ce66017295a65ec028084b90800be377f8James Zern      VP8FiltersInitSSE2();
2547c8da7ce66017295a65ec028084b90800be377f8James Zern    }
2557c8da7ce66017295a65ec028084b90800be377f8James Zern#endif
256fa39824bb690c5806358871f46940d0450973d8aJames Zern#if defined(WEBP_USE_NEON)
257fa39824bb690c5806358871f46940d0450973d8aJames Zern    if (VP8GetCPUInfo(kNEON)) {
258fa39824bb690c5806358871f46940d0450973d8aJames Zern      VP8FiltersInitNEON();
259fa39824bb690c5806358871f46940d0450973d8aJames Zern    }
260fa39824bb690c5806358871f46940d0450973d8aJames Zern#endif
2617c8da7ce66017295a65ec028084b90800be377f8James Zern#if defined(WEBP_USE_MIPS_DSP_R2)
2627c8da7ce66017295a65ec028084b90800be377f8James Zern    if (VP8GetCPUInfo(kMIPSdspR2)) {
2637c8da7ce66017295a65ec028084b90800be377f8James Zern      VP8FiltersInitMIPSdspR2();
2647c8da7ce66017295a65ec028084b90800be377f8James Zern    }
2657c8da7ce66017295a65ec028084b90800be377f8James Zern#endif
266fa39824bb690c5806358871f46940d0450973d8aJames Zern#if defined(WEBP_USE_MSA)
267fa39824bb690c5806358871f46940d0450973d8aJames Zern    if (VP8GetCPUInfo(kMSA)) {
268fa39824bb690c5806358871f46940d0450973d8aJames Zern      VP8FiltersInitMSA();
269fa39824bb690c5806358871f46940d0450973d8aJames Zern    }
270fa39824bb690c5806358871f46940d0450973d8aJames Zern#endif
2717c8da7ce66017295a65ec028084b90800be377f8James Zern  }
2727c8da7ce66017295a65ec028084b90800be377f8James Zern  filters_last_cpuinfo_used = VP8GetCPUInfo;
2737c8da7ce66017295a65ec028084b90800be377f8James Zern}
274