⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 blit_soft.c

📁 betaplayer的源码 tcpmp的老版本
💻 C
📖 第 1 页 / 共 3 页
字号:
/*****************************************************************************
 *
 * This program is free software ; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 *
 * $Id: blit_soft.c 202 2005-01-25 01:27:33Z picard $
 *
 * BetaPlayer Blit
 * Copyright (c) 2004 Gabor Kovacs
 *
 ****************************************************************************/

#include "../stdafx.h"
#include "../dyncode/dyncode.h"
#include "blit_soft.h"

#define SAT(Value) (Value < 0 ? 0: (Value > 255 ? 255: Value))

static rgb Gray1[2] = { 
	{0,0,0},{255,255,255}
};
static rgb Gray2[4] = { 
	{0,0,0},{85,85,85},{170,170,170},{255,255,255} 
};
static rgb Gray4[16] = { 
	{0,0,0},{17,17,17},{34,34,34},{51,51,51},
	{68,68,68},{85,85,85},{102,102,102},{119,119,119},
	{136,136,136},{153,153,153},{170,170,170},{187,187,187},
	{204,204,204},{221,221,221},{238,238,238},{255,255,255}
};

typedef struct blitpack
{
	blitfx FX;
	video Dst;
	video Src;
	rect DstRect;
	rect SrcRect;
	blit_soft Code[2];
	struct blitpack* Next;
	int RScaleX;
	int RScaleY;
	int SrcAlignPos;
	int DstAlignPos;
	int DstAlignSize;
	bool_t SafeBorder;

} blitpack;

static blitpack* BlitPack = NULL;

void FreeBlit( blit_soft* p)
{
	CodeDone(&p->Code);

	Free(p->LookUp_Data);
	p->LookUp_Data = NULL;
}

void Blit_Init()
{
}

void Blit_Done()
{
	blitpack* q;
	blitpack* p;
	
	for (p=BlitPack;p;p=q)
	{
		q = p->Next;
		FreeBlit(&p->Code[0]);
		FreeBlit(&p->Code[1]);
		Free(p);
	}

	BlitPack = NULL;
}

static const rgb* DefaultPal( const pixel* Format )
{
	if (Format->Flags & PF_PALETTE)
	{
		if (!Format->Palette)
			switch (Format->BitCount)
			{
			case 1: return Gray1;
			case 2: return Gray2;
			case 4: return Gray4;
			}
		return Format->Palette;
	}
	return NULL;
}


int CalcScale( int v, int Min, int Max )
{
	if (v > Max) v = Max;
	if (v < Min) v = Min;
	return v;
}

int CalcRScale( int v, int Gray )
{
	if (v<=0) return 16;

	v = (16*1024 << 16) / v;

	if (Gray) // only 100% and 200% scale
		return v > 12288 ? 16:8;

	//align to 100%
	if (v > 16834-1024 && v < 16384+1024) 
		v = 16384;
	//align to 200%
	if (v > 8192-1024 && v < 8192+1024) 
		v = 8192;
	//align to 50%
	if (v > 32768-1024 && v < 32768+1024) 
		v = 32768;

#if defined(SH3)
	if (v < 12288)
		return 8;
	return 16;
//	if (v<1024) v=1024;
//	return ((v+1024) >> 11) << 1;
#else
	if (v<512) v=512;
	return (v+512) >> 10;
#endif
}

void* BlitCreate( const video* Dst, 
			      const video* Src, const blitfx* FX, int* OutCaps )
{
	bool_t Gray;
	int Caps = VC_BRIGHTNESS|VC_DITHER|VC_SATURATION|VC_CONTRAST|VC_RGBADJUST;

	blitpack* p = BlitPack;
	if (p)
		BlitPack = p->Next;
	else
	{
		p = (blitpack*) CAlloc(sizeof(blitpack),1);
		if (!p)
			return NULL;

		CodeInit(&p->Code[0].Code);
		CodeInit(&p->Code[1].Code);
	}

	if (!BlitCompile(&p->Code[0],Dst,Src,FX,0) ||
		((FX->Flags & BLITFX_ONLYDIFF) && !BlitCompile(&p->Code[1],Dst,Src,FX,1)))
	{
		p->Next = BlitPack;
		BlitPack = 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);

	// default alignment
	p->SrcAlignPos = 2;
	p->DstAlignPos = 2;
	p->DstAlignSize = 2;

	if (Gray && Dst->Pixel.BitCount == 2) // arm_gray, mips_gray, sh3_gray 
		p->DstAlignPos = p->DstAlignSize = 4;
#if defined(ARM)
	else
	if (PlanarYUV(&Dst->Pixel,NULL,NULL,NULL)) // arm_yuv
	{
		p->SrcAlignPos = p->DstAlignPos = p->DstAlignSize = 8;
		Caps = VC_BRIGHTNESS;
	}
	else
	if (p->Code[0].WMMX && PlanarYUV420(&Src->Pixel) && 
		(p->RScaleX==16 || p->RScaleX==8 || p->RScaleX==32) && (p->RScaleY==16 || p->RScaleY==8 || p->RScaleY==32))
	{
		p->SrcAlignPos = p->DstAlignPos = p->DstAlignSize = 8;
		if (p->RScaleX==8) p->DstAlignSize = 16;
	}
	else 
	if (PlanarYUV420(&Src->Pixel) && p->RScaleX == 32 && p->RScaleY == 32) //arm_half
		p->DstAlignPos = p->DstAlignSize = 4;
	else 
	if (PlanarYUV420(&Src->Pixel) &&
		(p->RScaleX == 8 || p->RScaleY == 8) && //arm_fix with double 
		(p->RScaleX == 8 || p->RScaleX == 16) && 
		(p->RScaleY == 8 || p->RScaleY == 16) && !p->Code[0].ArithStretch)
		p->DstAlignSize = 4;
#elif defined(SH3) || defined(MIPS)
	if (p->RScaleX == 8 || p->RScaleY == 8) //sh3_fix,mips_fix
		p->DstAlignSize = 4;
#else
	// universal
	Caps = VC_BRIGHTNESS | VC_DITHER;
	if (AnyYUV(&Dst->Pixel)) 
		Caps &= ~VC_DITHER;
#endif

	if (OutCaps)
		*OutCaps = Caps;

	return p;
}

void BlitAlign( void* Handle, rect* DstRect, rect* SrcRect )
{
	int i;
	int ShrinkX,ShrinkY;
	int SrcRight;
	int SrcBottom;
	int SrcAdjWidth,SrcAdjHeight;
	blitpack* p = Handle;
	int RScaleX,RScaleY;

	if (!p) return;

	RScaleX = p->RScaleX;
	RScaleY = p->RScaleY;

	p->SafeBorder = 0;

	if (p->Code[0].ArithStretch && (RScaleX != 16) && (RScaleX != 32))
	{
		//avoid bilinear scale overrun (shrink source)

		if ((p->Src.Pixel.Flags & PF_SAFEBORDER) && p->DstAlignSize > 2)
			p->SafeBorder = 1; // build a one pixel border before blitting on right and bottom side
		else
		{
			//only horizontal bilinear filtering is supported (arm_stretch)
			if (SrcRect->Width>2) 
				SrcRect->Width -= 2;
		}
	}

	SrcRight = SrcRect->x + SrcRect->Width;
	SrcBottom = SrcRect->y + SrcRect->Height;
	
	// convert source to destination space
	if (p->FX.Direction & DIR_SWAPXY)
	{
		SwapInt(&RScaleX,&RScaleY);
		SwapRect(SrcRect);
	}

	SrcAdjWidth = SrcRect->Width * 16 / RScaleX;
	SrcAdjHeight = SrcRect->Height * 16 / RScaleY;

	ShrinkX = DstRect->Width - SrcAdjWidth;
	if (ShrinkX>=0) //shrink destination?
	{
		ShrinkX >>= 1;
		DstRect->x += ShrinkX;
		DstRect->Width = SrcAdjWidth;
	}
	else //adjust source position
	{
		ShrinkX = 0;
		SrcRect->x += (SrcAdjWidth - DstRect->Width) * RScaleX >> 5;
		SrcRect->Width = -1; // need calc
	}
	
	ShrinkY = DstRect->Height - SrcAdjHeight;
	if (ShrinkY>=0) //shrink Dst?
	{
		ShrinkY >>= 1;
		DstRect->y += ShrinkY;
		DstRect->Height = SrcAdjHeight;
	}
	else //adjust source position
	{
		ShrinkY = 0;
		SrcRect->y += (SrcAdjHeight - DstRect->Height) * RScaleY >> 5;
		SrcRect->Height = -1; // need calc
	}

	i = DstRect->Width & (p->DstAlignSize-1); 
	DstRect->Width -= i; 
	i >>= 1;
	ShrinkX += i;
	DstRect->x += i;

	i = DstRect->Height & (p->DstAlignSize-1);
	DstRect->Height -= i;
	i >>= 1;
	ShrinkY += i;
	DstRect->y += i;

	i = DstRect->x & (p->DstAlignPos-1);
	if (i && ShrinkX < i)
	{
		DstRect->Width -= p->DstAlignPos - i;
		DstRect->Width &= ~(p->DstAlignSize-1); 
		DstRect->x += p->DstAlignPos - i;
	}
	else
		DstRect->x -= i;

	i = DstRect->y & (p->DstAlignPos-1);
	if (i && ShrinkY < i)
	{
		DstRect->Height -= p->DstAlignPos - i;
		DstRect->Height &= ~(p->DstAlignSize-1);
		DstRect->y += p->DstAlignPos - i;
	}
	else
		DstRect->y -= i;

	SrcRect->x &= ~(p->SrcAlignPos-1);
	SrcRect->y &= ~(p->SrcAlignPos-1);

	// convert source back to it's space (if needed)
	if (SrcRect->Width < 0)
		SrcRect->Width = (DstRect->Width * RScaleX / 16 + 1) & ~1;
	if (SrcRect->Height < 0)
		SrcRect->Height = (DstRect->Height * RScaleY / 16 + 1) & ~1;

	if (p->FX.Direction & DIR_SWAPXY)
		SwapRect(SrcRect);

	if (SrcRect->x + SrcRect->Width > SrcRight)
		SrcRect->Width = SrcRight - SrcRect->x;

	if (SrcRect->y + SrcRect->Height > SrcBottom)
		SrcRect->Height = SrcBottom - SrcRect->y;

	p->DstRect = *DstRect;
	p->SrcRect = *SrcRect;
}

void BlitRelease(void* Handle)
{
	blitpack* p = (blitpack*)Handle;
	if (p)
	{
		p->Next = BlitPack;
		BlitPack = p;
	}
}

int AnyAlign( rect* DstRect, rect* SrcRect, const blitfx* FX, 
			  int DstAlignSize, int DstAlignPos,
			  int MinScale, int MaxScale )
{
	int i,ShrinkX,ShrinkY;
	int ScaleX,ScaleY;
	int SrcRight;
	int SrcBottom;
	int SrcAdjWidth,SrcAdjHeight;

	if (!DstRect || !SrcRect || !FX)
		return ERR_INVALID_PARAM;

	ScaleX = CalcScale(FX->ScaleX,MinScale,MaxScale);
	ScaleY = CalcScale(FX->ScaleY,MinScale,MaxScale);
	SrcRight = SrcRect->x + SrcRect->Width;
	SrcBottom = SrcRect->y + SrcRect->Height;

	// convert source to destination space
	if (FX->Direction & DIR_SWAPXY)
	{
		SwapInt(&ScaleX,&ScaleY);
		SwapRect(SrcRect);
	}

	SrcAdjWidth = (SrcRect->Width * ScaleX + 32768 ) >> 16;
	SrcAdjHeight = (SrcRect->Height * ScaleY + 32768 ) >> 16;

	ShrinkX = DstRect->Width - SrcAdjWidth;
	if (ShrinkX>0) //shrink destination?
	{
		ShrinkX >>= 1;
		DstRect->x += ShrinkX;
		DstRect->Width = SrcAdjWidth;
	}
	else //adjust source position
	{
		ShrinkX = 0;
		SrcRect->x += ((SrcAdjWidth - DstRect->Width) << 15) / ScaleX;
		SrcRect->Width = -1;
	}
	
	ShrinkY = DstRect->Height - SrcAdjHeight;
	if (ShrinkY>0) //shrink Dst?
	{
		ShrinkY >>= 1;
		DstRect->y += ShrinkY;
		DstRect->Height = SrcAdjHeight;
	}
	else //adjust source position
	{
		ShrinkY = 0;
		SrcRect->y += ((SrcAdjHeight - DstRect->Height) << 15) / ScaleY;
		SrcRect->Height = -1;
	}

	// final alignment

	i = DstRect->Width & (DstAlignSize-1); 
	DstRect->Width -= i; 
	i >>= 1;
	ShrinkX += i;
	DstRect->x += i;

	i = DstRect->Height & (DstAlignSize-1);
	DstRect->Height -= i;
	i >>= 1;
	ShrinkY += i;
	DstRect->y += i;

	i = DstRect->x & (DstAlignPos-1);
	if (i && ShrinkX < i)
	{
		DstRect->Width -= DstAlignPos - i;
		DstRect->Width &= ~(DstAlignSize-1); 
		DstRect->x += DstAlignPos - i;
	}
	else
		DstRect->x -= i;

	i = DstRect->y & (DstAlignPos-1);
	if (i && ShrinkY < i)
	{
		DstRect->Height -= DstAlignPos - i;
		DstRect->Height &= ~(DstAlignSize-1);
		DstRect->y += DstAlignPos - i;
	}
	else
		DstRect->y -= i;

	SrcRect->x &= ~1;
	SrcRect->y &= ~1;

	if (SrcRect->Width < 0)
		SrcRect->Width = ((DstRect->Width << 16) / ScaleX +1) & ~1;
	if (SrcRect->Height < 0)
		SrcRect->Height = ((DstRect->Height << 16) / ScaleY +1) & ~1;

	if (FX->Direction & DIR_SWAPXY)
		SwapRect(SrcRect);

	if (SrcRect->x + SrcRect->Width > SrcRight)
		SrcRect->Width = SrcRight - SrcRect->x;

	if (SrcRect->y + SrcRect->Height > SrcBottom)
		SrcRect->Height = SrcBottom - SrcRect->y;

	return ERR_NONE;
}

void SafeBorder( const planes Planes, const video* Format )
{
	//!!!
}

static INLINE void SurfacePtr( uint8_t** Ptr, const planes Planes, const video* Format, int BPP, int x, int y, int Pitch)
{
	int Adj = (x & 1) << 1;
   	Ptr[0] = (uint8_t*)Planes[0] + ((x * BPP) >> 3) + y * Pitch;

	if (Format->Pixel.Flags & (PF_YUV420|PF_YUV422|PF_YUV444))
	{
		if (Format->Pixel.Flags & PF_YUV420)
		{
			Ptr[1] = (uint8_t*)Planes[1] + (x >> 1) + (y >> 1) * (Pitch >> 1);
			Ptr[2] = (uint8_t*)Planes[2] + (x >> 1) + (y >> 1) * (Pitch >> 1);
		}
		else
		if (Format->Pixel.Flags & PF_YUV422)
		{
			Ptr[1] = (uint8_t*)Planes[1] + (x >> 1) + y * (Pitch >> 1);
			Ptr[2] = (uint8_t*)Planes[2] + (x >> 1) + y * (Pitch >> 1);
		}
		else
		if (Format->Pixel.Flags & PF_YUV444)
		{
			Ptr[1] = (uint8_t*)Planes[1] + x + y * Pitch;
			Ptr[2] = (uint8_t*)Planes[2] + x + y * Pitch;
		}
	}
	else
	if (Format->Pixel.Flags & PF_FOURCC)
		switch (Format->Pixel.FourCC)
		{
		case FOURCC_IMC2:
			Ptr[2] = (uint8_t*)Planes[0] + Format->Height * Pitch + (x >> 1) + (y >> 1) * Pitch;
			Ptr[1] = Ptr[1] + (Pitch >> 1);
			break;
		case FOURCC_IMC4:
			Ptr[1] = (uint8_t*)Planes[0] + Format->Height * Pitch + (x >> 1) + (y >> 1) * Pitch;
			Ptr[2] = Ptr[1] + (Pitch >> 1);
			break;
		case FOURCC_I420:
		case FOURCC_IYUV:
			Ptr[1] = (uint8_t*)Planes[0] + Format->Height * Pitch + (x >> 1) + (y >> 1) * (Pitch >> 1);
			Ptr[2] = Ptr[1] + ((Format->Height * Pitch) >> 2);
			break;
		case FOURCC_YV16: 
			Ptr[2] = (uint8_t*)Planes[0] + Format->Height * Pitch + (x >> 1) + y * (Pitch >> 1);
			Ptr[1] = Ptr[2] + ((Format->Height * Pitch) >> 1);
			break;
		case FOURCC_YV12: 
			Ptr[2] = (uint8_t*)Planes[0] + Format->Height * Pitch + (x >> 1) + (y >> 1) * (Pitch >> 1);
			Ptr[1] = Ptr[2] + ((Format->Height * Pitch) >> 2);
			break;
		case FOURCC_YUY2:
		case FOURCC_YUNV:
		case FOURCC_V422:
		case FOURCC_YUYV:
			Ptr[1] = Ptr[0]+1-Adj;
			Ptr[2] = Ptr[0]+3-Adj;
			break;
		case FOURCC_YVYU:
			Ptr[1] = Ptr[0]+3-Adj;
			Ptr[2] = Ptr[0]+1-Adj;
			break;
		case FOURCC_UYVY:
		case FOURCC_Y422:
		case FOURCC_UYNV:
			Ptr[1] = Ptr[0]-Adj;
			Ptr[2] = Ptr[0]+2-Adj;
			Ptr[0]++;
			break;
		case FOURCC_VYUY:
			Ptr[2] = Ptr[0]-Adj;
			Ptr[1] = Ptr[0]+2-Adj;
			Ptr[0]++;
			break;
		}
}

void BlitImage( void* Handle, const planes Dst, const planes Src, const planes SrcLast, int DstPitch, int SrcPitch )
{
	blitpack* Pack = (blitpack*)Handle;
	uint8_t* DstPtr[MAXPLANES];
	uint8_t* SrcPtr[MAXPLANES];
	bool_t OnlyDiff;
	int Width,Height;
	blit_soft* p;
	int Src2SrcLast;
	int DstStepX;
	int DstStepY;
	int DstX;
	int DstY;
	int SrcY;

	// nothing to do?
	if (!Pack || Pack->DstRect.Width<=0 || Pack->DstRect.Height<=0)
		return;

	OnlyDiff = (Pack->FX.Flags & BLITFX_ONLYDIFF) && SrcLast && SrcLast[0] != NULL;

	p = &Pack->Code[OnlyDiff];

	// calculate the Src and Dst pointers
	//   Src: always upperleft corner
	//   Dst: according to swapxy and mirroring

	Width = Pack->DstRect.Width;
	Height = Pack->DstRect.Height;

	if (p->SwapXY)
		SwapInt(&Width,&Height);

	if (DstPitch < 0)
		DstPitch = Pack->Dst.Pitch;
	if (SrcPitch < 0)
		SrcPitch = Pack->Src.Pitch;

	SrcY = Pack->SrcRect.y;
	if (p->SrcUpDown)
		SrcY += Pack->SrcRect.Height-1;

	if (Pack->SafeBorder)
		SafeBorder(Src,&Pack->Src);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -