📄 overlay_hires.c
字号:
/*****************************************************************************
*
* 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -