📄 blit_soft.c
字号:
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
bool_t BlitCompile(blit_soft* p,const video* NewDst,const video* NewSrc,
const blitfx* NewFX,bool_t NewOnlyDiff)
{
int i;
bool_t Gray,SrcPlanarYUV,DstPlanarYUV;
if (EqPixel(&p->Dst,&NewDst->Pixel) &&
EqPixel(&p->Src,&NewSrc->Pixel) &&
EqBlitFX(&p->FX,NewFX) &&
NewOnlyDiff == p->OnlyDiff)
return p->Entry != NULL;
CodeStart(&p->Code);
p->Dst = NewDst->Pixel;
p->Src = NewSrc->Pixel;
p->FX = *NewFX;
p->OnlyDiff = NewOnlyDiff;
p->SwapXY = (p->FX.Direction & DIR_SWAPXY) != 0;
p->DstLeftRight = (p->FX.Direction & DIR_MIRRORLEFTRIGHT) != 0;
p->DstUpDown = (p->FX.Direction & DIR_MIRRORUPDOWN) != 0;
p->SrcUpDown = (p->FX.Flags & BLITFX_AVOIDTEARING) && !p->SwapXY && p->DstUpDown != ((p->FX.Flags & BLITFX_VMEMUPDOWN) != 0);
if (p->SrcUpDown)
p->DstUpDown = !p->DstUpDown;
// it's faster using slices with rotation (not just with AVOIDTEARING)
p->Slices = (p->SwapXY != ((p->FX.Flags & BLITFX_VMEMROTATED) != 0));
p->SlicesReverse = (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->DstBPP = GetBPP(&p->Dst);
p->DstBPP2 = -3;
for (i=p->DstBPP;i>1;i>>=1)
++p->DstBPP2;
p->SrcPalette = DefaultPal(&p->Src);
p->DstPalette = DefaultPal(&p->Dst);
Free(p->LookUp_Data);
p->LookUp_Data = NULL;
p->ColorLookup = (p->FX.Flags & BLITFX_COLOR_LOOKUP) != 0;
#ifdef ARM
p->ARM5 = (QueryPlatform(PLATFORM_CAPS) & CAPS_ARM_5E)!=0;
p->WMMX = (QueryPlatform(PLATFORM_CAPS) & CAPS_ARM_WMMX)!=0 && !QueryAdvPlatform(ADVPLATFORM_NOWMMX) && (p->Dst.Flags & PF_16ALIGNED) && (p->Src.Flags & PF_16ALIGNED);
p->QAdd = (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,AnyYUV(&p->Src));
p->ArithStretch = (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;
p->RSize = BitMaskSize(p->Dst.RBitMask);
p->GSize = BitMaskSize(p->Dst.GBitMask);
p->BSize = BitMaskSize(p->Dst.BBitMask);
p->RPos = BitMaskPos(p->Dst.RBitMask);
p->GPos = BitMaskPos(p->Dst.GBitMask);
p->BPos = BitMaskPos(p->Dst.BBitMask);
#if defined(ARM) || defined(SH3) || defined(MIPS)
if (SrcPlanarYUV)
{
#if defined(ARM)
if (DstPlanarYUV &&
((p->SrcUVX2==p->DstUVX2 && p->SrcUVY2==p->DstUVY2 && !(p->SwapXY && p->SrcUVX2 != p->SrcUVY2)) ||
(p->DstUVX2==1 && p->DstUVY2==1)))
Fix_YUV_YUV(p);
#endif
if ((p->Dst.Flags & (PF_RGB|PF_PALETTE)) && (p->Dst.BitCount == 8 || p->Dst.BitCount == 16))
{
#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->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 && p->SrcUVX2==1 && p->SrcUVY2==1)
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)
if (!p->Entry)
{
// use YUV internal calulaction?
bool_t YUV = (AnyYUV(&p->Dst) ||
(p->Dst.BitCount==8 && p->Dst.Flags & PF_PALETTE)) && AnyYUV(&p->Src);
p->DstType = UniversalType(&p->Dst,YUV);
p->SrcType = UniversalType(&p->Src,YUV);
if (p->SrcType>=0 && p->DstType>=0)
p->Entry = BlitUniversal;
if (p->SrcUVX2 == p->DstUVX2 &&
!p->SwapXY &&
!p->DstLeftRight &&
p->RScaleX == 16 && p->RScaleY==16 &&
p->SrcType == 12 &&
p->DstType == 12)
p->Entry = Blit_PYUV_PYUV;
}
#endif
return p->Entry != NULL;
}
static 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 = (v*m) >> 8;
}
m = p->FX.Contrast;
if (m<0) m >>= 1; // adjust negtive interval: -128..0 -> -64..0
m = 4*m + 256;
v = (v*m) >> 8;
if (r) *r = v;
return (int)v;
}
static int CAdd( blit_soft* p, int64_t* r, int64_t v, int v0, int vUV )
{
int m;
m = p->FX.Saturation;
if (m<0) m >>= 1; // adjust negtive interval: -128..0 -> -64..0
m = 4*m+256;
v += ((256 - m) * vUV) >> 1;
m = p->FX.Contrast;
if (m<0) m >>= 1; // adjust negtive interval: -128..0 -> -64..0
m = 4*m + 256;
v += ((256 - m)*(v0 - v)) >> 8;
if (r) *r = v;
return (int)v;
}
static INLINE bool_t InRange32( int64_t v )
{
return v >= -MAX_INT && v <= MAX_INT;
}
static INLINE uint8_t RotateRight8(int v,int Bits)
{
Bits &= 7;
return (uint8_t)( ((v >> Bits) & ((1 << (8-Bits))-1)) | (v << (8-Bits)));
}
void CalcLookUp( blit_soft* p, bool_t Dither )
{
#if defined(ARM)
const int Safe = 512;
// 4*256:Y + (256+Safe*2)*n:SAT + 4*256:U + 4*256:V
int SatOfsR = 4*256+Safe;
int SatOfsG = 4*256+Safe;
int SatOfsB = 4*256+Safe;
p->LookUp_Size = 4*256*3 + (256+Safe*2);
if (Dither)
{
if (p->GSize == p->RSize)
SatOfsG = SatOfsR;
else
{
p->LookUp_Size += (256+Safe*2);
SatOfsG = SatOfsR + (256+Safe*2);
}
if (p->BSize == p->RSize)
SatOfsB = SatOfsR;
else
if (p->BSize == p->GSize)
SatOfsB = SatOfsG;
else
{
p->LookUp_Size += (256+Safe*2);
SatOfsB = SatOfsG + (256+Safe*2);
}
}
p->LookUp_U = (p->LookUp_Size - 4*256*2) >> 2;
p->LookUp_V = (p->LookUp_Size - 4*256) >> 2;
p->LookUp_Data = CAlloc(p->LookUp_Size,1);
if (p->LookUp_Data)
{
int v;
int32_t* YMul = (int32_t*)p->LookUp_Data;
int32_t* UMul = (int32_t*)p->LookUp_Data + p->LookUp_U;
int32_t* VMul = (int32_t*)p->LookUp_Data + p->LookUp_V;
uint8_t* SatR = (uint8_t*)p->LookUp_Data + SatOfsR;
uint8_t* SatG = (uint8_t*)p->LookUp_Data + SatOfsG;
uint8_t* SatB = (uint8_t*)p->LookUp_Data + SatOfsB;
for (v=0;v<256;++v)
{
*YMul = (p->_YMul * v) << LOOKUP_FIX;
*UMul = (((p->_BUMul * v + p->_BAdd + (SatOfsB << 16)) << LOOKUP_FIX) & 0xFFFF0000) |
(((p->_GUMul * v) >> (16-LOOKUP_FIX)) & 0xFFFF); //BUMul | GUMul
*VMul = (((p->_RVMul * v + p->_RAdd + (SatOfsR << 16)) << LOOKUP_FIX) & 0xFFFF0000) |
(((p->_GVMul * v + p->_GAdd + (SatOfsG << 16)) >> (16-LOOKUP_FIX)) & 0xFFFF); //BUMul | GUMul
++YMul;
++UMul;
++VMul;
}
if (Dither)
{
for (v=-Safe;v<256+Safe;++v)
{
SatR[v] = RotateRight8(SAT(v),8-p->RSize);
SatG[v] = RotateRight8(SAT(v),8-p->GSize);
SatB[v] = RotateRight8(SAT(v),8-p->BSize);
}
}
else
{
for (v=-Safe;v<256+Safe;++v)
SatR[v] = (uint8_t)SAT(v);
}
}
#elif defined(MIPS)
const int Safe = 256;
// 256:Y + (128+Safe*2)*n:SAT + 8*256:U + 8*256:V
int SatOfsR = 256+Safe;
int SatOfsG = 256+Safe;
int SatOfsB = 256+Safe;
p->LookUp_Size = 256+8*256*2 + (128+Safe*2);
if (p->GSize == p->RSize)
SatOfsG = SatOfsR;
else
{
p->LookUp_Size += (128+Safe*2);
SatOfsG = SatOfsR + (128+Safe*2);
}
if (p->BSize == p->RSize)
SatOfsB = SatOfsR;
else
if (p->BSize == p->GSize)
SatOfsB = SatOfsG;
else
{
p->LookUp_Size += (128+Safe*2);
SatOfsB = SatOfsG + (128+Safe*2);
}
p->LookUp_U = p->LookUp_Size - 8*256*2;
p->LookUp_V = p->LookUp_Size - 8*256;
p->LookUp_Data = CAlloc(p->LookUp_Size,1);
if (p->LookUp_Data)
{
int v;
uint8_t* YMul = (uint8_t*)p->LookUp_Data;
uint8_t** UMul = (uint8_t**)((uint8_t*)p->LookUp_Data + p->LookUp_U);
uint8_t** VMul = (uint8_t**)((uint8_t*)p->LookUp_Data + p->LookUp_V);
uint8_t* SatR = (uint8_t*)p->LookUp_Data + SatOfsR;
uint8_t* SatG = (uint8_t*)p->LookUp_Data + SatOfsG;
uint8_t* SatB = (uint8_t*)p->LookUp_Data + SatOfsB;
for (v=0;v<256;++v)
{
*YMul = (uint8_t)((p->_YMul * v) >> 17);
UMul[0] = SatB + ((p->_BUMul * v + p->_BAdd) >> 17);
*(int*)&UMul[1] = (p->_GUMul * v) >> 17;
VMul[0] = SatR + ((p->_RVMul * v + p->_RAdd) >> 17);
VMul[1] = SatG + ((p->_GVMul * v + p->_GAdd) >> 17);
++YMul;
UMul+=2;
VMul+=2;
}
for (v=-Safe;v<128+Safe;++v)
{
SatR[v] = (uint8_t)(SAT(v*2) >> (8-p->RSize));
SatG[v] = (uint8_t)(SAT(v*2) >> (8-p->GSize));
SatB[v] = (uint8_t)(SAT(v*2) >> (8-p->BSize));
}
}
#elif defined(SH3)
const int Safe = 256;
//LookUp_Data:
// [128..255|0..127]Y + 384 empty + 4*[128..255|0..127]U + 4*[128..255|0..127]V + (128+Safe*2)*n:SAT
int SatOfsR = 256+384+4*256*2+Safe;
int SatOfsG = 256+384+4*256*2+Safe;
int SatOfsB = 256+384+4*256*2+Safe;
p->LookUp_Size = 256+384+4*256*2 + (128+Safe*2);
if (p->GSize == p->RSize)
SatOfsG = SatOfsR;
else
{
p->LookUp_Size += (128+Safe*2);
SatOfsG = SatOfsR + (128+Safe*2);
}
if (p->BSize == p->RSize)
SatOfsB = SatOfsR;
else
if (p->BSize == p->GSize)
SatOfsB = SatOfsG;
else
{
p->LookUp_Size += (128+Safe*2);
SatOfsB = SatOfsG + (128+Safe*2);
}
p->LookUp_U = 128 + 384 + 4*128;
p->LookUp_V = 128 + 384 + 4*256 + 4*128;
p->LookUp_Data = CAlloc(p->LookUp_Size + Safe*2,1); //additional safe
if (p->LookUp_Data)
{
int v;
int8_t* YMul = (int8_t*)p->LookUp_Data;
int16_t* UMul = (int16_t*)((uint8_t*)p->LookUp_Data + 256 + 384);
int16_t* VMul = (int16_t*)((uint8_t*)p->LookUp_Data + 256 + 384 + 4*256);
int8_t* SatR = (int8_t*)p->LookUp_Data + SatOfsR;
int8_t* SatG = (int8_t*)p->LookUp_Data + SatOfsG;
int8_t* SatB = (int8_t*)p->LookUp_Data + SatOfsB;
for (v=0;v<256;++v)
{
*YMul = (int8_t)(((p->_YMul * ((v+128)&255)) >> 17)-128);
UMul[0] = (int16_t)(SatOfsB + ((p->_BUMul * ((v+128)&255) + p->_BAdd) >> 17));
UMul[1] = (int16_t)((p->_GUMul * ((v+128)&255)) >> 17);
VMul[0] = (int16_t)(SatOfsR + ((p->_RVMul * ((v+128)&255) + p->_RAdd) >> 17));
VMul[1] = (int16_t)(SatOfsG + ((p->_GVMul * ((v+128)&255) + p->_GAdd) >> 17));
++YMul;
UMul+=2;
VMul+=2;
}
for (v=-Safe;v<128+Safe;++v)
{
SatR[v] = (int8_t)(SAT(v*2) >> (8-p->RSize));
SatG[v] = (int8_t)(SAT(v*2) >> (8-p->GSize));
SatB[v] = (int8_t)(SAT(v*2) >> (8-p->BSize));
}
}
#endif
}
void CalcColor( blit_soft* p )
{
#ifdef ARM
if (p->QAdd)
{
//saturation: signed 32bit / 3 (qdadd will triple)
int64_t YMul;
int64_t RVMul;
int64_t RAdd;
int64_t GUMul;
int64_t GVMul;
int64_t GAdd;
int64_t BUMul;
int64_t BAdd;
CMul(p,&YMul,0x63C000,0);
CMul(p,&RVMul,0x88B2AA,1);
CAdd(p,&RAdd,(p->FX.Brightness+p->FX.RGBAdjust[0])*0x63C000 - (int64_t)0x75400000,0x2AAAAAAA,0x88B2AA);
CMul(p,&GUMul,-0x218555,1);
CMul(p,&GVMul,-0x45A555,1);
CAdd(p,&GAdd,(p->FX.Brightness+p->FX.RGBAdjust[1])*0x63C000 + (int64_t)0x02AEAAAA,0x2AAAAAAA,-0x218555-0x45A555);
CMul(p,&BUMul,0xACD2AA,1);
CAdd(p,&BAdd,(p->FX.Brightness+p->FX.RGBAdjust[2])*0x63C000 - (int64_t)0x87500000,0x2AAAAAAA,0xACD2AA);
if (InRange32(YMul*0xF0) &&
InRange32(RVMul*0x10+RAdd) &&
InRange32(RVMul*0xF0+RAdd) &&
InRange32((GVMul+GUMul)*0x10+GAdd) &&
InRange32((GVMul+GUMul)*0xF0+GAdd) &&
InRange32(BUMul*0x10+BAdd) &&
InRange32(BUMul*0xF0+BAdd))
{
p->_YMul = (int)YMul;
p->_RVMul = (int)RVMul;
p->_RAdd = (int)RAdd;
p->_GUMul = (int)GUMul;
p->_GVMul = (int)GVMul;
p->_GAdd = (int)GAdd;
p->_BUMul = (int)BUMul;
p->_BAdd = (int)BAdd;
}
else
p->QAdd = 0;
}
if (!p->QAdd)
#endif
{
//saturation: unsigned 24bit
p->_YMul = CMul(p,NULL,0x12B40,0);
p->_RVMul = CMul(p,NULL,0x19A18,1);
p->_RAdd = CAdd(p,NULL,(p->FX.Brightness+p->FX.RGBAdjust[0])*0x12B40 - 0x0DFC000,0x800000,0x19A18);
p->_GUMul = CMul(p,NULL,-0x06490,1);
p->_GVMul = CMul(p,NULL,-0x0D0F0,1);
p->_GAdd = CAdd(p,NULL,(p->FX.Brightness+p->FX.RGBAdjust[1])*0x12B40 + 0x0880C00,0x800000,-0x06490-0x0D0F0);
p->_BUMul = CMul(p,NULL,0x20678,1);
p->_BAdd = CAdd(p,NULL,(p->FX.Brightness+p->FX.RGBAdjust[2])*0x12B40 - 0x115F000,0x800000,0x20678);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -