• [置顶] Windows显示驱动(WDDM)编程初步(2)


    欢迎转载作者:张佩】【原文http://www.yiiyee.cn/Blog/wddm2/

    第二部分专门只讲VIDPN。这是后面内容的基础。WDDM框架用VIDPN这个概念,来描述它所要处理的显示关系。

    VIDPN

    VIDPN的全称是Video Present Network,这个因为词组不太好翻译(直译可以是:视频提交网络,但颇为难听),所以一般都直接讲它的英文。

    VIDPN是WDDM引入的概念,用来描述通过显卡设备(Adapter)建立的若干个显示源(Source)和若干个目标接口(Target)之间的关系。系统按照VIDPN所定义的方式,将一个或多个显示源(Source)通过显卡设备,输出到这些目标接口(Target)上。

    基本元素

    组成VIDPN网络的,是下面这样一些基本元素:

    显示源(Source):这是一系列可提交到显卡设备,并显示出来的图像内容。

    源模式(Source Mode):一个源(Source)需要一个模式(Mode)来定义它的属性,包括长、宽、颜色格式和比特深度(Bit Depth)等。

    源模式集合(Source Mode Set):一个源(Source)的所有模式(Mode)的集合(Set),称为源模式集合。网络中所有源的模式集合,称为集合集(Sets)。

    目标(Target):一系列物理接口,显卡设备通过它们来输出源内容。可以把它们理解成显卡上的多个接口。虽然不是很准确,但如果你愿意,也可以直接把它们理解成接在显卡设备上的若干个显示器设备——这里之所以讲不是很准确,因为从接口到最终显示,中间还存在显示器设备对图像内容的处理。作为显示器设备,另有元素Monitor Source Mode Set来标识它所能够支持的Mode。但KMDOD项目中并没有用到这个元素,它默认由显示设备自己处理Target Mode和Monitor Mode间关系。

    目标模式(Target Mode):一个目标(Target)也需要一个模式(Mode)来定义它的属性,它比源更复杂一些,除了长、宽、颜色格式和深度外,还有刷新率、缓冲区长度(Pitch)等。

    目标模式集合(Source Mode Set):一个目标(Target)的所有模式(Mode)集合(Set),就是源模式集合。网络中所有目标的模式集合,称为集合集(Sets)。

    确定的模式(Pinned Mode):在一条Path中,不管Source还是Target,在另一方Mode确定的情况下,选择出来的能够和另一方相匹配的一个模式,称为确定的模式(Pinned Mode)。Pin是钉子的意思,即表示板上钉钉的Mode。

    路径(Path):把一个源(Source)和一个目标(Target)之间的连接,称为一个路径(Path)。VIDPN网络中可能存在若干个Path,但至少有一个Path。

    拓扑结构(Topology):由若干个Path组成的结构,称为拓扑结构。

    从MSDN文档中还会看到其它的一些元素,如输出设备(也就是显示设备或Monitor)、输出Codec(用作输出信号或格式转换)等,但上面这些却是组成VIDPN最基本和重要的元素。KMDOD项目中也并未用到此外的其它元素。

    拓扑结构

    下面介绍几个VIDPN网络拓扑结构的例子,都取自MSDN文档。

    示例1

    下面列几张VIDPN的拓扑图,解释其中所包含的上述基本元素。

    VIDPN1

    在上面的这个VIDPN的拓扑结构中,它有两个源(source1、source2)和三个目标(DVI、HD15、S-Video)。这是一种老式显卡,可以看到接口类型都比较旧。它提供了三种输出头,但只能支持两个输出源。这样一个源(Source1)输出到DVI口,另外一个源(Source2)以克隆模式(Clone Mode)同时输出到HD15和S-Video两个口上。两个源之间则是扩展模式(External Mode)。

     

    Path1: Source 1-> DVI
    Path2: Source2->HD15
    Path3: Source2->S-video


    三条Path组成了这个VIDPN的拓扑结构。每个Source 和Target都各有它们的mode 和mode set。在最后确定的时候,它们各自的pinned mode将被运用。

    示例2

    示例1中讲到一个VIDPN,两个Source对应到三个Target。那么Source和Target的数量各由什么决定的呢?从下面的图中可以清楚看到,Source的数量是由显卡内部的Codec决定的。

    VIDPN2

    显卡内部因为只有两个Codec,所以它仅能提供两条Surface处理的管线(PipeLine)。这和显卡本身的处理能力有关系。但是一个被处理过的Surface却可以被轻易地输出到多个Target,这一步仅仅需要少量的硬件连线就可以实现了。所以Target的数量,取决于显卡自己的设计和定位,提供比Source数量更多的Target头也是可以的。

    元素关系

    MSDN用下图解释了这么多VIDPN元素之间的对应关系。

    VIDPN3

    这是一张一对多和多对一的结构图。理解它们的关系很重要。总结而言,可把上面的四种关系翻译成下面的文字:

    1. 一个VIDPN,包含一个拓扑结构;

             一个拓扑结构包含若干条Path;

            每个Path中,包含一个Target和一个Source;

            一个Target只能在唯一的Path中;

            但一个Source可以存在于若干个Path中(Clone模式,见示例1)。

    1. 一个VIDPN包含多个Source Mode Set;

            一个Source Mode Set由多个Source Mode组成。

    1. 一个VIDPN包含多个Target Mode Set;

            一个Target Mode Set由多个Target Mode组成。

    1. 一个VIDPN包含多个Monitor source mode set;

            一个Monitor source mode set由多个Monitor source mode组成。

    框架接口

    前文我们介绍了框架和小端口之间的关系,框架对小端口提供了强有力的支持,胜过再造的力量。这个再造的力量,源自于框架向小端口所提供的各种接口。所谓接口,其实就是框架业已实现的种种功能,而以函数形式提供给小端口驱动使用。形式上,它们被封装在若干个不同的数据结构中。

    框架为小端口驱动提供的各种接口,其组织上,基本是根据VIDPN的各主要元素来划分的,下面会看到。我们会对这些接口做简单介绍,并列出接口的详细定义。

    框架回调接口

    框架回调接口是唯一由WDDM框架直接向小端口驱动提供的接口。其它接口都是直接或间接地,可以通过框架回调接口获取到。之所以把这个接口称为框架回调接口,因为它提供的所有函数名称,都依照DxgkCbXXX这样的格式命名。Cb是Callback的缩写。在WDDM的语境中,我们把这个接口中的所有函数,称为由框架提供的回调函数。

    这个接口由DDI函数DxgkDdiStartDevice在调用的时候,作为参数传入。它的定义如下:

    typedef struct _DXGKRNL_INTERFACE {
      ULONG                                 Size;
      ULONG                                 Version;
      HANDLE                                DeviceHandle;
      DXGKCB_EVAL_ACPI_METHOD               DxgkCbEvalAcpiMethod;
      DXGKCB_GET_DEVICE_INFORMATION         DxgkCbGetDeviceInformation;
      DXGKCB_INDICATE_CHILD_STATUS          DxgkCbIndicateChildStatus;
      DXGKCB_MAP_MEMORY                     DxgkCbMapMemory;
      DXGKCB_QUEUE_DPC                      DxgkCbQueueDpc;
      DXGKCB_QUERY_SERVICES                 DxgkCbQueryServices;
      DXGKCB_READ_DEVICE_SPACE              DxgkCbReadDeviceSpace;
      DXGKCB_SYNCHRONIZE_EXECUTION          DxgkCbSynchronizeExecution;
      DXGKCB_UNMAP_MEMORY                   DxgkCbUnmapMemory;
      DXGKCB_WRITE_DEVICE_SPACE             DxgkCbWriteDeviceSpace;
      DXGKCB_IS_DEVICE_PRESENT              DxgkCbIsDevicePresent;
      DXGKCB_GETHANDLEDATA                  DxgkCbGetHandleData;
      DXGKCB_GETHANDLEPARENT                DxgkCbGetHandleParent;
      DXGKCB_ENUMHANDLECHILDREN             DxgkCbEnumHandleChildren;
      DXGKCB_NOTIFY_INTERRUPT               DxgkCbNotifyInterrupt;
      DXGKCB_NOTIFY_DPC                     DxgkCbNotifyDpc;
      DXGKCB_QUERYVIDPNINTERFACE            DxgkCbQueryVidPnInterface;
      DXGKCB_QUERYMONITORINTERFACE          DxgkCbQueryMonitorInterface;
      DXGKCB_GETCAPTUREADDRESS              DxgkCbGetCaptureAddress;
      DXGKCB_LOG_ETW_EVENT                  DxgkCbLogEtwEvent;
      DXGKCB_EXCLUDE_ADAPTER_ACCESS         DxgkCbExcludeAdapterAccess;
    #if DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WIN8)
      DXGKCB_CREATECONTEXTALLOCATION        DxgkCbCreateContextAllocation;
      DXGKCB_DESTROYCONTEXTALLOCATION       DxgkCbDestroyContextAllocation;
      DXGKCB_SETPOWERCOMPONENTACTIVE        DxgkCbSetPowerComponentActive;
      DXGKCB_SETPOWERCOMPONENTIDLE          DxgkCbSetPowerComponentIdle;
      DXGKCB_ACQUIRE_POST_DISPLAY_OWNERSHIP DxgkCbAcquirePostDisplayOwnership;
      DXGKCB_POWERRUNTIMECONTROLREQUEST     DxgkCbPowerRuntimeControlRequest;
      DXGKCB_SETPOWERCOMPONENTLATENCY       DxgkCbSetPowerComponentLatency;
      DXGKCB_SETPOWERCOMPONENTRESIDENCY     DxgkCbSetPowerComponentResidency;
    #endif 
    } DXGKRNL_INTERFACE, *PDXGKRNL_INTERFACE;

    VIDPN接口

    这个接口用来管理VIDPN相关的操作。可通过框架回调接口中的DxgkCbQueryVidPnInterface获取到,示例代码如下:

    // 函数:IsSupportedVidPn
    CONST DXGK_VIDPN_INTERFACE* pVidPnInterface;
    NTSTATUS Status = m_DxgkInterface.DxgkCbQueryVidPnInterface(
                        pIsSupportedVidPn;hDesiredVidPn, //
                        DXGK_VIDPN_INTERFACE_VERSION_V1,
                        pVidPnInterface);

    结构体定义如下:

    typedef struct _DXGK_VIDPN_INTERFACE {
      DXGK_VIDPN_INTERFACE_VERSION               Version;
      DXGKDDI_VIDPN_GETTOPOLOGY                  pfnGetTopology;
      DXGKDDI_VIDPN_ACQUIRESOURCEMODESET         pfnAcquireSourceModeSet;
      DXGKDDI_VIDPN_RELEASESOURCEMODESET         pfnReleaseSourceModeSet;
      DXGKDDI_VIDPN_CREATENEWSOURCEMODESET       pfnCreateNewSourceModeSet;
      DXGKDDI_VIDPN_ASSIGNSOURCEMODESET          pfnAssignSourceModeSet;
      DXGKDDI_VIDPN_ASSIGNMULTISAMPLINGMETHODSET pfnAssignMultisamplingMethodSet;
      DXGKDDI_VIDPN_ACQUIRETARGETMODESET         pfnAcquireTargetModeSet;
      DXGKDDI_VIDPN_RELEASETARGETMODESET         pfnReleaseTargetModeSet;
      DXGKDDI_VIDPN_CREATENEWTARGETMODESET       pfnCreateNewTargetModeSet;
      DXGKDDI_VIDPN_ASSIGNTARGETMODESET          pfnAssignTargetModeSet;
    } DXGK_VIDPN_INTERFACE;

    TOPOLOGY接口

    这个接口用来管理VIDPN的拓扑结构。可以通过调用VIDPN接口的pfnGetTopology函数得到。示例代码如下:

        // 函数:IsSupportedVidPn
        D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
        CONST DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
        Status = pVidPnInterface->pfnGetTopology(
                    pIsSupportedVidPn->hDesiredVidPn, 
                    &hVidPnTopology, 
                    &pVidPnTopologyInterface);

    结构体定义如下:

    typedef struct _DXGK_VIDPNTOPOLOGY_INTERFACE {
      DXGKDDI_VIDPNTOPOLOGY_GETNUMPATHS               pfnGetNumPaths;
      DXGKDDI_VIDPNTOPOLOGY_GETNUMPATHSFROMSOURCE     pfnGetNumPathsFromSource;
      DXGKDDI_VIDPNTOPOLOGY_ENUMPATHTARGETSFROMSOURCE pfnEnumPathTargetsFromSource;
      DXGKDDI_VIDPNTOPOLOGY_GETPATHSOURCEFROMTARGET   pfnGetPathSourceFromTarget;
      DXGKDDI_VIDPNTOPOLOGY_ACQUIREPATHINFO           pfnAcquirePathInfo;
      DXGKDDI_VIDPNTOPOLOGY_ACQUIREFIRSTPATHINFO      pfnAcquireFirstPathInfo;
      DXGKDDI_VIDPNTOPOLOGY_ACQUIRENEXTPATHINFO       pfnAcquireNextPathInfo;
      DXGKDDI_VIDPNTOPOLOGY_UPDATEPATHSUPPORTINFO     pfnUpdatePathSupportInfo;
      DXGKDDI_VIDPNTOPOLOGY_RELEASEPATHINFO           pfnReleasePathInfo;
      DXGKDDI_VIDPNTOPOLOGY_CREATENEWPATHINFO         pfnCreateNewPathInfo;
      DXGKDDI_VIDPNTOPOLOGY_ADDPATH                   pfnAddPath;
      DXGKDDI_VIDPNTOPOLOGY_REMOVEPATH                pfnRemovePath;
    } DXGK_VIDPNTOPOLOGY_INTERFACE;

    SOURCE MODE SET接口

    这个接口用来管理VIDPN中的Source Mode Set。可以通过调用VIDPN接口的pfnAcquireSourceModeSet函数得到。示例代码如下:

    //函数:CommitVidPn
    CONST DXGK_VIDPNSOURCEMODESET_INTERFACE* pVidPnSourceModeSetInterface = NULL;
    Status = pVidPnInterface->pfnAcquireSourceModeSet(
    pCommitVidPn->hFunctionalVidPn,
           pCommitVidPn->AffectedVidPnSourceId,
           &hVidPnSourceModeSet,
           &pVidPnSourceModeSetInterface);

    结构体定义如下:

    typedef struct _DXGK_VIDPNSOURCEMODESET_INTERFACE {
      DXGKDDI_VIDPNSOURCEMODESET_GETNUMMODES           pfnGetNumModes;
      DXGKDDI_VIDPNSOURCEMODESET_ACQUIREFIRSTMODEINFO  pfnAcquireFirstModeInfo;
      DXGKDDI_VIDPNSOURCEMODESET_ACQUIRENEXTMODEINFO   pfnAcquireNextModeInfo;
      DXGKDDI_VIDPNSOURCEMODESET_ACQUIREPINNEDMODEINFO pfnAcquirePinnedModeInfo;
      DXGKDDI_VIDPNSOURCEMODESET_RELEASEMODEINFO       pfnReleaseModeInfo;
      DXGKDDI_VIDPNSOURCEMODESET_CREATENEWMODEINFO     pfnCreateNewModeInfo;
      DXGKDDI_VIDPNSOURCEMODESET_ADDMODE               pfnAddMode;
      DXGKDDI_VIDPNSOURCEMODESET_PINMODE               pfnPinMode;
    } DXGK_VIDPNSOURCEMODESET_INTERFACE;

    TARGET MODE SET 接口

    这个接口用来管理VIDPN中的Target Mode Set。可以通过调用VIDPN接口的pfnAcquireTargetModeSet函数得到。示例代码如下:

    // 函数:EnumVidPnCofuncModality
    CONST DXGK_VIDPNTARGETMODESET_INTERFACE* pVidPnTargetModeSetInterface = NULL;
    Status = pVidPnInterface->pfnAcquireTargetModeSet(
                       pEnumCofuncModality->hConstrainingVidPn,
                       pVidPnPresentPath->VidPnTargetId,
                       &hVidPnTargetModeSet,
                       &pVidPnTargetModeSetInterface)

    结构体定义如下:

    typedef struct _DXGK_VIDPNTARGETMODESET_INTERFACE {
      DXGKDDI_VIDPNTARGETMODESET_GETNUMMODES           pfnGetNumModes;
      DXGKDDI_VIDPNTARGETMODESET_ACQUIREFIRSTMODEINFO  pfnAcquireFirstModeInfo;
      DXGKDDI_VIDPNTARGETMODESET_ACQUIRENEXTMODEINFO   pfnAcquireNextModeInfo;
      DXGKDDI_VIDPNTARGETMODESET_ACQUIREPINNEDMODEINFO pfnAcquirePinnedModeInfo;
      DXGKDDI_VIDPNTARGETMODESET_RELEASEMODEINFO       pfnReleaseModeInfo;
      DXGKDDI_VIDPNTARGETMODESET_CREATENEWMODEINFO     pfnCreateNewModeInfo;
      DXGKDDI_VIDPNTARGETMODESET_ADDMODE               pfnAddMode;
      DXGKDDI_VIDPNTARGETMODESET_PINMODE               pfnPinMode;
    } DXGK_VIDPNTARGETMODESET_INTERFACE;

    MONITOR接口

    除了上面这些由框架提供的常用接口外,还有一些未曾在KMDOD项目中用到的接口:

    Monitor接口:DXGK_MONITOR_INTERFACE

    这个接口可通过框架回调接口中的DxgkCbQueryMonitorInterface回调函数获取。通过这个接口,可以获取Monitor的Monitor Source Mode Set接口和刷新率范围。它有两个版本,版本2中增加了函数,用来获取Windows操作系统为Monitor增加的必须支持的Mode。

    Monitor Source Mode Set接口:DXGK_MONITORSOURCEMODESET_INTERFACE

    这个接口可通过Monitor接口中的接口函数pfnAcquireMonitorSourceModeSet获取,它提供了操作显示器Mode相关的函数。

     

    版本历史

    V1.0:2013/8/5


  • 相关阅读:
    iOS学习之MVC,MVVM,MVP模式优缺点
    iOS学习之单例模式
    iOS学习之观察者模式
    iOS学习之设计模式
    iOS学习之SKTagView的使用
    iOS学习之cocoaPods
    iOS学习之git的使用
    iOS学习之block
    [学习笔记]一个实例理解Lingo的灵敏性分析
    爬虫实例(二)——爬取某宝评论
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3238902.html
Copyright © 2020-2023  润新知