gps/GPSResources/tcpmp/common/overlay/overlay_hires.c

897 lines
21 KiB
C
Raw Normal View History

2019-05-01 12:32:35 +00:00
/*****************************************************************************
*
* 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: overlay_hires.c 543 2006-01-07 22:06:24Z picard $
*
* The Core Pocket Media Player
* Copyright (c) 2004-2005 Gabor Kovacs
*
****************************************************************************/
#include "../common.h"
#if defined(TARGET_PALMOS)
#include "../palmos/pace.h"
#ifdef HAVE_PALMONE_SDK
#include <68K/System/PalmDisplayExtent.h>
static UInt16 DEX = sysInvalidRefNum;
#endif
#undef CPU_TYPE
#define CPU_TYPE CPU_68K
#include "RotationMgrLib.h"
static UInt16 RotM = sysInvalidRefNum;
typedef struct xscaledesc
{
uint32_t Next;
uint32_t Base;
uint32_t Id;
uint32_t Cmd;
} xscaledesc;
typedef struct hiresbuffer
{
block Buffer;
uint32_t DescPhy;
xscaledesc* Desc;
uint32_t SurfacePhy;
uint8_t* Surface;
} hiresbuffer;
#define MAGIC 0xBABE0000
#define XSCALE_LCD_BASE 0x44000000
#define LCCR0 (0x000/4)
#define LCCR1 (0x004/4)
#define LCCR2 (0x008/4)
#define LCCR3 (0x00C/4)
#define LCCR4 (0x010/4)
#define LCCR5 (0x014/4)
#define LCSR0 (0x038/4)
#define LCSR1 (0x034/4)
#define FBR0 (0x020/4)
#define FDADR0 (0x200/4)
#define FSADR0 (0x204/4)
#define FIDR0 (0x208/4)
#define OMAP_LCD_BASE 0xfffec000
#define OMAP_DMA_BASE 0xfffedb00
#define OMAP_PAL_SIZE 32
#define OMAP_CONTROL 0
#define OMAP_TIMING0 1
#define OMAP_TIMING1 2
#define OMAP_TIMING2 3
#define OMAP_STATUS 4
#define OMAP_DMA_CONTROL 0
#define OMAP_DMA_TOP_L 1
#define OMAP_DMA_TOP_U 2
#define OMAP_DMA_BOTTOM_L 3
#define OMAP_DMA_BOTTOM_U 4
typedef struct hires hires;
typedef int (*hiresfunc)(hires* This);
struct hires
{
overlay Overlay;
bool_t UseLocking;
bool_t Locked;
char* Bits;
int Offset;
int BufferCount;
hiresbuffer Buffer[3];
int Next;
int PhyWidth;
int PhyHeight;
int SurfaceSize;
int SurfaceOffset;
int OrigPitch;
uint32_t OrigPhy;
uint32_t OrigPhyEnd;
int Border[4];
volatile uint32_t* Regs;
volatile uint16_t* Regs2;
int Caps;
int Model;
bool_t UseBorder;
bool_t TripleBuffer;
bool_t LowLevelFailed;
hiresfunc LowLevelAlloc;
hiresfunc LowLevelGet;
hiresfunc LowLevelGetOrig;
hiresfunc LowLevelSetOrig;
hiresfunc LowLevelFlip;
};
static char* GetBits()
{
BitmapType* Bitmap;
WinHandle Win = WinGetDisplayWindow();
if (!Win)
return NULL;
Bitmap = WinGetBitmap(Win);
if (!Bitmap)
return NULL;
return BmpGetBits(Bitmap);
}
static bool_t ProcessRawInfo(video* Video,char* Bits,char* RawBits,int Width,int Height,int Pitch,int* Offset,bool_t MovedSIP)
{
int Dir = GetOrientation();
Video->Pitch = Pitch;
if (Width > Height) // native landscape device
Dir = CombineDir(Dir,DIR_SWAPXY|DIR_MIRRORUPDOWN,0);
// trust GetBits() if it's inside the Raw buffer
if (Bits >= RawBits && Bits < RawBits + Height*Pitch)
return 0;
if (!MovedSIP && Dir==0) // assuming working GetBits() with RotM in native mode
return 0;
if (Dir & DIR_SWAPXY)
SwapInt(&Video->Width,&Video->Height);
if (Width > Height) // native landscape device
{
if ((Dir & DIR_SWAPXY)==0 ? GetHandedness() : (Dir & DIR_MIRRORLEFTRIGHT)!=0)
*Offset = (Width-Video->Width)*(Video->Pixel.BitCount >> 3);
}
else
{
// native portrait device
if ((Dir & DIR_SWAPXY) && MovedSIP) // don't adjust for RotM (SIP stays on native bottom)
{
// assuming taskbar and SIP is in the upper part of the screen in landscape mode
if (Height > 320+32 && Video->Height <= 320+32 && DIASupported() && !DIAGet(DIA_SIP))
Height = 320+32; // closed slider on Tungsten T3
*Offset = (Height-Video->Height)*Pitch;
}
}
Video->Direction = Dir;
return 1;
}
char* QueryScreen(video* Video,int* Offset,int* Mode)
{
char* Bits = GetBits();
QueryDesktop(Video);
*Offset = 0;
if (Mode) *Mode = 0;
#ifdef HAVE_PALMONE_SDK
if (DEX != sysInvalidRefNum)
{
UInt16 Pitch;
Coord Width,Height;
char* RawBits = DexGetDisplayAddress(DEX);
if (RawBits)
{
DexGetDisplayDimensions(DEX,&Width,&Height,&Pitch);
if (ProcessRawInfo(Video,Bits,RawBits,Width,Height,Pitch,Offset,1))
{
if (Mode) *Mode = 1;
return RawBits;
}
}
}
#endif
if (RotM != sysInvalidRefNum)
{
UInt32 RawBits;
UInt32 Width,Height,Pitch;
if (RotationMgrAttributeGet(RotM,kRotationMgrAttrDisplayAddress,&RawBits)==errNone && RawBits &&
RotationMgrAttributeGet(RotM,kRotationMgrAttrDisplayWidth,&Width)==errNone &&
RotationMgrAttributeGet(RotM,kRotationMgrAttrDisplayHeight,&Height)==errNone &&
RotationMgrAttributeGet(RotM,kRotationMgrAttrDisplayRowBytes,&Pitch)==errNone &&
ProcessRawInfo(Video,Bits,(char*)RawBits,Width,Height,Pitch,Offset,0))
{
if (Mode) *Mode = 2;
return (char*)RawBits;
}
}
if (Video->Pitch < Video->Width*(Video->Pixel.BitCount/8))
return NULL;
return Bits;
}
static int BufferFree(hires* p)
{
int n;
for (n=0;n<p->BufferCount;++n)
FreeBlock(&p->Buffer[n].Buffer);
p->BufferCount = 0;
memset(&p->Buffer,0,sizeof(p->Buffer));
return ERR_NONE;
}
static int Init(hires* p)
{
int Mode;
p->Overlay.SetFX = BLITFX_AVOIDTEARING;
p->UseLocking = 0;
if (QueryPlatform(PLATFORM_MODEL)==MODEL_ZODIAC)
{
int Dir = GetOrientation();
if (Dir & DIR_SWAPXY)
{
p->Overlay.SetFX |= BLITFX_VMEMROTATED;
if (Dir & DIR_MIRRORLEFTRIGHT)
p->Overlay.SetFX |= BLITFX_VMEMUPDOWN;
}
}
p->Bits = QueryScreen(&p->Overlay.Output.Format.Video,&p->Offset,&Mode);
if (!p->Bits)
return ERR_INVALID_PARAM;
if (!Mode)
p->Bits = NULL; // use GetBits() during Lock()
p->OrigPitch = p->Overlay.Output.Format.Video.Pitch;
p->Next = 0;
p->LowLevelFailed = 0;
return ERR_NONE;
}
static void Hide(hires* p)
{
if (p->Overlay.Overlay)
{
p->LowLevelSetOrig(p);
p->Overlay.Overlay = 0;
p->Overlay.Output.Format.Video.Pitch = p->OrigPitch;
}
}
static void Done(hires* p)
{
Hide(p);
BufferFree(p);
}
static int UpdateAlloc(hires* p)
{
int MaxCount = 1;
if (p->TripleBuffer)
MaxCount = 3;
if (p->UseBorder)
{
p->SurfaceSize = (p->PhyWidth+p->Border[0]+p->Border[1])*(p->PhyHeight+p->Border[2]+p->Border[3])*2;
p->SurfaceOffset = ((p->PhyWidth+p->Border[0]+p->Border[1])*p->Border[2]+p->Border[0])*2;
}
else
{
p->SurfaceSize = p->PhyWidth*p->PhyHeight*2;
p->SurfaceOffset = 0;
}
while (p->BufferCount<MaxCount)
if (p->LowLevelAlloc(p) == ERR_NONE)
++p->BufferCount;
else
break;
if (p->BufferCount==2)
{
FreeBlock(&p->Buffer[1].Buffer);
--p->BufferCount;
}
if (!p->BufferCount)
return ERR_OUT_OF_MEMORY;
return ERR_NONE;
}
static int Update(hires* p)
{
if (p->Overlay.FullScreenViewport && (p->UseBorder || p->TripleBuffer) &&
!p->LowLevelFailed && (p->Overlay.Overlay || (p->LowLevelGetOrig && p->LowLevelGetOrig(p)==ERR_NONE)))
{
p->Overlay.Overlay = 1;
if (UpdateAlloc(p)!=ERR_NONE || (p->BufferCount<3 && !p->UseBorder))
{
Hide(p);
p->LowLevelFailed = 1;
BufferFree(p);
}
else
{
int n;
for (n=0;n<p->BufferCount;++n)
memset(p->Buffer[n].Surface,0,p->SurfaceSize);
}
}
else
Hide(p);
p->Overlay.DoPowerOff = p->Overlay.Overlay;
return OverlayUpdateAlign(&p->Overlay);
}
static int Show(hires* p)
{
if (!p->Overlay.Show && p->Overlay.Overlay)
{
p->LowLevelSetOrig(p);
p->Next = 0;
}
return ERR_NONE;
}
static int Reset(hires* p)
{
int Pitch = p->Overlay.Output.Format.Video.Pitch;
Init(p);
if (p->Overlay.Overlay)
p->Overlay.Output.Format.Video.Pitch = Pitch;
return ERR_NONE;
}
static int Lock(hires* p, planes Planes, bool_t OnlyAligned)
{
if (p->Overlay.Overlay)
{
int Next = p->Next+1;
if (Next == p->BufferCount)
Next = 0;
// use new buffer only if it's not the current
if (p->LowLevelGet(p) != Next)
p->Next = Next;
Planes[0] = p->Buffer[p->Next].Surface + p->SurfaceOffset;
}
else
if (p->UseLocking && p->Overlay.CurrTime>=0 && // don't use locking with benchmark
(Planes[0] = WinScreenLock(p->Overlay.Dirty?winLockCopy:winLockDontCare)) != NULL)
p->Locked = 1;
else
if (p->Bits)
Planes[0] = p->Bits + p->Offset;
else
{
char* Bits = GetBits();
if (!Bits)
return ERR_DEVICE_ERROR;
Planes[0] = Bits;
}
return ERR_NONE;
}
static int Unlock(hires* p)
{
if (p->Overlay.Overlay)
return p->LowLevelFlip(p);
else
if (p->Locked)
WinScreenUnlock();
return ERR_NONE;
}
//-------------------------------------------------------------------------------
static int XScaleGetOrig(hires* p)
{
int ReTry = 0;
do
{
ThreadSleep(2);
if (++ReTry == 5) return ERR_NOT_SUPPORTED;
}
while (!(p->Regs[LCCR0] & 1)); // again if lcd disabled
p->PhyWidth = (p->Regs[LCCR1] & 0x3FF)+1;
p->PhyHeight = (p->Regs[LCCR2] & 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->Regs[FDADR0];
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 XScaleAlloc(hires* p)
{
hiresbuffer* Buffer = p->Buffer+p->BufferCount;
if (!AllocBlock(16+sizeof(xscaledesc)+256+p->SurfaceSize,&Buffer->Buffer,0,HEAP_ANYWR))
return ERR_OUT_OF_MEMORY;
Buffer->Desc = (xscaledesc*)ALIGN16((uintptr_t)Buffer->Buffer.Ptr);
Buffer->DescPhy = MemVirtToPhy(Buffer->Desc);
if (!Buffer->DescPhy)
{
FreeBlock(&Buffer->Buffer);
return ERR_NOT_SUPPORTED;
}
Buffer->Surface = (uint8_t*)Buffer->Desc+sizeof(xscaledesc)+256;
Buffer->SurfacePhy = Buffer->DescPhy+sizeof(xscaledesc)+256;
Buffer->Desc->Base = Buffer->SurfacePhy;
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