Windows 图形 API 可以分为保留模式(retained-mode)API 和 直接模式(immediate-mode)API。Direct2D 属于直接模式的 API 接口,而 WPF(Windows Presentation Foundation) 属于保留模式。

保留模式的 API 是声明式的。应用程序从图形原件构造场景,例如形状和线条。一个图形库在内存中存储场景模型。为了绘制一帧,图形库将场景转换为一个绘图命令集合。在不同帧之间,图形库将场景保存在内存中。为了改变已经渲染的画面,应用程序会发送新的命令来更新场景。例如,添加或移除一个形状。下面是重绘的过程演示:

保留模式绘制过程

直接模式的 API 是程序化的。每次都会绘制一个新的帧,应用程序会直接发送绘图命令,在两帧之间,图形库不会存储场景模型,具体的场景跟踪需要程序自身来负责。

直接模式绘制过程

保留模式的 API 使用比较简单,因为大部分工作都是由 API 来完成的。例如,初始化、状态维护以及场景清除等。另一方面,它们使用起来不是很灵活,因为 API 维护了自己的场景模型。而且,保留模式的 API 可能需要更多的内存用来提供场景模型的维护更新工作。

在 Windows vista 之前,应用程序会直接绘制到屏幕上。换句话说,程序可以直接操作显卡内存。如果一个程序不能正确绘制,则会引起一些人为的视觉错乱。例如,如果用户拖拽一个窗口从另一个窗口上方经过。假若底层的窗口无法立刻重绘,则会导致其窗口上留下上层窗口拖拽的痕迹。

窗口拖拽痕迹

这些痕迹是因为两个窗口都绘制到同一块内存引起的,为了避免这种问题,引入了桌面窗口管理器(DWM)的概念。

当 DWM 开启时,窗口不再被直接绘制到显存中,而是绘制到离屏内存缓冲区中,也叫离屏表面(offscreen surface),最后将它们绘制的结果合并后显示到屏幕上。

DWM

相比于老式的图形架构,DWM 有很多优势:

  • 更少的重绘消息。当一个窗口遮住另一个窗口,被遮住的窗口不需要重绘。

  • 减少显示问题。如上面描述的窗口拖拽引起的痕迹残留问题。

  • 视觉特效。因为DWM负责屏幕影像的合成,它可以显示一些特效,例如毛玻璃效果或者透明边框效果。

  • 对于高 DPI 的屏幕,可以自动缩放。虽然使用缩放的方法应对高 DPI 屏幕显示问题并不是最好的方法,但是对于一些旧的应用来说不失为一种适当的妥协方式。

  • 多视图。DWM 可以用各种有趣的方式使用离屏表面,例如,在 Windows 操作系统中涉及到的一些窗口特效:Flip 3D、缩略图和过渡动画等等。

需要注意 DWM 系统可能是关闭的。一方面某些图形显卡可能不支持 DWM 系统,另一方面也可能是用户在操作系统设置中主动关闭它。也就是说,在你的程序中不能单纯的依赖 DWM 系统,你应该在代码中获取 DWM 的开关状态,以保证应用程序绘图工作的正常运行。