支持多个 PDEV

本部分演示应用程序如何在仍加载当前 PDEV 时创建新的 PDEV。 控制面板显示程序要求显示驱动程序支持启用其他 PDEV,因为应用程序有可能使用新桌面创建新的 PDEV。 具体而言,最终用户可以单击"显示"图标,对屏幕大小、颜色数量和刷新速率等元素的更改运行测试。 显示程序会动态创建新的桌面,以测试显示器的模式更改。

当用户单击"显示"图标以请求模式更改时,GDI 将执行以下步骤。 这些步骤假定当前驱动程序实例没有活动的 Direct3D、WNDOBJ 或 DRIVEROBJ 对象。

  1. 暂时禁用当前 PDEV。 调用 旧 PDEV (DrvAssertMode) 。 如果微型端口驱动程序要假定控制,则使用 FALSE 进行调用;如果使用 PDEV,则使用 TRUE 进行调用。

  2. 调用 DrvEnableDriver 以加载新的驱动程序 ((如果新的 PDEV 实例需要) )。

  3. 创建新的 PDEV

  4. 如果驱动程序驱动程序 (DirectDraw,则获取 DirectDraw) 。 只有在第一次调用成功时,才对 DrvGetDirectDrawInfo 进行第二次调用。

    • 调用 DrvGetDirectDrawInfo ( 新的 PDEV 实例) 。
    • 调用 DrvGetDirectDrawInfo ( 新的 PDEV 实例) 。
  5. 如果驱动程序 (DrvGetDirectDrawInfo 的上一次调用成功,请启用 DirectDraw) :调用 DrvEnableDirectDraw (新的 PDEV 实例) 。

  6. 如果两个实例使用相同的驱动程序 (并且 DirectDraw 被驱动程序挂钩,则将旧的 PDEV 状态复制到新的 PDEV 实例) :调用 DrvResetPDEV

  7. 通知每个驱动程序实例其新的 HDEV 关联。 第一次调用 DrvCompletePDEV 会通知新的驱动程序实例;第二个调用通知旧的驱动程序实例。

    • 调用 DrvCompletePDEV (新的 PDEV 实例) 。
    • 调用 旧 PDEV 实例 (DrvCompletePDEV) 。

    驱动程序应在需要 HDEV 的 GDI 的任何回调中使用新的 HDEV 值。

  8. 如果驱动程序 (且 DirectDraw 处于活动状态,则禁用 DirectDraw) :调用旧 PDEV 实例 (DrvDisableDirectDraw) 。

  9. 禁用 surface:调用 旧 PDEV (DrvDisableSurface) 。

  10. 禁用 PDEV:调用 旧 PDEV (DrvDisablePDEV) 。

此示例中,当用户单击"应用"时,GDI 会暂时禁用当前 PDEV,然后创建与对话框中的显示模式选择匹配的第二个 PDEV。 在测试模式下,用户查看显示屏幕上的位图后,第二个 PDEV 将被销毁,显示程序将还原桌面的原始 PDEV。 请注意,如果无法还原回原始显示设置,则如果设置与硬件和驱动程序不兼容,则系统将不可用。

如果驱动程序的当前实例拥有 Direct3D、WNDOBJ 或 DRIVEROBJ 对象,则上一模式更改序列的驱动程序视图将更改,如下所示 (请注意,在 Windows 2000 和更高版本中,只要驱动程序初始化) ,DirectDraw 就会始终启用:

  • 将延迟销毁拥有驱动程序实例。 具体而言,在模式更改时,不会对步骤 7、步骤 8 和步骤 9 中的 DrvCompletePDEV 进行第二次调用。 因此,由于在步骤 1 中调用 DrvAssertMode (FALSE) ,旧的驱动程序实例被禁用,并且会一直保留,直到系统将模式更改回原始模式,或者直到引用该实例的所有对象被销毁。

  • 如果系统在销毁引用对象之前还原回原始模式,则原始驱动程序实例将恢复。 也就是说,步骤 2 到步骤 5 不会发生,并且通过调用 DrvAssertMode (TRUE 来重新启动原始驱动程序实例) (请参阅步骤 1) 。

  • 如果在销毁所有引用对象之前系统未还原回原始模式,则销毁最终引用对象时将销毁驱动程序实例。 也就是说,在步骤 7、步骤 8 和步骤 9 中对 DrvCompletePDEV 的第二次调用将在销毁最终引用对象时发生 (例如,当所有拥有的进程都终止时) 。

这意味着,随时都可以调用 Direct3D 或 OpenGL 驱动程序来销毁非活动驱动程序实例。 即使驱动程序的另一个实例当前处于活动状态,或者该驱动程序处于全屏 MS-DOS 模式,或者如果另一个驱动程序完全拥有硬件(例如 VGA 驱动程序 (,也可以调用这些驱动程序) 。 因此, DrvDisableDirectDrawDrvDisableSurfaceDrvDisablePDEV 例程 (请参阅驱动程序的步骤 8-10) 不能假定设备采用图形模式,并且它们拥有独占访问权限。 通常,驱动程序不应在 DrvDisableXxx 例程中操作其视频硬件,除非通过记住上次 DrvAssertMode 调用中的状态来知道其实例当前处于活动状态 () 。

PDEV 是驱动程序私有的,包含表示关联物理设备的所有信息和数据。 若要创建多个 PDV,图形驱动程序必须满足以下两个要求:

  1. 驱动程序不得使用全局变量而不是取消引用 PDEV 结构的成员。 如果使用全局变量,则它们可能包含或指向创建新 PDEV 或还原旧 PDEV 时随机数据。 所有状态信息都必须保存在 PDEV 中。 PDEV 始终传递给任何图形操作,因此用于获取或设置全局数据。
  2. DrvDisableSurfaceDrvDisablePDEVDrvDisableDriver 例程必须在图形驱动程序中实现,以便应用程序可以创建和销毁其他 PDEV,并在某些情况下加载多个驱动程序。

注意

如果驱动程序的版本号为 1.0,GDI 将不会调用驱动程序来创建第二个 PDEV。 驱动程序的版本号在 DRVENABLEDATA 中返回

有时,显示程序的测试位图会使用与当前加载的驱动程序不同的驱动程序显示。 例如,如果系统使用 VGA 驱动程序以 16 颜色模式运行,并且使用 VGA64K 显示驱动程序测试 64K 颜色模式,则测试完成后,VGA64K 驱动程序将动态加载和卸载。