207 lines
5.8 KiB
C++
207 lines
5.8 KiB
C++
/* -----------------------------------------------------------------------------
|
|
GSFramework
|
|
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
|
----------------------------------------------------------------------------- */
|
|
|
|
|
|
#include "picture/pict.h"
|
|
#if __PLATFORM_WINDOWS__ && __MMX__
|
|
#include "mmintrin.h"
|
|
#endif
|
|
|
|
using namespace GS;
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
static void mmx_yuv2rgb (uchar *py, uchar *pu, uchar *pv, uchar *image)
|
|
{
|
|
#if __PLATFORM_WINDOWS__ && __MMX__
|
|
static __m64 mmx_80w = {0x0080008000800080LL};
|
|
static __m64 mmx_U_green = {0xf37df37df37df37dLL};
|
|
static __m64 mmx_U_blue = {0x4093409340934093LL};
|
|
static __m64 mmx_V_red = {0x3312331233123312LL};
|
|
static __m64 mmx_V_green = {0xe5fce5fce5fce5fcLL};
|
|
static __m64 mmx_10w = {0x1010101010101010LL};
|
|
static __m64 mmx_00ffw = {0x00ff00ff00ff00ffLL};
|
|
static __m64 mmx_Y_coeff = {0x253f253f253f253fLL};
|
|
static __m64 mmx_A_unpack = {0xffffffffffffffffLL};
|
|
|
|
__asm
|
|
{
|
|
push esi
|
|
pxor mm4, mm4 ; mm4 = 0
|
|
|
|
mov esi, pu
|
|
movd mm0, [esi] ; mm0 = 00 00 00 00 u3 u2 u1 u0
|
|
mov esi, pv
|
|
movd mm1, [esi] ; mm1 = 00 00 00 00 v3 v2 v1 v0
|
|
mov esi, py
|
|
movq mm6, [esi] ; mm6 = Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
|
|
|
|
; Multiply part of the conversion.
|
|
punpcklbw mm0, mm4 ; mm0 = u3 u2 u1 u0
|
|
punpcklbw mm1, mm4 ; mm1 = v3 v2 v1 v0
|
|
psubsw mm0, mmx_80w ; u -= 128
|
|
psubsw mm1, mmx_80w ; v -= 128
|
|
psllw mm0, 3 ; promote precision
|
|
psllw mm1, 3 ; promote precision
|
|
movq mm2, mm0 ; mm2 = u3 u2 u1 u0
|
|
movq mm3, mm1 ; mm3 = v3 v2 v1 v0
|
|
pmulhw mm2, mmx_U_green ; mm2 = u * u_green
|
|
pmulhw mm3, mmx_V_green ; mm3 = v * v_green
|
|
pmulhw mm0, mmx_U_blue ; mm0 = chroma_b
|
|
pmulhw mm1, mmx_V_red ; mm1 = chroma_r
|
|
paddsw mm2, mm3 ; mm2 = chroma_g
|
|
|
|
psubusb mm6, mmx_10w ; Y -= 16
|
|
movq mm7, mm6 ; mm7 = Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
|
|
pand mm6, mmx_00ffw ; mm6 = Y6 Y4 Y2 Y0
|
|
psrlw mm7, 8 ; mm7 = Y7 Y5 Y3 Y1
|
|
psllw mm6, 3 ; promote precision
|
|
psllw mm7, 3 ; promote precision
|
|
pmulhw mm6, mmx_Y_coeff ; mm6 = luma_rgb even
|
|
pmulhw mm7, mmx_Y_coeff ; mm7 = luma_rgb odd
|
|
|
|
; Addition part of the conversion for even and odd pixels.
|
|
movq mm3, mm0 ; mm3 = chroma_b
|
|
movq mm4, mm1 ; mm4 = chroma_r
|
|
movq mm5, mm2 ; mm5 = chroma_g
|
|
paddsw mm0, mm6 ; mm0 = B6 B4 B2 B0
|
|
paddsw mm3, mm7 ; mm3 = B7 B5 B3 B1
|
|
paddsw mm1, mm6 ; mm1 = R6 R4 R2 R0
|
|
paddsw mm4, mm7 ; mm4 = R7 R5 R3 R1
|
|
paddsw mm2, mm6 ; mm2 = G6 G4 G2 G0
|
|
paddsw mm5, mm7 ; mm5 = G7 G5 G3 G1
|
|
packuswb mm0, mm0 ; saturate to 0-255
|
|
packuswb mm1, mm1 ; saturate to 0-255
|
|
packuswb mm2, mm2 ; saturate to 0-255
|
|
packuswb mm3, mm3 ; saturate to 0-255
|
|
packuswb mm4, mm4 ; saturate to 0-255
|
|
packuswb mm5, mm5 ; saturate to 0-255
|
|
punpcklbw mm0, mm3 ; mm0 = B7 B6 B5 B4 B3 B2 B1 B0
|
|
punpcklbw mm1, mm4 ; mm1 = R7 R6 R5 R4 R3 R2 R1 R0
|
|
punpcklbw mm2, mm5 ; mm2 = G7 G6 G5 G4 G3 G2 G1 G0
|
|
|
|
mov esi, image
|
|
;pxor mm3, mm3
|
|
movq mm3, mmx_A_unpack
|
|
movq mm6, mm0
|
|
movq mm7, mm1
|
|
movq mm4, mm0
|
|
movq mm5, mm1
|
|
punpcklbw mm6, mm2
|
|
punpcklbw mm7, mm3
|
|
punpcklwd mm6, mm7
|
|
movq [esi], mm6
|
|
movq mm6, mm0
|
|
punpcklbw mm6, mm2
|
|
punpckhwd mm6, mm7
|
|
movq [esi + 8], mm6
|
|
punpckhbw mm4, mm2
|
|
punpckhbw mm5, mm3
|
|
punpcklwd mm4, mm5
|
|
movq [esi + 16], mm4
|
|
movq mm4, mm0
|
|
punpckhbw mm4, mm2
|
|
punpckhwd mm4, mm5
|
|
movq [esi + 24], mm4
|
|
pop esi
|
|
|
|
emms
|
|
}
|
|
#endif
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
void Picture::YUV422toRGB32(uchar * const yuv_plane[3], uchar *rgb32, int width, int height, int dst_pitch, int dst_height)
|
|
{
|
|
// Default pitch if none specified.
|
|
if (!dst_pitch)
|
|
dst_pitch = width * 4;
|
|
if (!dst_height)
|
|
dst_height = height;
|
|
|
|
// Target resolution.
|
|
int c_width = dst_pitch / 4;
|
|
|
|
if (width < c_width)
|
|
c_width = width;
|
|
if (height < dst_height)
|
|
dst_height = height;
|
|
|
|
#pragma omp parallel for
|
|
for (int y = 0; y < dst_height; ++y)
|
|
{
|
|
uchar *p_out = rgb32 + dst_pitch * y,
|
|
*p_yuv[3] = {
|
|
yuv_plane[0] + width * y,
|
|
yuv_plane[1] + (width / 2) * (y / 2),
|
|
yuv_plane[2] + (width / 2) * (y / 2)
|
|
};
|
|
|
|
// Convert scan line.
|
|
for (int x = 0; x < c_width; x += 8)
|
|
{
|
|
mmx_yuv2rgb(p_yuv[0], p_yuv[1], p_yuv[2], p_out);
|
|
|
|
p_yuv[0] += 8;
|
|
p_yuv[1] += 4;
|
|
p_yuv[2] += 4;
|
|
p_out += 32;
|
|
}
|
|
}
|
|
}
|
|
void Picture::UnpackYCbCr(uchar *y, uchar *cb, uchar *cr)
|
|
{
|
|
if (!y || !cb || !cr || (GetBpp() != 32))
|
|
return;
|
|
|
|
uchar *pdata = GetData();
|
|
for (uint n = 0; n < (GetHeight() * GetWidth()); ++n)
|
|
{
|
|
float r = (float)pdata[0], g = (float)pdata[1], b = (float)pdata[2];
|
|
|
|
*y++ = (uchar)( 0.2990f * r + 0.5870f * g + 0.1140f * b + 0.5f);
|
|
*cb++ = (uchar)(-0.1687f * r - 0.3313f * g + 0.5000f * b + 128.f + 0.5f);
|
|
*cr++ = (uchar)( 0.5000f * r - 0.4187f * g - 0.0813f * b + 128.f + 0.5f);
|
|
pdata += 4;
|
|
}
|
|
}
|
|
void Picture::PackYCbCr(uchar *y, uchar *cb, uchar *cr)
|
|
{
|
|
if (!y || !cb || !cr || (GetBpp() != 32))
|
|
return;
|
|
|
|
uchar *pdata = GetData();
|
|
for (uint n = 0; n < (GetHeight() * GetWidth()); ++n)
|
|
{
|
|
float _y = (float)*y++, _cb = ((float)*cb++) - 128.f, _cr = ((float)*cr++) - 128.f;
|
|
|
|
float r = _y + 1.402f * _cr;
|
|
float g = _y - 0.34414f * _cb - 0.71414f * _cr;
|
|
float b = _y + 1.77200f * _cb;
|
|
|
|
if (r < 0)
|
|
pdata[0] = 0;
|
|
else if (r > 255.f)
|
|
pdata[0] = 255;
|
|
else pdata[0] = (uchar)r;
|
|
|
|
if (g < 0)
|
|
pdata[1] = 0;
|
|
else if (g > 255.f)
|
|
pdata[1] = 255;
|
|
else pdata[1] = (uchar)g;
|
|
|
|
if (b < 0)
|
|
pdata[2] = 0;
|
|
else if (b > 255.f)
|
|
pdata[2] = 255;
|
|
else pdata[2] = (uchar)b;
|
|
|
|
pdata += 4;
|
|
}
|
|
}
|
|
//------------------------------------------------------------------------------
|