比较 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 使用布雷森汉姆的线条绘制算法。

Direct2D 呈现不透明、透明、别名和反别名基元。 新式 UI 通常使用透明度和动画。 使用 Direct2D 可以更轻松地创建新式 UI,因为它对它接受和呈现透明内容的方式有严格的保证,并且其所有基元都使用硬件加速呈现。 Direct2D 不是 GDI 的纯超集:在 Gpu 上实现时,基元在 Direct2D 中不存在时速度不合理。 由于 Direct2D 是基于 3D 加速构建的,因此也可以轻松地与 Direct3D 一起使用。

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

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

figure 1 - direct2d compared to 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。

figure 2 - evolution of gdi display rendering

还有一些其他因素导致 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。