📄 blit_soft.c
字号:
if ((x & 1) || DstUVX2==0)
dx2+=DstStepX2;
cR=cG=cB=0;
break;
case 11: //RGB->Packed YUV
Y = ((2105 * cR) + (4128 * cG) + (802 * cB))/0x2000 + 16;
U = (-(1212 * cR) - (2384 * cG) + (3596 * cB))/0x2000 + 128;
V = ((3596 * cR) - (3015 * cG) - (582 * cB))/0x2000 + 128;
Y=SAT(Y);
U=SAT(U);
V=SAT(V);
*q = (uint8_t)Y;
Dst[1][4*(dx >> 5)] = (uint8_t)U;
Dst[2][4*(dx >> 5)] = (uint8_t)V;
cR=cG=cB=0;
break;
case 12: //YUV->Planar YUV
Y += YAdd;
Y=SAT(Y);
*q = (uint8_t)Y;
Dst[1][dx2 >> 3] = (uint8_t)U;
Dst[2][dx2 >> 3] = (uint8_t)V;
if ((x & 1) || DstUVX2==0)
dx2+=DstStepX2;
Y=U=V=0;
break;
case 13: //YUV->Packed YUV
Y += YAdd;
Y=SAT(Y);
*q = (uint8_t)Y;
Dst[1][4*(dx >> 5)] = (uint8_t)U;
Dst[2][4*(dx >> 5)] = (uint8_t)V;
Y=U=V=0;
break;
case 1: //RGB->Pal1
w = ((cR << DstPos[0]) & DstMask[0]) |
((cG << DstPos[1]) & DstMask[1]) |
((cB << DstPos[2]) & DstMask[2]);
wp = PalLookUp + (w >> 8)*4;
w = wp[0];
w ^= DstInvert;
*q &= ~(1 << ((~dx)&7));
*q |= (w << ((~dx)&7));
if (PalDither)
{
cR -= wp[1];
cG -= wp[2];
cB -= wp[3];
}
else
cR=cG=cB=0;
break;
case 2: //RGB->Pal2
w = ((cR << DstPos[0]) & DstMask[0]) |
((cG << DstPos[1]) & DstMask[1]) |
((cB << DstPos[2]) & DstMask[2]);
wp = PalLookUp + (w >> 8)*4;
w = wp[0];
w ^= DstInvert;
*q &= ~(3 << ((~dx)&6));
*q |= (w << ((~dx)&6));
if (PalDither)
{
cR -= wp[1];
cG -= wp[2];
cB -= wp[3];
}
else
cR=cG=cB=0;
break;
case 3: //RGB->Pal4
w = ((cR << DstPos[0]) & DstMask[0]) |
((cG << DstPos[1]) & DstMask[1]) |
((cB << DstPos[2]) & DstMask[2]);
wp = PalLookUp + (w >> 8)*4;
w = wp[0];
w ^= DstInvert;
*q &= ~(15 << ((~dx)&4));
*q |= (w << ((~dx)&4));
if (PalDither)
{
cR -= wp[1];
cG -= wp[2];
cB -= wp[3];
}
else
cR=cG=cB=0;
break;
case 14: //YUV->Pal8
w = ((Y << DstPos[0]) & DstMask[0]) |
((U << DstPos[1]) & DstMask[1]) |
((V << DstPos[2]) & DstMask[2]);
wp = PalLookUp + (w >> 8)*4;
w = wp[0];
w ^= DstInvert;
*q = (uint8_t)w;
if (PalDither)
{
Y -= wp[1];
U -= wp[2];
V -= wp[3];
}
else
Y=U=V=0;
break;
case 4: //RGB->Pal8
w = ((cR << DstPos[0]) & DstMask[0]) |
((cG << DstPos[1]) & DstMask[1]) |
((cB << DstPos[2]) & DstMask[2]);
wp = PalLookUp + (w >> 8)*4;
w = wp[0];
w ^= DstInvert;
*q = (uint8_t)w;
if (PalDither)
{
cR -= wp[1];
cG -= wp[2];
cB -= wp[3];
}
else
cR=cG=cB=0;
break;
case 5: //RGB->RGB8
w = ((cR << DstPos[0]) & DstMask[0]) |
((cG << DstPos[1]) & DstMask[1]) |
((cB << DstPos[2]) & DstMask[2]);
*q = (uint8_t)((w >> 8) ^ DstInvert);
cR &= DitherMask[0];
cG &= DitherMask[1];
cB &= DitherMask[2];
break;
case 6: //RGB->RGB16
w = ((cR << DstPos[0]) & DstMask[0]) |
((cG << DstPos[1]) & DstMask[1]) |
((cB << DstPos[2]) & DstMask[2]);
*(uint16_t*)q = (uint16_t)((w >> 8) ^ DstInvert);
cR &= DitherMask[0];
cG &= DitherMask[1];
cB &= DitherMask[2];
break;
case 7: //RGB->RGB24
w = ((cR << DstPos[0]) & DstMask[0]) |
((cG << DstPos[1]) & DstMask[1]) |
((cB << DstPos[2]) & DstMask[2]);
w >>= 8;
w ^= DstInvert;
q[0] = (uint8_t)(w);
q[1] = (uint8_t)(w >> 8);
q[2] = (uint8_t)(w >> 16);
cR &= DitherMask[0];
cG &= DitherMask[1];
cB &= DitherMask[2];
break;
default: //RGB->RGB32
w = ((cR << DstPos[0]) & DstMask[0]) |
((cG << DstPos[1]) & DstMask[1]) |
((cB << DstPos[2]) & DstMask[2]);
*(uint32_t*)q = (w >> 8) ^ DstInvert;
cR &= DitherMask[0];
cG &= DitherMask[1];
cB &= DitherMask[2];
break;
}
}
dy += DstStepY;
if ((y & 1) || DstUVY2==0)
dy2 += DstStepY2;
sy0 = sy;
sy += SrcStepY[y&15];
Src[0] += SrcPitch * (sy - sy0);
Src[1] += (SrcPitch >> SrcUVPitch2) * ((sy >> SrcUVY2) - (sy0 >> SrcUVY2));
Src[2] += (SrcPitch >> SrcUVPitch2) * ((sy >> SrcUVY2) - (sy0 >> SrcUVY2));
}
}
#endif
static bool_t BlitCompile(blit_soft* p,
const pixel* NewDst,const pixel* NewSrc,
const blitfx* NewFX,bool_t NewOnlyDiff)
{
int i;
bool_t Gray,SrcPlanarYUV,DstPlanarYUV;
if (EqPixel(&p->Dst,NewDst) &&
EqPixel(&p->Src,NewSrc) &&
EqBlitFX(&p->FX,NewFX) &&
NewOnlyDiff == p->OnlyDiff)
return p->Entry != NULL;
CodeStart(&p->Code);
// defaults
p->Caps = VC_BRIGHTNESS|VC_DITHER|VC_SATURATION|VC_CONTRAST|VC_RGBADJUST;
p->SrcAlignPos = 2;
p->DstAlignPos = 2;
p->DstAlignSize = 2;
p->Dst = *NewDst;
p->Src = *NewSrc;
p->FX = *NewFX;
p->OnlyDiff = (boolmem_t)NewOnlyDiff;
p->SwapXY = (boolmem_t)((p->FX.Direction & DIR_SWAPXY) != 0);
p->DstLeftRight = (boolmem_t)((p->FX.Direction & DIR_MIRRORLEFTRIGHT) != 0);
p->DstUpDown = (boolmem_t)((p->FX.Direction & DIR_MIRRORUPDOWN) != 0);
p->SrcUpDown = (boolmem_t)((p->FX.Flags & BLITFX_AVOIDTEARING) && !p->SwapXY && p->DstUpDown != ((p->FX.Flags & BLITFX_VMEMUPDOWN) != 0));
if (p->SrcUpDown)
p->DstUpDown = (boolmem_t)!p->DstUpDown;
// it's faster using slices with rotation (not just with AVOIDTEARING)
// probably because of ram page trashing (during vertical writing)
p->Slices = (boolmem_t)(p->SwapXY != ((p->FX.Flags & BLITFX_VMEMROTATED) != 0));
p->SlicesReverse = (boolmem_t)((p->SwapXY ? p->DstUpDown : p->DstLeftRight) == ((p->FX.Flags & BLITFX_VMEMUPDOWN) != 0));
Gray = (p->Dst.Flags & PF_PALETTE) && (p->Dst.BitCount == 4 || p->Dst.BitCount == 2);
p->RScaleX = CalcRScale(p->FX.ScaleX,Gray);
p->RScaleY = CalcRScale(p->FX.ScaleY,Gray);
// important these integeres should be 1 or 0
p->DstHalfX = p->SrcHalfX = p->RScaleX == 32;
p->DstHalfY = p->SrcHalfY = p->RScaleY == 32;
p->DstDoubleX = p->SrcDoubleX = p->RScaleX == 8;
p->DstDoubleY = p->SrcDoubleY = p->RScaleY == 8;
if (p->SwapXY)
{
SwapInt(&p->DstHalfX,&p->DstHalfY);
SwapInt(&p->DstDoubleX,&p->DstDoubleY);
}
p->SrcBPP = GetBPP(&p->Src);
p->SrcBPP2 = -3;
for (i=p->SrcBPP;i>1;i>>=1)
++p->SrcBPP2;
p->DstBPP = GetBPP(&p->Dst);
p->DstBPP2 = -3;
for (i=p->DstBPP;i>1;i>>=1)
++p->DstBPP2;
p->SrcYUV = (boolmem_t)AnyYUV(&p->Src);
p->SrcPalette = DefaultPal(&p->Src);
p->DstPalette = DefaultPal(&p->Dst);
free(p->LookUp_Data);
p->LookUp_Data = NULL;
p->ColorLookup = (boolmem_t)((p->FX.Flags & BLITFX_COLOR_LOOKUP) != 0);
#ifdef ARM
p->ARM5 = (boolmem_t)((QueryPlatform(PLATFORM_CAPS) & CAPS_ARM_5E)!=0);
p->WMMX = (boolmem_t)((QueryPlatform(PLATFORM_CAPS) & CAPS_ARM_WMMX)!=0 &&
!QueryAdvanced(ADVANCED_NOWMMX) && (p->Dst.Flags & PF_16ALIGNED) && (p->Src.Flags & PF_16ALIGNED));
p->QAdd = (boolmem_t)((QueryPlatform(PLATFORM_CAPS) & CAPS_ARM_5E)!=0 &&
!p->DstPalette && !p->WMMX && !(p->FX.Flags & BLITFX_DITHER) && !p->ColorLookup);
#endif
CalcColor(p);
if (p->DstPalette)
BuildPalLookUp(p,p->SrcYUV);
p->ArithStretch = (boolmem_t)((p->FX.Flags & BLITFX_ARITHSTRETCHALWAYS) != 0);
if ((p->FX.Flags & BLITFX_ARITHSTRETCH50) && p->RScaleX==32 && p->RScaleY==32)
p->ArithStretch = 1;
if (p->DstPalette)
p->ArithStretch = 0;
SrcPlanarYUV = PlanarYUV(&p->Src,&p->SrcUVX2,&p->SrcUVY2,&p->SrcUVPitch2);
DstPlanarYUV = PlanarYUV(&p->Dst,&p->DstUVX2,&p->DstUVY2,&p->DstUVPitch2);
p->DirX = p->DstLeftRight ? -1:1;
for (i=0;i<3;++i)
{
p->DstSize[i] = BitMaskSize(p->Dst.BitMask[i]);
p->DstPos[i] = BitMaskPos(p->Dst.BitMask[i]);
p->SrcSize[i] = BitMaskSize(p->Src.BitMask[i]);
p->SrcPos[i] = BitMaskPos(p->Src.BitMask[i]);
}
#if defined(ARM)
if ((p->Dst.Flags & PF_RGB) && p->Dst.BitCount==16 && !p->SrcYUV)
Any_RGB_RGB(p);
if (!p->SrcYUV && DstPlanarYUV && p->RScaleX==16 && p->RScaleY==16)
Fix_Any_YUV(p);
#endif
#if (defined(ARM) || defined(SH3) || defined(MIPS)) && defined(CONFIG_DYNCODE)
if (SrcPlanarYUV)
{
#if defined(ARM)
if (DstPlanarYUV && p->RScaleX==16 && p->RScaleY==16 &&
((p->SrcUVX2==p->DstUVX2 && p->SrcUVY2==p->DstUVY2 && !(p->SwapXY && p->SrcUVX2 != p->SrcUVY2)) ||
(p->DstUVX2==1 && p->DstUVY2==1)))
Fix_Any_YUV(p);
if (PackedYUV(&p->Dst) && p->RScaleX==16 && p->RScaleY==16 && p->SrcUVY2<2 && p->SrcUVX2<2)
Fix_PackedYUV_YUV(p);
#endif
if ((p->Dst.Flags & (PF_RGB|PF_PALETTE)) && (p->Dst.BitCount == 8 || p->Dst.BitCount == 16 || p->Dst.BitCount == 32))
{
#if defined(ARM)
if (p->Dst.BitCount == 16 && p->WMMX && PlanarYUV420(&p->Src) &&
(p->RScaleX==16 || p->RScaleX==8 || p->RScaleX==32) && (p->RScaleY==16 || p->RScaleY==8 || p->RScaleY==32))
WMMXFix_RGB_UV(p);
else
if ((p->Dst.BitCount == 16 || p->Dst.BitCount==32) && p->SrcUVX2==1 && p->SrcUVY2==1 && p->RScaleX == 16 && p->RScaleY == 16)
Fix_RGB_UV(p);
else
if (p->Dst.BitCount == 16 && p->SrcUVX2==1 && p->SrcUVY2==1 &&
(p->RScaleX == 8 || p->RScaleX == 16) &&
(p->RScaleY == 8 || p->RScaleY == 16) && !p->ArithStretch)
Fix_RGB_UV(p);
else
if (p->Dst.BitCount == 16 && p->SrcUVX2==1 && p->SrcUVY2==1 && p->RScaleX == 32 && p->RScaleY == 32)
Half_RGB_UV(p);
else
Stretch_RGB_UV(p);
#else
#if !defined(MIPS)
if (p->SrcUVX2==1 && p->SrcUVY2==1 &&
(p->RScaleX == 8 || p->RScaleX == 16) &&
(p->RScaleY == 8 || p->RScaleY == 16))
#endif
Fix_RGB_UV(p);
#endif
}
else
if (Gray)
Fix_Gray_UV(p);
}
#endif
CodeBuild(&p->Code);
if (p->Code.Size)
p->Entry = (blitsoftentry)p->Code.Code;
else
p->Entry = NULL;
#if defined(_M_IX86) && !defined(TARGET_SYMBIAN)
if (p->FX.Direction==0 && p->RScaleX==16 && p->RScaleY==16)
{
uint32_t In = DefFourCC(&p->Src);
uint32_t Out = DefFourCC(&p->Dst);
#ifdef CONFIG_CONTEXT
int Caps = QueryPlatform(PLATFORM_CAPS);
#else
int Caps = CPUCaps();
#endif
const blitmmx* i;
for (i=BlitMMX;i->In;++i)
if (i->In==In && i->Out==Out)
{
p->Caps &= ~VC_DITHER;
if (AnyYUV(&p->Src))
CalcYUVMMX(p);
if (Caps & CAPS_X86_MMX2)
p->Entry = i->Func[1];
else if (Caps & CAPS_X86_3DNOW)
p->Entry = i->Func[2];
else
p->Entry = i->Func[0];
break;
}
}
#endif
if (!p->Entry)
{
// use YUV internal calulaction?
bool_t YUV = (AnyYUV(&p->Dst) ||
(p->Dst.BitCount==8 && p->Dst.Flags & PF_PALETTE)) && p->SrcYUV;
p->DstType = UniversalType(&p->Dst,YUV);
p->SrcType = UniversalType(&p->Src,YUV);
#if defined(_M_IX86) || !defined(CONFIG_DYNCODE) || defined(BLITTEST)
if (p->SrcType>=0 && p->DstType>=0)
{
// universal
if (AnyYUV(&p->Dst))
p->Caps &= ~VC_DITHER;
else
p->Caps = VC_BRIGHTNESS | VC_DITHER;
p->Entry = BlitUniversal;
}
if (p->SrcUVX2 == 1 && !p->SwapXY && !p->DstLeftRight && p->SrcType == 10)
{
if (p->DstType == 8 &&
p->Dst.BitMask[0] == 0xFF0000 &&
p->Dst.BitMask[1] == 0x00FF00 &&
p->Dst.BitMask[2] == 0x0000FF)
{
p->Caps = VC_BRIGHTNESS;
p->Entry = Blit_PYUV_RGB32;
}
if (p->DstType == 6 &&
p->Dst.BitMask[0] == 0xF800 &&
p->Dst.BitMask[1] == 0x07E0 &&
p->Dst.BitMask[2] == 0x001F)
{
p->Caps = VC_BRIGHTNESS;
p->Entry = Blit_PYUV_RGB16;
}
}
if (p->SrcUVX2 == p->DstUVX2 && !p->SwapXY && !p->DstLeftRight &&
p->RScaleX == 16 && p->RScaleY==16 &&
p->SrcType == 12 && p->DstType == 12)
{
CalcYUVLookUp(p);
p->Caps &= ~VC_DITHER;
p->Entry = Blit_PYUV_PYUV;
}
#endif
if (p->SrcUVX2 == p->DstUVX2 &&
p->SrcUVY2 == p->DstUVY2 && !p->SwapXY && !p->DstLeftRight &&
(p->RScaleX != 16 || p->RScaleY != 16) &&
(p->RScaleX == 16 || p->RScaleX == 8 || p->RScaleX == 32 || p->RScaleX == 4 || p->RScaleX == 64) &&
(p->RScaleY == 16 || p->RScaleY == 8 || p->RScaleY == 32 || p->RScaleX == 4 || p->RScaleX == 64) &&
p->SrcType == 12 && p->DstType == 12 &&
!p->FX.Saturation && !p->FX.Contrast && !p->FX.RGBAdjust[0] &&
!p->FX.RGBAdjust[1] && !p->FX.RGBAdjust[2] && !p->FX.Brightness)
{
p->Caps = 0;
p->Entry = Blit_PYUV_PYUV_2;
}
}
return p->Entry != NULL;
}
blitpack* BlitCreate(const video* Dst,
const video* Src, const blitfx* FX, int* OutCaps)
{
blitfx CopyFX;
bool_t Gray;
blitpack* p = BlitAlloc();
if (!p) return NULL;
if (!FX)
{
memset(&CopyFX,0,sizeof(CopyFX));
CopyFX.ScaleX = SCALE_ONE;
CopyFX.ScaleY = SCALE_ONE;
FX = &CopyFX;
}
if (!BlitCompile(&p->Code[0],&Dst->Pixel,&Src->Pixel,FX,0) ||
((FX->Flags & BLITFX_ONLYDIFF) && !BlitCompile(&p->Code[1],&Dst->Pixel,&Src->Pixel,FX,1)))
{
BlitRelease(p);
return NULL;
}
p->FX = *FX;
p->Dst = *Dst;
p->Src = *Src;
Gray = (Dst->Pixel.Flags & PF_PALETTE) &&
(Dst->Pixel.BitCount == 4 || Dst->Pixel.BitCount == 2);
p->RScaleX = CalcRScale(FX->ScaleX,Gray);
p->RScaleY = CalcRScale(FX->ScaleY,Gray);
if (OutCaps)
*OutCaps = p->Code[0].Caps;
return p;
}
static NOINLINE int CMul(blit_soft* p, int64_t* r, int64_t v, bool_t UV)
{
int m;
if (UV)
{
m = p->FX.Saturation;
if (m<0) m >>= 1; // adjust negtive interval: -128..0 -> -64..0
m = 4*m+256;
v *= m;
if (v<0)
v -= 128;
else
v += 128;
v >>= 8;
}
m = p->FX.Contrast;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -