关闭

Vista is evil!

919人阅读 评论(0) 收藏 举报

最近做了件事情,就是让我们现在的系统能够在vista aero下跑起来。

其实这个问题很多人都碰到过,就是vista aero下GDI和3D API(d3d,opengl)是不能在一个区域里一起工作的。为什么会有这种现象呢?可以参考下这篇blog: http://blogs.msdn.com/greg_schechter/archive/2006/05/02/588934.aspx

上面提到了一个概念叫composite。我来以我自己的方式来解释一下,根据我以前做vista display driver的经验,在aero打开时,wdm进程会为每一个窗口都会创建一个render target。所有的绘制操作都会在这个render target上完成。但系统实现时不可能不考虑到硬件的情况——render target一般都是在video memory或者是在CPU读非常慢的AGP/PCIE memory里,而很多GDI绘制是需要read back的,典型的如XOR drawing。所以MS在实现系统时,弄了个叫shadow buffer的东西(driver层的概念,对用户层是透明的),此shadow buffer是在system memory中的,所有的基于SetPixel()/GetPixel()的GDI绘制都会先发生在此shadow buffer上,然后由OS在认为合适的时候"composite"到此窗口对应的render target上去。

这样就引入了一个问题——如何"composite"?整个窗口都copy? 显然不行,那样效率太低。虽然MS没有明确的文档说明这个问题,但我的观点是MS会以"GDI影响范围的screen aligned rectangle"来进行composite。比如你沿着水平方向画了条长度为N的像素的线段,那么恭喜你,OS只会更新此线段上的N个像素;然而假如你延45度方向画了条N个像素的线段,那么OS将会更新以此线段为对角线的正方形。这种做法也是因为图形硬件的缘故,基于screen aligned rectangle的更新对硬件来说是友好的。

然而,这样做却引入了更大的问题——假如shadow buffer上的内容和render target上的不一致,那么这种更新就是完全错误的。而这种情况在3D API和GDI同时绘制一个区域时一定会发生——3D API直接绘制到render target上,GDI先绘制到shadow buffer上,然后在composite。而以前的OS或者是vista basic mode时,GDI都是直接在frame buffer上操作的。可以想象一下vista aero下,3D API和GDI同时绘制一个区域时会有什么结果发生?

遗憾的是:MS吧这个难题留给了应用程序开发者。要解决这个问题只有两种办法:

1. 全部使用GDI或3D API来进行某一screen aligned rectagnle的绘制,比如GDI绘制屏幕左侧的面板区域,3D API绘制右侧的游戏场景预览区域,注意必须是screen aligned rectangle;

2. 强制shadow buffer在3D API绘制完成后,从render target上download数据下来进行更新,从而保持一致;

其实2基本不具备使用价值,read back不仅慢,重要的是他要flush GPU(即我们通常听到的打断流水线),效率可想而知。所以我的做法是用了1,即用3D API实现了一套替代GDI功能的方法。那个虚线的ellipse烦得我够呛,不过除了设计接口,其他的都是体力活。现在我只在d3d9下实现了,opengl和d3d10如果其他同事有兴趣,让他们照着做吧。

 

最后说点题外话,现在中国的股市,楼市真让人看不懂。有人说股市是泡沫,有人说还要涨到6k点以上,不过大家普遍看到北京奥运前中国的经济。楼市也很奇怪,京沪深等地方房价15000+还算说得过去,毕竟全中国的人都想往这里挤。可连武汉这种鸟不拉shit的地方房价都要7k+了,这种房价市民居然还排两天对抢购。实在看不懂,希望疯狂之后大家慢慢降温,骤变对百姓一点好处都没有。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:13771次
    • 积分:245
    • 等级:
    • 排名:千里之外
    • 原创:10篇
    • 转载:0篇
    • 译文:0篇
    • 评论:8条
    最新评论
    朋友&敌人