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

503 lines
13 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_gapi.c 543 2006-01-07 22:06:24Z picard $
*
* The Core Pocket Media Player
* Copyright (c) 2004-2005 Gabor Kovacs
*
****************************************************************************/
#include "../common.h"
#ifdef TARGET_WINCE
#define WIN32_LEAN_AND_MEAN
#ifndef STRICT
#define STRICT
#endif
#include <windows.h>
typedef struct GXDisplayProperties
{
int cxWidth;
int cyHeight;
int cbxPitch;
int cbyPitch;
int cBPP;
int ffFormat;
} GXDisplayProperties;
#define SHFS_SHOWTASKBAR 0x0001
#define SHFS_HIDETASKBAR 0x0002
#define SHFS_SHOWSIPBUTTON 0x0004
#define SHFS_HIDESIPBUTTON 0x0008
#define SHFS_SHOWSTARTICON 0x0010
#define SHFS_HIDESTARTICON 0x0020
#define GX_FULLSCREEN 0x01
#define kfLandscape 0x08
#define kfPalette 0x10
#define kfDirect 0x20
#define kfDirect555 0x40
#define kfDirect565 0x80
#define kfDirect888 0x100
#define kfDirect444 0x200
#define kfDirectInverted 0x400
typedef struct gapi
{
overlay Overlay;
bool_t Windows;
bool_t Opened;
bool_t DRAM;
void* Wnd;
int AdjustPtr;
uint8_t* DirectPtr;
uint8_t* Pointer;
HMODULE GX;
HMODULE AygShell;
GXDisplayProperties Info;
int (*GXOpenDisplay)(HWND hWnd, DWORD dwFlags);
int (*GXCloseDisplay)();
void* (*GXBeginDraw)();
int (*GXEndDraw)();
GXDisplayProperties (*GXGetDisplayProperties)();
int (*GXSetViewport)(DWORD dwTop, DWORD dwHeight, DWORD, DWORD);
BOOL (*GXIsDisplayDRAMBuffer)();
BOOL (WINAPI* SHFullScreen)(HWND, DWORD);
} gapi;
static const datatable Params[] =
{
{ GAPI_WIDTH, TYPE_INT, DF_SETUP | DF_RDONLY | DF_HIDDEN },
{ GAPI_HEIGHT, TYPE_INT, DF_SETUP | DF_RDONLY | DF_HIDDEN },
{ GAPI_PITCHX, TYPE_INT, DF_SETUP | DF_RDONLY | DF_HIDDEN },
{ GAPI_PITCHY, TYPE_INT, DF_SETUP | DF_RDONLY | DF_HIDDEN },
{ GAPI_BPP, TYPE_INT, DF_SETUP | DF_RDONLY | DF_HIDDEN },
{ GAPI_FORMAT, TYPE_INT, DF_SETUP | DF_RDONLY|DF_HEX | DF_HIDDEN },
{ GAPI_DRAM, TYPE_BOOL, DF_SETUP | DF_RDONLY | DF_HIDDEN },
{ GAPI_POINTER, TYPE_INT, DF_SETUP | DF_RDONLY|DF_HEX | DF_HIDDEN },
DATATABLE_END(GAPI_ID)
};
static int Enum(gapi* p, int* No, datadef* Param)
{
if (OverlayEnum(&p->Overlay,No,Param)==ERR_NONE)
return ERR_NONE;
return NodeEnumTable(No,Param,Params);
}
static int Get(gapi* p,int No,void* Data,int Size)
{
int Result = OverlayGet(&p->Overlay,No,Data,Size);
switch (No)
{
case GAPI_WIDTH: GETVALUE(p->Info.cxWidth,int); break;
case GAPI_HEIGHT: GETVALUE(p->Info.cyHeight,int); break;
case GAPI_PITCHX: GETVALUE(p->Info.cbxPitch,int); break;
case GAPI_PITCHY: GETVALUE(p->Info.cbyPitch,int); break;
case GAPI_BPP: GETVALUE(p->Info.cBPP,int); break;
case GAPI_FORMAT: GETVALUE(p->Info.ffFormat,int); break;
case GAPI_DRAM: GETVALUE(p->DRAM,bool_t); break;
case GAPI_POINTER: GETVALUE((int)p->Pointer,int); break;
}
return Result;
}
static bool_t LoadDriver(gapi* p)
{
HMODULE GX;
tchar_t Path[MAXPATH];
if (p->Windows)
GetSystemPath(Path,TSIZEOF(Path),T("gx.dll"));
else
tcscpy_s(Path,TSIZEOF(Path),T("gx.dll"));
if ((GX = LoadLibrary(Path))==NULL)
{
if (!p->Windows)
{
p->Windows = 1;
return LoadDriver(p);
}
return 0;
}
if (p->GX)
FreeLibrary(p->GX);
p->GX = GX;
GetProc(&p->GX,&p->GXOpenDisplay,T("?GXOpenDisplay@@YAHPAUHWND__@@K@Z"),0);
GetProc(&p->GX,&p->GXCloseDisplay,T("?GXCloseDisplay@@YAHXZ"),0);
GetProc(&p->GX,&p->GXBeginDraw,T("?GXBeginDraw@@YAPAXXZ"),0);
GetProc(&p->GX,&p->GXEndDraw,T("?GXEndDraw@@YAHXZ"),0);
GetProc(&p->GX,&p->GXGetDisplayProperties,T("?GXGetDisplayProperties@@YA?AUGXDisplayProperties@@XZ"),0);
GetProc(&p->GX,&p->GXSetViewport,T("?GXSetViewport@@YAHKKKK@Z"),1);
GetProc(&p->GX,&p->GXIsDisplayDRAMBuffer,T("?GXIsDisplayDRAMBuffer@@YAHXZ"),1);
return p->GX!=NULL;
}
static int Init(gapi* p)
{
GXDisplayProperties Info;
video GDI;
int Caps = QueryPlatform(PLATFORM_CAPS);
if (!p->Opened)
{
ShowError(p->Overlay.Node.Class,GAPI_ID,GAPI_OPEN_ERROR);
return ERR_NOT_SUPPORTED; // don't show device error
}
Info = p->Info;
if (Info.cxWidth == GetSystemMetrics(SM_CXSCREEN) &&
Info.cyHeight < GetSystemMetrics(SM_CYSCREEN))
{
// HPC devices we need the taskbar counted in the height too
RECT WorkArea;
SystemParametersInfo(SPI_GETWORKAREA,0,&WorkArea,0);
if (WorkArea.top == 0 && WorkArea.bottom == Info.cyHeight)
Info.cyHeight = GetSystemMetrics(SM_CYSCREEN);
}
p->Overlay.Output.Format.Video.Direction = 0;
p->Overlay.Output.Format.Video.Aspect = ASPECT_ONE;
if (Info.ffFormat & kfPalette)
{
QueryDesktop(&GDI);
p->Overlay.Output.Format.Video.Pixel.Flags = PF_PALETTE;
p->Overlay.Output.Format.Video.Pixel.BitCount = Info.cBPP;
p->Overlay.Output.Format.Video.Pixel.Palette = GDI.Pixel.Palette;
}
else
if (Info.ffFormat & kfDirect444)
DefaultRGB(&p->Overlay.Output.Format.Video.Pixel,Info.cBPP,4,4,4,0,0,0);
else
if (Info.ffFormat & kfDirect565)
{
if (Caps & CAPS_ONLY12BITRGB)
DefaultRGB(&p->Overlay.Output.Format.Video.Pixel,Info.cBPP,4,4,4,1,2,1);
else
DefaultRGB(&p->Overlay.Output.Format.Video.Pixel,Info.cBPP,5,6,5,0,0,0);
}
else
if (Info.ffFormat & kfDirect555)
DefaultRGB(&p->Overlay.Output.Format.Video.Pixel,Info.cBPP,5,5,5,0,0,0);
else
if (Info.ffFormat & kfDirect888)
DefaultRGB(&p->Overlay.Output.Format.Video.Pixel,Info.cBPP,8,8,8,0,0,0);
if (Info.ffFormat & kfDirectInverted)
p->Overlay.Output.Format.Video.Pixel.Flags |= PF_INVERTED;
// get signed x/y pitches in bits
Info.cbxPitch <<= 3;
Info.cbyPitch <<= 3;
// one pitch is probably zero when BPP<8
if (!Info.cbxPitch)
if (Info.cbyPitch < 0)
Info.cbxPitch = -Info.cBPP;
else
Info.cbxPitch = Info.cBPP;
else
if (!Info.cbyPitch)
if (Info.cbxPitch < 0)
Info.cbyPitch = Info.cBPP;
else
Info.cbyPitch = -Info.cBPP;
// one of the pitches absolute value must be BPP
if (abs(Info.cbyPitch) < abs(Info.cbxPitch))
{
if (abs(Info.cbxPitch) < Info.cyHeight*Info.cBPP &&
abs(Info.cbxPitch) >= Info.cxWidth*Info.cBPP) //swapped gapi resolution
SwapInt(&Info.cxWidth,&Info.cyHeight);
Info.ffFormat |= kfLandscape;
Info.cbyPitch = Info.cbyPitch<0 ? -Info.cBPP : Info.cBPP;
}
else
{
if (abs(Info.cbyPitch) < Info.cxWidth*Info.cBPP &&
abs(Info.cbyPitch) >= Info.cyHeight*Info.cBPP) //swapped gapi resolution
SwapInt(&Info.cxWidth,&Info.cyHeight);
Info.ffFormat &= ~kfLandscape;
Info.cbxPitch = Info.cbxPitch<0 ? -Info.cBPP : Info.cBPP;
}
p->Overlay.Output.Format.Video.Width = Info.cxWidth;
p->Overlay.Output.Format.Video.Height = Info.cyHeight;
// we need the physical start of the framebuffer
p->AdjustPtr = 0;
if (Info.cbxPitch<0)
p->AdjustPtr += (Info.cbxPitch * (Info.cxWidth-1)) >> 3;
if (Info.cbyPitch<0)
p->AdjustPtr += (Info.cbyPitch * (Info.cyHeight-1)) >> 3;
if (Info.ffFormat & kfLandscape)
{
p->Overlay.Output.Format.Video.Direction |= DIR_SWAPXY;
p->Overlay.Output.Format.Video.Pitch = abs(Info.cbxPitch) >> 3;
SwapInt(&p->Overlay.Output.Format.Video.Width,&p->Overlay.Output.Format.Video.Height);
if (Info.cbxPitch<0)
p->Overlay.Output.Format.Video.Direction |= DIR_MIRRORUPDOWN;
if (Info.cbyPitch<0)
p->Overlay.Output.Format.Video.Direction |= DIR_MIRRORLEFTRIGHT;
}
else
{
p->Overlay.Output.Format.Video.Pitch = abs(Info.cbyPitch) >> 3;
if (Info.cbxPitch<0)
p->Overlay.Output.Format.Video.Direction |= DIR_MIRRORLEFTRIGHT;
if (Info.cbyPitch<0)
p->Overlay.Output.Format.Video.Direction |= DIR_MIRRORUPDOWN;
}
if (!p->DRAM)
{
p->Overlay.SetFX = BLITFX_AVOIDTEARING;
if ((Info.cxWidth > Info.cyHeight) && (Caps & CAPS_PORTRAIT))
p->Overlay.SetFX |= BLITFX_VMEMROTATED;
if ((Info.cyHeight > Info.cxWidth) && (Caps & CAPS_LANDSCAPE))
p->Overlay.SetFX |= BLITFX_VMEMROTATED;
}
else
p->Overlay.ClearFX = BLITFX_ONLYDIFF;
// wm2003se gapi emulation?
if (QueryPlatform(PLATFORM_VER) >= 421)
{
if (p->Overlay.Output.Format.Video.Width == 240 && p->Overlay.Output.Format.Video.Height == 320 && p->Overlay.Output.Format.Video.Pitch == 640)
p->Overlay.Output.Format.Video.Pitch = 480;
}
if (Info.cxWidth == 240 && Info.cyHeight == 320)
AdjustOrientation(&p->Overlay.Output.Format.Video,0);
return ERR_NONE;
}
static void Done(gapi* p)
{
}
static int Reset(gapi* p)
{
Done(p);
Init(p);
return ERR_NONE;
}
static int Lock(gapi* p, planes Planes, bool_t OnlyAligned)
{
if (!p->Opened)
return ERR_INVALID_PARAM;
if (p->DirectPtr)
p->Pointer = p->DirectPtr + p->AdjustPtr;
else
{
if (p->DRAM && p->GXSetViewport)
{
int Top,Height;
if (OnlyAligned)
{
Top = p->Overlay.GUIAlignedRect.y;
Height = p->Overlay.GUIAlignedRect.Height;
}
else
{
Top = p->Overlay.Viewport.y;
Height = p->Overlay.Viewport.Height;
}
if (p->Overlay.Output.Format.Video.Pixel.Flags & PF_PIXELDOUBLE)
{
Top >>= 1;
Height >>= 1;
}
p->GXSetViewport(Top,Height,0,0); // coords in windows space
}
p->Pointer = (uint8_t*)p->GXBeginDraw();
if (!p->Pointer)
return ERR_NOT_SUPPORTED;
p->Pointer += p->AdjustPtr;
}
Planes[0] = p->Pointer;
return ERR_NONE;
}
static int Unlock(gapi* p)
{
if (!p->DirectPtr)
p->GXEndDraw();
return ERR_NONE;
}
static int UpdateWnd(gapi* p)
{
void* Wnd = Context()->Wnd;
if (p->Wnd != Wnd)
{
p->Wnd = Wnd;
if (p->Wnd && !p->Opened)
{
HWND WndTask;
while (!p->GX || !p->GXOpenDisplay(p->Wnd,GX_FULLSCREEN))
{
if (!p->Windows)
{
p->Windows = 1; // try gx.dll in \windows directory (HPC with .NET)
if (LoadDriver(p))
continue;
}
return ERR_NOT_SUPPORTED;
}
// just in case GXOpenDisplay hides these things
if (p->SHFullScreen)
{
p->SHFullScreen(p->Wnd,SHFS_SHOWSTARTICON);
p->SHFullScreen(p->Wnd,SHFS_SHOWTASKBAR);
}
WndTask = FindWindow(T("HHTaskbar"),NULL);
if (WndTask)
ShowWindow(WndTask,SW_SHOWNA);
p->Info = p->GXGetDisplayProperties();
if (!p->Info.cxWidth || !p->Info.cyHeight) // this shouldn't happen
{
p->GXCloseDisplay();
return ERR_DEVICE_ERROR;
}
p->DirectPtr = NULL;
p->Opened = 1;
p->DRAM = 0;
if (p->GXIsDisplayDRAMBuffer)
p->DRAM = p->GXIsDisplayDRAMBuffer() != 0;
// detect fake DRAM
if (p->DRAM && !(p->Info.ffFormat & kfLandscape) && QueryPlatform(PLATFORM_MODEL)==MODEL_SPV_C500_ORIGROM)
{
p->GXSetViewport(0,0,0,0);
p->DirectPtr = p->GXBeginDraw();
}
if (QueryPlatform(PLATFORM_VER) >= 421)
IsOrientationChanged(); // force requery of orientation (GXOpenDisplay changes to portrait)
Init(p); // we need the output format
}
else
if (p->Opened && !p->Wnd && !p->DirectPtr)
{
p->GXCloseDisplay();
p->Opened = 0;
}
}
return ERR_NONE;
}
static int Set(gapi* p,int No,const void* Data,int Size)
{
int Result = OverlaySet(&p->Overlay,No,Data,Size);
switch (No)
{
case NODE_SETTINGSCHANGED:
Result = UpdateWnd(p);
break;
}
return Result;
}
static int Create(gapi* p)
{
if (NodeEnumObject(NULL,RAW_ID))
return ERR_NOT_SUPPORTED;
p->Overlay.Node.Enum = Enum;
p->Overlay.Node.Get = Get;
p->Overlay.Node.Set = Set;
p->Overlay.Lock = Lock;
p->Overlay.Unlock = Unlock;
p->Overlay.Init = Init;
p->Overlay.Done = Done;
p->Overlay.Reset = Reset;
p->Overlay.Node.Get = Get;
p->Overlay.Node.Enum = Enum;
if (!LoadDriver(p))
return ERR_NOT_SUPPORTED;
p->AygShell = LoadLibrary(T("aygshell.dll"));
GetProc(&p->AygShell,&p->SHFullScreen,T("SHFullScreen"),1);
return ERR_NONE;
}
static void Delete(gapi* p)
{
if (p->GX)
FreeLibrary(p->GX);
if (p->AygShell)
FreeLibrary(p->AygShell);
}
static const nodedef GAPI =
{
sizeof(gapi)|CF_GLOBAL,
GAPI_ID,
OVERLAY_CLASS,
PRI_DEFAULT+50,
(nodecreate)Create,
(nodedelete)Delete,
};
void OverlayGAPI_Init()
{
NodeRegisterClass(&GAPI);
}
void OverlayGAPI_Done()
{
NodeUnRegisterClass(GAPI_ID);
}
#endif