本部分包含 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 < pPresentData->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<MPO_PLANE_CTX*> 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