ddraw显示详解

前些时间做过一个ddraw显示来代替原来的gdi显示,显示的速度快了许多,在不断的探索中,终于明白了ddraw的用法。现在记下来。本人文字功底欠佳,如有不明白的地方,一起讨论。

 

1.ddraw 与 gdi的区别

 

两者都可以用来显示,gdi是windows比较抵触的绘图方式,ddraw是用gdi来实现的,但是ddraw利用了硬件加速。ddraw更多的应用于游戏编程当中,在wince6.0上是可以使用ddraw的,所以手机编程中用draw会提程序速度。

 

2。 我的开发环境是Windows Mobile 6.0 ,用ddraw blt方式来实现显示。

 

 

 

 

 

ddraw采用了COM的形式架构,如果实在 .c  的文件名下编译会有链接错误,这个注意,关于COM这个还没有顾上研究。

 

第一步: 创建一个DirectDraw : DirectDrawCreate(NULL, &mini_suf_ddraw_api, NULL);

 

第二步:设置显示模式为全屏独占模式: mini_suf_ddraw_api->SetCooperativeLevel(suf_hwnd, DDSCL_FULLSCREEN);

 

第三步:创建一个主表面: 

mini_suf_dds_desc.dwSize = sizeof(mini_suf_dds_desc) ; 
 mini_suf_dds_desc.dwFlags = DDSD_CAPS;
 mini_suf_dds_desc.ddsCaps.dwCaps =DDSCAPS_PRIMARYSURFACE;

 //创建主表面
 ret = mini_suf_ddraw_api->CreateSurface(&mini_suf_dds_desc, &mini_suf_dds_ptr, NULL); 

 

主表面是和显存直接相关的,可以说你往这个表面写任何东西都会直接的反映到显示屏幕上。先前我直接往这个主表面写数据,发现有刷新的问题,原因就是在这里。所以我的程序中采用了向附表面写数据然后copy到主表面,这样做是稍微有点损失效率。

 

第四步: 创建一个副表面:

int systemWidth = GetSystemMetrics(SM_CXSCREEN);
 int systemHeight = GetSystemMetrics(SM_CYSCREEN);
 mini_suf_dds_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT ;//|DDSD_CAPS ;//| DDSD_CAPS;
 //mini_suf_dds_desc.ddsCaps.dwCaps =  ;
 mini_suf_dds_desc.dwWidth = systemWidth; //mini_suf_dds_desc.dwWidth;
 mini_suf_dds_desc.dwHeight = systemHeight; //mini_suf_dds_desc.dwHeight;
 ret = mini_suf_ddraw_api->CreateSurface(&mini_suf_dds_desc, &mini_suf_dds_buf, NULL);

 

这个地方又有玄机:我好不容易研究出来的。为啥副表面非得指定设备的宽和高。因为主表面的创建是完全和设备相关的,显示屏啥样就创建成啥样,但是附表面只是一个缓存区,需要这些宽高。

 

第五步: 加锁 :

 mini_suf_dds_buf->Lock(0, &mini_suf_dds_desc, DDLOCK_WAITNOTBUSY, 0) ;

 

我老觉得这个Lock太害人了,我原来以为是和互斥锁差不多呢,其实根本不是那么回事。其实调用lock的时候,返回了好多参数给DDSURFACEDESC结构体,包括显存地址(这个是最关键的),包括显示的宽高。

加锁是加了副表面的锁,所以获得的是副表面的显存地址,我们就是要往这个副表面的显存里写东西。加锁加到主表面那就傻了,这个还和flip有关系

 

flip是创建了两个相关表面,当一个表面数据写满后交换这两个表面的地址,交换地址就是通过每次的lock来实现的。这个在后边的flip实现有详细介绍。

 

第六步  显示

mini_suf_dds_ptr->Blt(NULL, mini_suf_dds_buf, NULL, NULL, NULL);

 

这就没啥说的了,直接将副表面的数据copy到主表面,实现显示,和bitblt类似。

 

 

 

3. ddrwa的flip显示实现。

 

第一步. 创建 

基本和前面类似,参数不同而已,

mini_suf_dds_desc.dwSize = sizeof(mini_suf_dds_desc) ; 
 mini_suf_dds_desc.dwFlags = DDSD_CAPS|DDSD_BACKBUFFERCOUNT;//|DDSD_HEIGHT|DDSD_WIDTH;
 mini_suf_dds_desc.ddsCaps.dwCaps =DDSCAPS_PRIMARYSURFACE|DDSCAPS_FLIP;
 mini_suf_dds_desc.dwBackBufferCount = 1; //一个后台缓存
 /*mini_suf_dds_desc.dwWidth = 480;
 mini_suf_dds_desc.dwHeight = 640;
 mini_suf_dds_desc.ddpfPixelFormat.dwRGBBitCount = 16;*/

 //创建主表面
 ret = mini_suf_ddraw_api->CreateSurface(&mini_suf_dds_desc, &mini_suf_dds_ptr, NULL);

创建了带一个后台缓存的主表面,在真正的游戏编程当中,有很多的后台缓存表面,贴上位图,不断的进行切换,windows自带的例子有这样的。

 

 

第二步. 加锁 的时候要切换表面的显存地址的, 前面的代码是没有切换的注意啊。

 

  int ret;
  //mini_suf_dds_buf->Restore();
  ret = mini_suf_dds_buf->Lock(0, &mini_suf_dds_desc, 0, 0) ;
  if(ret != DD_OK) 
   InitFail(_T("lock field"));
  g_pddrawBitmapBuf = (U8 *) mini_suf_dds_desc.lpSurface;

 

 

第三步. 显示: 就简单了。

 

 mini_suf_dds_ptr->Flip( NULL, 0 );

 

4.横屏

 

横盘的时候,和手机本身和Windwos Mobile 的版本有相当大的关系。

 

 

 

 

 

 

这是我写的自动横屏的部分,刚开始我旋转90度,死活不行,改成270度就好了,不知道微软是咋滴了,换个手机就好了。

 

 

总结:

手机软件开发,一定不能忘记手机本身的局限性。

还要在一个问题无法解决的时候,多多尝试,自己写写demo程序,这个提高自己编码能力最快的办法。

 

 

 

 

 

 

 

 

 

 

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值