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