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

📄 overlay_hires.c

📁 大名鼎鼎的CE下播放软件,TCPPMP的源代码!!!2410下可以流畅的解QVGA的H264,MPEG4等格式.
💻 C
📖 第 1 页 / 共 2 页
字号:
	Buffer->Desc->Id = MAGIC|(p->BufferCount << 4); 
	Buffer->Desc->Next = Buffer->DescPhy; 
	Buffer->Desc->Cmd = p->SurfaceSize | (1<<21);
	return ERR_NONE;
}
	
static int XScaleGet(hires* p)
{
	int Id = p->Regs[FIDR0] & ~15;
	uint32_t Phy = p->Regs[FDADR0] & ~15;

	if ((Id & 0xFFFF0000) == MAGIC)
		return (Id >> 4) & 0xFF;

	if (Phy == p->OrigPhy || Phy == p->OrigPhy+sizeof(xscaledesc))
		return -1;

	p->OrigPhy = Phy; // changed...
	return -1; 
}

static void XScaleQuickDisable(hires* p)
{
	int n = p->Regs[LCCR0];
	n &= ~(1<<10); //DIS
	n &= ~1;	   //ENB
	p->Regs[LCCR0] = n;
	ThreadSleep(1);
}

static void XScaleDisable(hires* p)
{
	int i;
	int n = p->Regs[LCCR0];
	if (n & 1)
	{
		n |= 1<<10; //DIS
		p->Regs[LCCR0] = n;

		for (i=0;i<30;++i)
		{
			if (!(p->Regs[LCCR0] & 1)) 
				break;
			ThreadSleep(1);
		}

		if (i==30)
			XScaleQuickDisable(p);
	}
}

static void XScaleEnable(hires* p,uint32_t Phy)
{
	int n = p->Regs[LCCR0];
	n &= ~(1<<10); //DIS
	n |= 1; //EN;
	p->Regs[FBR0] = 0;
	p->Regs[FDADR0] = Phy;
	p->Regs[LCCR0] = n;
	ThreadSleep(1);
}

static NOINLINE bool_t TimeAdjust(volatile uint32_t* p,int x,int left,int right,bool_t UseBorder)
{
	int o1,o2;
	uint32_t n;
	uint32_t v = *p;

	if (UseBorder)
		x += left+right;
	--x;
	n = v & 0x3FF;
	if ((int)n == x)
		return 0;

	v &= ~0x3FF;
	v |= x;

	x -= n;
	if (x>=left)
		o1 = left;
	else
	if (x<=-left)
		o1 = -left;
	else
		o1 = x >> 1;
	o2 = x - o1;

	n = (v >> 16) & 0xFF;
	v &= ~0xFF0000;
	v |= (n-o2) << 16; 

	n = (v >> 24) & 0xFF;
	v &= ~0xFF000000;
	v |= (n-o1) << 24; 

	*p = v;
	return 1;
}

static NOINLINE bool_t Adjust(hires* p,volatile uint32_t* p1,volatile uint32_t* p2,bool_t UseBorder)
{
	bool_t Changed;
	Changed = TimeAdjust(p1,p->PhyWidth,p->Border[0],p->Border[1],UseBorder);
	Changed = TimeAdjust(p2,p->PhyHeight,p->Border[2],p->Border[3],UseBorder) || Changed;
	return Changed;
}

static void XScaleChange(hires* p,uint32_t Phy,bool_t UseBorder)
{
	XScaleDisable(p);
	if (Adjust(p,&p->Regs[LCCR1],&p->Regs[LCCR2],UseBorder))
	{
		// PXA270 bug. need to enable/disable twice
		XScaleEnable(p,Phy);
		XScaleDisable(p);
	}
	XScaleEnable(p,Phy);
}

static int XScaleSetOrig(hires* p)
{
	if (XScaleGet(p)>=0)
		XScaleChange(p,p->OrigPhy,0);
	return ERR_NONE;
}

static int XScaleFlip(hires* p)
{
	uint32_t DescPhy = p->Buffer[p->Next].DescPhy;
	p->Buffer[p->Next].Desc->Next = DescPhy; // close chain

	if (!(p->Regs[LCCR0] & 1)) // is lcd enabled?
		return ERR_DEVICE_ERROR;

	if (XScaleGet(p)<0)
		XScaleChange(p,DescPhy,p->UseBorder);
	else
	{
		// modify last frames tail to new frame
		int Current = p->Next-1;
		if (Current<0)
			Current = p->BufferCount-1;
		p->Buffer[Current].Desc->Next = DescPhy;
	}
	return ERR_NONE;
}

//-------------------------------------------------------------------------------

static int OMAPGetOrig(hires* p)
{
	int ReTry = 0;
	do
	{
		ThreadSleep(1);
		if (++ReTry == 5) return ERR_NOT_SUPPORTED;
	}
	while (!(p->Regs[OMAP_CONTROL] & 1)); // again if lcd disabled

	p->PhyWidth = (p->Regs[OMAP_TIMING0] & 0x3FF)+1;
	p->PhyHeight = (p->Regs[OMAP_TIMING1] & 0x3FF)+1;

	if (p->Overlay.Output.Format.Video.Width > p->PhyWidth ||
		p->Overlay.Output.Format.Video.Height > p->PhyHeight)
		return ERR_NOT_SUPPORTED; // this shouldn't happen

	p->OrigPhy = (p->Regs2[OMAP_DMA_TOP_U] << 16) | p->Regs2[OMAP_DMA_TOP_L];
	p->OrigPhyEnd = (p->Regs2[OMAP_DMA_BOTTOM_U] << 16) | p->Regs2[OMAP_DMA_BOTTOM_L];

	if (!p->OrigPhy)
		return ERR_NOT_SUPPORTED; // this shouldn't happen

	// assuming physical direction and size is already correct
	p->Overlay.Output.Format.Video.Pitch = p->PhyWidth*2;
	if (p->UseBorder)
		p->Overlay.Output.Format.Video.Pitch += (p->Border[0]+p->Border[1])*2;
	return ERR_NONE;
}

static int OMAPAlloc(hires* p)
{
	hiresbuffer* Buffer = p->Buffer+p->BufferCount;
	if (!AllocBlock(p->SurfaceSize+16+OMAP_PAL_SIZE,&Buffer->Buffer,0,HEAP_ANYWR))
		return ERR_OUT_OF_MEMORY;
	Buffer->Surface = (uint8_t*)ALIGN16((uintptr_t)Buffer->Buffer.Ptr)+OMAP_PAL_SIZE;

	memset(Buffer->Surface-OMAP_PAL_SIZE,0,OMAP_PAL_SIZE); //clear palette
	Buffer->Surface[-OMAP_PAL_SIZE+1] = 0x40; //set 16bit mode framebuffer

	Buffer->SurfacePhy = MemVirtToPhy(Buffer->Surface);
	if (!Buffer->SurfacePhy)
	{
		FreeBlock(&Buffer->Buffer);
		return ERR_NOT_SUPPORTED;
	}
	return ERR_NONE;
}

static int OMAPGet(hires* p)
{
	uint32_t Phy = p->Regs2[OMAP_DMA_TOP_L] | (p->Regs2[OMAP_DMA_TOP_U] << 16);
	int n;

	for (n=0;n<p->BufferCount;++n)
		if (Phy == p->Buffer[n].SurfacePhy-OMAP_PAL_SIZE)
			return 0;

	p->OrigPhy = Phy;
	return -1; 
}

static void OMAPDisable(hires* p)
{
	int i;
	int n = p->Regs[OMAP_CONTROL];
	if (n & 1)
	{
		n &= ~1;
		p->Regs[OMAP_CONTROL] = n;

		for (i=0;i<50;++i)
		{
			if (p->Regs[OMAP_STATUS] & 1) 
				break;
			ThreadSleep(1);
		}
	}
}

static void OMAPEnable(hires* p)
{
	int v = p->Regs[OMAP_CONTROL];
	v |= 1;
	p->Regs[OMAP_CONTROL] = v;
	ThreadSleep(1);
}

static void OMAPChange(hires* p,uint32_t Phy,uint32_t PhyEnd,bool_t UseBorder)
{
	bool_t Old = (p->Regs[OMAP_CONTROL] & 1);
	OMAPDisable(p);
	Adjust(p,&p->Regs[OMAP_TIMING0],&p->Regs[OMAP_TIMING1],UseBorder);
	p->Regs2[OMAP_DMA_TOP_U] = (uint16_t)(Phy >> 16);
	p->Regs2[OMAP_DMA_TOP_L] = (uint16_t)(Phy);
	p->Regs2[OMAP_DMA_BOTTOM_U] = (uint16_t)(PhyEnd >> 16);
	p->Regs2[OMAP_DMA_BOTTOM_L] = (uint16_t)(PhyEnd);
	if (Old) OMAPEnable(p);
}

static int OMAPSetOrig(hires* p)
{
	if (OMAPGet(p)>=0)
		OMAPChange(p,p->OrigPhy,p->OrigPhyEnd,0);
	return ERR_NONE;
}

static int OMAPFlip(hires* p)
{
	if (!(p->Regs[OMAP_CONTROL] & 1)) // is lcd enabled?
		return ERR_DEVICE_ERROR;

	if (OMAPGet(p)<0)
		OMAPChange(p,p->Buffer[0].SurfacePhy-OMAP_PAL_SIZE,p->Buffer[0].SurfacePhy+p->SurfaceSize-2,p->UseBorder);
	return ERR_NONE;
}

//-------------------------------------------------------------------------------

static const datatable Params[] = 
{
	{ HIRES_TRIPLEBUFFER,			TYPE_BOOL, DF_SETUP|DF_CHECKLIST },
	{ HIRES_USEBORDER,				TYPE_BOOL, DF_SETUP|DF_CHECKLIST },
	{ HIRES_USEBORDER_INFO,			TYPE_LABEL, DF_SETUP },

	DATATABLE_END(HIRES_ID)
};

static int Enum(hires* p, int* No, datadef* Param)
{
	int Result;
	if (OverlayEnum(&p->Overlay,No,Param)==ERR_NONE)
		return ERR_NONE;
	Result = NodeEnumTable(No,Param,Params);
	if (Result==ERR_NONE)
	{
		if (Param->No == HIRES_TRIPLEBUFFER && (!p->Regs || !(p->Caps & CAPS_ARM_XSCALE)))
			Param->Flags |= DF_HIDDEN;
		if (Param->No == HIRES_USEBORDER && !p->Regs)
			Param->Flags |= DF_HIDDEN;
	}
	return Result;
}

static int Get(hires* p,int No,void* Data,int Size)
{
	int Result = OverlayGet(&p->Overlay,No,Data,Size);
	switch (No) 
	{
	case HIRES_TRIPLEBUFFER: GETVALUE(p->TripleBuffer,bool_t); break;
	case HIRES_USEBORDER: GETVALUE(p->UseBorder,bool_t); break;
	}
	return Result;
}

static int UpdateLowLevel(hires* p)
{
	p->LowLevelFailed = 0;
	Hide(p);
	BufferFree(p);
	OverlayUpdateFX(&p->Overlay,1);
	return ERR_NONE;
}

static int Set(hires* p,int No,const void* Data,int Size)
{
	int Result = OverlaySet(&p->Overlay,No,Data,Size);
	switch (No)
	{
	case HIRES_TRIPLEBUFFER: SETVALUECMP(p->TripleBuffer,bool_t,UpdateLowLevel(p),EqBool); break;
	case HIRES_USEBORDER: SETVALUECMP(p->UseBorder,bool_t,UpdateLowLevel(p),EqBool); break;
	}
	return Result;
}

extern bool_t SwapLandscape;

static int Create(hires* p)
{
	p->Overlay.Node.Enum = (nodeenum)Enum;
	p->Overlay.Node.Get = (nodeget)Get;
	p->Overlay.Node.Set = (nodeset)Set;
	p->Overlay.Init = (ovlfunc)Init;
	p->Overlay.Done = (ovldone)Done;
	p->Overlay.Reset = (ovlfunc)Reset;
	p->Overlay.Lock = (ovllock)Lock;
	p->Overlay.Unlock = (ovlfunc)Unlock;
	p->Overlay.UpdateShow = (ovlfunc)Show;
	p->Overlay.Update = (ovlfunc)Update;

	p->Caps = QueryPlatform(PLATFORM_CAPS);
	if (p->Caps & CAPS_ARM_XSCALE)
	{
		p->Regs = (volatile uint32_t*)MemPhyToVirt(XSCALE_LCD_BASE);
		if (p->Regs)
		{
			p->LowLevelGet = XScaleGet;
			p->LowLevelGetOrig = XScaleGetOrig;
			p->LowLevelSetOrig = XScaleSetOrig;
			p->LowLevelFlip = XScaleFlip;
			p->LowLevelAlloc = XScaleAlloc;
			p->Border[0] = 2;
			p->Border[1] = 2;
			p->Border[2] = p->Border[3] = 2;
		}
	}
	else
	{
		p->Regs = (volatile uint32_t*)MemPhyToVirt(OMAP_LCD_BASE);
		p->Regs2 = (volatile uint16_t*)MemPhyToVirt(OMAP_DMA_BASE);
		if (!p->Regs || !p->Regs2)
		{
			p->Regs = NULL;
			p->Regs2 = NULL;
		}
		else
		{
			p->LowLevelGet = OMAPGet;
			p->LowLevelGetOrig = OMAPGetOrig;
			p->LowLevelSetOrig = OMAPSetOrig;
			p->LowLevelFlip = OMAPFlip;
			p->LowLevelAlloc = OMAPAlloc;
			p->Border[0] = 14; // OMAP width has to be multiple of 16
			p->Border[1] = 2;
			p->Border[2] = p->Border[3] = 2;
		}
	}

	p->Model = QueryPlatform(PLATFORM_MODEL);
	// don't use triple buffering on 320x320 devices by default
	p->TripleBuffer = (Context()->StartUpMemory > 3*1024*1024) &&
		(p->Model==MODEL_TUNGSTEN_T3 ||
		p->Model==MODEL_TUNGSTEN_T5 ||
		p->Model==MODEL_PALM_TX ||
		p->Model==MODEL_LIFEDRIVE);

	// only device always supporting borderless mode is LifeDrive (?)
	p->UseBorder = 
		p->Model==MODEL_LIFEDRIVE ||
		p->Model==MODEL_PALM_TX;
	return ERR_NONE;
}

static const nodedef HIRES = 
{
	sizeof(hires)|CF_GLOBAL|CF_SETTINGS,
	HIRES_ID,
	OVERLAY_CLASS,
	PRI_DEFAULT+10,
	(nodecreate)Create,
};

void OverlayHIRES_Init() 
{
#ifdef HAVE_PALMONE_SDK
	if (SysLibFind(dexLibName, &DEX) == sysErrLibNotFound)
		SysLibLoad(dexLibType, dexLibCreator, &DEX);
	if (DEX != sysInvalidRefNum && SysLibOpen(DEX)!=errNone)
		DEX = sysInvalidRefNum;
#endif

	if (SysLibFind(kRotationMgrLibName, &RotM) == sysErrLibNotFound)
		SysLibLoad(kRotationMgrLibType, kRotationMgrLibCreator, &RotM);
	if (RotM != sysInvalidRefNum && SysLibOpen(RotM)!=errNone)
		RotM = sysInvalidRefNum;

	if (RotM != sysInvalidRefNum)
	{
		UInt32 Width,Height;
		if (RotationMgrAttributeGet(RotM,kRotationMgrAttrDisplayWidth,&Width)==errNone &&
			RotationMgrAttributeGet(RotM,kRotationMgrAttrDisplayHeight,&Height)==errNone &&
			Width < Height) // native portrait -> landscape modes are swapped by Mobile Stream
			SwapLandscape = 1;
	}

	NodeRegisterClass(&HIRES);
}

void OverlayHIRES_Done() 
{
	NodeUnRegisterClass(HIRES_ID);

#ifdef HAVE_PALMONE_SDK
	if (DEX != sysInvalidRefNum)
	{
		SysLibClose(DEX);
		DEX = sysInvalidRefNum;
	}
#endif
	if (RotM != sysInvalidRefNum)
	{
		SysLibClose(RotM);
		RotM = sysInvalidRefNum;
	}
}

#endif

⌨️ 快捷键说明

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