1 /*
2  * Copyright (c) 2016, Alliance for Open Media. All rights reserved
3  *
4  * This source code is subject to the terms of the BSD 2 Clause License and
5  * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6  * was not distributed with this source code in the LICENSE file, you can
7  * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8  * Media Patent License 1.0 was not distributed with this source code in the
9  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10 */
11 
12 #include <math.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <limits>
16 
17 #include "third_party/googletest/src/googletest/include/gtest/gtest.h"
18 
19 #include "./av1_rtcd.h"
20 #include "./aom_dsp_rtcd.h"
21 #include "test/acm_random.h"
22 #include "test/clear_system_state.h"
23 #include "test/register_state_check.h"
24 #include "test/util.h"
25 #include "av1/common/blockd.h"
26 #include "av1/common/scan.h"
27 #include "aom/aom_integer.h"
28 #include "aom_ports/aom_timer.h"
29 
30 using libaom_test::ACMRandom;
31 
32 namespace {
33 typedef void (*FwdTxfmFunc)(const int16_t *in, tran_low_t *out, int stride);
34 typedef void (*InvTxfmFunc)(const tran_low_t *in, uint8_t *out, int stride);
35 typedef void (*InvTxfmWithBdFunc)(const tran_low_t *in, uint8_t *out,
36                                   int stride, int bd);
37 
38 template <InvTxfmFunc fn>
wrapper(const tran_low_t * in,uint8_t * out,int stride,int bd)39 void wrapper(const tran_low_t *in, uint8_t *out, int stride, int bd) {
40   (void)bd;
41   fn(in, out, stride);
42 }
43 
44 typedef std::tr1::tuple<FwdTxfmFunc, InvTxfmWithBdFunc, InvTxfmWithBdFunc,
45                         TX_SIZE, int, int, int>
46     PartialInvTxfmParam;
47 const int kMaxNumCoeffs = 1024;
48 const int kCountTestBlock = 10000;
49 
50 class PartialIDctTest : public ::testing::TestWithParam<PartialInvTxfmParam> {
51  public:
~PartialIDctTest()52   virtual ~PartialIDctTest() {}
SetUp()53   virtual void SetUp() {
54     rnd_.Reset(ACMRandom::DeterministicSeed());
55     ftxfm_ = GET_PARAM(0);
56     full_itxfm_ = GET_PARAM(1);
57     partial_itxfm_ = GET_PARAM(2);
58     tx_size_ = GET_PARAM(3);
59     last_nonzero_ = GET_PARAM(4);
60     bit_depth_ = GET_PARAM(5);
61     pixel_size_ = GET_PARAM(6);
62     mask_ = (1 << bit_depth_) - 1;
63 
64     switch (tx_size_) {
65       case TX_4X4: size_ = 4; break;
66       case TX_8X8: size_ = 8; break;
67       case TX_16X16: size_ = 16; break;
68       case TX_32X32: size_ = 32; break;
69       default: FAIL() << "Wrong Size!"; break;
70     }
71 
72     // Randomize stride_ to a value less than or equal to 1024
73     stride_ = rnd_(1024) + 1;
74     if (stride_ < size_) {
75       stride_ = size_;
76     }
77     // Align stride_ to 16 if it's bigger than 16.
78     if (stride_ > 16) {
79       stride_ &= ~15;
80     }
81 
82     input_block_size_ = size_ * size_;
83     output_block_size_ = size_ * stride_;
84 
85     input_block_ = reinterpret_cast<tran_low_t *>(
86         aom_memalign(16, sizeof(*input_block_) * input_block_size_));
87     output_block_ = reinterpret_cast<uint8_t *>(
88         aom_memalign(16, pixel_size_ * output_block_size_));
89     output_block_ref_ = reinterpret_cast<uint8_t *>(
90         aom_memalign(16, pixel_size_ * output_block_size_));
91   }
92 
TearDown()93   virtual void TearDown() {
94     aom_free(input_block_);
95     input_block_ = NULL;
96     aom_free(output_block_);
97     output_block_ = NULL;
98     aom_free(output_block_ref_);
99     output_block_ref_ = NULL;
100     libaom_test::ClearSystemState();
101   }
102 
InitMem()103   void InitMem() {
104     memset(input_block_, 0, sizeof(*input_block_) * input_block_size_);
105     if (pixel_size_ == 1) {
106       for (int j = 0; j < output_block_size_; ++j) {
107         output_block_[j] = output_block_ref_[j] = rnd_.Rand16() & mask_;
108       }
109     } else {
110       ASSERT_EQ(2, pixel_size_);
111       uint16_t *const output = reinterpret_cast<uint16_t *>(output_block_);
112       uint16_t *const output_ref =
113           reinterpret_cast<uint16_t *>(output_block_ref_);
114       for (int j = 0; j < output_block_size_; ++j) {
115         output[j] = output_ref[j] = rnd_.Rand16() & mask_;
116       }
117     }
118   }
119 
InitInput()120   void InitInput() {
121     const int max_coeff = 32766 / 4;
122     int max_energy_leftover = max_coeff * max_coeff;
123     for (int j = 0; j < last_nonzero_; ++j) {
124       int16_t coeff = static_cast<int16_t>(sqrt(1.0 * max_energy_leftover) *
125                                            (rnd_.Rand16() - 32768) / 65536);
126       max_energy_leftover -= coeff * coeff;
127       if (max_energy_leftover < 0) {
128         max_energy_leftover = 0;
129         coeff = 0;
130       }
131       input_block_[av1_default_scan_orders[tx_size_].scan[j]] = coeff;
132     }
133   }
134 
135  protected:
136   int last_nonzero_;
137   TX_SIZE tx_size_;
138   tran_low_t *input_block_;
139   uint8_t *output_block_;
140   uint8_t *output_block_ref_;
141   int size_;
142   int stride_;
143   int pixel_size_;
144   int input_block_size_;
145   int output_block_size_;
146   int bit_depth_;
147   int mask_;
148   FwdTxfmFunc ftxfm_;
149   InvTxfmWithBdFunc full_itxfm_;
150   InvTxfmWithBdFunc partial_itxfm_;
151   ACMRandom rnd_;
152 };
153 
TEST_P(PartialIDctTest,RunQuantCheck)154 TEST_P(PartialIDctTest, RunQuantCheck) {
155   DECLARE_ALIGNED(16, int16_t, input_extreme_block[kMaxNumCoeffs]);
156   DECLARE_ALIGNED(16, tran_low_t, output_ref_block[kMaxNumCoeffs]);
157 
158   InitMem();
159   for (int i = 0; i < kCountTestBlock; ++i) {
160     // Initialize a test block with input range [-mask_, mask_].
161     if (i == 0) {
162       for (int k = 0; k < input_block_size_; ++k) {
163         input_extreme_block[k] = mask_;
164       }
165     } else if (i == 1) {
166       for (int k = 0; k < input_block_size_; ++k) {
167         input_extreme_block[k] = -mask_;
168       }
169     } else {
170       for (int k = 0; k < input_block_size_; ++k) {
171         input_extreme_block[k] = rnd_.Rand8() % 2 ? mask_ : -mask_;
172       }
173     }
174 
175     ftxfm_(input_extreme_block, output_ref_block, size_);
176 
177     // quantization with minimum allowed step sizes
178     input_block_[0] = (output_ref_block[0] / 4) * 4;
179     for (int k = 1; k < last_nonzero_; ++k) {
180       const int pos = av1_default_scan_orders[tx_size_].scan[k];
181       input_block_[pos] = (output_ref_block[pos] / 4) * 4;
182     }
183 
184     ASM_REGISTER_STATE_CHECK(
185         full_itxfm_(input_block_, output_block_ref_, stride_, bit_depth_));
186     ASM_REGISTER_STATE_CHECK(
187         partial_itxfm_(input_block_, output_block_, stride_, bit_depth_));
188     ASSERT_EQ(0, memcmp(output_block_ref_, output_block_,
189                         pixel_size_ * output_block_size_))
190         << "Error: partial inverse transform produces different results";
191   }
192 }
193 
TEST_P(PartialIDctTest,ResultsMatch)194 TEST_P(PartialIDctTest, ResultsMatch) {
195   for (int i = 0; i < kCountTestBlock; ++i) {
196     InitMem();
197     InitInput();
198 
199     ASM_REGISTER_STATE_CHECK(
200         full_itxfm_(input_block_, output_block_ref_, stride_, bit_depth_));
201     ASM_REGISTER_STATE_CHECK(
202         partial_itxfm_(input_block_, output_block_, stride_, bit_depth_));
203     ASSERT_EQ(0, memcmp(output_block_ref_, output_block_,
204                         pixel_size_ * output_block_size_))
205         << "Error: partial inverse transform produces different results";
206   }
207 }
208 
TEST_P(PartialIDctTest,AddOutputBlock)209 TEST_P(PartialIDctTest, AddOutputBlock) {
210   for (int i = 0; i < kCountTestBlock; ++i) {
211     InitMem();
212     for (int j = 0; j < last_nonzero_; ++j) {
213       input_block_[av1_default_scan_orders[tx_size_].scan[j]] = 10;
214     }
215 
216     ASM_REGISTER_STATE_CHECK(
217         full_itxfm_(input_block_, output_block_ref_, stride_, bit_depth_));
218     ASM_REGISTER_STATE_CHECK(
219         partial_itxfm_(input_block_, output_block_, stride_, bit_depth_));
220     ASSERT_EQ(0, memcmp(output_block_ref_, output_block_,
221                         pixel_size_ * output_block_size_))
222         << "Error: Transform results are not correctly added to output.";
223   }
224 }
225 
TEST_P(PartialIDctTest,SingleExtremeCoeff)226 TEST_P(PartialIDctTest, SingleExtremeCoeff) {
227   const int16_t max_coeff = INT16_MAX;
228   const int16_t min_coeff = INT16_MIN;
229   for (int i = 0; i < last_nonzero_; ++i) {
230     memset(input_block_, 0, sizeof(*input_block_) * input_block_size_);
231     // Run once for min and once for max.
232     for (int j = 0; j < 2; ++j) {
233       const int coeff = j ? min_coeff : max_coeff;
234 
235       memset(output_block_, 0, pixel_size_ * output_block_size_);
236       memset(output_block_ref_, 0, pixel_size_ * output_block_size_);
237       input_block_[av1_default_scan_orders[tx_size_].scan[i]] = coeff;
238 
239       ASM_REGISTER_STATE_CHECK(
240           full_itxfm_(input_block_, output_block_ref_, stride_, bit_depth_));
241       ASM_REGISTER_STATE_CHECK(
242           partial_itxfm_(input_block_, output_block_, stride_, bit_depth_));
243       ASSERT_EQ(0, memcmp(output_block_ref_, output_block_,
244                           pixel_size_ * output_block_size_))
245           << "Error: Fails with single coeff of " << coeff << " at " << i
246           << ".";
247     }
248   }
249 }
250 
TEST_P(PartialIDctTest,DISABLED_Speed)251 TEST_P(PartialIDctTest, DISABLED_Speed) {
252   // Keep runtime stable with transform size.
253   const int kCountSpeedTestBlock = 500000000 / input_block_size_;
254   InitMem();
255   InitInput();
256 
257   for (int i = 0; i < kCountSpeedTestBlock; ++i) {
258     ASM_REGISTER_STATE_CHECK(
259         full_itxfm_(input_block_, output_block_ref_, stride_, bit_depth_));
260   }
261   aom_usec_timer timer;
262   aom_usec_timer_start(&timer);
263   for (int i = 0; i < kCountSpeedTestBlock; ++i) {
264     partial_itxfm_(input_block_, output_block_, stride_, bit_depth_);
265   }
266   libaom_test::ClearSystemState();
267   aom_usec_timer_mark(&timer);
268   const int elapsed_time =
269       static_cast<int>(aom_usec_timer_elapsed(&timer) / 1000);
270   printf("idct%dx%d_%d (bitdepth %d) time: %5d ms\n", size_, size_,
271          last_nonzero_, bit_depth_, elapsed_time);
272 
273   ASSERT_EQ(0, memcmp(output_block_ref_, output_block_,
274                       pixel_size_ * output_block_size_))
275       << "Error: partial inverse transform produces different results";
276 }
277 
278 using std::tr1::make_tuple;
279 
280 const PartialInvTxfmParam c_partial_idct_tests[] = {
281   make_tuple(&aom_fdct32x32_c, &wrapper<aom_idct32x32_1024_add_c>,
282              &wrapper<aom_idct32x32_1024_add_c>, TX_32X32, 1024, 8, 1),
283   make_tuple(&aom_fdct32x32_c, &wrapper<aom_idct32x32_1024_add_c>,
284              &wrapper<aom_idct32x32_135_add_c>, TX_32X32, 135, 8, 1),
285   make_tuple(&aom_fdct32x32_c, &wrapper<aom_idct32x32_1024_add_c>,
286              &wrapper<aom_idct32x32_34_add_c>, TX_32X32, 34, 8, 1),
287   make_tuple(&aom_fdct32x32_c, &wrapper<aom_idct32x32_1024_add_c>,
288              &wrapper<aom_idct32x32_1_add_c>, TX_32X32, 1, 8, 1),
289   make_tuple(&aom_fdct16x16_c, &wrapper<aom_idct16x16_256_add_c>,
290              &wrapper<aom_idct16x16_256_add_c>, TX_16X16, 256, 8, 1),
291   make_tuple(&aom_fdct16x16_c, &wrapper<aom_idct16x16_256_add_c>,
292              &wrapper<aom_idct16x16_38_add_c>, TX_16X16, 38, 8, 1),
293   make_tuple(&aom_fdct16x16_c, &wrapper<aom_idct16x16_256_add_c>,
294              &wrapper<aom_idct16x16_10_add_c>, TX_16X16, 10, 8, 1),
295   make_tuple(&aom_fdct16x16_c, &wrapper<aom_idct16x16_256_add_c>,
296              &wrapper<aom_idct16x16_1_add_c>, TX_16X16, 1, 8, 1),
297   make_tuple(&aom_fdct8x8_c, &wrapper<aom_idct8x8_64_add_c>,
298              &wrapper<aom_idct8x8_64_add_c>, TX_8X8, 64, 8, 1),
299   make_tuple(&aom_fdct8x8_c, &wrapper<aom_idct8x8_64_add_c>,
300              &wrapper<aom_idct8x8_12_add_c>, TX_8X8, 12, 8, 1),
301   make_tuple(&aom_fdct8x8_c, &wrapper<aom_idct8x8_64_add_c>,
302              &wrapper<aom_idct8x8_1_add_c>, TX_8X8, 1, 8, 1),
303   make_tuple(&aom_fdct4x4_c, &wrapper<aom_idct4x4_16_add_c>,
304              &wrapper<aom_idct4x4_16_add_c>, TX_4X4, 16, 8, 1),
305   make_tuple(&aom_fdct4x4_c, &wrapper<aom_idct4x4_16_add_c>,
306              &wrapper<aom_idct4x4_1_add_c>, TX_4X4, 1, 8, 1)
307 };
308 
309 INSTANTIATE_TEST_CASE_P(C, PartialIDctTest,
310                         ::testing::ValuesIn(c_partial_idct_tests));
311 
312 #if HAVE_NEON && !CONFIG_HIGHBITDEPTH
313 const PartialInvTxfmParam neon_partial_idct_tests[] = {
314   make_tuple(&aom_fdct32x32_c, &wrapper<aom_idct32x32_1024_add_c>,
315              &wrapper<aom_idct32x32_1_add_neon>, TX_32X32, 1, 8, 1),
316   make_tuple(&aom_fdct16x16_c, &wrapper<aom_idct16x16_256_add_c>,
317              &wrapper<aom_idct16x16_10_add_neon>, TX_16X16, 10, 8, 1),
318   make_tuple(&aom_fdct16x16_c, &wrapper<aom_idct16x16_256_add_c>,
319              &wrapper<aom_idct16x16_1_add_neon>, TX_16X16, 1, 8, 1),
320   make_tuple(&aom_fdct8x8_c, &wrapper<aom_idct8x8_64_add_c>,
321              &wrapper<aom_idct8x8_12_add_neon>, TX_8X8, 12, 8, 1),
322   make_tuple(&aom_fdct8x8_c, &wrapper<aom_idct8x8_64_add_c>,
323              &wrapper<aom_idct8x8_1_add_neon>, TX_8X8, 1, 8, 1),
324   make_tuple(&aom_fdct4x4_c, &wrapper<aom_idct4x4_16_add_c>,
325              &wrapper<aom_idct4x4_1_add_neon>, TX_4X4, 1, 8, 1)
326 };
327 
328 INSTANTIATE_TEST_CASE_P(NEON, PartialIDctTest,
329                         ::testing::ValuesIn(neon_partial_idct_tests));
330 #endif  // HAVE_NEON && !CONFIG_HIGHBITDEPTH
331 
332 #if HAVE_SSE2
333 const PartialInvTxfmParam sse2_partial_idct_tests[] = {
334   make_tuple(&aom_fdct32x32_c, &wrapper<aom_idct32x32_1024_add_c>,
335              &wrapper<aom_idct32x32_1024_add_sse2>, TX_32X32, 1024, 8, 1),
336   make_tuple(&aom_fdct32x32_c, &wrapper<aom_idct32x32_1024_add_c>,
337              &wrapper<aom_idct32x32_1024_add_sse2>, TX_32X32, 135, 8, 1),
338   make_tuple(&aom_fdct32x32_c, &wrapper<aom_idct32x32_1024_add_c>,
339              &wrapper<aom_idct32x32_34_add_sse2>, TX_32X32, 34, 8, 1),
340   make_tuple(&aom_fdct32x32_c, &wrapper<aom_idct32x32_1024_add_c>,
341              &wrapper<aom_idct32x32_1_add_sse2>, TX_32X32, 1, 8, 1),
342   make_tuple(&aom_fdct16x16_c, &wrapper<aom_idct16x16_256_add_c>,
343              &wrapper<aom_idct16x16_256_add_sse2>, TX_16X16, 256, 8, 1),
344   make_tuple(&aom_fdct16x16_c, &wrapper<aom_idct16x16_256_add_c>,
345              &wrapper<aom_idct16x16_10_add_sse2>, TX_16X16, 10, 8, 1),
346   make_tuple(&aom_fdct16x16_c, &wrapper<aom_idct16x16_256_add_c>,
347              &wrapper<aom_idct16x16_1_add_sse2>, TX_16X16, 1, 8, 1),
348   make_tuple(&aom_fdct8x8_c, &wrapper<aom_idct8x8_64_add_c>,
349              &wrapper<aom_idct8x8_64_add_sse2>, TX_8X8, 64, 8, 1),
350   make_tuple(&aom_fdct8x8_c, &wrapper<aom_idct8x8_64_add_c>,
351              &wrapper<aom_idct8x8_12_add_sse2>, TX_8X8, 12, 8, 1),
352   make_tuple(&aom_fdct8x8_c, &wrapper<aom_idct8x8_64_add_c>,
353              &wrapper<aom_idct8x8_1_add_sse2>, TX_8X8, 1, 8, 1),
354   make_tuple(&aom_fdct4x4_c, &wrapper<aom_idct4x4_16_add_c>,
355              &wrapper<aom_idct4x4_16_add_sse2>, TX_4X4, 16, 8, 1),
356   make_tuple(&aom_fdct4x4_c, &wrapper<aom_idct4x4_16_add_c>,
357              &wrapper<aom_idct4x4_1_add_sse2>, TX_4X4, 1, 8, 1)
358 };
359 
360 INSTANTIATE_TEST_CASE_P(SSE2, PartialIDctTest,
361                         ::testing::ValuesIn(sse2_partial_idct_tests));
362 
363 #endif  // HAVE_SSE2
364 
365 #if HAVE_SSSE3
366 const PartialInvTxfmParam ssse3_partial_idct_tests[] = {
367   make_tuple(&aom_fdct32x32_c, &wrapper<aom_idct32x32_1024_add_c>,
368              &wrapper<aom_idct32x32_1024_add_ssse3>, TX_32X32, 1024, 8, 1),
369   make_tuple(&aom_fdct32x32_c, &wrapper<aom_idct32x32_1024_add_c>,
370              &wrapper<aom_idct32x32_135_add_ssse3>, TX_32X32, 135, 8, 1),
371   make_tuple(&aom_fdct32x32_c, &wrapper<aom_idct32x32_1024_add_c>,
372              &wrapper<aom_idct32x32_34_add_ssse3>, TX_32X32, 34, 8, 1),
373   make_tuple(&aom_fdct8x8_c, &wrapper<aom_idct8x8_64_add_c>,
374              &wrapper<aom_idct8x8_64_add_ssse3>, TX_8X8, 64, 8, 1),
375   make_tuple(&aom_fdct8x8_c, &wrapper<aom_idct8x8_64_add_c>,
376              &wrapper<aom_idct8x8_12_add_ssse3>, TX_8X8, 12, 8, 1)
377 };
378 
379 INSTANTIATE_TEST_CASE_P(SSSE3, PartialIDctTest,
380                         ::testing::ValuesIn(ssse3_partial_idct_tests));
381 #endif  // HAVE_SSSE3
382 
383 #if HAVE_AVX2
384 const PartialInvTxfmParam avx2_partial_idct_tests[] = {
385   make_tuple(&aom_fdct16x16_c, &wrapper<aom_idct16x16_256_add_c>,
386              &wrapper<aom_idct16x16_256_add_avx2>, TX_16X16, 256, 8, 1),
387   make_tuple(&aom_fdct16x16_c, &wrapper<aom_idct16x16_256_add_c>,
388              &wrapper<aom_idct16x16_38_add_avx2>, TX_16X16, 38, 8, 1),
389   make_tuple(&aom_fdct16x16_c, &wrapper<aom_idct16x16_256_add_c>,
390              &wrapper<aom_idct16x16_10_add_avx2>, TX_16X16, 10, 8, 1),
391   make_tuple(&aom_fdct16x16_c, &wrapper<aom_idct16x16_256_add_c>,
392              &wrapper<aom_idct16x16_1_add_avx2>, TX_16X16, 1, 8, 1),
393   make_tuple(&aom_fdct32x32_c, &wrapper<aom_idct32x32_1024_add_c>,
394              &wrapper<aom_idct32x32_1024_add_avx2>, TX_32X32, 1024, 8, 1),
395   make_tuple(&aom_fdct32x32_c, &wrapper<aom_idct32x32_1024_add_c>,
396              &wrapper<aom_idct32x32_135_add_avx2>, TX_32X32, 135, 8, 1),
397   make_tuple(&aom_fdct32x32_c, &wrapper<aom_idct32x32_1024_add_c>,
398              &wrapper<aom_idct32x32_34_add_avx2>, TX_32X32, 34, 8, 1),
399   make_tuple(&aom_fdct32x32_c, &wrapper<aom_idct32x32_1024_add_c>,
400              &wrapper<aom_idct32x32_1_add_avx2>, TX_32X32, 1, 8, 1),
401 };
402 
403 INSTANTIATE_TEST_CASE_P(AVX2, PartialIDctTest,
404                         ::testing::ValuesIn(avx2_partial_idct_tests));
405 #endif  // HAVE_AVX2
406 
407 #if HAVE_DSPR2 && !CONFIG_HIGHBITDEPTH
408 const PartialInvTxfmParam dspr2_partial_idct_tests[] = {
409   make_tuple(&aom_fdct32x32_c, &wrapper<aom_idct32x32_1024_add_c>,
410              &wrapper<aom_idct32x32_1024_add_dspr2>, TX_32X32, 1024, 8, 1),
411   make_tuple(&aom_fdct32x32_c, &wrapper<aom_idct32x32_1024_add_c>,
412              &wrapper<aom_idct32x32_1024_add_dspr2>, TX_32X32, 135, 8, 1),
413   make_tuple(&aom_fdct32x32_c, &wrapper<aom_idct32x32_1024_add_c>,
414              &wrapper<aom_idct32x32_34_add_dspr2>, TX_32X32, 34, 8, 1),
415   make_tuple(&aom_fdct32x32_c, &wrapper<aom_idct32x32_1024_add_c>,
416              &wrapper<aom_idct32x32_1_add_dspr2>, TX_32X32, 1, 8, 1),
417   make_tuple(&aom_fdct16x16_c, &wrapper<aom_idct16x16_256_add_c>,
418              &wrapper<aom_idct16x16_256_add_dspr2>, TX_16X16, 256, 8, 1),
419   make_tuple(&aom_fdct16x16_c, &wrapper<aom_idct16x16_256_add_c>,
420              &wrapper<aom_idct16x16_10_add_dspr2>, TX_16X16, 10, 8, 1),
421   make_tuple(&aom_fdct16x16_c, &wrapper<aom_idct16x16_256_add_c>,
422              &wrapper<aom_idct16x16_1_add_dspr2>, TX_16X16, 1, 8, 1),
423   make_tuple(&aom_fdct8x8_c, &wrapper<aom_idct8x8_64_add_c>,
424              &wrapper<aom_idct8x8_64_add_dspr2>, TX_8X8, 64, 8, 1),
425   make_tuple(&aom_fdct8x8_c, &wrapper<aom_idct8x8_64_add_c>,
426              &wrapper<aom_idct8x8_12_add_dspr2>, TX_8X8, 12, 8, 1),
427   make_tuple(&aom_fdct8x8_c, &wrapper<aom_idct8x8_64_add_c>,
428              &wrapper<aom_idct8x8_1_add_dspr2>, TX_8X8, 1, 8, 1),
429   make_tuple(&aom_fdct4x4_c, &wrapper<aom_idct4x4_16_add_c>,
430              &wrapper<aom_idct4x4_16_add_dspr2>, TX_4X4, 16, 8, 1),
431   make_tuple(&aom_fdct4x4_c, &wrapper<aom_idct4x4_16_add_c>,
432              &wrapper<aom_idct4x4_1_add_dspr2>, TX_4X4, 1, 8, 1)
433 };
434 
435 INSTANTIATE_TEST_CASE_P(DSPR2, PartialIDctTest,
436                         ::testing::ValuesIn(dspr2_partial_idct_tests));
437 #endif  // HAVE_DSPR2 && !CONFIG_HIGHBITDEPTH
438 
439 #if HAVE_MSA && !CONFIG_HIGHBITDEPTH
440 const PartialInvTxfmParam msa_partial_idct_tests[] = {
441   make_tuple(&aom_fdct32x32_c, &wrapper<aom_idct32x32_1024_add_c>,
442              &wrapper<aom_idct32x32_1024_add_msa>, TX_32X32, 1024, 8, 1),
443   make_tuple(&aom_fdct32x32_c, &wrapper<aom_idct32x32_1024_add_c>,
444              &wrapper<aom_idct32x32_1024_add_msa>, TX_32X32, 135, 8, 1),
445   make_tuple(&aom_fdct32x32_c, &wrapper<aom_idct32x32_1024_add_c>,
446              &wrapper<aom_idct32x32_34_add_msa>, TX_32X32, 34, 8, 1),
447   make_tuple(&aom_fdct32x32_c, &wrapper<aom_idct32x32_1024_add_c>,
448              &wrapper<aom_idct32x32_1_add_msa>, TX_32X32, 1, 8, 1),
449   make_tuple(&aom_fdct16x16_c, &wrapper<aom_idct16x16_256_add_c>,
450              &wrapper<aom_idct16x16_256_add_msa>, TX_16X16, 256, 8, 1),
451   make_tuple(&aom_fdct16x16_c, &wrapper<aom_idct16x16_256_add_c>,
452              &wrapper<aom_idct16x16_10_add_msa>, TX_16X16, 10, 8, 1),
453   make_tuple(&aom_fdct16x16_c, &wrapper<aom_idct16x16_256_add_c>,
454              &wrapper<aom_idct16x16_1_add_msa>, TX_16X16, 1, 8, 1),
455   make_tuple(&aom_fdct8x8_c, &wrapper<aom_idct8x8_64_add_c>,
456              &wrapper<aom_idct8x8_64_add_msa>, TX_8X8, 64, 8, 1),
457   make_tuple(&aom_fdct8x8_c, &wrapper<aom_idct8x8_64_add_c>,
458              &wrapper<aom_idct8x8_12_add_msa>, TX_8X8, 12, 8, 1),
459   make_tuple(&aom_fdct8x8_c, &wrapper<aom_idct8x8_64_add_c>,
460              &wrapper<aom_idct8x8_1_add_msa>, TX_8X8, 1, 8, 1),
461   make_tuple(&aom_fdct4x4_c, &wrapper<aom_idct4x4_16_add_c>,
462              &wrapper<aom_idct4x4_16_add_msa>, TX_4X4, 16, 8, 1),
463   make_tuple(&aom_fdct4x4_c, &wrapper<aom_idct4x4_16_add_c>,
464              &wrapper<aom_idct4x4_1_add_msa>, TX_4X4, 1, 8, 1)
465 };
466 
467 INSTANTIATE_TEST_CASE_P(MSA, PartialIDctTest,
468                         ::testing::ValuesIn(msa_partial_idct_tests));
469 #endif  // HAVE_MSA && !CONFIG_HIGHBITDEPTH
470 
471 }  // namespace
472