📄 overlay_hires.c
字号:
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 + -