gps/GPSResources/tcpmpVerOld/sonyhhe/ge2d.c

425 lines
11 KiB
C
Executable File

/*****************************************************************************
*
* 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: ge2d.c 543 2006-01-07 22:06:24Z picard $
*
* The Core Pocket Media Player
* Copyright (c) 2004-2005 Gabor Kovacs
*
* Big thanks to Mobile Stream (http://www.mobile-stream.com)
* for reverse enginerring the GE2D interface
*
****************************************************************************/
#include "../common/common.h"
#if defined(TARGET_PALMOS)
#include "../common/palmos/pace.h"
#if defined(_M_IX86)
//#define GE2DEMU
#endif
#define GE2D_ID FOURCC('G','E','2','D')
#define sonyGE2DLibType 'aexo'
#define sonyGE2DLibCreator 'SeGE'
enum {
sonyGE2DFormatYCbCr422 = 1,
sonyGE2DFormatYCbCr422Planar,
sonyGE2DFormatYCbCr420Planar
};
#define sonyGE2DBlitPixelCoord 0x2
typedef UInt32 GE2DInsnType;
typedef struct GE2DBitmapType
{
UInt8 format; /* 0x00 */
UInt8 zero; /* 0x01 */
UInt16 pitch; /* 0x02 */
UInt16 chromaPitch;/* 0x04 */
UInt16 width; /* 0x06 */
UInt16 height; /* 0x08 */
UInt16 unused; /* 0x0a */
void * plane1P; /* 0x0c: Y */
void * plane2P; /* 0x10: Cb */
void * plane3P; /* 0x14: Cr */
} GE2DBitmapType;
typedef struct GE2DLibAPIType
{
Err (*GE2DLibOpen)();
Err (*GE2DLibClose)();
Err (*GE2DProgramBlit)(GE2DInsnType *,
void *, UInt16,
const void *, UInt16,
UInt16, UInt16, UInt8);
Err (*GE2DBlitWithAlpha)(void *, UInt16,
const void *, UInt16,
UInt16, UInt16, UInt8);
Err (*GE2DBlit)(void *dstBitsP, UInt16 dstPitch,
const void *srcBitsP, UInt16 srcPitch,
UInt16 srcWidth, UInt16 srcHeight, UInt8 ff);
Err (*GE2DBlitWithMask)(void *dstBitsP, UInt16 dstPitch,
const void *srcBitsP, UInt16 srcPitch,
UInt16 srcWidth, UInt16 srcHeight,
UInt8 ff, const void *maskBitsP);
Err (*GE2DBlitBitmap)(void *dstP, Coord left, Coord top,
UInt16 dstWidth, UInt16 dstHeight, GE2DBitmapType *);
Err (*GE2DConvertBitmap)(GE2DBitmapType *, GE2DBitmapType *);
Err (*GE2DProgramBlitBitmapWithMask)(GE2DInsnType *programP,
void *dstP, Coord left, Coord top,
UInt16 dstWidth, UInt16 dstHeight,
GE2DBitmapType *bmpP, const void *p7);
Err (*GE2DProgramBlitBitmap)(GE2DInsnType *programP,
void *dstP, Coord left, Coord top,
UInt16 dstWidth, UInt16 dstHeight, GE2DBitmapType *bmpP);
Err (*GE2DScaleBitmap)(GE2DBitmapType *dstBmpP, GE2DBitmapType *srcBmpP);
Err (*GE2DShowOverlay)(Coord left, Coord top, GE2DBitmapType *);
Err (*GE2DHideOverlay)();
Err (*GE2DRunProgram)(const GE2DInsnType *programP);
Err (*GE2DRunProgram2)(const GE2DInsnType *programP);
Err (*GE2D_60)(UInt16 x, UInt16 y);
Err (*GE2D_64)();
Err (*GE2D_68)(void *);
Err (*GE2D_72)(RectangleType *);
Err (*GE2D_76)(FormType *);
Err (*GE2D_80)(Boolean);
Err (*GE2D_84)();
Err (*GE2DSetLock)(Boolean lock);
} GE2DLibAPIType;
typedef struct ge2d
{
overlay p;
point Offset;
GE2DBitmapType Buffer;
GE2DBitmapType Scale;
int BufferSize;
int ScaleSize;
rect OverlayRect;
blitfx SoftFX;
char* Bits;
} ge2d;
static UInt32 LibRef = 0;
#if defined(GE2DEMU)
#include "ge2demu.c"
#else
static GE2DLibAPIType API;
#endif
extern char* QueryScreen(video* Video,int* Offset,int* Mode);
static void FreeBuffer(GE2DBitmapType* p,int* Allocated)
{
free(p->plane1P);
free(p->plane2P);
free(p->plane3P);
memset(p,0,sizeof(GE2DBitmapType));
*Allocated = 0;
}
static bool_t AllocBuffer(GE2DBitmapType* p,int w,int h,int* Allocated)
{
int size;
w = (w+1) & ~1;
h = (h+1) & ~1;
size = w*h;
p->format = sonyGE2DFormatYCbCr420Planar;
p->zero = 0;
p->pitch = (UInt16)w;
p->chromaPitch = (UInt16)(w >> 1);
p->width = (UInt16)w;
p->height = (UInt16)h;
p->unused = 0;
if (*Allocated < size)
{
free(p->plane1P);
free(p->plane2P);
free(p->plane3P);
p->plane1P = malloc(size);
p->plane2P = malloc(size/4);
p->plane3P = malloc(size/4);
if (!p->plane1P || !p->plane2P || !p->plane3P)
{
FreeBuffer(p,Allocated);
return 0;
}
*Allocated = size;
}
memset(p->plane1P,0,size);
memset(p->plane2P,128,size/4);
memset(p->plane2P,128,size/4);
return 1;
}
static int GetMode(ge2d* p)
{
int Offset;
p->Bits = QueryScreen(&p->p.Output.Format.Video,&Offset,NULL);
if (!p->p.Output.Format.Video.Pitch || !p->p.Output.Format.Video.Pixel.BitCount)
return ERR_INVALID_PARAM;
p->Offset.x = (Offset % p->p.Output.Format.Video.Pitch) / (p->p.Output.Format.Video.Pixel.BitCount/8);
p->Offset.y = Offset / p->p.Output.Format.Video.Pitch;
return ERR_NONE;
}
static int Init(ge2d* p)
{
//p->p.SetFX = BLITFX_AVOIDTEARING;
p->p.Overlay = 0;
if (GetMode(p) != ERR_NONE)
return ERR_INVALID_PARAM;
if (!AllocBuffer(&p->Buffer,p->p.Input.Format.Video.Width,p->p.Input.Format.Video.Height,&p->BufferSize))
return ERR_OUT_OF_MEMORY;
return ERR_NONE;
}
static void Done(ge2d* p)
{
FreeBuffer(&p->Buffer,&p->BufferSize);
FreeBuffer(&p->Scale,&p->ScaleSize);
}
static int UpdateOverlay(ge2d* p)
{
if (p->p.Overlay)
{
if (p->p.Show)
{
int x = p->p.DstAlignedRect.x;
int y = p->p.DstAlignedRect.y;
x += p->Offset.x;
y += p->Offset.y;
PALMCALL3(API.GE2DShowOverlay,(Coord)x,(Coord)y,p->Scale.format? &p->Scale : &p->Buffer);
}
else
PALMCALL0(API.GE2DHideOverlay);
}
return ERR_NONE;
}
static int Update(ge2d* p)
{
blitfx OvlFX = p->p.FX;
video Buffer;
if (p->p.Overlay)
PALMCALL0(API.GE2DHideOverlay);
p->SoftFX = p->p.FX;
p->SoftFX.ScaleX = SCALE_ONE; // scale handled by hardware
p->SoftFX.ScaleY = SCALE_ONE;
OvlFX.Direction = 0;
//align to 100%
if (OvlFX.ScaleX > SCALE_ONE-(SCALE_ONE/16) && OvlFX.ScaleX < SCALE_ONE+(SCALE_ONE/16) &&
OvlFX.ScaleY > SCALE_ONE-(SCALE_ONE/16) && OvlFX.ScaleY < SCALE_ONE+(SCALE_ONE/16))
{
OvlFX.ScaleX = SCALE_ONE;
OvlFX.ScaleY = SCALE_ONE;
}
if (p->SoftFX.Direction & DIR_SWAPXY)
SwapInt(&OvlFX.ScaleX,&OvlFX.ScaleY);
memset(&Buffer,0,sizeof(Buffer));
Buffer.Pixel.Flags = PF_YUV420;
Buffer.Width = p->p.Input.Format.Video.Width;
Buffer.Height = p->p.Input.Format.Video.Height;
Buffer.Direction = CombineDir(p->p.InputDirection,p->p.OrigFX.Direction,p->p.Output.Format.Video.Direction);
if (Buffer.Direction & DIR_SWAPXY)
SwapInt(&Buffer.Width,&Buffer.Height);
Buffer.Pitch = Buffer.Width;
for (;;)
{
VirtToPhy(&p->p.Viewport,&p->p.DstAlignedRect,&p->p.Output.Format.Video);
VirtToPhy(NULL,&p->OverlayRect,&Buffer);
AnyAlign(&p->p.DstAlignedRect, &p->OverlayRect, &OvlFX, 2, 1, SCALE_ONE/256, SCALE_ONE*256);
if ((OvlFX.ScaleX != SCALE_ONE || OvlFX.ScaleY != SCALE_ONE) &&
(p->p.DstAlignedRect.Width != p->OverlayRect.Width && p->p.DstAlignedRect.Height != p->OverlayRect.Height))
{
if (!AllocBuffer(&p->Scale,p->p.DstAlignedRect.Width,p->p.DstAlignedRect.Height,&p->ScaleSize))
{
// fallback to 100%
OvlFX.ScaleX = SCALE_ONE;
OvlFX.ScaleY = SCALE_ONE;
continue;
}
}
else
FreeBuffer(&p->Scale,&p->ScaleSize);
break;
}
VirtToPhy(NULL,&p->p.SrcAlignedRect,&p->p.Input.Format.Video);
BlitRelease(p->p.Soft);
p->p.Soft = BlitCreate(&Buffer,&p->p.Input.Format.Video,&p->SoftFX,&p->p.Caps);
BlitAlign(p->p.Soft,&p->OverlayRect,&p->p.SrcAlignedRect);
if (!AllocBuffer(&p->Buffer,p->OverlayRect.Width,p->OverlayRect.Height,&p->BufferSize))
return ERR_OUT_OF_MEMORY;
Buffer.Width = p->OverlayRect.Width;
Buffer.Height = p->OverlayRect.Height;
Buffer.Pitch = Buffer.Width;
p->OverlayRect.x = 0;
p->OverlayRect.y = 0;
BlitRelease(p->p.Soft);
p->p.Soft = BlitCreate(&Buffer,&p->p.Input.Format.Video,&p->SoftFX,&p->p.Caps);
BlitAlign(p->p.Soft,&p->OverlayRect,&p->p.SrcAlignedRect);
if (!p->Scale.format) // no scaling -> adjust dst rectangle with soft yuv blitting alignement
{
p->p.DstAlignedRect.x += (p->p.DstAlignedRect.Width - p->OverlayRect.Width) >> 1;
p->p.DstAlignedRect.y += (p->p.DstAlignedRect.Height - p->OverlayRect.Height) >> 1;
p->p.DstAlignedRect.Width = p->OverlayRect.Width;
p->p.DstAlignedRect.Height = p->OverlayRect.Height;
}
PhyToVirt(&p->p.DstAlignedRect,&p->p.GUIAlignedRect,&p->p.Output.Format.Video);
return UpdateOverlay(p);
}
static INLINE void FlushDCache(void *p, int n)
{
SonyCleanDCache(p,n);
SonyInvalidateDCache(p,n);
}
static int Blit(ge2d* p, const constplanes Data, const constplanes DataLast )
{
int n;
planes Planes;
Planes[0] = p->Buffer.plane1P;
Planes[1] = p->Buffer.plane3P;
Planes[2] = p->Buffer.plane2P;
BlitImage(p->p.Soft,Planes,Data,DataLast,-1,-1);
n = p->Buffer.width * p->Buffer.height;
FlushDCache(Planes[0],n);
FlushDCache(Planes[1],n/4);
FlushDCache(Planes[2],n/4);
if (p->Scale.format)
PALMCALL2(API.GE2DScaleBitmap,&p->Scale,&p->Buffer);
if (!p->p.Overlay)
{
PALMCALL6(API.GE2DBlitBitmap,p->Bits,
(Coord)(p->p.DstAlignedRect.x + p->Offset.x),
(Coord)(p->p.DstAlignedRect.y + p->Offset.y),
(Coord)(p->p.Output.Format.Video.Pitch>>1),(Coord)p->p.Output.Format.Video.Height,
p->Scale.format? &p->Scale : &p->Buffer);
}
return ERR_NONE;
}
static int Reset(ge2d* p)
{
return GetMode(p);
}
static int Create(ge2d* p)
{
p->p.Init = (ovlfunc)Init;
p->p.Done = (ovldone)Done;
p->p.Reset = (ovlfunc)Reset;
p->p.Blit = (ovlblit)Blit;
p->p.Update = (ovlfunc)Update;
p->p.UpdateShow = (ovlfunc)UpdateOverlay;
QueryDesktop(&p->p.Output.Format.Video);
return ERR_NONE;
}
static const nodedef GE2D =
{
sizeof(ge2d)|CF_GLOBAL,
GE2D_ID,
OVERLAY_CLASS,
PRI_DEFAULT+50,
(nodecreate)Create,
};
void GE2D_Init()
{
#if !defined(GE2DEMU)
Err err;
// UInt32 CompanyID;
// FtrGet(sysFtrCreator, sysFtrNumOEMCompanyID, &CompanyID);
// if (CompanyID != 'sony')
// return;
err = SysFindModule(sonyGE2DLibType, sonyGE2DLibCreator, 0, 0, &LibRef);
if (err)
err = SysLoadModule(sonyGE2DLibType, sonyGE2DLibCreator, 0, 0, &LibRef);
if (err)
return;
if (SysGetEntryAddresses(LibRef, 0, 22, (void **)(void *)&API) != errNone)
return;
#endif
PALMCALL0(API.GE2DLibOpen);
NodeRegisterClass(&GE2D);
}
void GE2D_Done()
{
NodeUnRegisterClass(GE2D_ID);
if (LibRef)
{
PALMCALL0(API.GE2DLibClose);
//SysUnloadModule(LibRef);
LibRef = 0;
}
}
#else
void GE2D_Init() {}
void GE2D_Done() {}
#endif