上次在参考研究mobile sdk 6.0中自带的DDraw例子时发现在模拟器上跑到创建后备缓冲时由于不支持DDSCAPS_BACKBUFFER而导致程序不能运行,google了一通发现m$网站和其他一些论坛上也有人问过类似问题,得到的答案貌似是说emlator上不能跑DDraw和D3D的程序,要测只能用device,其实只要自己实现一个创建后备缓冲以及用blit模拟flip的方式就可以在模拟器上跑了,并不是模拟器根本就没有实现DDraw,只是没有实现硬件后备缓冲、翻转等操作(其实在现在的PC模拟器上的这2种方式应该也没有什么效率上的差异吧)。
具体代码:
//************************************
// Method: InitDDraw 初始化DDraw
// FullName: InitDDraw
// Access: public
// Returns: BOOL
// Qualifier:
// Parameter: void
//************************************
BOOL InitDDraw( void )
{
DDSURFACEDESC ddsd;
HRESULT hRet;
DDCAPS ddCaps;
DDCAPS ddHelCaps;
// DDraw对象
hRet = DirectDrawCreate(NULL, &g_pDD, NULL);
if (hRet != DD_OK)
{
InitFail(g_hGameWnd,hRet,_T("DDraw failed to create!"));
return FALSE;
}
// 全屏排他模式
hRet = g_pDD->SetCooperativeLevel(g_hGameWnd, DDSCL_FULLSCREEN);
if (hRet != DD_OK)
{
InitFail(g_hGameWnd,hRet,_T("Failed to set cooperative level!"));
return FALSE;
}
// 取DDraw可用能力
g_pDD->GetCaps(&ddCaps, &ddHelCaps);
// flip和backbuffer有1个不支持就启用单缓冲模式
if (!(ddCaps.ddsCaps.dwCaps & DDSCAPS_BACKBUFFER) || !(ddCaps.ddsCaps.dwCaps & DDSCAPS_FLIP))
{
// 单缓冲模式
g_bSingleBuffer = TRUE;
}
// 显示模式设置
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
hRet = g_pDD->GetDisplayMode(&ddsd);
if(hRet != DD_OK)
{
InitFail(g_hGameWnd,hRet,_T("GetDisplayMode Failed!"));
return FALSE;
}
g_dwScreenX = ddsd.dwWidth;
g_dwScreenY = ddsd.dwHeight;
g_dwScreenBpp = ddsd.ddpfPixelFormat.dwRGBBitCount;
// color key 硬件能力
g_dwTransType = DDBLT_KEYSRC;
ddCaps.dwSize = sizeof(ddCaps);
if(g_bSingleBuffer)
{
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
}
else
{
ddsd.dwFlags = DDSD_CAPS|DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE|DDSCAPS_FLIP;
ddsd.dwBackBufferCount = 1;
}
// 主缓冲创建
hRet = g_pDD->CreateSurface(&ddsd, &g_pDDSPrimary, NULL);
if (hRet != DD_OK)
{
if (hRet = DDERR_NOFLIPHW)
{
InitFail(g_hGameWnd,hRet,_T("******** Display driver doesn't support flipping surfaces. ********"));
return FALSE;
}
InitFail(g_hGameWnd,hRet,_T("CreateSurface FrontBuffer Failed!"));
return FALSE;
}
if (g_bSingleBuffer)
{
ddsd.dwFlags = DDSD_WIDTH|DDSD_HEIGHT;
ddsd.dwWidth = g_dwScreenX;
ddsd.dwHeight = g_dwScreenY;
hRet = g_pDD->CreateSurface(&ddsd,&g_pDDSBack,NULL);
if(hRet != DD_OK)
{
InitFail(g_hGameWnd,hRet,_T("BackBuffer failed to create!"));
return FALSE;
}
}
else
{
// Get a pointer to the back buffer
hRet = g_pDDSPrimary->EnumAttachedSurfaces(&g_pDDSBack, EnumFunction);
if (hRet != DD_OK)
{
InitFail(g_hGameWnd,hRet,_T("EnumAttachedSurfaces Failed!"));
return FALSE;
}
}
return TRUE;
}
在绘图循环的时候这样处理flip:
HRESULT ddrval;
RECT src, dest;
src.left = 0;
src.top = 0;
src.right = g_dwScreenX;
src.bottom = g_dwScreenY;
dest.left = 0;
dest.top = 0;
dest.right = g_dwScreenX;
dest.bottom = g_dwScreenY;
// Flip the surfaces
while( 1 )
{
if (g_bSingleBuffer)
{
//copy back buffer to front.
ddrval = g_pDDSPrimary->Blt(&dest, g_pDDSBack, &src, DDBLT_WAITNOTBUSY, NULL );
}
else
{
ddrval = g_pDDSPrimary->Flip(NULL, 0);
}
if( ddrval == DD_OK )
{
break;
}
if( ddrval == DDERR_SURFACELOST )
{
if( !RestoreSurfaces() )
{
return 0;
}
}
if( ddrval != DDERR_WASSTILLDRAWING )
{
break;
}
}
博主友情提示:
如您在评论中需要提及如QQ号、电子邮件地址或其他隐私敏感信息,欢迎使用>>博主专用加密工具v3<<处理后发布,原文只有博主可以看到。
请问一下,如何定制支持 DDraw 的模拟器,
我定制出来的,看到 windows 目录下已经有了 ddraw.dll ,但是运行 DirectDrawCreate 就返回失败了。
不需要什么额外的定制吧,我写这个程序的时候用的就是微软官网上下载的windows mobile的sdk,你可以先试试sdk里自带的ddraw程序能不能正常编译运行。
需要定制支持ddraw.的SDK .默认定制的SDK 里没有对DDRAW 支持。 K-Res使用的不过是官方已经定制好的并且支持DDRAW 的SDK