1/*
2 *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11
12#include <string.h>
13#include <limits.h>
14#include <stdio.h>
15
16#include "./vpx_config.h"
17#if CONFIG_VP8_ENCODER
18#include "./vp8_rtcd.h"
19#endif
20#if CONFIG_VP9_ENCODER
21#include "./vp9_rtcd.h"
22#endif
23#include "vpx_mem/vpx_mem.h"
24
25#include "test/acm_random.h"
26#include "test/clear_system_state.h"
27#include "test/register_state_check.h"
28#include "test/util.h"
29#include "third_party/googletest/src/include/gtest/gtest.h"
30
31
32typedef unsigned int (*sad_m_by_n_fn_t)(const unsigned char *source_ptr,
33                                        int source_stride,
34                                        const unsigned char *reference_ptr,
35                                        int reference_stride,
36                                        unsigned int max_sad);
37typedef std::tr1::tuple<int, int, sad_m_by_n_fn_t> sad_m_by_n_test_param_t;
38
39typedef void (*sad_n_by_n_by_4_fn_t)(const uint8_t *src_ptr,
40                                     int src_stride,
41                                     const unsigned char * const ref_ptr[],
42                                     int ref_stride,
43                                     unsigned int *sad_array);
44typedef std::tr1::tuple<int, int, sad_n_by_n_by_4_fn_t>
45        sad_n_by_n_by_4_test_param_t;
46
47using libvpx_test::ACMRandom;
48
49namespace {
50class SADTestBase : public ::testing::Test {
51 public:
52  SADTestBase(int width, int height) : width_(width), height_(height) {}
53
54  static void SetUpTestCase() {
55    source_data_ = reinterpret_cast<uint8_t*>(
56        vpx_memalign(kDataAlignment, kDataBlockSize));
57    reference_data_ = reinterpret_cast<uint8_t*>(
58        vpx_memalign(kDataAlignment, kDataBufferSize));
59  }
60
61  static void TearDownTestCase() {
62    vpx_free(source_data_);
63    source_data_ = NULL;
64    vpx_free(reference_data_);
65    reference_data_ = NULL;
66  }
67
68  virtual void TearDown() {
69    libvpx_test::ClearSystemState();
70  }
71
72 protected:
73  // Handle blocks up to 4 blocks 64x64 with stride up to 128
74  static const int kDataAlignment = 16;
75  static const int kDataBlockSize = 64 * 128;
76  static const int kDataBufferSize = 4 * kDataBlockSize;
77
78  virtual void SetUp() {
79    source_stride_ = (width_ + 31) & ~31;
80    reference_stride_ = width_ * 2;
81    rnd_.Reset(ACMRandom::DeterministicSeed());
82  }
83
84  virtual uint8_t* GetReference(int block_idx) {
85    return reference_data_ + block_idx * kDataBlockSize;
86  }
87
88  // Sum of Absolute Differences. Given two blocks, calculate the absolute
89  // difference between two pixels in the same relative location; accumulate.
90  unsigned int ReferenceSAD(unsigned int max_sad, int block_idx = 0) {
91    unsigned int sad = 0;
92    const uint8_t* const reference = GetReference(block_idx);
93
94    for (int h = 0; h < height_; ++h) {
95      for (int w = 0; w < width_; ++w) {
96        sad += abs(source_data_[h * source_stride_ + w]
97               - reference[h * reference_stride_ + w]);
98      }
99      if (sad > max_sad) {
100        break;
101      }
102    }
103    return sad;
104  }
105
106  void FillConstant(uint8_t *data, int stride, uint8_t fill_constant) {
107    for (int h = 0; h < height_; ++h) {
108      for (int w = 0; w < width_; ++w) {
109        data[h * stride + w] = fill_constant;
110      }
111    }
112  }
113
114  void FillRandom(uint8_t *data, int stride) {
115    for (int h = 0; h < height_; ++h) {
116      for (int w = 0; w < width_; ++w) {
117        data[h * stride + w] = rnd_.Rand8();
118      }
119    }
120  }
121
122  int width_, height_;
123  static uint8_t* source_data_;
124  int source_stride_;
125  static uint8_t* reference_data_;
126  int reference_stride_;
127
128  ACMRandom rnd_;
129};
130
131class SADTest : public SADTestBase,
132    public ::testing::WithParamInterface<sad_m_by_n_test_param_t> {
133 public:
134  SADTest() : SADTestBase(GET_PARAM(0), GET_PARAM(1)) {}
135
136 protected:
137  unsigned int SAD(unsigned int max_sad, int block_idx = 0) {
138    unsigned int ret;
139    const uint8_t* const reference = GetReference(block_idx);
140
141    REGISTER_STATE_CHECK(ret = GET_PARAM(2)(source_data_, source_stride_,
142                                            reference, reference_stride_,
143                                            max_sad));
144    return ret;
145  }
146
147  void CheckSad(unsigned int max_sad) {
148    unsigned int reference_sad, exp_sad;
149
150    reference_sad = ReferenceSAD(max_sad);
151    exp_sad = SAD(max_sad);
152
153    if (reference_sad <= max_sad) {
154      ASSERT_EQ(exp_sad, reference_sad);
155    } else {
156      // Alternative implementations are not required to check max_sad
157      ASSERT_GE(exp_sad, reference_sad);
158    }
159  }
160};
161
162class SADx4Test : public SADTestBase,
163    public ::testing::WithParamInterface<sad_n_by_n_by_4_test_param_t> {
164 public:
165  SADx4Test() : SADTestBase(GET_PARAM(0), GET_PARAM(1)) {}
166
167 protected:
168  void SADs(unsigned int *results) {
169    const uint8_t* refs[] = {GetReference(0), GetReference(1),
170                             GetReference(2), GetReference(3)};
171
172    REGISTER_STATE_CHECK(GET_PARAM(2)(source_data_, source_stride_,
173                                      refs, reference_stride_,
174                                      results));
175  }
176
177  void CheckSADs() {
178    unsigned int reference_sad, exp_sad[4];
179
180    SADs(exp_sad);
181    for (int block = 0; block < 4; block++) {
182      reference_sad = ReferenceSAD(UINT_MAX, block);
183
184      EXPECT_EQ(exp_sad[block], reference_sad) << "block " << block;
185    }
186  }
187};
188
189uint8_t* SADTestBase::source_data_ = NULL;
190uint8_t* SADTestBase::reference_data_ = NULL;
191
192TEST_P(SADTest, MaxRef) {
193  FillConstant(source_data_, source_stride_, 0);
194  FillConstant(reference_data_, reference_stride_, 255);
195  CheckSad(UINT_MAX);
196}
197
198TEST_P(SADx4Test, MaxRef) {
199  FillConstant(source_data_, source_stride_, 0);
200  FillConstant(GetReference(0), reference_stride_, 255);
201  FillConstant(GetReference(1), reference_stride_, 255);
202  FillConstant(GetReference(2), reference_stride_, 255);
203  FillConstant(GetReference(3), reference_stride_, 255);
204  CheckSADs();
205}
206
207TEST_P(SADTest, MaxSrc) {
208  FillConstant(source_data_, source_stride_, 255);
209  FillConstant(reference_data_, reference_stride_, 0);
210  CheckSad(UINT_MAX);
211}
212
213TEST_P(SADx4Test, MaxSrc) {
214  FillConstant(source_data_, source_stride_, 255);
215  FillConstant(GetReference(0), reference_stride_, 0);
216  FillConstant(GetReference(1), reference_stride_, 0);
217  FillConstant(GetReference(2), reference_stride_, 0);
218  FillConstant(GetReference(3), reference_stride_, 0);
219  CheckSADs();
220}
221
222TEST_P(SADTest, ShortRef) {
223  int tmp_stride = reference_stride_;
224  reference_stride_ >>= 1;
225  FillRandom(source_data_, source_stride_);
226  FillRandom(reference_data_, reference_stride_);
227  CheckSad(UINT_MAX);
228  reference_stride_ = tmp_stride;
229}
230
231TEST_P(SADx4Test, ShortRef) {
232  int tmp_stride = reference_stride_;
233  reference_stride_ >>= 1;
234  FillRandom(source_data_, source_stride_);
235  FillRandom(GetReference(0), reference_stride_);
236  FillRandom(GetReference(1), reference_stride_);
237  FillRandom(GetReference(2), reference_stride_);
238  FillRandom(GetReference(3), reference_stride_);
239  CheckSADs();
240  reference_stride_ = tmp_stride;
241}
242
243TEST_P(SADTest, UnalignedRef) {
244  // The reference frame, but not the source frame, may be unaligned for
245  // certain types of searches.
246  int tmp_stride = reference_stride_;
247  reference_stride_ -= 1;
248  FillRandom(source_data_, source_stride_);
249  FillRandom(reference_data_, reference_stride_);
250  CheckSad(UINT_MAX);
251  reference_stride_ = tmp_stride;
252}
253
254TEST_P(SADx4Test, UnalignedRef) {
255  // The reference frame, but not the source frame, may be unaligned for
256  // certain types of searches.
257  int tmp_stride = reference_stride_;
258  reference_stride_ -= 1;
259  FillRandom(source_data_, source_stride_);
260  FillRandom(GetReference(0), reference_stride_);
261  FillRandom(GetReference(1), reference_stride_);
262  FillRandom(GetReference(2), reference_stride_);
263  FillRandom(GetReference(3), reference_stride_);
264  CheckSADs();
265  reference_stride_ = tmp_stride;
266}
267
268TEST_P(SADTest, ShortSrc) {
269  int tmp_stride = source_stride_;
270  source_stride_ >>= 1;
271  FillRandom(source_data_, source_stride_);
272  FillRandom(reference_data_, reference_stride_);
273  CheckSad(UINT_MAX);
274  source_stride_ = tmp_stride;
275}
276
277TEST_P(SADx4Test, ShortSrc) {
278  int tmp_stride = source_stride_;
279  source_stride_ >>= 1;
280  FillRandom(source_data_, source_stride_);
281  FillRandom(GetReference(0), reference_stride_);
282  FillRandom(GetReference(1), reference_stride_);
283  FillRandom(GetReference(2), reference_stride_);
284  FillRandom(GetReference(3), reference_stride_);
285  CheckSADs();
286  source_stride_ = tmp_stride;
287}
288
289TEST_P(SADTest, MaxSAD) {
290  // Verify that, when max_sad is set, the implementation does not return a
291  // value lower than the reference.
292  FillConstant(source_data_, source_stride_, 255);
293  FillConstant(reference_data_, reference_stride_, 0);
294  CheckSad(128);
295}
296
297using std::tr1::make_tuple;
298
299//------------------------------------------------------------------------------
300// C functions
301#if CONFIG_VP8_ENCODER
302const sad_m_by_n_fn_t sad_16x16_c = vp8_sad16x16_c;
303const sad_m_by_n_fn_t sad_8x16_c = vp8_sad8x16_c;
304const sad_m_by_n_fn_t sad_16x8_c = vp8_sad16x8_c;
305const sad_m_by_n_fn_t sad_8x8_c = vp8_sad8x8_c;
306const sad_m_by_n_fn_t sad_4x4_c = vp8_sad4x4_c;
307#endif
308#if CONFIG_VP9_ENCODER
309const sad_m_by_n_fn_t sad_64x64_c_vp9 = vp9_sad64x64_c;
310const sad_m_by_n_fn_t sad_32x32_c_vp9 = vp9_sad32x32_c;
311const sad_m_by_n_fn_t sad_16x16_c_vp9 = vp9_sad16x16_c;
312const sad_m_by_n_fn_t sad_8x16_c_vp9 = vp9_sad8x16_c;
313const sad_m_by_n_fn_t sad_16x8_c_vp9 = vp9_sad16x8_c;
314const sad_m_by_n_fn_t sad_8x8_c_vp9 = vp9_sad8x8_c;
315const sad_m_by_n_fn_t sad_8x4_c_vp9 = vp9_sad8x4_c;
316const sad_m_by_n_fn_t sad_4x8_c_vp9 = vp9_sad4x8_c;
317const sad_m_by_n_fn_t sad_4x4_c_vp9 = vp9_sad4x4_c;
318#endif
319const sad_m_by_n_test_param_t c_tests[] = {
320#if CONFIG_VP8_ENCODER
321  make_tuple(16, 16, sad_16x16_c),
322  make_tuple(8, 16, sad_8x16_c),
323  make_tuple(16, 8, sad_16x8_c),
324  make_tuple(8, 8, sad_8x8_c),
325  make_tuple(4, 4, sad_4x4_c),
326#endif
327#if CONFIG_VP9_ENCODER
328  make_tuple(64, 64, sad_64x64_c_vp9),
329  make_tuple(32, 32, sad_32x32_c_vp9),
330  make_tuple(16, 16, sad_16x16_c_vp9),
331  make_tuple(8, 16, sad_8x16_c_vp9),
332  make_tuple(16, 8, sad_16x8_c_vp9),
333  make_tuple(8, 8, sad_8x8_c_vp9),
334  make_tuple(8, 4, sad_8x4_c_vp9),
335  make_tuple(4, 8, sad_4x8_c_vp9),
336  make_tuple(4, 4, sad_4x4_c_vp9),
337#endif
338};
339INSTANTIATE_TEST_CASE_P(C, SADTest, ::testing::ValuesIn(c_tests));
340
341#if CONFIG_VP9_ENCODER
342const sad_n_by_n_by_4_fn_t sad_64x64x4d_c = vp9_sad64x64x4d_c;
343const sad_n_by_n_by_4_fn_t sad_64x32x4d_c = vp9_sad64x32x4d_c;
344const sad_n_by_n_by_4_fn_t sad_32x64x4d_c = vp9_sad32x64x4d_c;
345const sad_n_by_n_by_4_fn_t sad_32x32x4d_c = vp9_sad32x32x4d_c;
346const sad_n_by_n_by_4_fn_t sad_32x16x4d_c = vp9_sad32x16x4d_c;
347const sad_n_by_n_by_4_fn_t sad_16x32x4d_c = vp9_sad16x32x4d_c;
348const sad_n_by_n_by_4_fn_t sad_16x16x4d_c = vp9_sad16x16x4d_c;
349const sad_n_by_n_by_4_fn_t sad_16x8x4d_c = vp9_sad16x8x4d_c;
350const sad_n_by_n_by_4_fn_t sad_8x16x4d_c = vp9_sad8x16x4d_c;
351const sad_n_by_n_by_4_fn_t sad_8x8x4d_c = vp9_sad8x8x4d_c;
352const sad_n_by_n_by_4_fn_t sad_8x4x4d_c = vp9_sad8x4x4d_c;
353const sad_n_by_n_by_4_fn_t sad_4x8x4d_c = vp9_sad4x8x4d_c;
354const sad_n_by_n_by_4_fn_t sad_4x4x4d_c = vp9_sad4x4x4d_c;
355INSTANTIATE_TEST_CASE_P(C, SADx4Test, ::testing::Values(
356                        make_tuple(64, 64, sad_64x64x4d_c),
357                        make_tuple(64, 32, sad_64x32x4d_c),
358                        make_tuple(32, 64, sad_32x64x4d_c),
359                        make_tuple(32, 32, sad_32x32x4d_c),
360                        make_tuple(32, 16, sad_32x16x4d_c),
361                        make_tuple(16, 32, sad_16x32x4d_c),
362                        make_tuple(16, 16, sad_16x16x4d_c),
363                        make_tuple(16, 8, sad_16x8x4d_c),
364                        make_tuple(8, 16, sad_8x16x4d_c),
365                        make_tuple(8, 8, sad_8x8x4d_c),
366                        make_tuple(8, 4, sad_8x4x4d_c),
367                        make_tuple(4, 8, sad_4x8x4d_c),
368                        make_tuple(4, 4, sad_4x4x4d_c)));
369#endif  // CONFIG_VP9_ENCODER
370
371//------------------------------------------------------------------------------
372// ARM functions
373#if HAVE_MEDIA
374#if CONFIG_VP8_ENCODER
375const sad_m_by_n_fn_t sad_16x16_armv6 = vp8_sad16x16_armv6;
376INSTANTIATE_TEST_CASE_P(MEDIA, SADTest, ::testing::Values(
377                        make_tuple(16, 16, sad_16x16_armv6)));
378#endif
379#endif
380
381#if HAVE_NEON
382#if CONFIG_VP8_ENCODER
383const sad_m_by_n_fn_t sad_16x16_neon = vp8_sad16x16_neon;
384const sad_m_by_n_fn_t sad_8x16_neon = vp8_sad8x16_neon;
385const sad_m_by_n_fn_t sad_16x8_neon = vp8_sad16x8_neon;
386const sad_m_by_n_fn_t sad_8x8_neon = vp8_sad8x8_neon;
387const sad_m_by_n_fn_t sad_4x4_neon = vp8_sad4x4_neon;
388INSTANTIATE_TEST_CASE_P(NEON, SADTest, ::testing::Values(
389                        make_tuple(16, 16, sad_16x16_neon),
390                        make_tuple(8, 16, sad_8x16_neon),
391                        make_tuple(16, 8, sad_16x8_neon),
392                        make_tuple(8, 8, sad_8x8_neon),
393                        make_tuple(4, 4, sad_4x4_neon)));
394#endif
395#endif
396
397//------------------------------------------------------------------------------
398// x86 functions
399#if HAVE_MMX
400#if CONFIG_VP8_ENCODER
401const sad_m_by_n_fn_t sad_16x16_mmx = vp8_sad16x16_mmx;
402const sad_m_by_n_fn_t sad_8x16_mmx = vp8_sad8x16_mmx;
403const sad_m_by_n_fn_t sad_16x8_mmx = vp8_sad16x8_mmx;
404const sad_m_by_n_fn_t sad_8x8_mmx = vp8_sad8x8_mmx;
405const sad_m_by_n_fn_t sad_4x4_mmx = vp8_sad4x4_mmx;
406#endif
407#if CONFIG_VP9_ENCODER
408const sad_m_by_n_fn_t sad_16x16_mmx_vp9 = vp9_sad16x16_mmx;
409const sad_m_by_n_fn_t sad_8x16_mmx_vp9 = vp9_sad8x16_mmx;
410const sad_m_by_n_fn_t sad_16x8_mmx_vp9 = vp9_sad16x8_mmx;
411const sad_m_by_n_fn_t sad_8x8_mmx_vp9 = vp9_sad8x8_mmx;
412const sad_m_by_n_fn_t sad_4x4_mmx_vp9 = vp9_sad4x4_mmx;
413#endif
414
415const sad_m_by_n_test_param_t mmx_tests[] = {
416#if CONFIG_VP8_ENCODER
417  make_tuple(16, 16, sad_16x16_mmx),
418  make_tuple(8, 16, sad_8x16_mmx),
419  make_tuple(16, 8, sad_16x8_mmx),
420  make_tuple(8, 8, sad_8x8_mmx),
421  make_tuple(4, 4, sad_4x4_mmx),
422#endif
423#if CONFIG_VP9_ENCODER
424  make_tuple(16, 16, sad_16x16_mmx_vp9),
425  make_tuple(8, 16, sad_8x16_mmx_vp9),
426  make_tuple(16, 8, sad_16x8_mmx_vp9),
427  make_tuple(8, 8, sad_8x8_mmx_vp9),
428  make_tuple(4, 4, sad_4x4_mmx_vp9),
429#endif
430};
431INSTANTIATE_TEST_CASE_P(MMX, SADTest, ::testing::ValuesIn(mmx_tests));
432#endif
433
434#if HAVE_SSE
435#if CONFIG_VP9_ENCODER
436#if CONFIG_USE_X86INC
437const sad_m_by_n_fn_t sad_4x4_sse_vp9 = vp9_sad4x4_sse;
438const sad_m_by_n_fn_t sad_4x8_sse_vp9 = vp9_sad4x8_sse;
439INSTANTIATE_TEST_CASE_P(SSE, SADTest, ::testing::Values(
440                        make_tuple(4, 4, sad_4x4_sse_vp9),
441                        make_tuple(4, 8, sad_4x8_sse_vp9)));
442
443const sad_n_by_n_by_4_fn_t sad_4x8x4d_sse = vp9_sad4x8x4d_sse;
444const sad_n_by_n_by_4_fn_t sad_4x4x4d_sse = vp9_sad4x4x4d_sse;
445INSTANTIATE_TEST_CASE_P(SSE, SADx4Test, ::testing::Values(
446                        make_tuple(4, 8, sad_4x8x4d_sse),
447                        make_tuple(4, 4, sad_4x4x4d_sse)));
448#endif  // CONFIG_USE_X86INC
449#endif  // CONFIG_VP9_ENCODER
450#endif  // HAVE_SSE
451
452#if HAVE_SSE2
453#if CONFIG_VP8_ENCODER
454const sad_m_by_n_fn_t sad_16x16_wmt = vp8_sad16x16_wmt;
455const sad_m_by_n_fn_t sad_8x16_wmt = vp8_sad8x16_wmt;
456const sad_m_by_n_fn_t sad_16x8_wmt = vp8_sad16x8_wmt;
457const sad_m_by_n_fn_t sad_8x8_wmt = vp8_sad8x8_wmt;
458const sad_m_by_n_fn_t sad_4x4_wmt = vp8_sad4x4_wmt;
459#endif
460#if CONFIG_VP9_ENCODER
461#if CONFIG_USE_X86INC
462const sad_m_by_n_fn_t sad_64x64_sse2_vp9 = vp9_sad64x64_sse2;
463const sad_m_by_n_fn_t sad_64x32_sse2_vp9 = vp9_sad64x32_sse2;
464const sad_m_by_n_fn_t sad_32x64_sse2_vp9 = vp9_sad32x64_sse2;
465const sad_m_by_n_fn_t sad_32x32_sse2_vp9 = vp9_sad32x32_sse2;
466const sad_m_by_n_fn_t sad_32x16_sse2_vp9 = vp9_sad32x16_sse2;
467const sad_m_by_n_fn_t sad_16x32_sse2_vp9 = vp9_sad16x32_sse2;
468const sad_m_by_n_fn_t sad_16x16_sse2_vp9 = vp9_sad16x16_sse2;
469const sad_m_by_n_fn_t sad_16x8_sse2_vp9 = vp9_sad16x8_sse2;
470const sad_m_by_n_fn_t sad_8x16_sse2_vp9 = vp9_sad8x16_sse2;
471const sad_m_by_n_fn_t sad_8x8_sse2_vp9 = vp9_sad8x8_sse2;
472const sad_m_by_n_fn_t sad_8x4_sse2_vp9 = vp9_sad8x4_sse2;
473#endif
474#endif
475const sad_m_by_n_test_param_t sse2_tests[] = {
476#if CONFIG_VP8_ENCODER
477  make_tuple(16, 16, sad_16x16_wmt),
478  make_tuple(8, 16, sad_8x16_wmt),
479  make_tuple(16, 8, sad_16x8_wmt),
480  make_tuple(8, 8, sad_8x8_wmt),
481  make_tuple(4, 4, sad_4x4_wmt),
482#endif
483#if CONFIG_VP9_ENCODER
484#if CONFIG_USE_X86INC
485  make_tuple(64, 64, sad_64x64_sse2_vp9),
486  make_tuple(64, 32, sad_64x32_sse2_vp9),
487  make_tuple(32, 64, sad_32x64_sse2_vp9),
488  make_tuple(32, 32, sad_32x32_sse2_vp9),
489  make_tuple(32, 16, sad_32x16_sse2_vp9),
490  make_tuple(16, 32, sad_16x32_sse2_vp9),
491  make_tuple(16, 16, sad_16x16_sse2_vp9),
492  make_tuple(16, 8, sad_16x8_sse2_vp9),
493  make_tuple(8, 16, sad_8x16_sse2_vp9),
494  make_tuple(8, 8, sad_8x8_sse2_vp9),
495  make_tuple(8, 4, sad_8x4_sse2_vp9),
496#endif
497#endif
498};
499INSTANTIATE_TEST_CASE_P(SSE2, SADTest, ::testing::ValuesIn(sse2_tests));
500
501#if CONFIG_VP9_ENCODER
502#if CONFIG_USE_X86INC
503const sad_n_by_n_by_4_fn_t sad_64x64x4d_sse2 = vp9_sad64x64x4d_sse2;
504const sad_n_by_n_by_4_fn_t sad_64x32x4d_sse2 = vp9_sad64x32x4d_sse2;
505const sad_n_by_n_by_4_fn_t sad_32x64x4d_sse2 = vp9_sad32x64x4d_sse2;
506const sad_n_by_n_by_4_fn_t sad_32x32x4d_sse2 = vp9_sad32x32x4d_sse2;
507const sad_n_by_n_by_4_fn_t sad_32x16x4d_sse2 = vp9_sad32x16x4d_sse2;
508const sad_n_by_n_by_4_fn_t sad_16x32x4d_sse2 = vp9_sad16x32x4d_sse2;
509const sad_n_by_n_by_4_fn_t sad_16x16x4d_sse2 = vp9_sad16x16x4d_sse2;
510const sad_n_by_n_by_4_fn_t sad_16x8x4d_sse2 = vp9_sad16x8x4d_sse2;
511const sad_n_by_n_by_4_fn_t sad_8x16x4d_sse2 = vp9_sad8x16x4d_sse2;
512const sad_n_by_n_by_4_fn_t sad_8x8x4d_sse2 = vp9_sad8x8x4d_sse2;
513const sad_n_by_n_by_4_fn_t sad_8x4x4d_sse2 = vp9_sad8x4x4d_sse2;
514INSTANTIATE_TEST_CASE_P(SSE2, SADx4Test, ::testing::Values(
515                        make_tuple(64, 64, sad_64x64x4d_sse2),
516                        make_tuple(64, 32, sad_64x32x4d_sse2),
517                        make_tuple(32, 64, sad_32x64x4d_sse2),
518                        make_tuple(32, 32, sad_32x32x4d_sse2),
519                        make_tuple(32, 16, sad_32x16x4d_sse2),
520                        make_tuple(16, 32, sad_16x32x4d_sse2),
521                        make_tuple(16, 16, sad_16x16x4d_sse2),
522                        make_tuple(16, 8, sad_16x8x4d_sse2),
523                        make_tuple(8, 16, sad_8x16x4d_sse2),
524                        make_tuple(8, 8, sad_8x8x4d_sse2),
525                        make_tuple(8, 4, sad_8x4x4d_sse2)));
526#endif
527#endif
528#endif
529
530#if HAVE_SSE3
531#if CONFIG_VP8_ENCODER
532const sad_n_by_n_by_4_fn_t sad_16x16x4d_sse3 = vp8_sad16x16x4d_sse3;
533const sad_n_by_n_by_4_fn_t sad_16x8x4d_sse3 = vp8_sad16x8x4d_sse3;
534const sad_n_by_n_by_4_fn_t sad_8x16x4d_sse3 = vp8_sad8x16x4d_sse3;
535const sad_n_by_n_by_4_fn_t sad_8x8x4d_sse3 = vp8_sad8x8x4d_sse3;
536const sad_n_by_n_by_4_fn_t sad_4x4x4d_sse3 = vp8_sad4x4x4d_sse3;
537INSTANTIATE_TEST_CASE_P(SSE3, SADx4Test, ::testing::Values(
538                        make_tuple(16, 16, sad_16x16x4d_sse3),
539                        make_tuple(16, 8, sad_16x8x4d_sse3),
540                        make_tuple(8, 16, sad_8x16x4d_sse3),
541                        make_tuple(8, 8, sad_8x8x4d_sse3),
542                        make_tuple(4, 4, sad_4x4x4d_sse3)));
543#endif
544#endif
545
546#if HAVE_SSSE3
547#if CONFIG_USE_X86INC
548#if CONFIG_VP8_ENCODER
549const sad_m_by_n_fn_t sad_16x16_sse3 = vp8_sad16x16_sse3;
550INSTANTIATE_TEST_CASE_P(SSE3, SADTest, ::testing::Values(
551                        make_tuple(16, 16, sad_16x16_sse3)));
552#endif
553#endif
554#endif
555
556}  // namespace
557