Skip to content

DroidExtend 1.5.1

Choose a tag to compare

@Blank2007 Blank2007 released this 12 Oct 13:29

1.5.1 —— 投屏点不动的那两天,是驱动的一张表撑爆了

症状

驱动装得好好的:设备管理器里 MttVDD 在,Get-PnpDevice 报 Status=OK、ProblemCode=0,
DLL 和安装包里的哈希一致。但只要一点「开始投屏」就失败:

虚拟显示器: \\.\DISPLAY21 (Virtual Display Driver)
  激活显示器 attach rc=-1
  扩展拓扑 rc=31
RuntimeError: 虚拟显示器 \\.\DISPLAY21 无法激活(未上桌面)

重启驱动、重启电脑都没用。

根因

驱动把 vdd_settings.xml 里每一条分辨率和每一档全局刷新率相乘,铺成一张平表交给
Windows,而这张表存在一个固定大小的缓冲区里。溢出的那一声是驱动日志里的

[WARNING] Input buffer is too small for target modes.
[ERROR] Failed to report monitor arrival. Status: -1073741637

-1073741637 就是 STATUS_NOT_SUPPORTED:适配器起来了、监视器对象也创建了,
只有 IddCxMonitorArrival 被系统拒绝——于是桌面上根本没有这块屏,之后任何
「设置分辨率 / 接上桌面」的调用都注定失败。

而随安装包发出去的 vdd_settings.xml 是 22 条分辨率 × 5 档刷新率 = 110 种组合。
上游 issue #254
记录得很清楚:108 种组合失败,同一个文件删到 96 种就成功。

那 22 条全是手机/平板面板尺寸,是我为了「跟随手机分辨率」一条条加进去的——每一条都有理由,
唯独没有人做过加法。

修复

  1. 模式表从 22 条砍到 11 条 × 5 档 = 55 种组合。 砍掉的是重复的近似尺寸
    (1600x720 / 1920x864 / 2000x1200 这类),留下的仍然覆盖常见 16:9 / 16:10 / 21:9
    以及主流手机平板面板。
  2. host/vdd.py 加了硬上限 MAX_TARGET_MODES = 90。 add_resolution()
    在写入前先算还剩几行位置;满了就删掉我们自己加的那一条(标了 auto="1"),
    驱动自带的条目一条都不碰。宁可少一个尺寸,也不能再交出驱动接不住的表。
  3. 安装脚本会自愈。 tools/vdd_install.ps1 在安装时解析 vdd_settings.xml,
    发现超过 90 种组合就把随包的那份覆盖回去并写进日志。
    已经中招的机器,点一次「安装虚拟显示器驱动(需要管理员)」就好。

已经中招了怎么办

点一次 「安装虚拟显示器驱动(需要管理员)」,UAC 点“是”,驱动设备会重启,屏幕就回来了。
(不想升级也可以手动把 C:\VirtualDisplayDriver\vdd_settings.xml 里
<resolutions> 下的条目删到 18 条以内,然后重启驱动设备。)

验证

修好后:

state   : ready
adapter : \\.\DISPLAY46 | Virtual Display Driver
monitors: 1
   \\.\DISPLAY1           2560x1600  primary=True
   \\.\DISPLAY46          1280x720   primary=False
best_mode -> (2560, 1600, 144, True)

完整端到端(虚拟屏 → ddagrab → adb reverse → 手机):

live: ['\\.\DISPLAY1 2560x1600@300+0+0', '\\.\DISPLAY46 1920x1080@60+2560+0']
ddagrab 输出: #0=2560x1600, #1=1920x1080
已发送握手 1920x1080@60
perf fps=60 mbps=2.14 latency_avg_ms=10 latency_max_ms=42
FINAL capture: frames=1604 bytes=7488821 fps=56.3

一并说清楚

这一版的教训写在 开发日志.md 第 19 节:「文件是我生成的」不等于「文件是对的」,
而 resolutions 和 g_refresh_rate 在 XML 里看着像"二选一",实际是"全都乘一遍"。
另外,这类失败在界面上没有任何提示——真正的原因只在默认关闭的驱动日志里,
所以排查时先去驱动包里找日志开关,别在驱动编号一路上涨这条线索上浪费时间
(那是症状,不是原因)。

校验

文件 大小 SHA256
DroidExtend-Setup-1.5.1.exe 36444826 bytes 0979ce0da99713fd2d9e59c12a602387f06580603c9e6b1689d90d708a5cd8e9
DroidExtend.apk 194390 bytes 0b7dbe3418e9b67c68dd33ad77b6b3569d1a645793a7b4ab6ff98e90adc8cf52