> 技术文档 > window显示驱动开发—覆盖 DDI 编程注意事项

window显示驱动开发—覆盖 DDI 编程注意事项

在用户模式显示驱动程序中实现 覆盖 DDI 时,应考虑以下编程提示:

  • 如果驱动程序支持覆盖 DDI,则必须在 D3DCAPS9 结构的 Caps 成员中设置D3DCAPS_OVERLAY位。 DirectX 9.0 SDK 文档中介绍了 D3DCAPS9 结构。 驱动程序设置D3DCAPS_OVERLAY位以响应对其 GetCaps 函数的调用,其中D3DDDICAPS_GETD3D9CAPS值在 pData 参数指向的 D3DDDIARG_GETCAPS 结构的 Type 成员中设置。
  • 例如,当显示格式为 64 位而不是 32 位时, (, 当 DWM 将 D3DDDIFORMAT 枚举中的 D3DDDIFMT_A16B16G16R16F 值用于显示模式) 时,Direct3D 运行时会将覆盖颜色键的低 32 位放置在 D3DDDI_OVERLAYINFO 结构的 DstColorKeyLow 成员中,并将D3DDDI_OVERLAYINFO的 DstColorKeyHigh 成员中的高 32 位放置。

1. 能力报告与初始化

1.1 设置 D3DCAPS_OVERLAY 标志
在 GetCaps 函数中正确报告覆盖支持能力:

HRESULT APIENTRY GetCaps(D3DDDIARG_GETCAPS* pData) { switch (pData->Type) { case D3DDDICAPS_GETD3D9CAPS: { D3DCAPS9* pCaps = (D3DCAPS9*)pData->pData; pCaps->Caps |= D3DCAPS_OVERLAY; // 同时声明支持的覆盖格式 pCaps->OverlayFormats = D3DDDIFMT_A8R8G8B8 | D3DDDIFMT_NV12; break; } // 其他能力查询... } return S_OK;}

关键点:

  • 必须设置 D3DCAPS_OVERLAY 位
  • 通过 OverlayFormats 声明支持的像素格式

2. 高精度颜色键处理

2.1 64位颜色键分解
当显示模式使用 64 位格式(如 D3DDDIFMT_A16B16G16R16F)时:

typedef struct _D3DDDI_OVERLAYINFO { D3DDDIFORMAT Format; UINT DstColorKeyLow; // 低32位 UINT DstColorKeyHigh; // 高32位 // 其他字段...} D3DDDI_OVERLAYINFO;

实现示例:

void ApplyColorKey(OVERLAY_CTX* pCtx, const D3DDDI_OVERLAYINFO* pInfo) { if (pInfo->Format == D3DDDIFMT_A16B16G16R16F) { UINT64 colorKey = ((UINT64)pInfo->DstColorKeyHigh <DstColorKeyLow; HW_SetOverlayColorKey(pCtx->hOverlay, colorKey); } else { HW_SetOverlayColorKey(pCtx->hOverlay, pInfo->DstColorKeyLow); }}

3. 覆盖平面生命周期管理

3.1 完整的 CreateOverlay 实现

HRESULT APIENTRY CreateOverlay(D3DDDIARG_CREATEOVERLAY* pCreate) { // 验证硬件支持 if (!(pDevice->Caps.OverlayFormats & pCreate->OverlayFormat)) { return D3DDDIERR_UNSUPPORTEDFORMAT; } // 分配覆盖上下文 OVERLAY_CTX* pCtx = (OVERLAY_CTX*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(OVERLAY_CTX)); // 初始化硬件覆盖层 D3DKMT_CREATEOVERLAY createParams = {0}; createParams.hDevice = pDevice->hDevice; createParams.Format = pCreate->OverlayFormat; NTSTATUS status = D3DKMTCreateOverlay(&createParams); if (!NT_SUCCESS(status)) { HeapFree(GetProcessHeap(), 0, pCtx); return E_FAIL; } pCtx->hOverlay = createParams.hOverlay; pCreate->hOverlay = (HANDLE)pCtx; return S_OK;}

4. 高级功能实现

4.1 多平面混合

Z-order 控制代码:

HRESULT APIENTRY UpdateOverlay(D3DDDIARG_UPDATEOVERLAY* pUpdate) { OVERLAY_CTX* pCtx = (OVERLAY_CTX*)pUpdate->hOverlay; D3DKMT_UPDATEOVERLAY updateParams = {0}; updateParams.hOverlay = pCtx->hOverlay; updateParams.ZOrder = pUpdate->ZPos; // 关键参数 return D3DKMTUpdateOverlay(&updateParams);}

5. 性能优化技巧

5.1 避免模式切换

// 检测显示模式变化void OnDisplayModeChange(D3DDDIFORMAT newFormat) { if (currentOverlayFormat != newFormat) { // 需要重建覆盖平面 RecreateAllOverlays(); }}

5.2 硬件缩放优化

if (pUpdate->Flags.Stretch) { EnableHardwareScaling(pCtx, pUpdate->SrcRect, pUpdate->DstRect);}

6. 错误处理与调试

6.1 常见错误码

错误码 描述 D3DDDIERR_UNSUPPORTEDFORMAT 不支持的像素格式 D3DDDIERR_TOOMANYOPERATIONS 超出最大覆盖平面数 E_INVALIDARG 无效的矩形参数

6.2 调试日志

#define OVERLAY_TRACE(fmt, ...) \\ DbgPrintEx(DPFLTR_IHVVIDEO_ID, DPFLTR_TRACE_LEVEL, \\ \"[OVERLAY] \" fmt \"\\n\", __VA_ARGS__)// 使用示例OVERLAY_TRACE(\"CreateOverlay: hResource=0x%p, Format=%d\", pCreate->hResource, pCreate->OverlayFormat);

7. WHQL 认证要点

7.1 必须通过的测试
Device.Graphics.WDDM12.Overlay

  • 基本创建/销毁功能
  • 颜色键准确性测试

Device.Graphics.WDDM12.OverlayMultiPlane

  • 验证多平面混合正确性

7.2 认证检查清单

  • 正确设置 D3DCAPS_OVERLAY 标志
  • 支持至少一种 YUV 格式(如 NV12)
  • 实现 64 位颜色键处理
  • 通过 DWM 兼容性测试

8. 向后兼容性处理

#if (D3D_UMD_INTERFACE_VERSION >= D3D_UMD_INTERFACE_VERSION_WIN7) // 完整实现覆盖DDI#else // 返回 E_NOTIMPL 并记录警告 DbgPrint(\"Overlay requires Windows 7+ UMD model\\n\"); return E_NOTIMPL;#endif