/***************************************************************************** * * 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;nBufferCount;++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->BufferCountLowLevelAlloc(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;nBufferCount;++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;nBufferCount;++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