2 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
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.
16 #include "third_party/googletest/src/googletest/include/gtest/gtest.h"
17 #include "test/register_state_check.h"
18 #include "test/function_equivalence_test.h"
20 #include "config/aom_config.h"
21 #include "config/aom_dsp_rtcd.h"
22 #include "config/av1_rtcd.h"
24 #include "aom/aom_integer.h"
26 #include "av1/common/enums.h"
28 #include "aom_dsp/blend.h"
30 using libaom_test::FunctionEquivalenceTest
;
34 template <typename BlendA64Func
, typename SrcPixel
, typename DstPixel
>
35 class BlendA64MaskTest
: public FunctionEquivalenceTest
<BlendA64Func
> {
37 static const int kIterations
= 10000;
38 static const int kMaxWidth
= MAX_SB_SIZE
* 5; // * 5 to cover longer strides
39 static const int kMaxHeight
= MAX_SB_SIZE
;
40 static const int kBufSize
= kMaxWidth
* kMaxHeight
;
41 static const int kMaxMaskWidth
= 2 * MAX_SB_SIZE
;
42 static const int kMaxMaskSize
= kMaxMaskWidth
* kMaxMaskWidth
;
44 virtual ~BlendA64MaskTest() {}
46 virtual void Execute(const SrcPixel
*p_src0
, const SrcPixel
*p_src1
) = 0;
48 template <typename Pixel
>
49 void GetSources(Pixel
**src0
, Pixel
**src1
, Pixel
* /*dst*/) {
50 switch (this->rng_(3)) {
51 case 0: // Separate sources
55 case 1: // src0 == dst
57 src0_stride_
= dst_stride_
;
58 src0_offset_
= dst_offset_
;
61 case 2: // src1 == dst
64 src1_stride_
= dst_stride_
;
65 src1_offset_
= dst_offset_
;
71 void GetSources(uint16_t **src0
, uint16_t **src1
, uint8_t * /*dst*/) {
76 uint8_t Rand1() { return this->rng_
.Rand8() & 1; }
79 w_
= 4 << this->rng_(MAX_SB_SIZE_LOG2
- 1);
80 h_
= 4 << this->rng_(MAX_SB_SIZE_LOG2
- 1);
85 dst_offset_
= this->rng_(33);
86 dst_stride_
= this->rng_(kMaxWidth
+ 1 - w_
) + w_
;
88 src0_offset_
= this->rng_(33);
89 src0_stride_
= this->rng_(kMaxWidth
+ 1 - w_
) + w_
;
91 src1_offset_
= this->rng_(33);
92 src1_stride_
= this->rng_(kMaxWidth
+ 1 - w_
) + w_
;
95 this->rng_(kMaxWidth
+ 1 - w_
* (subx_
? 2 : 1)) + w_
* (subx_
? 2 : 1);
103 GetSources(&p_src0
, &p_src1
, &dst_ref_
[0]);
105 Execute(p_src0
, p_src1
);
107 for (int r
= 0; r
< h_
; ++r
) {
108 for (int c
= 0; c
< w_
; ++c
) {
109 ASSERT_EQ(dst_ref_
[dst_offset_
+ r
* dst_stride_
+ c
],
110 dst_tst_
[dst_offset_
+ r
* dst_stride_
+ c
])
111 << w_
<< "x" << h_
<< " r: " << r
<< " c: " << c
;
116 DstPixel dst_ref_
[kBufSize
];
117 DstPixel dst_tst_
[kBufSize
];
118 uint32_t dst_stride_
;
119 uint32_t dst_offset_
;
121 SrcPixel src0_
[kBufSize
];
122 uint32_t src0_stride_
;
123 uint32_t src0_offset_
;
125 SrcPixel src1_
[kBufSize
];
126 uint32_t src1_stride_
;
127 uint32_t src1_offset_
;
129 uint8_t mask_
[kMaxMaskSize
];
139 //////////////////////////////////////////////////////////////////////////////
141 //////////////////////////////////////////////////////////////////////////////
143 typedef void (*F8B
)(uint8_t *dst
, uint32_t dst_stride
, const uint8_t *src0
,
144 uint32_t src0_stride
, const uint8_t *src1
,
145 uint32_t src1_stride
, const uint8_t *mask
,
146 uint32_t mask_stride
, int w
, int h
, int subx
, int suby
);
147 typedef libaom_test::FuncParam
<F8B
> TestFuncs
;
149 class BlendA64MaskTest8B
: public BlendA64MaskTest
<F8B
, uint8_t, uint8_t> {
151 void Execute(const uint8_t *p_src0
, const uint8_t *p_src1
) {
152 params_
.ref_func(dst_ref_
+ dst_offset_
, dst_stride_
, p_src0
+ src0_offset_
,
153 src0_stride_
, p_src1
+ src1_offset_
, src1_stride_
, mask_
,
154 kMaxMaskWidth
, w_
, h_
, subx_
, suby_
);
155 ASM_REGISTER_STATE_CHECK(params_
.tst_func(
156 dst_tst_
+ dst_offset_
, dst_stride_
, p_src0
+ src0_offset_
,
157 src0_stride_
, p_src1
+ src1_offset_
, src1_stride_
, mask_
, kMaxMaskWidth
,
158 w_
, h_
, subx_
, suby_
));
162 TEST_P(BlendA64MaskTest8B
, RandomValues
) {
163 for (int iter
= 0; iter
< kIterations
&& !HasFatalFailure(); ++iter
) {
164 for (int i
= 0; i
< kBufSize
; ++i
) {
165 dst_ref_
[i
] = rng_
.Rand8();
166 dst_tst_
[i
] = rng_
.Rand8();
168 src0_
[i
] = rng_
.Rand8();
169 src1_
[i
] = rng_
.Rand8();
172 for (int i
= 0; i
< kMaxMaskSize
; ++i
)
173 mask_
[i
] = rng_(AOM_BLEND_A64_MAX_ALPHA
+ 1);
179 TEST_P(BlendA64MaskTest8B
, ExtremeValues
) {
180 for (int iter
= 0; iter
< kIterations
&& !HasFatalFailure(); ++iter
) {
181 for (int i
= 0; i
< kBufSize
; ++i
) {
182 dst_ref_
[i
] = rng_(2) + 254;
183 dst_tst_
[i
] = rng_(2) + 254;
184 src0_
[i
] = rng_(2) + 254;
185 src1_
[i
] = rng_(2) + 254;
188 for (int i
= 0; i
< kMaxMaskSize
; ++i
)
189 mask_
[i
] = rng_(2) + AOM_BLEND_A64_MAX_ALPHA
- 1;
196 INSTANTIATE_TEST_CASE_P(SSE4_1
, BlendA64MaskTest8B
,
197 ::testing::Values(TestFuncs(
198 aom_blend_a64_mask_c
, aom_blend_a64_mask_sse4_1
)));
199 #endif // HAVE_SSE4_1
201 //////////////////////////////////////////////////////////////////////////////
202 // 8 bit _d16 version
203 //////////////////////////////////////////////////////////////////////////////
205 typedef void (*F8B_D16
)(uint8_t *dst
, uint32_t dst_stride
, const uint16_t *src0
,
206 uint32_t src0_stride
, const uint16_t *src1
,
207 uint32_t src1_stride
, const uint8_t *mask
,
208 uint32_t mask_stride
, int w
, int h
, int subx
, int suby
,
209 ConvolveParams
*conv_params
);
210 typedef libaom_test::FuncParam
<F8B_D16
> TestFuncs_d16
;
212 class BlendA64MaskTest8B_d16
213 : public BlendA64MaskTest
<F8B_D16
, uint16_t, uint8_t> {
215 // max number of bits used by the source
216 static const int kSrcMaxBitsMask
= 0x3fff;
218 void Execute(const uint16_t *p_src0
, const uint16_t *p_src1
) {
219 ConvolveParams conv_params
;
220 conv_params
.round_0
= ROUND0_BITS
;
221 conv_params
.round_1
= COMPOUND_ROUND1_BITS
;
222 params_
.ref_func(dst_ref_
+ dst_offset_
, dst_stride_
, p_src0
+ src0_offset_
,
223 src0_stride_
, p_src1
+ src1_offset_
, src1_stride_
, mask_
,
224 kMaxMaskWidth
, w_
, h_
, subx_
, suby_
, &conv_params
);
225 ASM_REGISTER_STATE_CHECK(params_
.tst_func(
226 dst_tst_
+ dst_offset_
, dst_stride_
, p_src0
+ src0_offset_
,
227 src0_stride_
, p_src1
+ src1_offset_
, src1_stride_
, mask_
, kMaxMaskWidth
,
228 w_
, h_
, subx_
, suby_
, &conv_params
));
232 TEST_P(BlendA64MaskTest8B_d16
, RandomValues
) {
233 for (int iter
= 0; iter
< kIterations
&& !HasFatalFailure(); ++iter
) {
234 for (int i
= 0; i
< kBufSize
; ++i
) {
235 dst_ref_
[i
] = rng_
.Rand8();
236 dst_tst_
[i
] = rng_
.Rand8();
238 src0_
[i
] = rng_
.Rand16() & kSrcMaxBitsMask
;
239 src1_
[i
] = rng_
.Rand16() & kSrcMaxBitsMask
;
242 for (int i
= 0; i
< kMaxMaskSize
; ++i
)
243 mask_
[i
] = rng_(AOM_BLEND_A64_MAX_ALPHA
+ 1);
249 TEST_P(BlendA64MaskTest8B_d16
, ExtremeValues
) {
250 for (int iter
= 0; iter
< kIterations
&& !HasFatalFailure(); ++iter
) {
251 for (int i
= 0; i
< kBufSize
; ++i
) {
255 src0_
[i
] = kSrcMaxBitsMask
;
256 src1_
[i
] = kSrcMaxBitsMask
;
259 for (int i
= 0; i
< kMaxMaskSize
; ++i
)
260 mask_
[i
] = AOM_BLEND_A64_MAX_ALPHA
- 1;
267 INSTANTIATE_TEST_CASE_P(
268 SSE4_1
, BlendA64MaskTest8B_d16
,
269 ::testing::Values(TestFuncs_d16(aom_lowbd_blend_a64_d16_mask_c
,
270 aom_lowbd_blend_a64_d16_mask_sse4_1
)));
271 #endif // HAVE_SSE4_1
274 INSTANTIATE_TEST_CASE_P(
275 NEON
, BlendA64MaskTest8B_d16
,
276 ::testing::Values(TestFuncs_d16(aom_lowbd_blend_a64_d16_mask_c
,
277 aom_lowbd_blend_a64_d16_mask_neon
)));
280 //////////////////////////////////////////////////////////////////////////////
281 // High bit-depth version
282 //////////////////////////////////////////////////////////////////////////////
284 typedef void (*FHBD
)(uint8_t *dst
, uint32_t dst_stride
, const uint8_t *src0
,
285 uint32_t src0_stride
, const uint8_t *src1
,
286 uint32_t src1_stride
, const uint8_t *mask
,
287 uint32_t mask_stride
, int w
, int h
, int subx
, int suby
,
289 typedef libaom_test::FuncParam
<FHBD
> TestFuncsHBD
;
291 class BlendA64MaskTestHBD
: public BlendA64MaskTest
<FHBD
, uint16_t, uint16_t> {
293 void Execute(const uint16_t *p_src0
, const uint16_t *p_src1
) {
294 params_
.ref_func(CONVERT_TO_BYTEPTR(dst_ref_
+ dst_offset_
), dst_stride_
,
295 CONVERT_TO_BYTEPTR(p_src0
+ src0_offset_
), src0_stride_
,
296 CONVERT_TO_BYTEPTR(p_src1
+ src1_offset_
), src1_stride_
,
297 mask_
, kMaxMaskWidth
, w_
, h_
, subx_
, suby_
, bit_depth_
);
298 ASM_REGISTER_STATE_CHECK(params_
.tst_func(
299 CONVERT_TO_BYTEPTR(dst_tst_
+ dst_offset_
), dst_stride_
,
300 CONVERT_TO_BYTEPTR(p_src0
+ src0_offset_
), src0_stride_
,
301 CONVERT_TO_BYTEPTR(p_src1
+ src1_offset_
), src1_stride_
, mask_
,
302 kMaxMaskWidth
, w_
, h_
, subx_
, suby_
, bit_depth_
));
308 TEST_P(BlendA64MaskTestHBD
, RandomValues
) {
309 for (int iter
= 0; iter
< kIterations
&& !HasFatalFailure(); ++iter
) {
311 case 0: bit_depth_
= 8; break;
312 case 1: bit_depth_
= 10; break;
313 default: bit_depth_
= 12; break;
316 const int hi
= 1 << bit_depth_
;
318 for (int i
= 0; i
< kBufSize
; ++i
) {
319 dst_ref_
[i
] = rng_(hi
);
320 dst_tst_
[i
] = rng_(hi
);
325 for (int i
= 0; i
< kMaxMaskSize
; ++i
)
326 mask_
[i
] = rng_(AOM_BLEND_A64_MAX_ALPHA
+ 1);
332 TEST_P(BlendA64MaskTestHBD
, ExtremeValues
) {
333 for (int iter
= 0; iter
< 1000 && !HasFatalFailure(); ++iter
) {
335 case 0: bit_depth_
= 8; break;
336 case 1: bit_depth_
= 10; break;
337 default: bit_depth_
= 12; break;
340 const int hi
= 1 << bit_depth_
;
341 const int lo
= hi
- 2;
343 for (int i
= 0; i
< kBufSize
; ++i
) {
344 dst_ref_
[i
] = rng_(hi
- lo
) + lo
;
345 dst_tst_
[i
] = rng_(hi
- lo
) + lo
;
346 src0_
[i
] = rng_(hi
- lo
) + lo
;
347 src1_
[i
] = rng_(hi
- lo
) + lo
;
350 for (int i
= 0; i
< kMaxMaskSize
; ++i
)
351 mask_
[i
] = rng_(2) + AOM_BLEND_A64_MAX_ALPHA
- 1;
358 INSTANTIATE_TEST_CASE_P(
359 SSE4_1
, BlendA64MaskTestHBD
,
360 ::testing::Values(TestFuncsHBD(aom_highbd_blend_a64_mask_c
,
361 aom_highbd_blend_a64_mask_sse4_1
)));
362 #endif // HAVE_SSE4_1
364 //////////////////////////////////////////////////////////////////////////////
366 //////////////////////////////////////////////////////////////////////////////
368 typedef void (*FHBD_D16
)(uint8_t *dst
, uint32_t dst_stride
,
369 const CONV_BUF_TYPE
*src0
, uint32_t src0_stride
,
370 const CONV_BUF_TYPE
*src1
, uint32_t src1_stride
,
371 const uint8_t *mask
, uint32_t mask_stride
, int w
,
372 int h
, int subx
, int suby
, ConvolveParams
*conv_params
,
374 typedef libaom_test::FuncParam
<FHBD_D16
> TestFuncsHBD_d16
;
376 class BlendA64MaskTestHBD_d16
377 : public BlendA64MaskTest
<FHBD_D16
, uint16_t, uint16_t> {
379 // max number of bits used by the source
380 static const int kSrcMaxBitsMask
= (1 << 14) - 1;
381 static const int kSrcMaxBitsMaskHBD
= (1 << 16) - 1;
383 void Execute(const uint16_t *p_src0
, const uint16_t *p_src1
) {
384 ConvolveParams conv_params
;
385 conv_params
.round_0
= (bit_depth_
== 12) ? ROUND0_BITS
+ 2 : ROUND0_BITS
;
386 conv_params
.round_1
= COMPOUND_ROUND1_BITS
;
388 params_
.ref_func(CONVERT_TO_BYTEPTR(dst_ref_
+ dst_offset_
), dst_stride_
,
389 p_src0
+ src0_offset_
, src0_stride_
, p_src1
+ src1_offset_
,
390 src1_stride_
, mask_
, kMaxMaskWidth
, w_
, h_
, subx_
, suby_
,
391 &conv_params
, bit_depth_
);
392 if (params_
.tst_func
) {
393 ASM_REGISTER_STATE_CHECK(params_
.tst_func(
394 CONVERT_TO_BYTEPTR(dst_tst_
+ dst_offset_
), dst_stride_
,
395 p_src0
+ src0_offset_
, src0_stride_
, p_src1
+ src1_offset_
,
396 src1_stride_
, mask_
, kMaxMaskWidth
, w_
, h_
, subx_
, suby_
,
397 &conv_params
, bit_depth_
));
402 int src_max_bits_mask_
;
405 TEST_P(BlendA64MaskTestHBD_d16
, RandomValues
) {
406 if (params_
.tst_func
== NULL
) return;
407 for (int iter
= 0; iter
< kIterations
&& !HasFatalFailure(); ++iter
) {
409 case 0: bit_depth_
= 8; break;
410 case 1: bit_depth_
= 10; break;
411 default: bit_depth_
= 12; break;
414 (bit_depth_
== 8) ? kSrcMaxBitsMask
: kSrcMaxBitsMaskHBD
;
416 for (int i
= 0; i
< kBufSize
; ++i
) {
417 dst_ref_
[i
] = rng_
.Rand8();
418 dst_tst_
[i
] = rng_
.Rand8();
420 src0_
[i
] = rng_
.Rand16() & src_max_bits_mask_
;
421 src1_
[i
] = rng_
.Rand16() & src_max_bits_mask_
;
424 for (int i
= 0; i
< kMaxMaskSize
; ++i
)
425 mask_
[i
] = rng_(AOM_BLEND_A64_MAX_ALPHA
+ 1);
431 TEST_P(BlendA64MaskTestHBD_d16
, SaturatedValues
) {
432 for (bit_depth_
= 8; bit_depth_
<= 12; bit_depth_
+= 2) {
434 (bit_depth_
== 8) ? kSrcMaxBitsMask
: kSrcMaxBitsMaskHBD
;
436 for (int i
= 0; i
< kBufSize
; ++i
) {
438 dst_tst_
[i
] = (1 << bit_depth_
) - 1;
440 src0_
[i
] = src_max_bits_mask_
;
441 src1_
[i
] = src_max_bits_mask_
;
444 for (int i
= 0; i
< kMaxMaskSize
; ++i
) mask_
[i
] = AOM_BLEND_A64_MAX_ALPHA
;
450 INSTANTIATE_TEST_CASE_P(
451 C
, BlendA64MaskTestHBD_d16
,
452 ::testing::Values(TestFuncsHBD_d16(aom_highbd_blend_a64_d16_mask_c
, NULL
)));
454 // TODO(slavarnway): Enable the following in the avx2 commit. (56501)
457 INSTANTIATE_TEST_CASE_P(
458 SSE4_1
, BlendA64MaskTestHBD
,
459 ::testing::Values(TestFuncsHBD(aom_highbd_blend_a64_mask_c
,
460 aom_highbd_blend_a64_mask_avx2
)));