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

📄 overlay_xscale.c

📁 大名鼎鼎的CE下播放软件,TCPPMP的源代码!!!2410下可以流畅的解QVGA的H264,MPEG4等格式.
💻 C
📖 第 1 页 / 共 2 页
字号:
#endif

static void SetOrig(xscaledriver* p)
{
	int n;

#ifdef X50V
	if (p->X50v)
		X50vDisable(p);
	else
#endif
	{
		if (p->NotOrig)
		{
			if (p->OrigDescEnd && p->OrigDescEndSet)
			{
				p->OrigDescEnd->Next = p->OrigDescPhy[0];
				p->OrigDescEndSet = 0;
			}

			for (n=0;n<p->Count;++n)
				p->DescLast[n]->Next = p->OrigDescPhy[0];

			// wait for primary to be restored
			for (n=0;n<100;++n)
			{
				if (GetCurrent(p)<0)
					break;
				Sleep(1);
			}

			p->NotOrig = 0;
		}
	}
}

static void Done(xscale* p)
{
	SetOrig(p->Driver);
	if (p->Driver->Used == p)
		p->Driver->Used = NULL;
}

static int Reset(xscale* p)
{
	Done(p);
	Init(p);
	return ERR_NONE;
}

static xscaledesc* BuildDesc(xscaledesc* Desc,phymemblock* DescPhy,int DescPhyCount,phymemblock* BufferPhy,int BufferPhyCount,
							 int* Map,int Pitch,int Height,int Id)
{
	uint32_t First = DescPhy->Addr;
	uint32_t Last = 0;
	uint32_t DescAddr = 0;
	int n,m;

	for (n=0;n<Height;++n)
	{
		uint32_t Pos = Pitch * Map[n];
		int Length = Pitch;

		for (m=0;Length>0 && m<BufferPhyCount;++m)
		{
			if (Pos < BufferPhy[m].Length)
			{
				uint32_t Addr = BufferPhy[m].Addr + Pos;
				int Size = BufferPhy[m].Length - Pos;
				if (Size > Length)
					Size = Length;

				if (Size & 3) return NULL; // this shouldn't happen

				// add desc 
				if (Addr != Last)
				{
					DescAddr += sizeof(xscaledesc);
					if (DescAddr > DescPhy->Length)
					{
						// next desc block
						if (--DescPhyCount==0) return NULL; // not enough desc...
						++DescPhy;
						DescAddr = 0;
					}

					Desc->Next = DescPhy->Addr + DescAddr;
					Desc->Base = Addr;
					Desc->Id = Id;
					Desc->Cmd = Size;
					++Desc;
				}
				else
					Desc[-1].Cmd += Size;
				Last = Addr + Size;

				Length -= Size;
				Pos += Size;
			}

			Pos -= BufferPhy[m].Length;
		}
	}

	--Desc;
	Desc->Next = First;
	Desc->Cmd |= (1<<21);
	return Desc;
}

static bool_t Build(xscaledriver* p)
{
	int n;
	for (n=0;n<p->Count;++n)
	{
		p->DescLast[n] = BuildDesc(p->Desc[n],p->DescPhy[n],p->DescPhyCount[n],p->BufferPhy+p->MaxBlock*n,
			p->BufferPhyCount[n],p->Map,p->Width*2,p->Height,MAGIC | (n<<4));

		if (!p->DescLast[n])
			break;
	}

	if (n==p->Count)
	{
		for (n=p->OrigDescCount?1:0;n<p->Count;++n)
			memset(p->Buffer[n],0,p->BufferSize);
		return 1;
	}

	return 0;
}

static int UpdateAlign(xscale* p)
{
	rect FullScreen;
	int* ScaleY;
	blitfx FX = p->Overlay.FX;
	bool_t FullView;

	if (FX.Direction & DIR_SWAPXY)
		ScaleY = &FX.ScaleX;
	else
		ScaleY = &FX.ScaleY;

	PhyToVirt(NULL,&FullScreen,&p->Overlay.Output.Format.Video);
	FullView = p->Driver->Count && EqRect(&FullScreen,&p->Overlay.Viewport);

	if (FullView && p->Driver->Count>=3)
		p->Overlay.FX.Flags &= ~BLITFX_AVOIDTEARING; //flipping used

	p->Flip = 0;
	p->Next = 0;
	SetOrig(p->Driver);

	OverlayUpdateAlign(&p->Overlay);

	if (FullView && p->Driver->Count)
	{
		int n;
		for (n=0;n<p->Overlay.Output.Format.Video.Height;++n)
			p->Driver->Map[n]=n;

		if (p->Driver->SetupStretch && 
			((p->Overlay.Node.Class == XSCALE_LOW_ID && *ScaleY > SCALE_ONE/2) || *ScaleY > SCALE_ONE) && 
			!(p->Overlay.Output.Format.Video.Width & 1) && p->Overlay.Output.Format.Video.Height>0)
		{
			int Num,Den;
			int Adj;
			int LowSrc,HighSrc,CenterSrc;
			rect DstAlignedRect;
			rect SrcAlignedRect;

			*ScaleY = p->Overlay.Node.Class == XSCALE_LOW_ID ? SCALE_ONE/2 : SCALE_ONE;

			VirtToPhy(&p->Overlay.Viewport,&DstAlignedRect,&p->Overlay.Output.Format.Video);
			VirtToPhy(NULL,&SrcAlignedRect,&p->Overlay.Input.Format.Video);

			BlitRelease(p->Overlay.Soft);
			p->Overlay.Soft = BlitCreate(&p->Overlay.Output.Format.Video,&p->Overlay.Input.Format.Video,&FX,&p->Overlay.Caps);

			BlitAlign(p->Overlay.Soft, &DstAlignedRect, &SrcAlignedRect );

			LowSrc = -(DstAlignedRect.Height/2);
			HighSrc = LowSrc + DstAlignedRect.Height;
			CenterSrc = DstAlignedRect.y - LowSrc;

			Num = DstAlignedRect.Height;
			Den = p->Overlay.DstAlignedRect.Height;
			if (FX.Direction & DIR_SWAPXY)
			{
				Num *= p->Overlay.SrcAlignedRect.Width;
				Den *= SrcAlignedRect.Width;
			}
			else
			{
				Num *= p->Overlay.SrcAlignedRect.Height;
				Den *= SrcAlignedRect.Height;
			}
			Adj = Scale(p->Overlay.DstAlignedRect.Height,Num,2*Den);

			for (n=0;n<p->Overlay.DstAlignedRect.Height;++n)
			{	
				int i = Scale(n,Num,Den) - Adj;
				if (i >= HighSrc) i=HighSrc-1;
				if (i < LowSrc) i=LowSrc;
				p->Driver->Map[p->Overlay.DstAlignedRect.y+n] = CenterSrc + i;
			}
		}

		if (Build(p->Driver))
		{
			p->Overlay.FX.Flags |= BLITFX_AVOIDTEARING; //restore
			p->Flip = 1;
		}
	}

	return ERR_NONE;
}

static void Restore(xscaledriver* p,int Next)
{
	int n;
	char *s,*d;
	char *Src = (char*)p->Buffer[Next];
	char *Dst = (char*)p->OrigBuffer;
	int Middle = p->Height/2;
	int Pitch = p->Width*2;

	for (n=0;n<Middle;++n)
	{
		s = Src + p->Map[n] * Pitch;
		d = Dst + n*Pitch;
		if (s != d)
			memcpy(d,s,Pitch);
	}

	for (n=p->Height-1;n>=Middle;--n)
	{
		s = Src + p->Map[n] * Pitch;
		d = Dst + n*Pitch;
		if (s != d)
			memcpy(d,s,Pitch);
	}
}

static int UpdateShow(xscale* p)
{
	if (!p->Overlay.Show)
	{
		SetOrig(p->Driver);

		if (p->Flip)
		{
			// restore after SetOrig because it's vsynced and restore starts for upper part anyway
			Restore(p->Driver,p->Next); 
		}
		p->Next = 0;
	}
	return ERR_NONE;
}

static int Lock(xscale* p, planes Planes, bool_t OnlyAligned )
{
	if (p->Flip)
	{
		int Next = p->Next+1;
		if (Next == p->Driver->Count) 
			Next = 0;

		// use new buffer only if it's not the current
		if (GetCurrent(p->Driver) != Next) 
			p->Next = Next;

		Planes[0] = p->Driver->Buffer[p->Next];
	}
	else
		Planes[0] = p->Driver->OrigBuffer;

	return ERR_NONE;
}

static int Unlock(xscale* p )
{
	if (p->Flip)
	{
		int Current = GetCurrent(p->Driver);
		uint32_t DescPhy = p->Driver->DescPhy[p->Next]->Addr;

		// close chain
		p->Driver->DescLast[p->Next]->Next = DescPhy;

#ifdef X50V
		if (p->Driver->X50v && X50vEnable(p->Driver,DescPhy))
			Current = p->Next;
#endif

		DEBUG_MSG4(-1,T("%08x %08x %08x %d"),p->Driver->Regs[LCCR0],p->Driver->Regs[LCCR3],p->Driver->Regs[FDADR0],Current);

		if (Current<-1)
			return ERR_DEVICE_ERROR;

		if (Current<0)
		{
			if (p->Driver->OrigDescEnd)
			{
				p->Driver->OrigDescEnd->Next = DescPhy;
				p->Driver->OrigDescEndSet = 1;
			}
			else
			if (p->Driver->OrigDescCount>1) 
			{
				// multi desc original
				bool_t Old = (p->Driver->Regs[LCCR0] & 1);
				Disable(p->Driver);
				p->Driver->Regs[FBR0] = 0;
				p->Driver->Regs[FDADR0] = DescPhy;
				if (Old) Enable(p->Driver);
			}
			else // simply branch
				p->Driver->Regs[FBR0] = DescPhy | 1; 
		}
		else
		{
			// modify last frames tail to new frame
			Current = p->Next-1;
			if (Current<0)
				Current = p->Driver->Count-1;
			p->Driver->DescLast[Current]->Next = DescPhy;
		}
		p->Driver->NotOrig = 1;
	}

	return ERR_NONE;
}

static int UpdateStretch(xscaledriver* Driver)
{
	if (Driver->Used)
		UpdateAlign(Driver->Used);
	return ERR_NONE;
}

static int UpdateFlip(xscaledriver* Driver)
{
	if (Driver->Used)
	{
		xscale* p = Driver->Used;
		Done(p);
		FreeBuffer(Driver);
		Init(p);
		UpdateAlign(p);
		p->Overlay.Dirty = 1;
		p->Overlay.LastTime = -1;
	}
	return ERR_NONE;
}

static const datatable Params[] = 
{
	{ XSCALEDRIVER_STRETCH,			TYPE_BOOL, DF_SETUP|DF_CHECKLIST },
	{ XSCALEDRIVER_FLIP,			TYPE_BOOL, DF_SETUP|DF_CHECKLIST },
	{ XSCALEDRIVER_ALLOC_AT_START,	TYPE_BOOL, DF_SETUP|DF_CHECKLIST },

	DATATABLE_END(XSCALEDRIVER_ID)
};

static int Enum(xscaledriver* p, int* No, datadef* Param)
{
	return NodeEnumTable(No,Param,Params);
}

static int Get(xscaledriver* p,int No,void* Data,int Size)
{
	int Result = ERR_INVALID_PARAM;
	switch (No) 
	{
	case XSCALEDRIVER_STRETCH: GETVALUE(p->SetupStretch,bool_t); break;
	case XSCALEDRIVER_FLIP: GETVALUE(p->SetupFlip,bool_t); break;
	case XSCALEDRIVER_ALLOC_AT_START: GETVALUE(p->AllocAtStart,bool_t); break;
	}
	return Result;
}

static bool_t Selected()
{
	int Id;
	return NodeRegLoadValue(PLAYER_ID,PLAYER_VOUTPUTID,&Id,sizeof(Id),TYPE_INT) && (Id == XSCALE_ID || Id == XSCALE_LOW_ID);
}

static int Set(xscaledriver* p,int No,const void* Data,int Size)
{
	int Result = ERR_INVALID_PARAM;
	switch (No)
	{
	case XSCALEDRIVER_STRETCH: SETVALUECMP(p->SetupStretch,bool_t,UpdateStretch(p),EqBool); break;
	case XSCALEDRIVER_FLIP: SETVALUECMP(p->SetupFlip,bool_t,UpdateFlip(p),EqBool); break;
	case XSCALEDRIVER_ALLOC_AT_START: SETVALUE(p->AllocAtStart,bool_t,ERR_NONE); break;
	case NODE_SETTINGSCHANGED:
		if (p->AllocAtStart && p->AtStart && Selected())
		{
			if (!p->OrigBuffer)
				GetOrig(p);
			AllocBuffer(p);
		}
		p->AtStart = 0;
		break;
	case NODE_HIBERNATE:
		if (!p->Used && FreeBuffer(p))
			Result = ERR_NONE;
		break;
	}
	return Result;
}

static int Create(xscale* p)
{
	p->Driver = (xscaledriver*)NodeEnumObject(NULL,XSCALEDRIVER_ID);
	if (!p->Driver)
		return ERR_NOT_SUPPORTED;

	if (p->Overlay.Node.Class == XSCALE_LOW_ID && (p->Driver->Width*p->Driver->Height <= 320*240 || 
		(QueryPlatform(PLATFORM_CAPS) & CAPS_ARM_WMMX)!=0))
		return ERR_NOT_SUPPORTED;

	GetMode(p);
	p->Overlay.Init = Init;
	p->Overlay.Done= Done;
	p->Overlay.Reset = Reset;
	p->Overlay.Update = UpdateAlign;
	p->Overlay.UpdateShow = UpdateShow;
	p->Overlay.Lock = Lock;
	p->Overlay.Unlock = Unlock;
	return ERR_NONE;
}

static int CreateDriver(xscaledriver* p)
{
	bool_t Detected;
	int Caps = QueryPlatform(PLATFORM_CAPS);
	if (!(Caps & CAPS_ARM_XSCALE))
		return ERR_NOT_SUPPORTED;

	p->Node.Enum = Enum;
	p->Node.Get = Get;
	p->Node.Set = Set;

	p->AtStart = 1;
	p->OrigBuffer = NULL;
	p->OrigDescCount = 0;
	p->Regs = (uint32_t*)PhyMemBegin(LCD_BASE,LCD_SIZE,0);
	if (!p->Regs)
		return ERR_NOT_SUPPORTED;

#ifdef X50V
	p->X50v = QueryPlatform(PLATFORM_MODEL)==MODEL_AXIM_X50 && CheckModule(T("pvrvadd.dll"));
	if (p->X50v)
	{
		p->Width = 480;
		p->Height = 640;
		p->Marathon = (uint32_t*) 0xBC000000;
		p->GPIO = (uint32_t*) PhyMemBegin(GPIO_BASE,GPIO_SIZE,0);
		if (p->GPIO)
		{
			RawFrameBufferInfo Info;
			HDC DC= GetDC(NULL);
			memset(&Info,0,sizeof(Info));
			ExtEscape(DC, GETRAWFRAMEBUFFER, 0, NULL, sizeof(RawFrameBufferInfo), (char*)&Info);
			ReleaseDC(NULL,DC);

			p->OrigBuffer = Info.pFramePointer;
		}
	}
	else
#endif
	if (!(p->Regs[LCCR0] & 1) || ((p->Regs[LCCR3] >> 24) & 7)!=4) // LCD enabled, RGB 16bit
		return ERR_NOT_SUPPORTED;

	if (!NodeRegLoadValue(XSCALEDRIVER_ID, XSCALEDRIVER_DETECTED, &Detected, sizeof(Detected), TYPE_BOOL) || !Detected)
	{
		GetOrig(p);
		if (!p->OrigBuffer)
		{
			PhyMemEnd(p->Regs);
			p->Regs = NULL;
			return ERR_NOT_SUPPORTED;
		}
		Detected = 1;
		NodeRegSaveValue(XSCALEDRIVER_ID, XSCALEDRIVER_DETECTED, &Detected, sizeof(Detected), TYPE_BOOL);
	}

	p->AllocAtStart = 1;
	p->SetupFlip = 1;
	p->SetupStretch = (QueryPlatform(PLATFORM_CAPS) & CAPS_ARM_WMMX)==0;
	return ERR_NONE;
}

static void DeleteDriver(xscaledriver* p)
{
	if (p->Regs)
		SetOrig(p);

	FreeBuffer(p);
	FreeOrig(p);

#ifdef X50V
	if (p->GPIO)
	{
		PhyMemEnd(p->GPIO);
		p->GPIO = NULL;
	}	
#endif

	if (p->Regs)
	{
		PhyMemEnd(p->Regs);
		p->Regs = NULL;
	}	
}

static const nodedef XScaleDriver = 
{
	sizeof(xscaledriver)|CF_GLOBAL|CF_SETTINGS,
	XSCALEDRIVER_ID,
	NODE_CLASS,
	PRI_DEFAULT,
	(nodecreate)CreateDriver,
	(nodedelete)DeleteDriver,
};

static const nodedef XScale = 
{
	sizeof(xscale)|CF_GLOBAL,
	XSCALE_ID,
	OVERLAY_CLASS,
	PRI_DEFAULT+97,
	(nodecreate)Create,
};

static const nodedef XScaleLow = 
{
	sizeof(xscale)|CF_GLOBAL,
	XSCALE_LOW_ID,
	XSCALE_ID,
	PRI_DEFAULT+96,
};

void OverlayXScale_Init() 
{ 
	NodeRegisterClass(&XScaleDriver);
	NodeRegisterClass(&XScale);
	NodeRegisterClass(&XScaleLow);
}

void OverlayXScale_Done()
{
	NodeUnRegisterClass(XSCALE_LOW_ID);
	NodeUnRegisterClass(XSCALE_ID);
	NodeUnRegisterClass(XSCALEDRIVER_ID);
}

#else
void OverlayXScale_Init() {}
void OverlayXScale_Done() {}
#endif

⌨️ 快捷键说明

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