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 常见错误码
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