mirror of https://github.com/PCSX2/pcsx2.git
pcsx2: Add IPU dither block SSE2 implementation
This commit is contained in:
parent
f9b51e2656
commit
c533a65764
|
@ -21,7 +21,15 @@
|
|||
#include "yuv2rgb.h"
|
||||
#include "mpeg2lib/Mpeg.h"
|
||||
|
||||
void ipu_dither_reference(const macroblock_rgb32 &rgb32, macroblock_rgb16 &rgb16, int dte);
|
||||
void ipu_dither_sse2(const macroblock_rgb32 &rgb32, macroblock_rgb16 &rgb16, int dte);
|
||||
|
||||
__ri void ipu_dither(const macroblock_rgb32 &rgb32, macroblock_rgb16 &rgb16, int dte)
|
||||
{
|
||||
ipu_dither_sse2(rgb32, rgb16, dte);
|
||||
}
|
||||
|
||||
__ri void ipu_dither_reference(const macroblock_rgb32 &rgb32, macroblock_rgb16 &rgb16, int dte)
|
||||
{
|
||||
if (dte) {
|
||||
// I'm guessing values are rounded down when clamping.
|
||||
|
@ -55,3 +63,60 @@ __ri void ipu_dither(const macroblock_rgb32 &rgb32, macroblock_rgb16 &rgb16, int
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
__ri void ipu_dither_sse2(const macroblock_rgb32 &rgb32, macroblock_rgb16 &rgb16, int dte)
|
||||
{
|
||||
const __m128i alpha_test = _mm_set1_epi16(0x40);
|
||||
const __m128i dither_add_matrix[] = {
|
||||
_mm_setr_epi32(0x00000000, 0x00000000, 0x00000000, 0x00010101),
|
||||
_mm_setr_epi32(0x00020202, 0x00000000, 0x00030303, 0x00000000),
|
||||
_mm_setr_epi32(0x00000000, 0x00010101, 0x00000000, 0x00000000),
|
||||
_mm_setr_epi32(0x00030303, 0x00000000, 0x00020202, 0x00000000),
|
||||
};
|
||||
const __m128i dither_sub_matrix[] = {
|
||||
_mm_setr_epi32(0x00040404, 0x00000000, 0x00030303, 0x00000000),
|
||||
_mm_setr_epi32(0x00000000, 0x00020202, 0x00000000, 0x00010101),
|
||||
_mm_setr_epi32(0x00030303, 0x00000000, 0x00040404, 0x00000000),
|
||||
_mm_setr_epi32(0x00000000, 0x00010101, 0x00000000, 0x00020202),
|
||||
};
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
const __m128i dither_add = dither_add_matrix[i & 3];
|
||||
const __m128i dither_sub = dither_sub_matrix[i & 3];
|
||||
for (int n = 0; n < 2; ++n) {
|
||||
__m128i rgba_8_0123 = _mm_load_si128(reinterpret_cast<const __m128i *>(&rgb32.c[i][n * 8]));
|
||||
__m128i rgba_8_4567 = _mm_load_si128(reinterpret_cast<const __m128i *>(&rgb32.c[i][n * 8 + 4]));
|
||||
|
||||
// Dither and clamp
|
||||
if (dte) {
|
||||
rgba_8_0123 = _mm_adds_epu8(rgba_8_0123, dither_add);
|
||||
rgba_8_0123 = _mm_subs_epu8(rgba_8_0123, dither_sub);
|
||||
rgba_8_4567 = _mm_adds_epu8(rgba_8_4567, dither_add);
|
||||
rgba_8_4567 = _mm_subs_epu8(rgba_8_4567, dither_sub);
|
||||
}
|
||||
|
||||
// Split into channel components and extend to 16 bits
|
||||
const __m128i rgba_16_0415 = _mm_unpacklo_epi8(rgba_8_0123, rgba_8_4567);
|
||||
const __m128i rgba_16_2637 = _mm_unpackhi_epi8(rgba_8_0123, rgba_8_4567);
|
||||
const __m128i rgba_32_0246 = _mm_unpacklo_epi8(rgba_16_0415, rgba_16_2637);
|
||||
const __m128i rgba_32_1357 = _mm_unpackhi_epi8(rgba_16_0415, rgba_16_2637);
|
||||
const __m128i rg_64_01234567 = _mm_unpacklo_epi8(rgba_32_0246, rgba_32_1357);
|
||||
const __m128i ba_64_01234567 = _mm_unpackhi_epi8(rgba_32_0246, rgba_32_1357);
|
||||
|
||||
const __m128i zero = _mm_setzero_si128();
|
||||
__m128i r = _mm_unpacklo_epi8(rg_64_01234567, zero);
|
||||
__m128i g = _mm_unpackhi_epi8(rg_64_01234567, zero);
|
||||
__m128i b = _mm_unpacklo_epi8(ba_64_01234567, zero);
|
||||
__m128i a = _mm_unpackhi_epi8(ba_64_01234567, zero);
|
||||
|
||||
// Create RGBA
|
||||
r = _mm_srli_epi16(r, 3);
|
||||
g = _mm_slli_epi16(_mm_srli_epi16(g, 3), 5);
|
||||
b = _mm_slli_epi16(_mm_srli_epi16(b, 3), 10);
|
||||
a = _mm_slli_epi16(_mm_cmpeq_epi16(a, alpha_test), 15);
|
||||
|
||||
const __m128i rgba16 = _mm_or_si128(_mm_or_si128(r, g), _mm_or_si128(b, a));
|
||||
|
||||
_mm_store_si128(reinterpret_cast<__m128i *>(&rgb16.c[i][n * 8]), rgba16);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue