HDR 亮度协议

在 0.50.0 版本加入.

许多现代显示器能显示高于普通内容白色的亮度,Apple 称之为 扩展动态范围 (EDR)。本协议允许程序为文本、图像和光标请求额外亮度,同时不改变其他内容的显示。

所有值相对于 SDR 白色,即普通文本使用的白色,它仍按原有亮度绘制。亮度 100 百分比表示 SDR 白色,200 表示线性光强下两倍亮度,依此类推。显示器能提供的额外亮度称为 亮度余量,也以 SDR 白色的倍数表示:1 表示没有额外范围,4 表示最高四倍 SDR 白色。亮度余量会随显示器亮度设置及窗口所在屏幕变化。

终端将每个请求钳制到当前可用亮度余量。在非 HDR 显示器上,或用户关闭 HDR 时,所有请求都钳制为 1,输出与本协议出现前完全相同。请求绝不用于降低亮度,因此未考虑 HDR 的程序,在支持与不支持本协议的终端上外观相同。

文本

两个新的 SGR 属性使用冒号子参数,以 SDR 白色的百分比设置后续字符单元前景和背景亮度::

<ESC>[56:<percent>m      foreground brightness
<ESC>[57:<percent>m      background brightness

例如,以 SDR 白色两倍半的亮度显示橙色文本::

<ESC>[38;2;255;136;0m<ESC>[56:250mHello<ESC>[m

亮度独立于颜色的选择方式,适用于 38/48 设置的颜色、十六种基本色、256 色调色板,以及默认前景和背景。因此程序无需知道默认文本是什么颜色,也能请求更亮的默认文本。字符单元的下划线和删除线使用前景亮度。反显时亮度跟随其所属颜色,因此前景亮度为 200 百分比的反显单元会显示 200 百分比亮度的背景。

<ESC>[0m、不带子参数的 56 和 57,以及 100 或更低的值会重置属性。数值按四分之一步长取整(125、150、175 等),并钳制到 1675。超出亮度余量的请求按余量上限显示。暗淡 属性(2)与亮度独立;200 百分比的暗淡文本,是相对于两倍普通白色亮度而言的暗淡。

不认识这些属性的终端会忽略它们,因为多数终端都会忽略未知 SGR 参数及子参数,所以程序可无条件发送。如果终端会丢弃包含未知参数的整个 SGR 序列,同一序列中的颜色设置也会丢失;因此应像上例那样,在设置颜色之后,用独立 <ESC>[...m 发送亮度。百分比只在冒号子参数中识别;<ESC>[56;250m 表示无值的 56 后接一个无关参数。

图像

终端图形协议 增加 HDR 像素格式 f=64。数据为 RGBA,每个像素含四个 16 位浮点数(IEEE 754 半精度,小端序),使用 线性 扩展 sRGB,1.0 为 SDR 白色,更大的值更亮。Alpha 与 f=32 一样,采用直通值(非预乘)。其他键的行为与 f=32 相同:必须通过 s 和 v 指定宽高,可用 o=z 压缩,也可使用任意传输介质。此类图像的动画帧也必须为 f=64,且不能向其他格式图像添加 f=64 帧,否则回复 EINVAL。帧在线性光空间混合;帧背景色(Y 键)视为线性值,255 为 SDR 白色。HDR 图像忽略 广色域颜色 的色域键 G:按定义,其颜色是扩展 sRGB,可通过小于零或大于一的值表示 sRGB 以外的颜色。

超过亮度余量的像素按余量上限显示;余量较少时,图像高光会被裁剪。也可在传输命令中用 T=1 请求将高光压缩到可用余量内。令 H 为亮度余量,P 为图像的最大颜色分量(至少为 1.0,且包括已加载的动画帧),转折点 k = 0.75 H。若像素最大分量 m 高于转折点,则按 f(m)/m 缩放,其中::

f(m) = k + (m - k) / (1 + s (m - k))      s = 1 / (H - k) - 1 / (P - k)

因此转折点以下保持不变,P 恰好映射到 H,曲线在转折点连续,并保留像素色相。如果 P 未超出亮度余量,则不改变内容。默认 T=0 使用裁剪。

检查终端是否支持 f=64 时,使用图形协议规定的查询操作,附带 f=64 和单个像素数据;不认识此格式的终端回复 EINVAL。

矢量图像 使用相同的 HDR 呈现路径。亮度后缀和线性扩展 sRGB 绘制色适用于全部矢量图元,包括带样式文本、描边、渐变和符号。嵌套裁剪和分组不透明度保留 HDR 值;嵌入的 f=64 图像保留线性颜色。矢量图像也接受 T=1 进行色调映射。

光标

在 Silkie 中,块状光标亮度由配置选项 cursor_brightness 控制。让光标比所有文本都亮,可在拥挤屏幕上更容易找到它。

查询亮度余量

程序若想知道可用额外亮度(例如选择图像的不同渲染版本),可通过 XTGETTCAP 查询机制询问当前窗口的亮度余量,参阅 查询终端。查询名称为 kitty-query-hdr_headroom,答案为十进制数表示的亮度余量,无余量时为 1。例如,将查询名称编码为十六进制::

<ESC>P+q6b697474792d71756572792d6864725f68656164726f6f6d<ESC>\

亮度余量随时间变化,因此依赖较早获得的值前应重新查询。该查询不发送变化通知;需要通知的程序可开启 显示信息协议 事件,其中 headroom 字段是相同值。在 macOS 上,HDR 窗口出现后的约一秒内,显示器会逐渐提升扩展范围,因此启动时查得的值常比稍后的值小。

配置

Silkie 的 hdr 默认值为 detect。只要窗口所在显示器无需切换模式即可提供 HDR,就保持启用。在 macOS 上依据显示器的 EDR 能力,包括 MacBook 内置显示器,即使当前亮度余量暂时为 1。Wayland 则使用合成器已经提供的 HDR 余量。窗口在显示器间移动时重新检测;不支持的显示器使用 SDR。

Silkie 不改变显示器的 HDR 模式。如果外接显示器需要切换 HDR 模式,请先在系统显示设置中启用。hdr no 禁用 HDR,hdr auto 仅在 HDR 内容可见时请求,hdr always 则不论检测结果都请求。修改 hdr 后请重启 Silkie,因为帧缓冲区格式在创建窗口时选定。

用户可通过 hdr_max_headroom 限制亮度。终端先应用此上限,再钳制到显示器的可用余量;上面的查询报告的是经过该上限限制的余量。

macOS 支持 HDR 内容;Wayland 需要同时满足以下条件:

  • 合成器实现 color-management-v1 协议,支持参数化图像描述、扩展线性传递函数和可设置亮度。Mutter 50 具备这些能力。此时窗口绘制线性值,并告知合成器其范围从黑色延伸到内容实际达到的、显示器参考白色的若干倍亮度。

  • 图形驱动提供浮点色彩 EGL 窗口表面(EGL_EXT_pixel_format_float),因为每通道八位无法表示高于白色的值。预期 Mesa 的硬件驱动具有此能力,但尚未测试。NVIDIA 驱动(版本 595)不支持,Mesa 软件渲染也不支持,因此这些情况下窗口行为与未启用 hdr 相同。

Wayland 的亮度余量等于合成器报告的窗口所在显示器最大亮度,除以参考白色亮度。非 HDR 模式显示器上为 1,切入或切出 HDR 模式时会变化。若合成器不知道显示器峰值(例如虚拟显示器),则报告信号上限,使余量约为 49;hdr_max_headroom 会阻止 Silkie 使用这么大的值。

Wayland 的 HDR 窗口默认使用 sRGB 基色,除非 wayland_colorspace 请求更宽色域,见 广色域颜色。因为窗口只有一份描述,广色域基色会与线性值和亮度范围在同一描述中告知合成器,绘制内容也转换到这些基色。如果合成器只接受 sRGB 基色下的线性值,则窗口保持 HDR,但使用 sRGB。该组合已按与 HDR 相同的方式、相同的范围在 Mutter 50 上检查。

kitty --debug-rendering 显示窗口是否获得浮点表面,以及向合成器声明了什么。Wayland 支持已在 Mutter 50 上逐步检查,但由于缺少支持驱动,尚未检查浮点表面本身,也未在 HDR 显示器上实际观察。在 X11 或不满足上述条件的 Wayland 上,亮度余量始终为 1。