GAPI
简介
一 概述
同所有的Windows平台一样,WinCE平台通过GDI实现图形和文字的绘制工作,但是由于其中存在大量的转换和判断,导致其速度相对比较慢。为了提高渲染速度,微软提出了DirectDraw和Direct3D,然而对于嵌入式系统的WinCE,在WinCE5.0版本前是不能使用的。为此,微软在WinCE3.0后提供了GAPI来直接提供了对于帧缓存和按键输入的管理功能。
GAPI提供的函数相对较少,功能也有限,但是却足以支持各种主要的应用。基于GAPI的开发工作主要是实现对于帧缓存的数据管理。由于GAPI不提供基本的图形绘制功能,需要自己开发相关算法。
二 函数介绍
GAPI提供的函数有限,下面是主要函数列表
函数
|
PPC
|
SP
|
描述
|
X
|
X
|
准备进行绘制。
| |
X
|
X
|
释放所有GAPI使用的资源。
| |
X
|
X
|
释放GAPI使用的输入相关的资源, 并重新启用按键消息。
| |
X
|
X
|
当绘制完成后调用。
| |
X
|
X
|
返回一系列定义游戏控制方式的虚键码。
| |
X
|
X
|
返回保存显示硬件详细信息的结构体。
| |
X
|
X
|
返回设备是否是标准设备。
| |
X
|
X
|
打开显示,并确保帧缓存可用。
| |
X
|
X
|
打开非过滤按键消息模式。
| |
X
|
X
|
继续GAPI操作。
| |
X
|
X
|
定义一个GAPI视口。
| |
X
|
X
|
暂停GAPI操作。
|
对于各个函数,下面作比较详细的说明:
(一)按键输入相关
(1)GXDLL_API int GXOpenDisplay ( HWND hWnd, DWORD dwFlags );
如果成功返回1,否则返回0。可以使用GetLastError得到详细错误信息。
(2)GXDLL_API int GXCloseInput ();
如果成功返回1,否则返回0。可以使用GetLastError得到详细错误信息。
(3)GXDLL_API GXKeyList GXGetDefaultKeys ( int iOptions );
获得一系列虚键,以定义对于游戏最适合的按键布局。参数iOptions为定位模式,只能取GX_NORMALKEYS(绘图定位模式)或者GX_LANDSCAPEKEYS(场景定位模式)。
struct
GXKeyList
{
short vkUp; //
向上键
POINT ptUp; //
按键位置坐标(相对于屏幕设备坐标)
Short
vkDown; //
向下键
POINT ptDown; //
按键位置坐标(相对于屏幕设备坐标)
Short
vkLeft; //
向左键
POINT ptLeft; //
按键位置坐标(相对于屏幕设备坐标)
Short
vkRight; //
向右键
POINT ptRight; //
按键位置坐标(相对于屏幕设备坐标)
Short
vkA; //A
键
POINT ptA; //
按键位置坐标(相对于屏幕设备坐标)
Short
vkB; //B
键
POINT ptB; //
按键位置坐标(相对于屏幕设备坐标)
Short
vkC; //C
键
POINT ptC; //
按键位置坐标(相对于屏幕设备坐标)
Short
vkStart; //
开始键
POINT ptStart; //
按键位置坐标(相对于屏幕设备坐标)
};
其它说明可以参考MSDN。
(二)显示相关
(1)GXDLL_API int GXOpenDisplay ( HWND hWnd, DWORD dwFlags );
其中:
hWnd 全屏时指向全屏窗口的句柄
dwFlags 指定屏幕模式选项 ,可以为:
值
|
说明
|
KfFullScreen
|
使用全屏模式 (Pocket PC).
|
GX_FULLSCREEN
|
使用全屏模式 (Smartphone).
|
如果成功返回1,否则返回0。可以使用GetLastError得到详细错误信息。
(2) GXDLL_API int GXCloseDisplay ();
如果成功返回1,否则返回0。可以使用GetLastError得到详细错误信息。
(3) GXDLL_API GXDisplayProperties GXGetDisplayProperties ();
返回结构体,得到所有的显示属性。结构体定义如下
struct
GXDisplayProperties
{
DWORD cxWidth; //
屏幕的像素宽度
DWORD cyHeight; //
屏幕的像素高度
long
cbxPitch; //
为获得向右方向下个像素位置所需要移动的字节数
long
cbyPitch; //
为获得向下方向下个像素位置所需要移动的字节数
long
cBPP; //
每个像素的位数,必须是
2
的次方
DWORD ffFormat; //
像素格式,具体见下表
};
像素格式:
标识
|
说明
|
kfLandscape
|
Display is oriented on its side; 0,0 is in the lower-left corner; increasing addresses move up the screen. Generally, it is not an issue if you use cbxPitch and cbyPitch.
|
kfPalette
|
Display is palette based.
|
kfDirect
|
Display is direct mapped, no palette. This is a "helper" bit, so you do not have to check all the direct flags manually.
|
kfDirectInverted
|
Indicates the display colors are inverted. For example, with black and white colors, white is black.
|
kfDirect555
kfDirect565
kfDirect888
|
Format of a direct mapped pixel. Numbers specify bits per color in red-green-blue order. The Intel byte order is assumed: for kfDirect565, a left shift of 11 puts the low-order bits of a short or long into the red position.
|
特别说明:
对于每个像素的位数小于8(一个字节)的情况,为得到下一像素位置仅使用cbxPitch和cbyPitch是不够的,需要使用cBPP。下面是两个常见的情况:
unsigned char * pb;
if (cBPP < 8) // 每个像素4位
address = pb + ((x * cBPP) >> 3) + (y * cbyPitch);
else //每个像素8位或以上
address = pb + (x * cbxPitch) + (y * cbyPitch);
(4) GXDLL_API BOOL GXIsDisplayDRAMBuffer ();
如果是标准设备返回FALSE,如果是非标准设备返回TRUE。可以不使用此函数,但是请务必设置视口(viewport)。
(5) GXDLL_API int GXSetViewport ( DWORD dwTop, DWORD dwHeight, DWORD dwReserved1, DWORD dwReserved2 );
其中:
dwTop 视口的顶坐标再屏幕中的位置
dwHeight 视口高度
dwReserved1 保留字,必须为0
dwReserved2 保留字,必须为0
如果成功则返回1,错误则返回0,可以使用GetLastError获得错误的详细信息。此函数仅对于非标准设备有效,标准设备无效。
(6)GXDLL_API void * GXBeginDraw ();
为绘图作准备,返回显示存储区,如果不能锁定显示设备则返回NULL.
(7)GXDLL_API int GXEndDraw ();
当绘制完成后调用,成功返回1,否则返回0,可以使用GetLastError获得错误的详细信息。
(三)状态相关
(1)GXDLL_API int GXSuspend ();
暂停所有GAPI操作。成功返回1,否则返回0,可以使用GetLastError获得错误的详细信息。当存在WM_KILLFOCUS消息时,调用GXSuspend()。不需要和GXResume ()一一对应。
(2)GXDLL_API int GXResume ();
继续所有GAPI操作。成功返回1,否则返回0,可以使用GetLastError获得错误的详细信息。当存在WM_SETFOCUS消息时,调用GXResume()。不需要和GXSuspend()一一对应。
三 实际使用
实际使用GAPI的过程中,可以参考下面的步骤:
(1)获取GAPI开发相关文件(SDK)
http://www.microsoft.com/mobile/developer/downloads/gapi.asp
(2)将SDK的头文件、LIB文件、DLL文件配置到开发环境中
把“GX.H”包含文件复制到Pocket PC SDK的“Include”目录下,如果存在,说明已经配置好了。依赖CPU(ARM/X86)类型“GX.LIB”文件复制到Pocket PC SDK的相应“Lib”目录下。为支持GAPI程序的运行把依赖CPU类型的“GX.DLL” 文件复制到Pocket PC的“Windows”目录。
(3)创建项目,并加入头文件gx.h和gx.lib。
#include <gx.h>
#pragma comment(lib, "gx.lib")
(4)构建框架
初始化
// 创建窗口为全屏
if (GXOpenDisplay(hWnd, GX_FULLSCREEN) == 0) {
return FALSE; // 创建失败
}
// 获取显示属性
g_gxdp = GXGetDisplayProperties();
if ( GXIsDisplayDRAMBuffer() ) {
GXSetViewport(dwTop, dwHeight, 0, 0);
}
// 初始输入
GXOpenInput();
// 获取按键及布局信息
g_gxkl = GXGetDefaultKeys(GX_NORMALKEYS);
结束清理
GXCloseDisplay();
GXCloseInput();
(5)添加必要的响应(在窗口消息处理函数中,使用MFC开发时,重载相应的消息处理函数)
case WM_KILLFOCUS:
GXSuspend();
break;
case WM_SETFOCUS:
GXResume();
break;
case WM_KEYDOWN:
vkKey = (short)wParam;
if (vkKey == g_gxkl.vkUp) {
//处理函数
break;
}
if (vkKey == g_gxkl.vkDown) {
//处理函数
break;
}
if (vkKey == g_gxkl.vkLeft) {
//处理函数
break;
}
if (vkKey == g_gxkl.vkRight) {
//处理函数
break;
}
if (vkKey == g_gxkl.vkStart) {
//处理函数
break;
}
(6)在绘制函数中调用相关算法填充显示缓冲区
unsigned short * pusVideoBuffer = (unsigned short *)GXBeginDraw();
//实际图形绘制及图形缓冲区内容填充
GXEndDraw();
四 总结
GAPI提供了游戏制作所需要的主要两个功能:图形和输入控制。对于图形,由于其只是简单的暴露显示缓存(帧缓存),虽然提高了程序使用的自由度和绘制的效率,但是却需要自己实现各种基本的功能,这就加大了开发的难度。