> 技术文档 > window显示驱动开发—UMD 实现的 MPO 函数

window显示驱动开发—UMD 实现的 MPO 函数

本部分包含 WDDM 1.3 及更高版本的 UMD 必须实现的函数才能支持 MPO。

  • Direct3D:UMD 通过调用 UMD 的 CreateDevice 函数中的D3DDDI_DEVICEFUNCS结构的成员提供指向 D3D MPO 函数的指针。
  • DXGI:当调用特定于适配器的 CreateDevice(D3D10)函数时,UMD 通过DXGI1_3_DDI_BASE_FUNCTIONS结构的成员提供指向 DXGI MPO 函数的指针。 

下表列出了 UMD 为了支持 MPO 而必须实现的函数。

功能 DESCRIPTION pfnCheckMultiPlaneOverlaySupport (D3D) 由 D3D 运行时调用,以检查 MPO 的硬件支持的详细信息。 pfnCheckMultiPlaneOverlaySupport (DXGI) DirectX 图形基础结构(DXGI)运行时调用,以检查硬件对 MPOs 的支持情况。 pfnPresentMultiplaneOverlay (D3D) 由 D3D 运行时调用以通知 UMD 应用程序完成呈现并请求 UMD 显示源图面。 驱动程序应通过复制、翻转或执行颜色填充作来显示此图面。 pfnPresentMultiplaneOverlay (DXGI) DXGI 运行时调用该函数以通知 UMD,应用程序已完成渲染并请求 UMD 显示源表面。 UMD 应通过复制、翻转或执行颜色填充操作来显示表面。

 下表列出了 UMD 可以选择实现的 DXGI DDI 函数。

功能 DESCRIPTION pfnGetMultiPlaneOverlayCaps DXGI 运行时调用以请求 UMD 获取基本覆盖平面功能。 pfnGetMultiplaneOverlayGroupCaps DXGI 运行时调用以请求 UMD 获取一组覆盖平面功能。

1. Direct3D 部分 MPO 函数实现

1.1 通过 D3DDDI_DEVICEFUNCS 结构体暴露
在 CreateDevice 调用中,UMD 必须填充以下 MPO 相关函数指针:

typedef struct _D3DDDI_DEVICEFUNCS { // ... 标准 D3D 函数 ... // MPO 专用函数 (WDDM 1.3+) PFND3DDDI_CREATEOVERLAY pfnCreateOverlay; PFND3DDDI_UPDATEOVERLAY pfnUpdateOverlay; PFND3DDDI_FLIPOVERLAY  pfnFlipOverlay; PFND3DDDI_DESTROYOVERLAY pfnDestroyOverlay; PFND3DDDI_GETOVERLAYCOLORCONTROLS pfnGetOverlayColorControls; PFND3DDDI_SETOVERLAYCOLORCONTROLS pfnSetOverlayColorControls;} D3DDDI_DEVICEFUNCS;

关键函数实现示例
1. pfnCreateOverlay

HRESULT APIENTRY CreateOverlay( D3DDDIARG_CREATEOVERLAY* pCreateData){ // 验证硬件支持 if (!(pDevice->Caps.OverlayCaps & D3DDDI_OVERLAY_CAPS_HW)) return E_INVALIDARG; // 分配 MPO 平面资源 MPO_PLANE* pPlane = AllocateMpoPlane(pCreateData->VideoDesc); pCreateData->hOverlay = (HANDLE)pPlane; return S_OK;}

2. pfnUpdateOverlay

HRESULT APIENTRY UpdateOverlay( D3DDDIARG_UPDATEOVERLAY* pUpdateData){ MPO_PLANE* pPlane = (MPO_PLANE*)pUpdateData->hOverlay; // 硬件原子更新 HW_MPO_UPDATE update = { .SrcRect = pUpdateData->SrcRect, .DstRect = pUpdateData->DstRect, .Rotation = pUpdateData->Rotation }; return HwUpdateMpoPlane(pPlane->hHwPlane, &update);}

2. DXGI 部分 MPO 函数实现

2.1 通过 DXGI1_3_DDI_BASE_FUNCTIONS 结构体暴露
在 DXGI 设备创建时提供以下函数指针:

typedef struct DXGI1_3_DDI_BASE_FUNCTIONS { // ... 基础 DXGI 函数 ... // MPO 扩展函数 PFNDDXGI_DDI_PRESENT_MULTIPLANE_OVERLAY pfnPresentMultiplaneOverlay; PFNDDXGI_DDI_GET_MULTIPLANE_OVERLAY_CAPS pfnGetMultiplaneOverlayCaps; PFNDDXGI_DDI_CHECK_MULTIPLANE_OVERLAY_SUPPORT pfnCheckMultiplaneOverlaySupport;} DXGI1_3_DDI_BASE_FUNCTIONS;

关键函数实现示例
1. pfnPresentMultiplaneOverlay

​HRESULT APIENTRY PresentMultiplaneOverlay( DXGI_DDI_ARG_PRESENT_MULTIPLANE_OVERLAY* pPresentData){ // 验证每个平面 for (UINT i = 0; i NumPlanes; i++) { if (!ValidatePlane(pPresentData->pPlanes[i])) return DXGI_DDI_ERR_INVALID_CALL; } // 硬件提交 return HwPresentMpo(pPresentData->pPlanes, pPresentData->NumPlanes);}​

2. pfnGetMultiplaneOverlayCaps

​HRESULT APIENTRY GetMultiplaneOverlayCaps( DXGI_DDI_ARG_GET_MULTIPLANE_OVERLAY_CAPS* pCapsData){ pCapsData->Caps = { .MaxPlanes = 4, // 硬件支持的最大平面数 .SupportsRGB = TRUE, // 支持 RGB 平面 .SupportsYCbCr = TRUE, // 支持 YUV 平面 .SupportsRotation = TRUE // 支持硬件旋转 }; return S_OK;}​

3. MPO 功能验证流程

3.1 初始化阶段检查

sequenceDiagram UMD->>KMD: GetCaps(D3DDDICAPS_GETD3D9CAPS) KMD-->>UMD: 返回D3DCAPS_OVERLAY标志 UMD->>KMD: QueryInterface(DXGI1_3_DDI) KMD-->>UMD: 提供DXGI MPO函数表

3.2 运行时状态管理

// MPO 平面状态机typedef enum { MPO_STATE_FREE, // 未分配 MPO_STATE_ACTIVE, // 正在显示 MPO_STATE_PENDING, // 等待VSync} MPO_PLANE_STATE;

4. WHQL 认证必备实现

测试类别 必须通过的项目 Device.Graphics.MPO.Basic Create/Update/Destroy 平面基本操作 Device.Graphics.MPO.Format RGB/YUV/HDR 格式支持验证 Device.Graphics.MPO.Power 混合操作时的功耗合规性检查

5. 错误处理规范

错误码 触发条件 DXGI_DDI_ERR_UNSUPPORTED 硬件不支持请求的 MPO 功能 DXGI_DDI_ERR_INVALID_CALL 非法的平面属性或状态 E_ACCESSDENIED 尝试跨进程访问受保护平面

6. 性能优化技巧

6.1 平面重用池

class MpoPlanePool { std::vector m_freePlanes;public: MPO_PLANE_CTX* AllocatePlane(DXGI_FORMAT fmt) { // 从池中获取或新建平面 }};

6.2 硬件特性利用

  • Intel:使用 Plane Rotation 减少内存拷贝
  • NVIDIA:通过 Overlay Plane 降低视频播放功耗
  • AMD:结合 FreeSync 实现动态刷新率同步

7. 调试与验证工具

DirectX 控制面板:

dxcpl.exe -> MPO 诊断选项卡

ETW 追踪:

logman start MPOTrace -p Microsoft-Windows-DXG-Kernel 0xFFFF -o trace.etl

硬件寄存器检查:

// 读取显示控制器状态UINT regVal = ReadHwRegister(DISPLAY_ENGINE_MPO_STATUS);

8. 向后兼容性处理

#if (D3D_UMD_INTERFACE_VERSION >= D3D_UMD_INTERFACE_VERSION_WINBLUE) // 完整实现 WDDM 1.3 MPO 函数#else // 返回 E_NOTIMPL 并记录警告 DbgPrint(\"MPO requires WDDM 1.3+\\n\");#endif