在用户模式显示驱动程序中实现 覆盖 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 << 32) | pInfo->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