blob: 876d7a8fd0d3ba0b8e8978d4529bb92f471df018 [file] [log] [blame]
/*
* Copyright (c) 2021, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 3-Clause Clear License
* and the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear
* License was not distributed with this source code in the LICENSE file, you
* can obtain it at aomedia.org/license/software-license/bsd-3-c-c/. If the
* Alliance for Open Media Patent License 1.0 was not distributed with this
* source code in the PATENTS file, you can obtain it at
* aomedia.org/license/patent-license/.
*/
#include <assert.h>
#include <emmintrin.h> // SSE2
#include "config/aom_config.h"
#include "config/aom_dsp_rtcd.h"
#include "config/av1_rtcd.h"
#include "aom_dsp/blend.h"
#include "aom_dsp/x86/mem_sse2.h"
#include "aom_dsp/x86/synonyms.h"
#include "aom_ports/mem.h"
#include "av1/common/av1_common_int.h"
#include "av1/common/filter.h"
#include "av1/common/reconinter.h"
#include "av1/encoder/reconinter_enc.h"
unsigned int aom_get_mb_ss_sse2(const int16_t *src) {
__m128i vsum = _mm_setzero_si128();
int i;
for (i = 0; i < 32; ++i) {
const __m128i v = xx_loadu_128(src);
vsum = _mm_add_epi32(vsum, _mm_madd_epi16(v, v));
src += 8;
}
vsum = _mm_add_epi32(vsum, _mm_srli_si128(vsum, 8));
vsum = _mm_add_epi32(vsum, _mm_srli_si128(vsum, 4));
return _mm_cvtsi128_si32(vsum);
}
static INLINE __m128i highbd_comp_mask_pred_line_sse2(const __m128i s0,
const __m128i s1,
const __m128i a) {
const __m128i alpha_max = _mm_set1_epi16((1 << AOM_BLEND_A64_ROUND_BITS));
const __m128i round_const =
_mm_set1_epi32((1 << AOM_BLEND_A64_ROUND_BITS) >> 1);
const __m128i a_inv = _mm_sub_epi16(alpha_max, a);
const __m128i s_lo = _mm_unpacklo_epi16(s0, s1);
const __m128i a_lo = _mm_unpacklo_epi16(a, a_inv);
const __m128i pred_lo = _mm_madd_epi16(s_lo, a_lo);
const __m128i pred_l = _mm_srai_epi32(_mm_add_epi32(pred_lo, round_const),
AOM_BLEND_A64_ROUND_BITS);
const __m128i s_hi = _mm_unpackhi_epi16(s0, s1);
const __m128i a_hi = _mm_unpackhi_epi16(a, a_inv);
const __m128i pred_hi = _mm_madd_epi16(s_hi, a_hi);
const __m128i pred_h = _mm_srai_epi32(_mm_add_epi32(pred_hi, round_const),
AOM_BLEND_A64_ROUND_BITS);
const __m128i comp = _mm_packs_epi32(pred_l, pred_h);
return comp;
}
void aom_highbd_comp_mask_pred_sse2(uint16_t *comp_pred, const uint16_t *pred,
int width, int height, const uint16_t *ref,
int ref_stride, const uint8_t *mask,
int mask_stride, int invert_mask) {
int i = 0;
const uint16_t *src0 = invert_mask ? pred : ref;
const uint16_t *src1 = invert_mask ? ref : pred;
const int stride0 = invert_mask ? width : ref_stride;
const int stride1 = invert_mask ? ref_stride : width;
const __m128i zero = _mm_setzero_si128();
if (width == 8) {
do {
const __m128i s0 = _mm_loadu_si128((const __m128i *)(src0));
const __m128i s1 = _mm_loadu_si128((const __m128i *)(src1));
const __m128i m_8 = _mm_loadl_epi64((const __m128i *)mask);
const __m128i m_16 = _mm_unpacklo_epi8(m_8, zero);
const __m128i comp = highbd_comp_mask_pred_line_sse2(s0, s1, m_16);
_mm_storeu_si128((__m128i *)comp_pred, comp);
src0 += stride0;
src1 += stride1;
mask += mask_stride;
comp_pred += width;
i += 1;
} while (i < height);
} else if (width == 16) {
do {
const __m128i s0 = _mm_loadu_si128((const __m128i *)(src0));
const __m128i s2 = _mm_loadu_si128((const __m128i *)(src0 + 8));
const __m128i s1 = _mm_loadu_si128((const __m128i *)(src1));
const __m128i s3 = _mm_loadu_si128((const __m128i *)(src1 + 8));
const __m128i m_8 = _mm_loadu_si128((const __m128i *)mask);
const __m128i m01_16 = _mm_unpacklo_epi8(m_8, zero);
const __m128i m23_16 = _mm_unpackhi_epi8(m_8, zero);
const __m128i comp = highbd_comp_mask_pred_line_sse2(s0, s1, m01_16);
const __m128i comp1 = highbd_comp_mask_pred_line_sse2(s2, s3, m23_16);
_mm_storeu_si128((__m128i *)comp_pred, comp);
_mm_storeu_si128((__m128i *)(comp_pred + 8), comp1);
src0 += stride0;
src1 += stride1;
mask += mask_stride;
comp_pred += width;
i += 1;
} while (i < height);
#if CONFIG_WEDGE_MOD_EXT
} else if (width >= 32) {
#else
} else if (width == 32) {
#endif // CONFIG_WEDGE_MOD_EXT
do {
#if CONFIG_WEDGE_MOD_EXT
const int num_16_subs = (width >> 4);
for (int j = 0; j < num_16_subs; j++) {
#else
for (int j = 0; j < 2; j++) {
#endif // CONFIG_WEDGE_MOD_EXT
const __m128i s0 = _mm_loadu_si128((const __m128i *)(src0 + j * 16));
const __m128i s2 =
_mm_loadu_si128((const __m128i *)(src0 + 8 + j * 16));
const __m128i s1 = _mm_loadu_si128((const __m128i *)(src1 + j * 16));
const __m128i s3 =
_mm_loadu_si128((const __m128i *)(src1 + 8 + j * 16));
const __m128i m_8 = _mm_loadu_si128((const __m128i *)(mask + j * 16));
const __m128i m01_16 = _mm_unpacklo_epi8(m_8, zero);
const __m128i m23_16 = _mm_unpackhi_epi8(m_8, zero);
const __m128i comp = highbd_comp_mask_pred_line_sse2(s0, s1, m01_16);
const __m128i comp1 = highbd_comp_mask_pred_line_sse2(s2, s3, m23_16);
_mm_storeu_si128((__m128i *)(comp_pred + j * 16), comp);
_mm_storeu_si128((__m128i *)(comp_pred + 8 + j * 16), comp1);
}
src0 += stride0;
src1 += stride1;
mask += mask_stride;
comp_pred += width;
i += 1;
} while (i < height);
}
}