比较 Direct2D 和 GDI 硬件加速

Direct2DGDI 都是即时模式 2D 呈现 API,并且都提供一定程度的硬件加速。 本主题探讨 Direct2D 和 GDI 之间的差异,包括两个 API 的硬件加速功能过去和现在的差异。

本主题包含以下部分:

Direct2D 和 GDI 之间的差异

GDI 呈现不透明的别名几何图形,如多边形、椭圆形和线条。 它呈现别名和 ClearType 文本,并且可以通过 AlphaBlend API 支持透明度混合。 但是,它对透明度的处理不一致,大多数 GDI API 只是忽略 alpha 通道。 很少有 GDI API 保证 alpha 通道在操作后包含的内容。 更重要的是,GDI 的呈现不会轻易映射到 3D 操作,而新式 GPU 在其呈现引擎的 3D 部分上呈现效率最高。 例如, Direct2D 的锯齿线设计为仅实现为 GPU 上呈现的两个三角形,而 GDI 使用 Bresenham 的线条绘制算法。

Direct2D 呈现不透明、透明、锯齿和抗锯齿的基元。 新式 UI 通常使用透明度和动画。 使用 Direct2D 可以更轻松地创建新式 UI,因为它严格保证如何接受和呈现透明内容,并且其所有基元都是使用硬件加速呈现的。 Direct2D 不是 GDI 的纯超集:在 GPU 上实现时速度过慢的基元在 Direct2D 中不存在。 由于 Direct2D 是在强调 3D 加速的情况下构建的,因此与 Direct3D 一起使用也很容易。

自 Windows NT 4 以来,GDI 已在内核模式下运行。 应用程序调用 GDI,然后调用其内核模式对应项,后者将基元传递给自己的驱动程序模型。 然后,此驱动程序将结果发送到全局内核模式显示驱动程序。

从 Windows 2000 开始, GDI 和 GDI 驱动程序已在内核中称为“会话空间”的独立空间中运行。为每个登录会话创建一个会话地址空间,每个 GDI 实例在此不同的内核模式地址空间中独立运行。 但是,Direct2D 在用户模式下运行,并将绘图命令通过用户模式 Direct3D 驱动程序传递到内核模式驱动程序。

图 1 - direct2d 与 gdi 的比较

GDI 和 Direct2D 硬件加速

Direct2DGDI 硬件加速之间的最重要区别在于驱动它们的基础技术。 Direct2D 分层在 Direct3D 顶部,GDI 有自己的驱动程序模型,即 GDI 设备驱动程序接口 (DDI) ,对应于 GDI 基元。 Direct3D 驱动程序模型对应于 GPU 中的 3D 渲染硬件所呈现的内容。 首次定义 GDI DDI 时,大多数显示加速硬件都以 GDI 基元为目标。 随着时间的推移,越来越重视 3D 游戏加速,而不太重视应用程序加速。 因此,BitBlt API 是硬件加速的,而大多数其他 GDI 操作则不是。

这为 GDI 呈现到显示器的方式的一系列更改设置阶段。 下图显示了 GDI 显示呈现如何从 Windows XP 更改为 Windows 7。

图 2 - gdi 显示呈现的演变

还存在导致 GDI 驱动程序模型更改的一些其他因素,如下所述。

增加显示驱动程序的复杂性和大小

随着时间的推移,3D 驱动程序变得更加复杂。 更复杂的代码往往具有更多的缺陷,这使得驱动程序存在于用户模式(驱动程序 bug 不会导致系统重启)中是有益的。 如上图所示,显示驱动程序分为复杂的用户模式组件和更简单的内核模式组件。

同步会话和全局内核地址空间时困难

在 Windows XP 中,显示驱动程序存在于两个不同的地址空间中:会话空间和内核空间。 驱动程序的某些部分需要响应电源管理事件等事件。 这需要与会话地址空间中的驱动程序状态同步。 这是一项艰巨的任务,当显示驱动程序尝试处理这些不同的地址空间时,可能会导致缺陷。

复合窗口管理

桌面窗口管理器 (DWM) (Windows 7 中引入的合成窗口管理器)将所有窗口呈现到屏幕外图面,然后将它们组合在一起以在屏幕上显示。 这要求 GDI 能够呈现到图面,然后 Direct3D 将呈现该图面进行显示。 这在 XP 驱动程序模型中造成了问题,因为 GDI 和 Direct3D 是并行驱动程序堆栈。

因此,在 Windows Vista 中, GDI DDI 显示驱动程序是作为 Microsoft 提供的规范显示驱动程序 (CDD) 将 GDI 内容呈现到要组合到屏幕的系统内存位图中实现的。

Windows 7 中的 GDI 呈现

Windows Vista 中使用的驱动程序模型要求每个 GDI 窗口都由视频内存图面和系统内存图面提供支持。 这导致每个 GDI 窗口使用系统内存。

因此, GDI 在 Windows 7 中再次更改。 GDI 已修改为呈现到光圈内存段,而不是呈现到系统内存图面。 可以从包含窗口内容的视频内存图面更新光圈内存。 GDI 可以呈现回光圈内存,然后可将结果发送回窗口表面。 由于 GPU 可寻址光圈内存段,因此 GPU 可以加速对视频内存图面的这些更新。 例如,在这些情况下,文本呈现、BitBlts、AlphaBlend、TransparentBlt 和 StretchBlt 都会加速。

对比 Windows 7 中的 Direct2D 和 GDI 加速

Direct2DGDI 都是 2D 即时模式呈现 API,并且是硬件加速的。 但是,这两个 API 中仍然存在许多差异。

资源的位置

默认情况下,GDI 会将其资源(尤其是位图)保留在系统内存中。 Direct2D 在显示适配器上的视频内存中维护其资源。 当 GDI 需要更新视频内存时,必须通过总线完成此操作,除非资源已位于光圈内存段中,或者如果可以直接表示操作。 相比之下,Direct2D 只需将其基元转换为 Direct3D 基元,因为资源已在视频内存中。

呈现方法

为了保持兼容性, GDI 使用 CPU 对光圈内存执行大部分渲染。 相比之下, Direct2D 将其 API 调用转换为 Direct3D 基元和绘制操作。 然后,结果将呈现在 GPU 上。 将光圈内存复制到表示 GDI 窗口的视频内存图面时,某些 GDI 渲染是在 GPU 上执行的。

可伸缩性

Direct2D 的呈现调用都是到 GPU 的独立命令流。 每个 Direct2D 工厂表示不同的 Direct3D 设备。 GDI 对系统上的所有应用程序使用一个命令流。 GDI 的 方法可能会导致 GPU 和 CPU 呈现上下文开销的累积。

位置

Direct2D 完全在用户模式下运行,包括 Direct3D 运行时和用户模式 Direct3D 驱动程序。 这有助于防止内核中的代码缺陷导致系统崩溃。 但是,GDI 在内核模式下的会话空间中具有大部分功能,其 API 图面处于用户模式。

硬件加速的可用性

GDI 在 Windows XP 上是硬件加速,在运行桌面窗口管理器且使用 WDDM 1.1 驱动程序时,在 Windows 7 上加速。 Direct2D 在几乎任何 WDDM 驱动程序上都是硬件加速的,无论 DWM 是否在使用中。 在 Vista 上,GDI 将始终在 CPU 上呈现。

演示模型

首次设计 Windows 时,内存不足,无法将每个窗口存储在自己的位图中。 因此, GDI 始终以逻辑方式直接呈现到屏幕,并应用了各种剪辑区域,以确保应用程序不会在其窗口外呈现。 在 Direct2D 模型中,应用程序呈现到后台缓冲区,并在应用程序完成绘图时显示结果。 这使 Direct2D 能够比 GDI 更流畅地处理动画方案。

结论

现有 GDI 代码将继续在 Windows 7 下正常工作。 但是,在编写新的图形呈现代码时,应考虑 Direct2D ,因为它可以更好地利用新式 GPU。