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

发布于:2025-08-09 ⋅ 阅读:(18) ⋅ 点赞:(0)

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

网站公告

今日签到

点亮在社区的每一天
去签到