window 显示驱动开发-加载 OpenGL 可安装客户端驱动程序

OpenGL 运行时访问注册表,以确定要加载哪些 OpenGL 可安装客户端驱动程序 (ICD) 。 若要加载 OpenGL ICD,OpenGL 运行时:

  1. 通过调用 D3DKMTQueryAdapterInfo 函数,确定与 OpenGL ICD 关联的名称、版本和标志,该函数在 pData 参数指向的 D3DKMT_QUERYADAPTERINFO 结构的 Type 成员中设置KMTQAITYPE_UMOPENGLINFO值。
  2. 检查 D3DKMTQueryAdapterInfo 返回的 OpenGL ICD 的版本号,以验证 OpenGL ICD 的版本。
  3. 使用 OpenGL ICD 的名称加载 OpenGL ICD。
  4. 初始化对 OpenGL ICD 函数的访问。

若要查找 OpenGL ICD 的名称, D3DKMTQueryAdapterInfo 在以下项中搜索注册表:

HKLM/System/CurrentControlSet/Control/Class/{Adapter GUID}/0000/

一、注册表查询协议

1.1 多架构注册表布局

graph TD
    A[HKLM\System\CurrentControlSet\Control\Class\{Adapter GUID}] --> B[0000]
    B --> C[32位系统]
    C -->|键值| D1(OpenGLDriverNameWoW)
    C -->|键值| D2(OpenGLVersionWoW)
    B --> E[64位系统]
    E -->|键值| F1(OpenGLDriverName)
    E -->|键值| F2(OpenGLVersion)

关键注册表项说明

键名数据类型示例值适用环境
OpenGLDriverNameREG_SZ"nvoglv64.dll"原生64位应用
OpenGLDriverNameWoWREG_SZ"nvoglv32.dll"32位应用在64位系统
OpenGLVersionREG_DWORD0x00070000版本号(7.0)

二、D3DKMT查询流程

2.1 适配器信息获取

D3DKMT_QUERYADAPTERINFO info = {0};
info.hAdapter = hAdapterFromEnum;
info.Type = KMTQAITYPE_UMOPENGLINFO;

NTSTATUS status = D3DKMTQueryAdapterInfo(&info);
if (NT_SUCCESS(status)) {
    D3DDDI_UMOPENGLINFO* pOglInfo = (D3DDDI_UMOPENGLINFO*)info.pPrivateDriverData;
    // 解析pOglInfo结构体
}

UMOPENGLINFO数据结构:

typedef struct _D3DDDI_UMOPENGLINFO {
    ULONG Version;      // 0x00070000表示OpenGL 7.0
    CHAR  DriverName[260];
    ULONG Flags;        // 见下表
} D3DDDI_UMOPENGLINFO;

三、安全加载实现

3.1 版本验证逻辑

bool ValidateICDVersion(DWORD dwRuntimeVer, DWORD dwDriverVer) {
    // 主版本号比较
    WORD rtMajor = HIWORD(dwRuntimeVer);
    WORD drvMajor = HIWORD(dwDriverVer);
    
    // 次版本号比较
    WORD rtMinor = LOWORD(dwRuntimeVer) >> 8;
    WORD drvMinor = LOWORD(dwDriverVer) >> 8;

    return (drvMajor > rtMajor) || 
          ((drvMajor == rtMajor) && (drvMinor >= rtMinor));
}

3.2 动态加载最佳实践

HMODULE LoadICDSecurely(LPCSTR pszDriverName) {
    // 1. 验证数字签名
    if (!VerifyDriverSignature(pszDriverName)) {
        return NULL;
    }

    // 2. 设置安全加载标志
    DWORD dwOldFlags;
    SetThreadErrorMode(SEM_FAILCRITICALERRORS, &dwOldFlags);

    // 3. 显式指定加载路径
    char szSysPath[MAX_PATH];
    GetSystemDirectoryA(szSysPath, MAX_PATH);
    strcat_s(szSysPath, "\\drivers\\");
    strcat_s(szSysPath, pszDriverName);

    // 4. 加载库
    HMODULE hMod = LoadLibraryExA(szSysPath, NULL, 
        LOAD_LIBRARY_SEARCH_SYSTEM32);

    // 恢复错误模式
    SetThreadErrorMode(dwOldFlags, NULL);
    return hMod;
}

四、多架构支持矩阵

运行时环境注册表键驱动文件名后缀内存模型
32位系统OpenGLDriverName3232-bit
64位系统原生应用OpenGLDriverName6464-bit
64位系统WoW模式OpenGLDriverNameWoW3232-bit

五、故障排查指南

5.1 常见错误码

错误代码原因分析解决方案
ERROR_FILE_NOT_FOUNDICD文件路径错误检查System32/drivers目录
ERROR_INVALID_IMAGE驱动签名无效重新安装WHQL签名驱动
ERROR_BAD_EXE_FORMAT架构不匹配匹配正确的WoW/native版本

5.2 WinDbg调试命令

!gpuinfo -opengl   // 显示已加载ICD信息
!verify /d nvoglv64.dll  // 验证驱动签名

此键还包含 Microsoft Direct3D 用户模式显示驱动程序的名称。 此项包含 32 位 Windows Vista 显示驱动程序的四个注册表项(用于 32 位 Windows Vista)和四个用于 64 位 Windows Vista 上的 32 位 Windows Vista 显示驱动程序的注册表项。 以下条目适用于在 32 位 Windows Vista 上使用的 32 位 Windows Vista 显示驱动程序:

条目类型说明
UserModeDriverNameREG_SZDirect3D 用户模式显示驱动程序的名称,无论操作系统是否支持 OpenGL ICD,Direct3D 呈现设备操作都需要此名称。
OpenGLDriverNameREG_SZOpenGL ICD 的名称。 例如,如果 OpenGL ICD Mydriver.dll,则此项的值 Mydriver.dll
OpenGLVersionREG_DWORDOpenGL 运行时用于验证 OpenGL ICD 版本的 OpenGL ICD 的版本号。
OpenGLFlagsREG_DWORD标志位掩码。 目前,为兼容性设置了位 0 (0x00000001) 。 设置第 1 位 (0x00000002) 时,OpenGL 运行时不会在运行时调用 ICD 的交换缓冲区函数之前调用 ICD 的 finish 函数。

 以下条目适用于 64 位 Windows Vista 上使用的 32 位 Windows Vista 显示驱动程序: 

条目类型说明
UserModeDriverNameWowREG_SZ适用于 64 位 Windows Vista 的 32 位 Microsoft Direct3D 用户模式显示驱动程序的名称。
OpenGLDriverNameWowREG_SZ64 位 Windows Vista 的 32 位 OpenGL ICD 的名称。
OpenGLVersionWowREG_DWORD适用于 64 位 Windows Vista 的 32 位 OpenGL ICD 的版本号。
OpenGLFlagsWowREG_DWORD适用于 64 位 Windows Vista 的 32 位 OpenGL ICD 的标志位掩码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值