Blame libfreerdp/codec/rfx_sse2.c

Packit Service fa4841
/**
Packit Service fa4841
 * FreeRDP: A Remote Desktop Protocol Implementation
Packit Service fa4841
 * RemoteFX Codec Library - SSE2 Optimizations
Packit Service fa4841
 *
Packit Service fa4841
 * Copyright 2011 Stephen Erisman
Packit Service fa4841
 * Copyright 2011 Norbert Federa <norbert.federa@thincast.com>
Packit Service fa4841
 *
Packit Service fa4841
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit Service fa4841
 * you may not use this file except in compliance with the License.
Packit Service fa4841
 * You may obtain a copy of the License at
Packit Service fa4841
 *
Packit Service fa4841
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit Service fa4841
 *
Packit Service fa4841
 * Unless required by applicable law or agreed to in writing, software
Packit Service fa4841
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit Service fa4841
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit Service fa4841
 * See the License for the specific language governing permissions and
Packit Service fa4841
 * limitations under the License.
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
#ifdef HAVE_CONFIG_H
Packit Service fa4841
#include "config.h"
Packit Service fa4841
#endif
Packit Service fa4841
Packit Service fa4841
#include <stdio.h>
Packit Service fa4841
#include <stdlib.h>
Packit Service fa4841
#include <string.h>
Packit Service fa4841
#include <winpr/sysinfo.h>
Packit Service fa4841
Packit Service fa4841
#include <xmmintrin.h>
Packit Service fa4841
#include <emmintrin.h>
Packit Service fa4841
Packit Service fa4841
#include "rfx_types.h"
Packit Service fa4841
#include "rfx_sse2.h"
Packit Service fa4841
Packit Service fa4841
#ifdef _MSC_VER
Packit Service fa4841
#define __attribute__(...)
Packit Service fa4841
#endif
Packit Service fa4841
Packit Service fa4841
#define CACHE_LINE_BYTES 64
Packit Service fa4841
Packit Service fa4841
#ifndef __clang__
Packit Service fa4841
#define ATTRIBUTES __gnu_inline__, __always_inline__, __artificial__
Packit Service fa4841
#else
Packit Service fa4841
#define ATTRIBUTES __gnu_inline__, __always_inline__
Packit Service fa4841
#endif
Packit Service fa4841
Packit Service fa4841
#define _mm_between_epi16(_val, _min, _max)                    \
Packit Service fa4841
	do                                                         \
Packit Service fa4841
	{                                                          \
Packit Service fa4841
		_val = _mm_min_epi16(_max, _mm_max_epi16(_val, _min)); \
Packit Service fa4841
	} while (0)
Packit Service fa4841
Packit Service fa4841
static __inline void __attribute__((ATTRIBUTES)) _mm_prefetch_buffer(char* buffer, int num_bytes)
Packit Service fa4841
{
Packit Service fa4841
	__m128i* buf = (__m128i*)buffer;
Packit Service fa4841
	unsigned int i;
Packit Service fa4841
Packit Service fa4841
	for (i = 0; i < (num_bytes / sizeof(__m128i)); i += (CACHE_LINE_BYTES / sizeof(__m128i)))
Packit Service fa4841
	{
Packit Service fa4841
		_mm_prefetch((char*)(&buf[i]), _MM_HINT_NTA);
Packit Service fa4841
	}
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/* rfx_decode_ycbcr_to_rgb_sse2 code now resides in the primitives library. */
Packit Service fa4841
/* rfx_encode_rgb_to_ycbcr_sse2 code now resides in the primitives library. */
Packit Service fa4841
Packit Service fa4841
static __inline void __attribute__((ATTRIBUTES))
Packit Service fa4841
rfx_quantization_decode_block_sse2(INT16* buffer, const int buffer_size, const UINT32 factor)
Packit Service fa4841
{
Packit Service fa4841
	__m128i a;
Packit Service fa4841
	__m128i* ptr = (__m128i*)buffer;
Packit Service fa4841
	__m128i* buf_end = (__m128i*)(buffer + buffer_size);
Packit Service fa4841
Packit Service fa4841
	if (factor == 0)
Packit Service fa4841
		return;
Packit Service fa4841
Packit Service fa4841
	do
Packit Service fa4841
	{
Packit Service fa4841
		a = _mm_load_si128(ptr);
Packit Service fa4841
		a = _mm_slli_epi16(a, factor);
Packit Service fa4841
		_mm_store_si128(ptr, a);
Packit Service fa4841
		ptr++;
Packit Service fa4841
	} while (ptr < buf_end);
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static void rfx_quantization_decode_sse2(INT16* buffer, const UINT32* quantVals)
Packit Service fa4841
{
Packit Service fa4841
	_mm_prefetch_buffer((char*)buffer, 4096 * sizeof(INT16));
Packit Service fa4841
	rfx_quantization_decode_block_sse2(&buffer[0], 1024, quantVals[8] - 1);    /* HL1 */
Packit Service fa4841
	rfx_quantization_decode_block_sse2(&buffer[1024], 1024, quantVals[7] - 1); /* LH1 */
Packit Service fa4841
	rfx_quantization_decode_block_sse2(&buffer[2048], 1024, quantVals[9] - 1); /* HH1 */
Packit Service fa4841
	rfx_quantization_decode_block_sse2(&buffer[3072], 256, quantVals[5] - 1);  /* HL2 */
Packit Service fa4841
	rfx_quantization_decode_block_sse2(&buffer[3328], 256, quantVals[4] - 1);  /* LH2 */
Packit Service fa4841
	rfx_quantization_decode_block_sse2(&buffer[3584], 256, quantVals[6] - 1);  /* HH2 */
Packit Service fa4841
	rfx_quantization_decode_block_sse2(&buffer[3840], 64, quantVals[2] - 1);   /* HL3 */
Packit Service fa4841
	rfx_quantization_decode_block_sse2(&buffer[3904], 64, quantVals[1] - 1);   /* LH3 */
Packit Service fa4841
	rfx_quantization_decode_block_sse2(&buffer[3968], 64, quantVals[3] - 1);   /* HH3 */
Packit Service fa4841
	rfx_quantization_decode_block_sse2(&buffer[4032], 64, quantVals[0] - 1);   /* LL3 */
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static __inline void __attribute__((ATTRIBUTES))
Packit Service fa4841
rfx_quantization_encode_block_sse2(INT16* buffer, const int buffer_size, const UINT32 factor)
Packit Service fa4841
{
Packit Service fa4841
	__m128i a;
Packit Service fa4841
	__m128i* ptr = (__m128i*)buffer;
Packit Service fa4841
	__m128i* buf_end = (__m128i*)(buffer + buffer_size);
Packit Service fa4841
	__m128i half;
Packit Service fa4841
Packit Service fa4841
	if (factor == 0)
Packit Service fa4841
		return;
Packit Service fa4841
Packit Service fa4841
	half = _mm_set1_epi16(1 << (factor - 1));
Packit Service fa4841
Packit Service fa4841
	do
Packit Service fa4841
	{
Packit Service fa4841
		a = _mm_load_si128(ptr);
Packit Service fa4841
		a = _mm_add_epi16(a, half);
Packit Service fa4841
		a = _mm_srai_epi16(a, factor);
Packit Service fa4841
		_mm_store_si128(ptr, a);
Packit Service fa4841
		ptr++;
Packit Service fa4841
	} while (ptr < buf_end);
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static void rfx_quantization_encode_sse2(INT16* buffer, const UINT32* quantization_values)
Packit Service fa4841
{
Packit Service fa4841
	_mm_prefetch_buffer((char*)buffer, 4096 * sizeof(INT16));
Packit Service fa4841
	rfx_quantization_encode_block_sse2(buffer, 1024, quantization_values[8] - 6);        /* HL1 */
Packit Service fa4841
	rfx_quantization_encode_block_sse2(buffer + 1024, 1024, quantization_values[7] - 6); /* LH1 */
Packit Service fa4841
	rfx_quantization_encode_block_sse2(buffer + 2048, 1024, quantization_values[9] - 6); /* HH1 */
Packit Service fa4841
	rfx_quantization_encode_block_sse2(buffer + 3072, 256, quantization_values[5] - 6);  /* HL2 */
Packit Service fa4841
	rfx_quantization_encode_block_sse2(buffer + 3328, 256, quantization_values[4] - 6);  /* LH2 */
Packit Service fa4841
	rfx_quantization_encode_block_sse2(buffer + 3584, 256, quantization_values[6] - 6);  /* HH2 */
Packit Service fa4841
	rfx_quantization_encode_block_sse2(buffer + 3840, 64, quantization_values[2] - 6);   /* HL3 */
Packit Service fa4841
	rfx_quantization_encode_block_sse2(buffer + 3904, 64, quantization_values[1] - 6);   /* LH3 */
Packit Service fa4841
	rfx_quantization_encode_block_sse2(buffer + 3968, 64, quantization_values[3] - 6);   /* HH3 */
Packit Service fa4841
	rfx_quantization_encode_block_sse2(buffer + 4032, 64, quantization_values[0] - 6);   /* LL3 */
Packit Service fa4841
	rfx_quantization_encode_block_sse2(buffer, 4096, 5);
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static __inline void __attribute__((ATTRIBUTES))
Packit Service fa4841
rfx_dwt_2d_decode_block_horiz_sse2(INT16* l, INT16* h, INT16* dst, int subband_width)
Packit Service fa4841
{
Packit Service fa4841
	int y, n;
Packit Service fa4841
	INT16* l_ptr = l;
Packit Service fa4841
	INT16* h_ptr = h;
Packit Service fa4841
	INT16* dst_ptr = dst;
Packit Service fa4841
	int first;
Packit Service fa4841
	int last;
Packit Service fa4841
	__m128i l_n;
Packit Service fa4841
	__m128i h_n;
Packit Service fa4841
	__m128i h_n_m;
Packit Service fa4841
	__m128i tmp_n;
Packit Service fa4841
	__m128i dst_n;
Packit Service fa4841
	__m128i dst_n_p;
Packit Service fa4841
	__m128i dst1;
Packit Service fa4841
	__m128i dst2;
Packit Service fa4841
Packit Service fa4841
	for (y = 0; y < subband_width; y++)
Packit Service fa4841
	{
Packit Service fa4841
		/* Even coefficients */
Packit Service fa4841
		for (n = 0; n < subband_width; n += 8)
Packit Service fa4841
		{
Packit Service fa4841
			/* dst[2n] = l[n] - ((h[n-1] + h[n] + 1) >> 1); */
Packit Service fa4841
			l_n = _mm_load_si128((__m128i*)l_ptr);
Packit Service fa4841
			h_n = _mm_load_si128((__m128i*)h_ptr);
Packit Service fa4841
			h_n_m = _mm_loadu_si128((__m128i*)(h_ptr - 1));
Packit Service fa4841
Packit Service fa4841
			if (n == 0)
Packit Service fa4841
			{
Packit Service fa4841
				first = _mm_extract_epi16(h_n_m, 1);
Packit Service fa4841
				h_n_m = _mm_insert_epi16(h_n_m, first, 0);
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			tmp_n = _mm_add_epi16(h_n, h_n_m);
Packit Service fa4841
			tmp_n = _mm_add_epi16(tmp_n, _mm_set1_epi16(1));
Packit Service fa4841
			tmp_n = _mm_srai_epi16(tmp_n, 1);
Packit Service fa4841
			dst_n = _mm_sub_epi16(l_n, tmp_n);
Packit Service fa4841
			_mm_store_si128((__m128i*)l_ptr, dst_n);
Packit Service fa4841
			l_ptr += 8;
Packit Service fa4841
			h_ptr += 8;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		l_ptr -= subband_width;
Packit Service fa4841
		h_ptr -= subband_width;
Packit Service fa4841
Packit Service fa4841
		/* Odd coefficients */
Packit Service fa4841
		for (n = 0; n < subband_width; n += 8)
Packit Service fa4841
		{
Packit Service fa4841
			/* dst[2n + 1] = (h[n] << 1) + ((dst[2n] + dst[2n + 2]) >> 1); */
Packit Service fa4841
			h_n = _mm_load_si128((__m128i*)h_ptr);
Packit Service fa4841
			h_n = _mm_slli_epi16(h_n, 1);
Packit Service fa4841
			dst_n = _mm_load_si128((__m128i*)(l_ptr));
Packit Service fa4841
			dst_n_p = _mm_loadu_si128((__m128i*)(l_ptr + 1));
Packit Service fa4841
Packit Service fa4841
			if (n == subband_width - 8)
Packit Service fa4841
			{
Packit Service fa4841
				last = _mm_extract_epi16(dst_n_p, 6);
Packit Service fa4841
				dst_n_p = _mm_insert_epi16(dst_n_p, last, 7);
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			tmp_n = _mm_add_epi16(dst_n_p, dst_n);
Packit Service fa4841
			tmp_n = _mm_srai_epi16(tmp_n, 1);
Packit Service fa4841
			tmp_n = _mm_add_epi16(tmp_n, h_n);
Packit Service fa4841
			dst1 = _mm_unpacklo_epi16(dst_n, tmp_n);
Packit Service fa4841
			dst2 = _mm_unpackhi_epi16(dst_n, tmp_n);
Packit Service fa4841
			_mm_store_si128((__m128i*)dst_ptr, dst1);
Packit Service fa4841
			_mm_store_si128((__m128i*)(dst_ptr + 8), dst2);
Packit Service fa4841
			l_ptr += 8;
Packit Service fa4841
			h_ptr += 8;
Packit Service fa4841
			dst_ptr += 16;
Packit Service fa4841
		}
Packit Service fa4841
	}
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static __inline void __attribute__((ATTRIBUTES))
Packit Service fa4841
rfx_dwt_2d_decode_block_vert_sse2(INT16* l, INT16* h, INT16* dst, int subband_width)
Packit Service fa4841
{
Packit Service fa4841
	int x, n;
Packit Service fa4841
	INT16* l_ptr = l;
Packit Service fa4841
	INT16* h_ptr = h;
Packit Service fa4841
	INT16* dst_ptr = dst;
Packit Service fa4841
	__m128i l_n;
Packit Service fa4841
	__m128i h_n;
Packit Service fa4841
	__m128i tmp_n;
Packit Service fa4841
	__m128i h_n_m;
Packit Service fa4841
	__m128i dst_n;
Packit Service fa4841
	__m128i dst_n_m;
Packit Service fa4841
	__m128i dst_n_p;
Packit Service fa4841
	int total_width = subband_width + subband_width;
Packit Service fa4841
Packit Service fa4841
	/* Even coefficients */
Packit Service fa4841
	for (n = 0; n < subband_width; n++)
Packit Service fa4841
	{
Packit Service fa4841
		for (x = 0; x < total_width; x += 8)
Packit Service fa4841
		{
Packit Service fa4841
			/* dst[2n] = l[n] - ((h[n-1] + h[n] + 1) >> 1); */
Packit Service fa4841
			l_n = _mm_load_si128((__m128i*)l_ptr);
Packit Service fa4841
			h_n = _mm_load_si128((__m128i*)h_ptr);
Packit Service fa4841
			tmp_n = _mm_add_epi16(h_n, _mm_set1_epi16(1));
Packit Service fa4841
Packit Service fa4841
			if (n == 0)
Packit Service fa4841
				tmp_n = _mm_add_epi16(tmp_n, h_n);
Packit Service fa4841
			else
Packit Service fa4841
			{
Packit Service fa4841
				h_n_m = _mm_loadu_si128((__m128i*)(h_ptr - total_width));
Packit Service fa4841
				tmp_n = _mm_add_epi16(tmp_n, h_n_m);
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			tmp_n = _mm_srai_epi16(tmp_n, 1);
Packit Service fa4841
			dst_n = _mm_sub_epi16(l_n, tmp_n);
Packit Service fa4841
			_mm_store_si128((__m128i*)dst_ptr, dst_n);
Packit Service fa4841
			l_ptr += 8;
Packit Service fa4841
			h_ptr += 8;
Packit Service fa4841
			dst_ptr += 8;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		dst_ptr += total_width;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	h_ptr = h;
Packit Service fa4841
	dst_ptr = dst + total_width;
Packit Service fa4841
Packit Service fa4841
	/* Odd coefficients */
Packit Service fa4841
	for (n = 0; n < subband_width; n++)
Packit Service fa4841
	{
Packit Service fa4841
		for (x = 0; x < total_width; x += 8)
Packit Service fa4841
		{
Packit Service fa4841
			/* dst[2n + 1] = (h[n] << 1) + ((dst[2n] + dst[2n + 2]) >> 1); */
Packit Service fa4841
			h_n = _mm_load_si128((__m128i*)h_ptr);
Packit Service fa4841
			dst_n_m = _mm_load_si128((__m128i*)(dst_ptr - total_width));
Packit Service fa4841
			h_n = _mm_slli_epi16(h_n, 1);
Packit Service fa4841
			tmp_n = dst_n_m;
Packit Service fa4841
Packit Service fa4841
			if (n == subband_width - 1)
Packit Service fa4841
				tmp_n = _mm_add_epi16(tmp_n, dst_n_m);
Packit Service fa4841
			else
Packit Service fa4841
			{
Packit Service fa4841
				dst_n_p = _mm_loadu_si128((__m128i*)(dst_ptr + total_width));
Packit Service fa4841
				tmp_n = _mm_add_epi16(tmp_n, dst_n_p);
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			tmp_n = _mm_srai_epi16(tmp_n, 1);
Packit Service fa4841
			dst_n = _mm_add_epi16(tmp_n, h_n);
Packit Service fa4841
			_mm_store_si128((__m128i*)dst_ptr, dst_n);
Packit Service fa4841
			h_ptr += 8;
Packit Service fa4841
			dst_ptr += 8;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		dst_ptr += total_width;
Packit Service fa4841
	}
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static __inline void __attribute__((ATTRIBUTES))
Packit Service fa4841
rfx_dwt_2d_decode_block_sse2(INT16* buffer, INT16* idwt, int subband_width)
Packit Service fa4841
{
Packit Service fa4841
	INT16 *hl, *lh, *hh, *ll;
Packit Service fa4841
	INT16 *l_dst, *h_dst;
Packit Service fa4841
	_mm_prefetch_buffer((char*)idwt, subband_width * 4 * sizeof(INT16));
Packit Service fa4841
	/* Inverse DWT in horizontal direction, results in 2 sub-bands in L, H order in tmp buffer idwt.
Packit Service fa4841
	 */
Packit Service fa4841
	/* The 4 sub-bands are stored in HL(0), LH(1), HH(2), LL(3) order. */
Packit Service fa4841
	/* The lower part L uses LL(3) and HL(0). */
Packit Service fa4841
	/* The higher part H uses LH(1) and HH(2). */
Packit Service fa4841
	ll = buffer + subband_width * subband_width * 3;
Packit Service fa4841
	hl = buffer;
Packit Service fa4841
	l_dst = idwt;
Packit Service fa4841
	rfx_dwt_2d_decode_block_horiz_sse2(ll, hl, l_dst, subband_width);
Packit Service fa4841
	lh = buffer + subband_width * subband_width;
Packit Service fa4841
	hh = buffer + subband_width * subband_width * 2;
Packit Service fa4841
	h_dst = idwt + subband_width * subband_width * 2;
Packit Service fa4841
	rfx_dwt_2d_decode_block_horiz_sse2(lh, hh, h_dst, subband_width);
Packit Service fa4841
	/* Inverse DWT in vertical direction, results are stored in original buffer. */
Packit Service fa4841
	rfx_dwt_2d_decode_block_vert_sse2(l_dst, h_dst, buffer, subband_width);
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static void rfx_dwt_2d_decode_sse2(INT16* buffer, INT16* dwt_buffer)
Packit Service fa4841
{
Packit Service fa4841
	_mm_prefetch_buffer((char*)buffer, 4096 * sizeof(INT16));
Packit Service fa4841
	rfx_dwt_2d_decode_block_sse2(&buffer[3840], dwt_buffer, 8);
Packit Service fa4841
	rfx_dwt_2d_decode_block_sse2(&buffer[3072], dwt_buffer, 16);
Packit Service fa4841
	rfx_dwt_2d_decode_block_sse2(&buffer[0], dwt_buffer, 32);
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static __inline void __attribute__((ATTRIBUTES))
Packit Service fa4841
rfx_dwt_2d_encode_block_vert_sse2(INT16* src, INT16* l, INT16* h, int subband_width)
Packit Service fa4841
{
Packit Service fa4841
	int total_width;
Packit Service fa4841
	int x;
Packit Service fa4841
	int n;
Packit Service fa4841
	__m128i src_2n;
Packit Service fa4841
	__m128i src_2n_1;
Packit Service fa4841
	__m128i src_2n_2;
Packit Service fa4841
	__m128i h_n;
Packit Service fa4841
	__m128i h_n_m;
Packit Service fa4841
	__m128i l_n;
Packit Service fa4841
	total_width = subband_width << 1;
Packit Service fa4841
Packit Service fa4841
	for (n = 0; n < subband_width; n++)
Packit Service fa4841
	{
Packit Service fa4841
		for (x = 0; x < total_width; x += 8)
Packit Service fa4841
		{
Packit Service fa4841
			src_2n = _mm_load_si128((__m128i*)src);
Packit Service fa4841
			src_2n_1 = _mm_load_si128((__m128i*)(src + total_width));
Packit Service fa4841
Packit Service fa4841
			if (n < subband_width - 1)
Packit Service fa4841
				src_2n_2 = _mm_load_si128((__m128i*)(src + 2 * total_width));
Packit Service fa4841
			else
Packit Service fa4841
				src_2n_2 = src_2n;
Packit Service fa4841
Packit Service fa4841
			/* h[n] = (src[2n + 1] - ((src[2n] + src[2n + 2]) >> 1)) >> 1 */
Packit Service fa4841
			h_n = _mm_add_epi16(src_2n, src_2n_2);
Packit Service fa4841
			h_n = _mm_srai_epi16(h_n, 1);
Packit Service fa4841
			h_n = _mm_sub_epi16(src_2n_1, h_n);
Packit Service fa4841
			h_n = _mm_srai_epi16(h_n, 1);
Packit Service fa4841
			_mm_store_si128((__m128i*)h, h_n);
Packit Service fa4841
Packit Service fa4841
			if (n == 0)
Packit Service fa4841
				h_n_m = h_n;
Packit Service fa4841
			else
Packit Service fa4841
				h_n_m = _mm_load_si128((__m128i*)(h - total_width));
Packit Service fa4841
Packit Service fa4841
			/* l[n] = src[2n] + ((h[n - 1] + h[n]) >> 1) */
Packit Service fa4841
			l_n = _mm_add_epi16(h_n_m, h_n);
Packit Service fa4841
			l_n = _mm_srai_epi16(l_n, 1);
Packit Service fa4841
			l_n = _mm_add_epi16(l_n, src_2n);
Packit Service fa4841
			_mm_store_si128((__m128i*)l, l_n);
Packit Service fa4841
			src += 8;
Packit Service fa4841
			l += 8;
Packit Service fa4841
			h += 8;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		src += total_width;
Packit Service fa4841
	}
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static __inline void __attribute__((ATTRIBUTES))
Packit Service fa4841
rfx_dwt_2d_encode_block_horiz_sse2(INT16* src, INT16* l, INT16* h, int subband_width)
Packit Service fa4841
{
Packit Service fa4841
	int y;
Packit Service fa4841
	int n;
Packit Service fa4841
	int first;
Packit Service fa4841
	__m128i src_2n;
Packit Service fa4841
	__m128i src_2n_1;
Packit Service fa4841
	__m128i src_2n_2;
Packit Service fa4841
	__m128i h_n;
Packit Service fa4841
	__m128i h_n_m;
Packit Service fa4841
	__m128i l_n;
Packit Service fa4841
Packit Service fa4841
	for (y = 0; y < subband_width; y++)
Packit Service fa4841
	{
Packit Service fa4841
		for (n = 0; n < subband_width; n += 8)
Packit Service fa4841
		{
Packit Service fa4841
			/* The following 3 Set operations consumes more than half of the total DWT processing
Packit Service fa4841
			 * time! */
Packit Service fa4841
			src_2n =
Packit Service fa4841
			    _mm_set_epi16(src[14], src[12], src[10], src[8], src[6], src[4], src[2], src[0]);
Packit Service fa4841
			src_2n_1 =
Packit Service fa4841
			    _mm_set_epi16(src[15], src[13], src[11], src[9], src[7], src[5], src[3], src[1]);
Packit Service fa4841
			src_2n_2 = _mm_set_epi16(n == subband_width - 8 ? src[14] : src[16], src[14], src[12],
Packit Service fa4841
			                         src[10], src[8], src[6], src[4], src[2]);
Packit Service fa4841
			/* h[n] = (src[2n + 1] - ((src[2n] + src[2n + 2]) >> 1)) >> 1 */
Packit Service fa4841
			h_n = _mm_add_epi16(src_2n, src_2n_2);
Packit Service fa4841
			h_n = _mm_srai_epi16(h_n, 1);
Packit Service fa4841
			h_n = _mm_sub_epi16(src_2n_1, h_n);
Packit Service fa4841
			h_n = _mm_srai_epi16(h_n, 1);
Packit Service fa4841
			_mm_store_si128((__m128i*)h, h_n);
Packit Service fa4841
			h_n_m = _mm_loadu_si128((__m128i*)(h - 1));
Packit Service fa4841
Packit Service fa4841
			if (n == 0)
Packit Service fa4841
			{
Packit Service fa4841
				first = _mm_extract_epi16(h_n_m, 1);
Packit Service fa4841
				h_n_m = _mm_insert_epi16(h_n_m, first, 0);
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			/* l[n] = src[2n] + ((h[n - 1] + h[n]) >> 1) */
Packit Service fa4841
			l_n = _mm_add_epi16(h_n_m, h_n);
Packit Service fa4841
			l_n = _mm_srai_epi16(l_n, 1);
Packit Service fa4841
			l_n = _mm_add_epi16(l_n, src_2n);
Packit Service fa4841
			_mm_store_si128((__m128i*)l, l_n);
Packit Service fa4841
			src += 16;
Packit Service fa4841
			l += 8;
Packit Service fa4841
			h += 8;
Packit Service fa4841
		}
Packit Service fa4841
	}
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static __inline void __attribute__((ATTRIBUTES))
Packit Service fa4841
rfx_dwt_2d_encode_block_sse2(INT16* buffer, INT16* dwt, int subband_width)
Packit Service fa4841
{
Packit Service fa4841
	INT16 *hl, *lh, *hh, *ll;
Packit Service fa4841
	INT16 *l_src, *h_src;
Packit Service fa4841
	_mm_prefetch_buffer((char*)dwt, subband_width * 4 * sizeof(INT16));
Packit Service fa4841
	/* DWT in vertical direction, results in 2 sub-bands in L, H order in tmp buffer dwt. */
Packit Service fa4841
	l_src = dwt;
Packit Service fa4841
	h_src = dwt + subband_width * subband_width * 2;
Packit Service fa4841
	rfx_dwt_2d_encode_block_vert_sse2(buffer, l_src, h_src, subband_width);
Packit Service fa4841
	/* DWT in horizontal direction, results in 4 sub-bands in HL(0), LH(1), HH(2), LL(3) order,
Packit Service fa4841
	 * stored in original buffer. */
Packit Service fa4841
	/* The lower part L generates LL(3) and HL(0). */
Packit Service fa4841
	/* The higher part H generates LH(1) and HH(2). */
Packit Service fa4841
	ll = buffer + subband_width * subband_width * 3;
Packit Service fa4841
	hl = buffer;
Packit Service fa4841
	lh = buffer + subband_width * subband_width;
Packit Service fa4841
	hh = buffer + subband_width * subband_width * 2;
Packit Service fa4841
	rfx_dwt_2d_encode_block_horiz_sse2(l_src, ll, hl, subband_width);
Packit Service fa4841
	rfx_dwt_2d_encode_block_horiz_sse2(h_src, lh, hh, subband_width);
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static void rfx_dwt_2d_encode_sse2(INT16* buffer, INT16* dwt_buffer)
Packit Service fa4841
{
Packit Service fa4841
	_mm_prefetch_buffer((char*)buffer, 4096 * sizeof(INT16));
Packit Service fa4841
	rfx_dwt_2d_encode_block_sse2(buffer, dwt_buffer, 32);
Packit Service fa4841
	rfx_dwt_2d_encode_block_sse2(buffer + 3072, dwt_buffer, 16);
Packit Service fa4841
	rfx_dwt_2d_encode_block_sse2(buffer + 3840, dwt_buffer, 8);
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
void rfx_init_sse2(RFX_CONTEXT* context)
Packit Service fa4841
{
Packit Service fa4841
	if (!IsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE))
Packit Service fa4841
		return;
Packit Service fa4841
Packit Service fa4841
	PROFILER_RENAME(context->priv->prof_rfx_quantization_decode, "rfx_quantization_decode_sse2");
Packit Service fa4841
	PROFILER_RENAME(context->priv->prof_rfx_quantization_encode, "rfx_quantization_encode_sse2");
Packit Service fa4841
	PROFILER_RENAME(context->priv->prof_rfx_dwt_2d_decode, "rfx_dwt_2d_decode_sse2");
Packit Service fa4841
	PROFILER_RENAME(context->priv->prof_rfx_dwt_2d_encode, "rfx_dwt_2d_encode_sse2");
Packit Service fa4841
	context->quantization_decode = rfx_quantization_decode_sse2;
Packit Service fa4841
	context->quantization_encode = rfx_quantization_encode_sse2;
Packit Service fa4841
	context->dwt_2d_decode = rfx_dwt_2d_decode_sse2;
Packit Service fa4841
	context->dwt_2d_encode = rfx_dwt_2d_encode_sse2;
Packit Service fa4841
}